gem5 v24.0.0.0
Loading...
Searching...
No Matches
SimpleLTInitiator2_DMI.h
Go to the documentation of this file.
1/*****************************************************************************
2
3 Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
4 more contributor license agreements. See the NOTICE file distributed
5 with this work for additional information regarding copyright ownership.
6 Accellera licenses this file to you under the Apache License, Version 2.0
7 (the "License"); you may not use this file except in compliance with the
8 License. You may obtain a copy of the License at
9
10 http://www.apache.org/licenses/LICENSE-2.0
11
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 implied. See the License for the specific language governing
16 permissions and limitations under the License.
17
18 *****************************************************************************/
19
20//====================================================================
21// Nov 06, 2008
22//
23// Updated by:
24// Xiaopeng Qiu, JEDA Technologies, Inc
25// Email: qiuxp@jedatechnologies.net
26//
27// To fix violations of TLM2.0 rules, which are detected by JEDA
28// TLM2.0 checker.
29//
30//====================================================================
31
32#ifndef __SIMPLE_LT_INITIATOR2_DMI_H__
33#define __SIMPLE_LT_INITIATOR2_DMI_H__
34
35#include "tlm.h"
36#include "tlm_utils/simple_initiator_socket.h"
37#include <systemc>
38#include <cassert>
39#include <iostream>
40#include <iomanip>
41#include <map>
42
44{
45public:
51
52public:
54
55public:
58 unsigned int nrOfTransactions = 0x5,
59 unsigned int baseAddress = 0x0) :
60 sc_core::sc_module(name),
61 socket("socket"),
62 mNrOfTransactions(nrOfTransactions),
63 mBaseAddress(baseAddress),
65 {
66 mDMIDataReads.first.set_start_address(1);
67 mDMIDataReads.first.set_end_address(0);
68 mDMIDataWrites.first.set_start_address(1);
69 mDMIDataWrites.first.set_end_address(0);
70
71 // register invalidate method
73
74 // Initiator thread
76 }
77
79 {
84
85 } else if (mTransactionCount < 2 * mNrOfTransactions) {
87 mData = 0;
89
90 } else {
91 return false;
92 }
93
94 trans.set_data_ptr(reinterpret_cast<unsigned char*>(&mData));
95 trans.set_data_length(4);
96 trans.set_streaming_width(4);
97 trans.set_dmi_allowed(false);
99
101 return true;
102 }
103
105 {
106 if (trans.get_command() == tlm::TLM_WRITE_COMMAND) {
107 std::cout << name() << ": Send write request: A = 0x"
108 << std::hex << (unsigned int)trans.get_address()
109 << ", D = 0x" << mData << std::dec
110 << " @ " << sc_core::sc_time_stamp() << std::endl;
111
112 } else {
113 std::cout << name() << ": Send read request: A = 0x"
114 << std::hex << (unsigned int)trans.get_address() << std::dec
115 << " @ " << sc_core::sc_time_stamp() << std::endl;
116 }
117 }
118
120 {
122 std::cout << name() << ": Received error response @ "
123 << sc_core::sc_time_stamp() << std::endl;
124
125 } else {
126 std::cout << name() << ": Received ok response";
127 if (trans.get_command() == tlm::TLM_READ_COMMAND) {
128 std::cout << ": D = 0x" << std::hex << mData << std::dec;
129 }
130 std::cout << " @ " << sc_core::sc_time_stamp() << std::endl;
131 }
132 }
133
135 {
136 if (trans.get_command() == tlm::TLM_READ_COMMAND) {
137 return mDMIDataReads;
138
139 } else { // WRITE
140 return mDMIDataWrites;
141 }
142 }
143
144 void run()
145 {
146 transaction_type trans;
148
149 while (initTransaction(trans)) {
150 // Create transaction and initialise t
152
153 logStartTransation(trans);
154
156 // DMI handling:
157 // We do *not* use the DMI hint to check if it makes sense to ask for
158 // DMI pointers. So the pattern is:
159 // - if the address is not covered by a DMI region try to acquire DMI
160 // pointers
161 // - if we have a DMI pointer, do the DMI "transaction"
162 // - otherwise fall back to a normal transaction
164
165 std::pair<dmi_type, bool>& dmi_data = getDMIData(trans);
166
167 // Check if we need to acquire a DMI pointer
168 if((trans.get_address() < dmi_data.first.get_start_address()) ||
169 (trans.get_address() > dmi_data.first.get_end_address()) )
170 {
171 sc_dt::uint64 address = trans.get_address(); //save original address
172 dmi_data.second =
173 socket->get_direct_mem_ptr(trans,
174 dmi_data.first);
175 trans.set_address(address);
176 }
177 // Do DMI "transaction" if we have a valid region
178 if (dmi_data.second &&
179 (trans.get_address() >= dmi_data.first.get_start_address()) &&
180 (trans.get_address() <= dmi_data.first.get_end_address()) )
181 {
182 // We can handle the data here. As the logEndTransaction is assuming
183 // something to happen in the data structure, we really need to
184 // do this:
186 sc_dt::uint64 tmp = trans.get_address() - dmi_data.first.get_start_address();
187 if (trans.get_command() == tlm::TLM_WRITE_COMMAND)
188 {
189 *(unsigned int*)&dmi_data.first.get_dmi_ptr()[tmp] = mData;
190 }
191 else
192 {
193 mData = *(unsigned int*)&dmi_data.first.get_dmi_ptr()[tmp];
194 }
195
196 // Do the wait immediately. Note that doing the wait here eats almost
197 // all the performance anyway, so we only gain something if we're
198 // using temporal decoupling.
199 if (trans.get_command() == tlm::TLM_WRITE_COMMAND) {
200 wait(dmi_data.first.get_write_latency());
201
202 } else {
203 wait(dmi_data.first.get_read_latency());
204 }
205 }
206 else // we need a full transaction
207 {
208 socket->b_transport(trans, t);
209 wait(t);
210 }
211 logEndTransaction(trans);
212 }
213 wait();
214
215 }
216
217 // Invalidate DMI pointer(s)
219 sc_dt::uint64 end_range)
220 {
221 // FIXME: probably faster to always invalidate everything?
222 if (start_range <= mDMIDataReads.first.get_end_address ()&&
223 end_range >= mDMIDataReads.first.get_start_address()) {
224 mDMIDataReads.second = false;
225 }
226 if (start_range <= mDMIDataWrites.first.get_end_address ()&&
227 end_range >= mDMIDataWrites.first.get_start_address()) {
228 mDMIDataWrites.second = false;
229 }
230 }
231
232 // Test for transport_dbg, this one should fail in bus_dmi as we address
233 // a target that doesn't support transport_dbg:
234 // FIXME: use a configurable address
236 {
237 std::cout << name() << ", <<SimpleLTInitiator1>>:" << std::endl
238 << std::endl;
239 unsigned char data[32];
240
241 transaction_type trans;
243 trans.set_data_length(32);
244 trans.set_data_ptr(data);
245 trans.set_read();
246
247 unsigned int n = socket->transport_dbg(trans);
248
249 std::cout << "Mem @" << std::hex << mBaseAddress << std::endl;
250 unsigned int j = 0;
251
252 if (n > 0)
253 {
254 // always align endianness, so that we don't get a diff when
255 // printing the raw data
256 int e_start = 0;
257 int e_end = 4;
258 int e_increment = 1;
260 {
261 e_start = 3;
262 e_end = -1;
263 e_increment = -1;
264 }
265
266 for (unsigned int i=0; i<n; i+=4)
267 {
268 for (int k=e_start; k!=e_end; k+=e_increment)
269 {
270 std::cout << std::setw(2) << std::setfill('0')
271 << (int)data[i+k];
272 j++;
273 if (j==16) {
274 j=0;
275 std::cout << std::endl;
276 } else {
277 std::cout << " ";
278 }
279 }
280 }
281 }
282 else
283 {
284 std::cout << "OK: debug transaction didn't give data." << std::endl;
285 }
286 std::cout << std::dec << std::endl;
287 }
288private:
291
293 unsigned int mNrOfTransactions;
294 unsigned int mBaseAddress;
295 unsigned int mTransactionCount;
296 unsigned int mData;
297};
298
299#endif
const char data[]
std::pair< dmi_type, bool > mDMIDataWrites
std::pair< dmi_type, bool > & getDMIData(const transaction_type &trans)
void logEndTransaction(transaction_type &trans)
std::pair< dmi_type, bool > mDMIDataReads
bool initTransaction(transaction_type &trans)
tlm::tlm_sync_enum sync_enum_type
tlm_utils::simple_initiator_socket< SimpleLTInitiator2_dmi > initiator_socket_type
initiator_socket_type socket
SC_HAS_PROCESS(SimpleLTInitiator2_dmi)
tlm::tlm_generic_payload transaction_type
void invalidate_direct_mem_ptr(sc_dt::uint64 start_range, sc_dt::uint64 end_range)
SimpleLTInitiator2_dmi(sc_core::sc_module_name name, unsigned int nrOfTransactions=0x5, unsigned int baseAddress=0x0)
void logStartTransation(transaction_type &trans)
const char * name() const
Definition sc_object.cc:44
STL pair class.
Definition stl.hh:58
void set_data_ptr(unsigned char *data)
Definition gp.hh:189
void set_dmi_allowed(bool dmi_allowed)
Definition gp.hh:239
void set_response_status(const tlm_response_status response_status)
Definition gp.hh:204
void set_address(const sc_dt::uint64 address)
Definition gp.hh:185
void set_command(const tlm_command command)
Definition gp.hh:181
sc_dt::uint64 get_address() const
Definition gp.hh:184
tlm_response_status get_response_status() const
Definition gp.hh:199
void set_data_length(const unsigned int length)
Definition gp.hh:193
tlm_command get_command() const
Definition gp.hh:180
void set_streaming_width(const unsigned int streaming_width)
Definition gp.hh:213
void register_invalidate_direct_mem_ptr(MODULE *mod, void(MODULE::*cb)(sc_dt::uint64, sc_dt::uint64))
const sc_time SC_ZERO_TIME
Definition sc_time.cc:290
const sc_time & sc_time_stamp()
Definition sc_main.cc:127
uint64_t uint64
Definition sc_nbdefs.hh:172
@ TLM_READ_COMMAND
Definition gp.hh:84
@ TLM_WRITE_COMMAND
Definition gp.hh:85
@ TLM_OK_RESPONSE
Definition gp.hh:91
@ TLM_INCOMPLETE_RESPONSE
Definition gp.hh:92
tlm_sync_enum
Definition fw_bw_ifs.hh:31
bool host_has_little_endianness()
Definition helpers.hh:43
#define SC_THREAD(name)
Definition sc_module.hh:313

Generated on Tue Jun 18 2024 16:24:07 for gem5 by doxygen 1.11.0