gem5  v22.0.0.2
MultiSocketSimpleSwitchAT.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 __SIMPLESWITCHAT_H__
21 #define __SIMPLESWITCHAT_H__
22 
23 #include "tlm.h"
24 
25 #include "tlm_utils/multi_passthrough_initiator_socket.h"
26 #include "tlm_utils/multi_passthrough_target_socket.h"
27 #include "simpleAddressMap.h"
28 #include "extensionPool.h"
29 #include "tlm_utils/instance_specific_extensions.h"
30 #include "tlm_utils/peq_with_cb_and_phase.h"
31 
32 
33 /*
34 This class is a simple crossbar switch through which an arbitrary number of initiators
35 may communicate in parallel as long as they do not talk to the same target.
36 
37 If two requestors address the same target at the same point of time,
38 the choice who will be allowed to communicate
39 is done non-deterministically (based on the SystemC process exectution order).
40 
41 This could be avoided by changing the fwPEQ into a priority PEQ of some kind.
42 
43 The switch ensures that the end_req and end_resp rules are not violated when
44 many initiator talk to the same target.
45 */
47 {
48 public:
50  typedef tlm::tlm_phase phase_type;
54 
55 public:
56  target_socket_type target_socket; //the target multi socket
57 
58 private:
59  initiator_socket_type initiator_socket; //the initiator multi socket (private to enforce use of bindTarget function)
60  SimpleAddressMap m_addrMap; //a pretty simple address map
61  std::vector<std::deque<transaction_type*> > m_pendingReqs; //list of pending reqs per target
62  std::vector<std::deque<transaction_type*> > m_pendingResps; //list of pending resps per initiator
63  std::vector<sc_dt::uint64> m_masks; //address masks for each target
64  tlm_utils::instance_specific_extension_accessor accessMySpecificExtensions; //extension accessor to access private extensions
67 
68 
69  //an instance specific extension that tells us whether we are in a wrapped b_transport or not
71  public:
72  sc_core::sc_event event; //trigger this event when transaction is done
73  };
74 
75  //an instance specific extension that holds information about source and sink of a txn
76  // as well as information if the req still has to be cleared and if the txn is already
77  // complete on the target side
79  public:
80  unsigned int fwID; //socket number of sink
81  unsigned int bwID; //socket number of source
82  bool clearReq; //is the txn still in req phase?
83  bool alreadyComplete; //has the txn already completed on the target side?
84  };
85 
86  class internalPEQTypes{ //use the tpPEQ to delay connection infos
87  public:
90  };
91  ExtensionPool<ConnectionInfo> m_connInfoPool; //our pool of extensions
92  unsigned int m_target_count; //number of connected targets (see bindTargetSocket for explanation)
93 
94 public:
98  target_socket("target_socket"),
99  initiator_socket("initiator_socket"),
102  m_connInfoPool(10),
104  {
108  }
109 
111  ,sc_dt::uint64 low
113  ,sc_dt::uint64 mask = 0xffffffffffffffffULL){
114  initiator_socket(target); //bind sockets
115  //insert into address map and increase target count
116  // (we have to count the targets manually, because target_socket.size() is only reliable during simulation
117  // as it gets evaluated during end_of_elaboration)
119  m_masks.push_back(mask); //add the mask for this target
120  }
121 
122  unsigned int decode(const sc_dt::uint64& address)
123  {
124  return m_addrMap.decode(address);
125  }
126 
128  //initialize the lists of pending reqs and resps
131  }
132 
133 
134  void b_transport(int initiator_id, transaction_type& trans, sc_core::sc_time& t){
135  //first make sure that there is no BTag (just for debugging)
136  BTag* btag;
137  accessMySpecificExtensions(trans).get_extension(btag);
138  sc_assert(!btag);
139  BTag tag; //now add our BTag
140  bool added_mm=!trans.has_mm(); //in case there is no MM in we add it now
141  if (added_mm){
142  trans.set_mm(this);
143  trans.acquire(); //acquire the txn
144  }
145  accessMySpecificExtensions(trans).set_extension(&tag);
146  phase_type phase=tlm::BEGIN_REQ; //then simply use our nb implementation (respects all the rules)
147  initiatorNBTransport(initiator_id, trans, phase, t);
148  wait(tag.event); //and wait for the event to be triggered
149  if (added_mm){ //if we added MM
150  trans.release(); //we release our reference (this will not delete the txn but trigger the tag.event as soon as the ref count is zero)
151  if (trans.get_ref_count())
152  wait(tag.event); //wait for the ref count to get to zero
153  trans.set_mm(NULL); //remove the MM
154  }
155  //don't forget to remove the extension (instance specific extensions are not cleared off by MM)
156  accessMySpecificExtensions(trans).clear_extension(&tag);
157  }
158 
159  void free(transaction_type* txn){
160  BTag* btag;
161  accessMySpecificExtensions(*txn).get_extension(btag);
162  sc_assert(btag);
163  txn->reset(); //clean off all extension that were added down stream
164  btag->event.notify();
165  }
166 
167  //do a fw transmission
169  phase_type& phase,
171  unsigned int tgtSocketNumber){
172  switch (initiator_socket[tgtSocketNumber]->nb_transport_fw(trans, phase, t)) {
173  case tlm::TLM_ACCEPTED:
174  case tlm::TLM_UPDATED:
175  // Transaction not yet finished
176  if (phase != tlm::BEGIN_REQ)
177  {
178  sc_assert(phase!=tlm::END_RESP);
179  m_bwPEQ.notify(trans,phase,t);
180  }
181  break;
182  case tlm::TLM_COMPLETED:
183  // Transaction finished
184  ConnectionInfo* connInfo;
185  accessMySpecificExtensions(trans).get_extension(connInfo);
186  sc_assert(connInfo);
187  connInfo->alreadyComplete=true;
188  phase=tlm::BEGIN_RESP;
189  m_bwPEQ.notify(trans, phase, t);
190  break;
191  default:
192  sc_assert(0); exit(1);
193  };
194  }
195 
196  //nb_transport_fw
197  sync_enum_type initiatorNBTransport(int initiator_id,
198  transaction_type& trans,
199  phase_type& phase,
201  {
202  ConnectionInfo* connInfo;
203  accessMySpecificExtensions(trans).get_extension(connInfo);
204  m_fwPEQ.notify(trans,phase,t);
205  if (phase==tlm::BEGIN_REQ){
206  //add our private information to the txn
207  sc_assert(!connInfo);
208  connInfo=m_connInfoPool.construct();
209  connInfo->fwID=decode(trans.get_address());
210  connInfo->bwID=initiator_id;
211  connInfo->clearReq=true;
212  connInfo->alreadyComplete=false;
213  accessMySpecificExtensions(trans).set_extension(connInfo);
214  }
215  else
216  if (phase==tlm::END_RESP){
217  return tlm::TLM_COMPLETED;
218  }
219  else
220  {sc_assert(0); exit(1);}
221  return tlm::TLM_ACCEPTED;
222  }
223 
225  transaction_type& trans,
226  phase_type& phase,
228  {
229  if (phase != tlm::END_REQ && phase != tlm::BEGIN_RESP) {
230  std::cout << "ERROR: '" << name()
231  << "': Illegal phase received from target." << std::endl;
232  sc_assert(false); exit(1);
233  }
234  //simply stuff it into the bw PEQ
235  m_bwPEQ.notify(trans,phase,t);
236  return tlm::TLM_ACCEPTED;
237  }
238 
239  void bwPEQcb(transaction_type& trans, const phase_type& phase){
240  //first get our private info from the txn
241  ConnectionInfo* connInfo;
242  accessMySpecificExtensions(trans).get_extension(connInfo);
243  sc_assert(connInfo);
244  phase_type p=phase;
246  BTag* btag;
247  accessMySpecificExtensions(trans).get_extension(btag);
248  bool doCall=btag==NULL; //we only will do a bw call if we are not in a wrapped b_transport
249  if ((phase==tlm::END_REQ) | (connInfo->clearReq)){ //in case the target left out end_req clearReq reminds us to unlock the req port
250  sc_assert(m_pendingReqs[connInfo->fwID].size());
251  sc_assert(m_pendingReqs[connInfo->fwID].front()==&trans);
252  m_pendingReqs[connInfo->fwID].pop_front(); //allow another req to start at this target
253  if (m_pendingReqs[connInfo->fwID].size()){ //there was a pending req
255  initiatorNBTransport_core(*m_pendingReqs[connInfo->fwID].front(), ph, t,connInfo->fwID);
256  }
257  connInfo->clearReq=false;
258  }
259  //no else here, since we might clear the req AND begin a resp
260  if (phase==tlm::BEGIN_RESP){
261  m_pendingResps[connInfo->bwID].push_back(&trans);
262  doCall=m_pendingResps[connInfo->bwID].size()==1; //do a call in case the response socket was free
263  }
264 
265  if (doCall){ //we have to do a call on the bw of fw path
266  if (btag){ //only possible if BEGIN_RESP and resp socket was free
268  m_fwPEQ.notify(trans, ph, t);
269  }
270  else
271  switch (target_socket[connInfo->bwID]->nb_transport_bw(trans, p, t)){
272  case tlm::TLM_ACCEPTED:
273  case tlm::TLM_UPDATED:
274  break;
275  case tlm::TLM_COMPLETED:{
276  //covers a piggy bagged END_RESP to START_RESP
278  m_fwPEQ.notify(trans, ph, t);
279  }
280  break;
281  default:
282  sc_assert(0); exit(1);
283 
284  };
285  }
286  }
287 
288  //the following two functions (fwPEQcb and clearPEQcb) could be one, if we were allowed
289  // to stick END_RESP into a PEQ
290  void fwPEQcb(transaction_type& trans, const phase_type& phase){
291  ConnectionInfo* connInfo;
292  accessMySpecificExtensions(trans).get_extension(connInfo);
293  sc_assert(connInfo);
294  phase_type ph=phase;
296  if (phase==tlm::BEGIN_REQ){
297  trans.set_address(trans.get_address()&m_masks[connInfo->fwID]); //mask address
298  m_pendingReqs[connInfo->fwID].push_back(&trans);
299  if (m_pendingReqs[connInfo->fwID].size()==1){ //the socket is free
300  initiatorNBTransport_core(trans, ph, t, connInfo->fwID);
301  }
302  }
303  else
304  {
305  //phase is always END_RESP
306  BTag* btag;
307  accessMySpecificExtensions(trans).get_extension(btag);
308  accessMySpecificExtensions(trans).clear_extension(connInfo); //remove our specific extension as it is not needed any more
309  if (!connInfo->alreadyComplete) {
310  sync_enum_type tmp=initiator_socket[connInfo->fwID]->nb_transport_fw(trans, ph, t);
312  }
313  sc_assert(m_pendingResps[connInfo->bwID].size());
314  m_pendingResps[connInfo->bwID].pop_front(); //remove current response
315  if (m_pendingResps[connInfo->bwID].size()){ //if there was one pending
316  ph=tlm::BEGIN_RESP; //schedule its transmission
317  m_bwPEQ.notify(*m_pendingResps[connInfo->bwID].front(),ph,t);
318  }
319  m_connInfoPool.free(connInfo); //release connInfo
320  if (btag) btag->event.notify(t); //release b_transport
321  }
322  }
323 
324  void dump_status(){
325  std::cout<<"At "<<sc_core::sc_time_stamp()<<" status of "<<name()<<" is "<<std::endl
326  <<" Number of connected initiators: "<<target_socket.size()<<std::endl
327  <<" Number of connected targets: "<<initiator_socket.size()<<std::endl
328  <<" Pending requests:"<<std::endl;
329  for (unsigned int i=0; i<m_pendingReqs.size(); i++)
330  std::cout<<" "<<m_pendingReqs[i].size()<<" pending requests for target number "<<i<<std::endl;
331  std::cout<<" Pending responses:"<<std::endl;
332  for (unsigned int i=0; i<m_pendingResps.size(); i++)
333  std::cout<<" "<<m_pendingResps[i].size()<<" pending responses for initiator number "<<i<<std::endl;
334  std::cout<<" The address map is:"<<std::endl;
335  m_addrMap.dumpMap();
336 
337  }
338 };
339 
340 #endif
extensionPool.h
tlm_utils::multi_passthrough_initiator_socket::register_nb_transport_bw
void register_nb_transport_bw(MODULE *mod, sync_enum_type(MODULE::*cb)(int, transaction_type &, phase_type &, sc_core::sc_time &))
Definition: multi_passthrough_initiator_socket.h:118
tlm_utils::instance_specific_extension
Definition: instance_specific_extensions.h:74
SimpleAddressMap::dumpMap
void dumpMap()
Print map.
Definition: simpleAddressMap.h:82
MultiSocketSimpleSwitchAT::m_masks
std::vector< sc_dt::uint64 > m_masks
Definition: MultiSocketSimpleSwitchAT.h:80
sc_core::sc_module
Definition: sc_module.hh:101
tlm::tlm_phase
Definition: phase.hh:47
tlm::TLM_COMPLETED
@ TLM_COMPLETED
Definition: fw_bw_ifs.hh:65
simpleAddressMap.h
sc_core
Definition: messages.cc:31
MultiSocketSimpleSwitchAT::start_of_simulation
void start_of_simulation()
Definition: MultiSocketSimpleSwitchAT.h:144
tlm_utils::multi_passthrough_target_socket::register_b_transport
void register_b_transport(MODULE *mod, b_cb cb)
Definition: multi_passthrough_target_socket.h:164
tlm::TLM_UPDATED
@ TLM_UPDATED
Definition: fw_bw_ifs.hh:65
MultiSocketSimpleSwitchAT::target_socket_type
tlm_utils::multi_passthrough_target_socket< MultiSocketSimpleSwitchAT > target_socket_type
Definition: MultiSocketSimpleSwitchAT.h:69
MultiSocketSimpleSwitchAT::BTag::event
sc_core::sc_event event
Definition: MultiSocketSimpleSwitchAT.h:89
MultiSocketSimpleSwitchAT::m_bwPEQ
tlm_utils::peq_with_cb_and_phase< MultiSocketSimpleSwitchAT > m_bwPEQ
Definition: MultiSocketSimpleSwitchAT.h:82
tlm::END_REQ
@ END_REQ
Definition: phase.hh:42
sc_core::sc_module::sc_module
sc_module()
Definition: sc_module.cc:256
sc_core::SC_ZERO_TIME
const sc_time SC_ZERO_TIME
Definition: sc_time.cc:290
MultiSocketSimpleSwitchAT::sync_enum_type
tlm::tlm_sync_enum sync_enum_type
Definition: MultiSocketSimpleSwitchAT.h:68
MultiSocketSimpleSwitchAT::SC_HAS_PROCESS
SC_HAS_PROCESS(MultiSocketSimpleSwitchAT)
MultiSocketSimpleSwitchAT::targetNBTransport
sync_enum_type targetNBTransport(int portId, transaction_type &trans, phase_type &phase, sc_core::sc_time &t)
Definition: MultiSocketSimpleSwitchAT.h:241
std::vector
STL vector class.
Definition: stl.hh:37
MultiSocketSimpleSwitchAT::m_target_count
unsigned int m_target_count
Definition: MultiSocketSimpleSwitchAT.h:109
MultiSocketSimpleSwitchAT::bwPEQcb
void bwPEQcb(transaction_type &trans, const phase_type &phase)
Definition: MultiSocketSimpleSwitchAT.h:256
gem5::ArmISA::i
Bitfield< 7 > i
Definition: misc_types.hh:67
MultiSocketSimpleSwitchAT::bindTargetSocket
void bindTargetSocket(initiator_socket_type::base_target_socket_type &target, sc_dt::uint64 low, sc_dt::uint64 high, sc_dt::uint64 mask=0xffffffffffffffffULL)
Definition: MultiSocketSimpleSwitchAT.h:127
sc_assert
#define sc_assert(expr)
Definition: sc_report_handler.hh:135
MultiSocketSimpleSwitchAT::MultiSocketSimpleSwitchAT
MultiSocketSimpleSwitchAT(sc_core::sc_module_name name)
Definition: MultiSocketSimpleSwitchAT.h:113
tlm_utils::multi_passthrough_target_socket::size
unsigned int size()
Definition: multi_passthrough_target_socket.h:340
MultiSocketSimpleSwitchAT::phase_type
tlm::tlm_phase phase_type
Definition: MultiSocketSimpleSwitchAT.h:67
MultiSocketSimpleSwitchAT::m_addrMap
SimpleAddressMap m_addrMap
Definition: MultiSocketSimpleSwitchAT.h:77
MultiSocketSimpleSwitchAT::initiatorNBTransport_core
void initiatorNBTransport_core(transaction_type &trans, phase_type &phase, sc_core::sc_time &t, unsigned int tgtSocketNumber)
Definition: MultiSocketSimpleSwitchAT.h:185
gem5::high
high
Definition: intmath.hh:176
gem5::VegaISA::t
Bitfield< 51 > t
Definition: pagetable.hh:56
gem5::VegaISA::p
Bitfield< 54 > p
Definition: pagetable.hh:70
sc_dt::uint64
uint64_t uint64
Definition: sc_nbdefs.hh:206
MultiSocketSimpleSwitchAT::initiator_socket
initiator_socket_type initiator_socket
Definition: MultiSocketSimpleSwitchAT.h:76
MultiSocketSimpleSwitchAT::b_transport
void b_transport(int initiator_id, transaction_type &trans, sc_core::sc_time &t)
Definition: MultiSocketSimpleSwitchAT.h:151
sc_core::sc_event
Definition: sc_event.hh:169
sc_core::sc_time
Definition: sc_time.hh:49
MultiSocketSimpleSwitchAT::m_fwPEQ
tlm_utils::peq_with_cb_and_phase< MultiSocketSimpleSwitchAT > m_fwPEQ
Definition: MultiSocketSimpleSwitchAT.h:83
MultiSocketSimpleSwitchAT::initiatorNBTransport
sync_enum_type initiatorNBTransport(int initiator_id, transaction_type &trans, phase_type &phase, sc_core::sc_time &t)
Definition: MultiSocketSimpleSwitchAT.h:214
MultiSocketSimpleSwitchAT::target_socket
target_socket_type target_socket
Definition: MultiSocketSimpleSwitchAT.h:73
MultiSocketSimpleSwitchAT::initiator_socket_type
tlm_utils::multi_passthrough_initiator_socket< MultiSocketSimpleSwitchAT > initiator_socket_type
Definition: MultiSocketSimpleSwitchAT.h:70
gem5::ArmISA::mask
Bitfield< 3, 0 > mask
Definition: pcstate.hh:63
tlm_utils::multi_passthrough_target_socket< MultiSocketSimpleSwitchAT >
MultiSocketSimpleSwitchAT::BTag
Definition: MultiSocketSimpleSwitchAT.h:87
sc_core::sc_module_name
Definition: sc_module_name.hh:41
tlm_utils::multi_passthrough_initiator_socket< MultiSocketSimpleSwitchAT >
MultiSocketSimpleSwitchAT::ConnectionInfo::clearReq
bool clearReq
Definition: MultiSocketSimpleSwitchAT.h:99
MultiSocketSimpleSwitchAT::dump_status
void dump_status()
Definition: MultiSocketSimpleSwitchAT.h:341
tlm::END_RESP
@ END_RESP
Definition: phase.hh:44
MultiSocketSimpleSwitchAT::ConnectionInfo::bwID
unsigned int bwID
Definition: MultiSocketSimpleSwitchAT.h:98
MultiSocketSimpleSwitchAT::accessMySpecificExtensions
tlm_utils::instance_specific_extension_accessor accessMySpecificExtensions
Definition: MultiSocketSimpleSwitchAT.h:81
tlm_utils::peq_with_cb_and_phase< MultiSocketSimpleSwitchAT >
SimpleAddressMap
Simple address map implementation for the generic protocol.
Definition: simpleAddressMap.h:32
gem5::X86ISA::exit
Bitfield< 3 > exit
Definition: misc.hh:848
tlm_utils::instance_specific_extension_accessor
Definition: instance_specific_extensions_int.h:166
MultiSocketSimpleSwitchAT::decode
unsigned int decode(const sc_dt::uint64 &address)
Definition: MultiSocketSimpleSwitchAT.h:139
tlm_utils::multi_passthrough_initiator_socket< MultiSocketSimpleSwitchAT >::base_target_socket_type
base_type::base_target_socket_type base_target_socket_type
Definition: multi_passthrough_initiator_socket.h:94
MultiSocketSimpleSwitchAT::free
void free(transaction_type *txn)
Definition: MultiSocketSimpleSwitchAT.h:176
tlm::BEGIN_REQ
@ BEGIN_REQ
Definition: phase.hh:41
MultiSocketSimpleSwitchAT::ConnectionInfo::fwID
unsigned int fwID
Definition: MultiSocketSimpleSwitchAT.h:97
ExtensionPool
Definition: extensionPool.h:24
MultiSocketSimpleSwitchAT::internalPEQTypes::tlm_phase_type
tlm::tlm_phase tlm_phase_type
Definition: MultiSocketSimpleSwitchAT.h:106
MultiSocketSimpleSwitchAT::ConnectionInfo
Definition: MultiSocketSimpleSwitchAT.h:95
tlm_utils::multi_passthrough_initiator_socket::size
unsigned int size()
Definition: multi_passthrough_initiator_socket.h:302
tlm::tlm_generic_payload
Definition: gp.hh:133
MultiSocketSimpleSwitchAT::internalPEQTypes::tlm_payload_type
ConnectionInfo tlm_payload_type
Definition: MultiSocketSimpleSwitchAT.h:105
tlm_utils::multi_passthrough_target_socket::register_nb_transport_fw
void register_nb_transport_fw(MODULE *mod, nb_cb cb)
Definition: multi_passthrough_target_socket.h:148
sc_core::sc_object::name
const char * name() const
Definition: sc_object.cc:44
MultiSocketSimpleSwitchAT::m_pendingReqs
std::vector< std::deque< transaction_type * > > m_pendingReqs
Definition: MultiSocketSimpleSwitchAT.h:78
SimpleAddressMap::decode
unsigned int decode(sc_dt::uint64 address_)
Decode slave address.
Definition: simpleAddressMap.h:102
SimpleAddressMap::insert
void insert(sc_dt::uint64 baseAddress_, sc_dt::uint64 highAddress_, unsigned int portNumber_)
Insert a slave into the address map.
Definition: simpleAddressMap.h:146
tlm::tlm_sync_enum
tlm_sync_enum
Definition: fw_bw_ifs.hh:48
sc_core::sc_module::wait
void wait()
Definition: sc_module.cc:428
MultiSocketSimpleSwitchAT::m_pendingResps
std::vector< std::deque< transaction_type * > > m_pendingResps
Definition: MultiSocketSimpleSwitchAT.h:79
MultiSocketSimpleSwitchAT::transaction_type
tlm::tlm_generic_payload transaction_type
Definition: MultiSocketSimpleSwitchAT.h:66
MultiSocketSimpleSwitchAT::m_connInfoPool
ExtensionPool< ConnectionInfo > m_connInfoPool
Definition: MultiSocketSimpleSwitchAT.h:108
tlm_utils::peq_with_cb_and_phase::notify
void notify(tlm_payload_type &t, const tlm_phase_type &p, const sc_core::sc_time &when)
Definition: peq_with_cb_and_phase.h:222
MultiSocketSimpleSwitchAT
Definition: MultiSocketSimpleSwitchAT.h:46
MultiSocketSimpleSwitchAT::ConnectionInfo::alreadyComplete
bool alreadyComplete
Definition: MultiSocketSimpleSwitchAT.h:100
MultiSocketSimpleSwitchAT::fwPEQcb
void fwPEQcb(transaction_type &trans, const phase_type &phase)
Definition: MultiSocketSimpleSwitchAT.h:307
tlm::tlm_mm_interface
Definition: gp.hh:50
sc_core::sc_time_stamp
const sc_time & sc_time_stamp()
Definition: sc_main.cc:127
tlm::BEGIN_RESP
@ BEGIN_RESP
Definition: phase.hh:43
tlm::TLM_ACCEPTED
@ TLM_ACCEPTED
Definition: fw_bw_ifs.hh:65

Generated on Thu Jul 28 2022 13:32:43 for gem5 by doxygen 1.8.17