gem5 v24.0.0.0
Loading...
Searching...
No Matches
SimpleBusAT.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#ifndef __SIMPLEBUSAT_H__
21#define __SIMPLEBUSAT_H__
22
23//#include <systemc>
24#include "tlm.h"
25
26#include "tlm_utils/simple_target_socket.h"
27#include "tlm_utils/simple_initiator_socket.h"
28
29#include "tlm_utils/peq_with_get.h"
30
31template <int NR_OF_INITIATORS, int NR_OF_TARGETS>
33{
34public:
40
41public:
44
45public:
48 sc_core::sc_module(name),
49 mRequestPEQ("requestPEQ"),
50 mResponsePEQ("responsePEQ")
51 {
52 for (unsigned int i = 0; i < NR_OF_INITIATORS; ++i) {
56 }
57 for (unsigned int i = 0; i < NR_OF_TARGETS; ++i) {
60 }
61
64 }
65
66 //
67 // Dummy decoder:
68 // - address[31-28]: portId
69 // - address[27-0]: masked address
70 //
71
72 unsigned int getPortId(const sc_dt::uint64& address)
73 {
74 return (unsigned int)address >> 28;
75 }
76
77 sc_dt::uint64 getAddressOffset(unsigned int portId)
78 {
79 return portId << 28;
80 }
81
82 sc_dt::uint64 getAddressMask(unsigned int portId)
83 {
84 return 0xfffffff;
85 }
86
87 unsigned int decode(const sc_dt::uint64& address)
88 {
89 // decode address:
90 // - return initiator socket id
91
92 return getPortId(address);
93 }
94
95 //
96 // AT protocol
97 //
98
100 {
101 while (true) {
103
104 transaction_type* trans;
105 while ((trans = mRequestPEQ.get_next_transaction())!=0) {
106 unsigned int portId = decode(trans->get_address());
107 assert(portId < NR_OF_TARGETS);
108 initiator_socket_type* decodeSocket = &initiator_socket[portId];
109 trans->set_address(trans->get_address() & getAddressMask(portId));
110
111 // Fill in the destination port
113 assert(it != mPendingTransactions.end());
114 it->second.to = decodeSocket;
115
118
119 // FIXME: No limitation on number of pending transactions
120 // All targets (that return false) must support multiple transactions
121 switch ((*decodeSocket)->nb_transport_fw(*trans, phase, t)) {
123 case tlm::TLM_UPDATED:
124 // Transaction not yet finished
125 if (phase == tlm::BEGIN_REQ) {
126 // Request phase not yet finished
128
129 } else if (phase == tlm::END_REQ) {
130 // Request phase finished, but response phase not yet started
131 wait(t);
132
133 } else if (phase == tlm::BEGIN_RESP) {
134 mResponsePEQ.notify(*trans, t);
135 // Not needed to send END_REQ to initiator
136 continue;
137
138 } else { // END_RESP
139 assert(0); exit(1);
140 }
141
142 // only send END_REQ to initiator if BEGIN_RESP was not already send
143 if (it->second.from) {
144 phase = tlm::END_REQ;
146 (*it->second.from)->nb_transport_bw(*trans, phase, t);
147 }
148
149 break;
150
152 // Transaction finished
153 mResponsePEQ.notify(*trans, t);
154
155 // reset to destination port (we must not send END_RESP to target)
156 it->second.to = 0;
157
158 wait(t);
159 break;
160
161 default:
162 assert(0); exit(1);
163 };
164 }
165 }
166 }
167
169 {
170 while (true) {
172
173 transaction_type* trans;
174 while ((trans = mResponsePEQ.get_next_transaction())!=0) {
176 assert(it != mPendingTransactions.end());
177
180
181 target_socket_type* initiatorSocket = it->second.from;
182 // if BEGIN_RESP is send first we don't have to send END_REQ anymore
183 it->second.from = 0;
184
185 switch ((*initiatorSocket)->nb_transport_bw(*trans, phase, t)) {
187 // Transaction finished
188 wait(t);
189 break;
190
192 case tlm::TLM_UPDATED:
193 // Transaction not yet finished
195 break;
196
197 default:
198 assert(0); exit(1);
199 };
200
201 // forward END_RESP to target
202 if (it->second.to) {
203 phase = tlm::END_RESP;
205 #if ( ! NDEBUG )
206 sync_enum_type r = (*it->second.to)->nb_transport_fw(*trans, phase, t);
207 #endif /* ! NDEBUG */
208 assert(r == tlm::TLM_COMPLETED);
209 }
210
211 mPendingTransactions.erase(it);
212 trans->release();
213 }
214 }
215 }
216
217 //
218 // interface methods
219 //
220
222 transaction_type& trans,
223 phase_type& phase,
225 {
226 if (phase == tlm::BEGIN_REQ) {
227 trans.acquire();
228 addPendingTransaction(trans, 0, initiator_id);
229
230 mRequestPEQ.notify(trans, t);
231
232 } else if (phase == tlm::END_RESP) {
234 return tlm::TLM_COMPLETED;
235
236 } else {
237 std::cout << "ERROR: '" << name()
238 << "': Illegal phase received from initiator." << std::endl;
239 assert(false); exit(1);
240 }
241
242 return tlm::TLM_ACCEPTED;
243 }
244
246 transaction_type& trans,
247 phase_type& phase,
249 {
250 if (phase != tlm::END_REQ && phase != tlm::BEGIN_RESP) {
251 std::cout << "ERROR: '" << name()
252 << "': Illegal phase received from target." << std::endl;
253 assert(false); exit(1);
254 }
255
257 if (phase == tlm::BEGIN_RESP) {
258 mResponsePEQ.notify(trans, t);
259 }
260
261 return tlm::TLM_ACCEPTED;
262 }
263
264 unsigned int transportDebug(int initiator_id, transaction_type& trans)
265 {
266 unsigned int portId = decode(trans.get_address());
267 assert(portId < NR_OF_TARGETS);
268 initiator_socket_type* decodeSocket = &initiator_socket[portId];
269 trans.set_address( trans.get_address() & getAddressMask(portId) );
270
271 return (*decodeSocket)->transport_dbg(trans);
272 }
273
274 bool limitRange(unsigned int portId, sc_dt::uint64& low, sc_dt::uint64& high)
275 {
276 sc_dt::uint64 addressOffset = getAddressOffset(portId);
277 sc_dt::uint64 addressMask = getAddressMask(portId);
278
279 if (low > addressMask) {
280 // Range does not overlap with addressrange for this target
281 return false;
282 }
283
284 low += addressOffset;
285 if (high > addressMask) {
286 high = addressOffset + addressMask;
287
288 } else {
289 high += addressOffset;
290 }
291 return true;
292 }
293
294 bool getDMIPointer(int initiator_id,
295 transaction_type& trans,
296 tlm::tlm_dmi& dmi_data)
297 {
298 // FIXME: DMI not supported for AT bus?
299 sc_dt::uint64 address = trans.get_address();
300
301 unsigned int portId = decode(address);
302 assert(portId < NR_OF_TARGETS);
303 initiator_socket_type* decodeSocket = &initiator_socket[portId];
304 sc_dt::uint64 maskedAddress = address & getAddressMask(portId);
305
306 trans.set_address(maskedAddress);
307
308 bool result =
309 (*decodeSocket)->get_direct_mem_ptr(trans, dmi_data);
310
311 if (result)
312 {
313 // Range must contain address
314 assert(dmi_data.get_start_address() <= maskedAddress);
315 assert(dmi_data.get_end_address() >= maskedAddress);
316 }
317
318 // Should always succeed
319 sc_dt::uint64 start, end;
320 start = dmi_data.get_start_address();
321 end = dmi_data.get_end_address();
322
323 limitRange(portId, start, end);
324
325 dmi_data.set_start_address(start);
326 dmi_data.set_end_address(end);
327
328 return result;
329 }
330
331 void invalidateDMIPointers(int portId,
332 sc_dt::uint64 start_range,
333 sc_dt::uint64 end_range)
334 {
335 // FIXME: probably faster to always invalidate everything?
336
337 if ((portId >= 0) && !limitRange(portId, start_range, end_range)) {
338 // Range does not fall into address range of target
339 return;
340 }
341
342 for (unsigned int i = 0; i < NR_OF_INITIATORS; ++i) {
343 (target_socket[i])->invalidate_direct_mem_ptr(start_range, end_range);
344 }
345 }
346
347private:
350 int initiatorId)
351 {
352 const ConnectionInfo info = { &target_socket[initiatorId], to };
353 assert(mPendingTransactions.find(&trans) == mPendingTransactions.end());
354 mPendingTransactions[&trans] = info;
355 }
356
357private:
362 typedef std::map<transaction_type*, ConnectionInfo> PendingTransactions;
363 typedef typename PendingTransactions::iterator PendingTransactionsIterator;
364 typedef typename PendingTransactions::const_iterator PendingTransactionsConstIterator;
365
366private:
368
372
376};
377
378#endif
void invalidateDMIPointers(int portId, sc_dt::uint64 start_range, sc_dt::uint64 end_range)
tlm_utils::peq_with_get< transaction_type > mResponsePEQ
void ResponseThread()
sc_dt::uint64 getAddressMask(unsigned int portId)
Definition SimpleBusAT.h:82
unsigned int decode(const sc_dt::uint64 &address)
Definition SimpleBusAT.h:87
std::map< transaction_type *, ConnectionInfo > PendingTransactions
tlm::tlm_sync_enum sync_enum_type
Definition SimpleBusAT.h:37
bool getDMIPointer(int initiator_id, transaction_type &trans, tlm::tlm_dmi &dmi_data)
target_socket_type target_socket[NR_OF_INITIATORS]
Definition SimpleBusAT.h:42
unsigned int transportDebug(int initiator_id, transaction_type &trans)
tlm_utils::peq_with_get< transaction_type > mRequestPEQ
sc_core::sc_event mBeginResponseEvent
unsigned int getPortId(const sc_dt::uint64 &address)
Definition SimpleBusAT.h:72
sync_enum_type initiatorNBTransport(int initiator_id, transaction_type &trans, phase_type &phase, sc_core::sc_time &t)
tlm_utils::simple_initiator_socket_tagged< SimpleBusAT > initiator_socket_type
Definition SimpleBusAT.h:39
sc_core::sc_event mBeginRequestEvent
sync_enum_type targetNBTransport(int portId, transaction_type &trans, phase_type &phase, sc_core::sc_time &t)
tlm::tlm_phase phase_type
Definition SimpleBusAT.h:36
PendingTransactions mPendingTransactions
PendingTransactions::iterator PendingTransactionsIterator
tlm::tlm_generic_payload transaction_type
Definition SimpleBusAT.h:35
tlm_utils::simple_target_socket_tagged< SimpleBusAT > target_socket_type
Definition SimpleBusAT.h:38
sc_dt::uint64 getAddressOffset(unsigned int portId)
Definition SimpleBusAT.h:77
SC_HAS_PROCESS(SimpleBusAT)
void RequestThread()
Definition SimpleBusAT.h:99
PendingTransactions::const_iterator PendingTransactionsConstIterator
sc_core::sc_event mEndResponseEvent
bool limitRange(unsigned int portId, sc_dt::uint64 &low, sc_dt::uint64 &high)
initiator_socket_type initiator_socket[NR_OF_TARGETS]
Definition SimpleBusAT.h:43
sc_core::sc_event mEndRequestEvent
void addPendingTransaction(transaction_type &trans, initiator_socket_type *to, int initiatorId)
SimpleBusAT(sc_core::sc_module_name name)
Definition SimpleBusAT.h:47
const char * name() const
Definition sc_object.cc:44
sc_dt::uint64 get_start_address() const
Definition dmi.hh:59
sc_dt::uint64 get_end_address() const
Definition dmi.hh:60
void set_start_address(sc_dt::uint64 addr)
Definition dmi.hh:82
void set_end_address(sc_dt::uint64 addr)
Definition dmi.hh:83
void set_address(const sc_dt::uint64 address)
Definition gp.hh:185
sc_dt::uint64 get_address() const
Definition gp.hh:184
transaction_type * get_next_transaction()
sc_core::sc_event & get_event()
void notify(transaction_type &trans, const sc_core::sc_time &t)
void register_nb_transport_bw(MODULE *mod, sync_enum_type(MODULE::*cb)(int, transaction_type &, phase_type &, sc_core::sc_time &), int id)
void register_invalidate_direct_mem_ptr(MODULE *mod, void(MODULE::*cb)(int, sc_dt::uint64, sc_dt::uint64), int id)
void register_nb_transport_fw(MODULE *mod, sync_enum_type(MODULE::*cb)(int id, transaction_type &, phase_type &, sc_core::sc_time &), int id)
void register_transport_dbg(MODULE *mod, unsigned int(MODULE::*cb)(int id, transaction_type &), int id)
void register_get_direct_mem_ptr(MODULE *mod, bool(MODULE::*cb)(int id, transaction_type &, tlm::tlm_dmi &), int id)
const sc_time SC_ZERO_TIME
Definition sc_time.cc:290
uint64_t uint64
Definition sc_nbdefs.hh:172
@ BEGIN_RESP
Definition phase.hh:43
@ END_RESP
Definition phase.hh:44
@ BEGIN_REQ
Definition phase.hh:41
@ END_REQ
Definition phase.hh:42
tlm_sync_enum
Definition fw_bw_ifs.hh:31
@ TLM_COMPLETED
Definition fw_bw_ifs.hh:31
@ TLM_ACCEPTED
Definition fw_bw_ifs.hh:31
@ TLM_UPDATED
Definition fw_bw_ifs.hh:31
#define SC_THREAD(name)
Definition sc_module.hh:313
initiator_socket_type * to
target_socket_type * from

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