scc  2024.06
SystemC components library
ace_lite_initiator.h
1 /*******************************************************************************
2  * Copyright 2021-2022 MINRES Technologies GmbH
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *******************************************************************************/
16 
17 #ifndef _BUS_AXI_PIN_ACE_LITE_INITIATOR_H_
18 #define _BUS_AXI_PIN_ACE_LITE_INITIATOR_H_
19 
20 #include <axi/axi_tlm.h>
21 #include <axi/fsm/base.h>
22 #include <axi/fsm/protocol_fsm.h>
23 #include <cci_configuration>
24 #include <interfaces/axi/signal_if.h>
25 #include <scc/fifo_w_cb.h>
26 #include <systemc>
27 #include <tlm/scc/tlm_mm.h>
28 #include <tlm_utils/peq_with_cb_and_phase.h>
29 
31 namespace axi {
33 namespace pin {
34 
35 using namespace axi::fsm;
36 
37 template <typename CFG>
38 struct ace_lite_initiator : public sc_core::sc_module,
39  public aw_ace_lite<CFG, typename CFG::master_types>,
40  public wdata_ace_lite<CFG, typename CFG::master_types>,
41  public b_ace_lite<CFG, typename CFG::master_types>,
42  public ar_ace_lite<CFG, typename CFG::master_types>,
43  public rresp_ace_lite<CFG, typename CFG::master_types>,
44  protected axi::fsm::base,
45  public axi::ace_fw_transport_if<axi::axi_protocol_types> {
46  SC_HAS_PROCESS(ace_lite_initiator);
47 
48  using payload_type = axi::axi_protocol_types::tlm_payload_type;
49  using phase_type = axi::axi_protocol_types::tlm_phase_type;
50 
51  sc_core::sc_in<bool> clk_i{"clk_i"};
52 
54 
55  cci::cci_param<bool> pipelined_wrreq{"pipelined_wrreq", false};
56 
57  cci::cci_param<bool> mask_axi_id{"mask_axi_id", false};
58 
59  ace_lite_initiator(sc_core::sc_module_name const& nm, bool pipelined_wrreq = false)
60  : sc_core::sc_module(nm)
61  // ace_lite has no ack, therefore coherent= false
62  , base(CFG::BUSWIDTH, false)
63  , pipelined_wrreq("pipelined_wrreq", pipelined_wrreq) {
64  instance_name = name();
65  tsckt(*this);
66  SC_METHOD(clk_delay);
67  sensitive << clk_i.pos();
68  SC_THREAD(ar_t);
69  SC_THREAD(r_t);
70  SC_THREAD(aw_t);
71  SC_THREAD(wdata_t);
72  SC_THREAD(b_t);
73  }
74 
75 private:
76  void b_transport(payload_type& trans, sc_core::sc_time& t) override {
77  trans.set_dmi_allowed(false);
78  trans.set_response_status(tlm::TLM_OK_RESPONSE);
79  }
80 
81  tlm::tlm_sync_enum nb_transport_fw(payload_type& trans, phase_type& phase, sc_core::sc_time& t) override {
82  assert(trans.get_extension<axi::ace_extension>() && "missing ACE extension");
83  sc_core::sc_time delay; // FIXME: calculate delay correctly
84  fw_peq.notify(trans, phase, delay);
85  return tlm::TLM_ACCEPTED;
86  }
87 
88  bool get_direct_mem_ptr(payload_type& trans, tlm::tlm_dmi& dmi_data) override {
89  trans.set_dmi_allowed(false);
90  return false;
91  }
92 
93  unsigned int transport_dbg(payload_type& trans) override { return 0; }
94 
95  void end_of_elaboration() override { clk_if = dynamic_cast<sc_core::sc_clock*>(clk_i.get_interface()); }
96 
97  fsm_handle* create_fsm_handle() { return new fsm_handle(); }
98 
99  void setup_callbacks(fsm_handle* fsm_hndl);
100 
101  void clk_delay() { clk_delayed.notify(axi::CLK_DELAY); }
102 
103  void ar_t();
104  void r_t();
105  void aw_t();
106  void wdata_t();
107  void b_t();
115  static typename CFG::data_t get_cache_data_for_beat(fsm::fsm_handle* fsm_hndl);
116  std::array<unsigned, 3> outstanding_cnt{0, 0, 0};
117  sc_core::sc_clock* clk_if{nullptr};
118  sc_core::sc_event clk_delayed, clk_self, r_end_resp_evt, w_end_resp_evt;
119  void nb_fw(payload_type& trans, const phase_type& phase) {
120  auto t = sc_core::SC_ZERO_TIME;
121  base::nb_fw(trans, phase, t);
122  }
123  tlm_utils::peq_with_cb_and_phase<ace_lite_initiator> fw_peq{this, &ace_lite_initiator::nb_fw};
124  std::unordered_map<unsigned, std::deque<fsm_handle*>> rd_resp_by_id, wr_resp_by_id;
125  struct fifo_entry {
126  tlm::tlm_generic_payload* gp = nullptr;
127  bool last = false;
128  bool needs_end_req = false;
129  size_t beat_num = 0;
130  fifo_entry(tlm::tlm_generic_payload* gp, bool last, bool needs_end_req, size_t beat_num)
131  : gp(gp)
132  , last(last)
133  , needs_end_req(needs_end_req)
134  , beat_num(beat_num) {
135  if(gp->has_mm())
136  gp->acquire();
137  }
138  fifo_entry(tlm::tlm_generic_payload* gp, bool needs_end_req)
139  : gp(gp)
140  , needs_end_req(needs_end_req) {
141  if(gp->has_mm())
142  gp->acquire();
143  }
144  fifo_entry(fifo_entry const& o)
145  : gp(o.gp)
146  , last(o.last)
147  , needs_end_req(o.needs_end_req)
148  , beat_num(o.beat_num) {
149  if(gp && gp->has_mm())
150  gp->acquire();
151  }
152  fifo_entry& operator=(const fifo_entry& o) {
153  gp = o.gp;
154  last = o.last;
155  needs_end_req = o.needs_end_req;
156  beat_num = o.beat_num;
157  return *this;
158  }
159  ~fifo_entry() {
160  if(gp && gp->has_mm())
161  gp->release();
162  }
163  };
164  scc::fifo_w_cb<fifo_entry> ar_fifo{"ar_fifo"};
165  scc::fifo_w_cb<fifo_entry> aw_fifo{"aw_fifo"};
166  scc::fifo_w_cb<fifo_entry> wdata_fifo{"wdata_fifo"};
167  void write_ar(tlm::tlm_generic_payload& trans);
168  void write_aw(tlm::tlm_generic_payload& trans);
169  void write_wdata(tlm::tlm_generic_payload& trans, unsigned beat);
170 };
171 
172 } // namespace pin
173 } // namespace axi
174 
175 template <typename CFG> inline void axi::pin::ace_lite_initiator<CFG>::write_ar(tlm::tlm_generic_payload& trans) {
176  sc_dt::sc_uint<CFG::ADDRWIDTH> addr = trans.get_address();
177  this->ar_addr.write(addr);
178  if(auto ext = trans.get_extension<axi::ace_extension>()) {
179  auto id = ext->get_id();
180  if(!mask_axi_id.get_value() && id >= (1 << CFG::IDWIDTH))
181  SCCERR(SCMOD) << "AWID value larger than signal awid with width=" << CFG::IDWIDTH << " can carry";
182  this->ar_id->write(sc_dt::sc_uint<CFG::IDWIDTH>(id));
183  this->ar_len->write(sc_dt::sc_uint<8>(ext->get_length()));
184  this->ar_size->write(sc_dt::sc_uint<3>(ext->get_size()));
185  this->ar_burst->write(sc_dt::sc_uint<2>(axi::to_int(ext->get_burst())));
186  this->ar_lock->write(ext->is_exclusive());
187  this->ar_cache->write(sc_dt::sc_uint<4>(ext->get_cache()));
188  this->ar_prot.write(ext->get_prot());
189  this->ar_qos->write(ext->get_qos());
190  this->ar_region->write(ext->get_region());
191  this->ar_domain->write(sc_dt::sc_uint<2>((uint8_t)ext->get_domain()));
192  this->ar_snoop->write(sc_dt::sc_uint<4>((uint8_t)ext->get_snoop()));
193  this->ar_bar->write(sc_dt::sc_uint<2>((uint8_t)ext->get_barrier()));
194  this->ar_user->write(ext->get_user(axi::common::id_type::CTRL));
195  }
196 }
197 
198 template <typename CFG> inline void axi::pin::ace_lite_initiator<CFG>::write_aw(tlm::tlm_generic_payload& trans) {
199  sc_dt::sc_uint<CFG::ADDRWIDTH> addr = trans.get_address();
200  this->aw_addr.write(addr);
201  if(auto ext = trans.get_extension<axi::ace_extension>()) {
202  this->aw_prot.write(ext->get_prot());
203  // TBD?? this->aw_lock.write();
204  auto id = ext->get_id();
205  if(!mask_axi_id.get_value() && id >= (1 << CFG::IDWIDTH))
206  SCCERR(SCMOD) << "AWID value larger than signal awid with width=" << CFG::IDWIDTH << " can carry";
207  this->aw_id->write(sc_dt::sc_uint<CFG::IDWIDTH>(id));
208  this->aw_lock->write(ext->is_exclusive());
209  this->aw_len->write(sc_dt::sc_uint<8>(ext->get_length()));
210  this->aw_size->write(sc_dt::sc_uint<3>(ext->get_size()));
211  this->aw_burst->write(sc_dt::sc_uint<2>(axi::to_int(ext->get_burst())));
212  this->aw_cache->write(sc_dt::sc_uint<4>(ext->get_cache()));
213  this->aw_qos->write(sc_dt::sc_uint<4>(ext->get_qos()));
214  this->aw_region->write(sc_dt::sc_uint<4>(ext->get_region()));
215  this->aw_user->write(ext->get_user(axi::common::id_type::CTRL));
216  this->aw_domain->write(sc_dt::sc_uint<2>((uint8_t)ext->get_domain()));
217  this->aw_snoop->write(sc_dt::sc_uint<CFG::AWSNOOPWIDTH>((uint8_t)ext->get_snoop()));
218  this->aw_bar->write(sc_dt::sc_uint<2>((uint8_t)ext->get_barrier()));
219  /* ace_lite does not have unique* */
220  // this->aw_unique->write(ext->get_unique());
221  if(ext->is_stash_nid_en()) {
222  this->aw_stashniden->write(true);
223  this->aw_stashnid->write(sc_dt::sc_uint<11>(ext->get_stash_nid()));
224  }
225  if(ext->is_stash_lpid_en()) {
226  this->aw_stashlpiden->write(true);
227  this->aw_stashlpid->write(sc_dt::sc_uint<5>(ext->get_stash_lpid()));
228  }
229  }
230 }
231 
232 // FIXME: strb not yet correct
233 template <typename CFG> inline void axi::pin::ace_lite_initiator<CFG>::write_wdata(tlm::tlm_generic_payload& trans, unsigned beat) {
234  typename CFG::data_t data{0};
235  typename CFG::strb_t strb{0};
236  auto ext = trans.get_extension<axi::ace_extension>();
237  auto size = 1u << ext->get_size();
238  auto byte_offset = beat * size;
239  auto offset = (trans.get_address() + byte_offset) & (CFG::BUSWIDTH / 8 - 1);
240  auto beptr = trans.get_byte_enable_length() ? trans.get_byte_enable_ptr() + byte_offset : nullptr;
241  if(offset && (size + offset) > (CFG::BUSWIDTH / 8)) { // un-aligned multi-beat access
242  if(beat == 0) {
243  auto dptr = trans.get_data_ptr();
244  if(dptr)
245  for(size_t i = offset; i < size; ++i, ++dptr) {
246  auto bit_offs = i * 8;
247  data(bit_offs + 7, bit_offs) = *dptr;
248  if(beptr) {
249  strb[i] = *beptr == 0xff;
250  ++beptr;
251  } else
252  strb[i] = true;
253  }
254  } else {
255  auto beat_start_idx = byte_offset - offset;
256  auto data_len = trans.get_data_length();
257  auto dptr = trans.get_data_ptr() + beat_start_idx;
258  if(dptr)
259  for(size_t i = 0; i < size && (beat_start_idx + i) < data_len; ++i, ++dptr) {
260  auto bit_offs = i * 8;
261  data(bit_offs + 7, bit_offs) = *dptr;
262  if(beptr) {
263  strb[i] = *beptr == 0xff;
264  ++beptr;
265  } else
266  strb[i] = true;
267  }
268  }
269  } else { // aligned or single beat access
270  auto dptr = trans.get_data_ptr() + byte_offset;
271  if(dptr)
272  for(size_t i = 0; i < size; ++i, ++dptr) {
273  auto bit_offs = (offset + i) * 8;
274  data(bit_offs + 7, bit_offs) = *dptr;
275  if(beptr) {
276  strb[offset + i] = *beptr == 0xff;
277  ++beptr;
278  } else
279  strb[offset + i] = true;
280  }
281  }
282  this->w_data.write(data);
283  this->w_strb.write(strb);
284  if(!CFG::IS_LITE) {
285  this->w_id->write(ext->get_id());
286  if(this->w_user.get_interface())
287  this->w_user->write(ext->get_user(axi::common::id_type::DATA));
288  }
289 }
290 
291 template <typename CFG> typename CFG::data_t axi::pin::ace_lite_initiator<CFG>::get_cache_data_for_beat(fsm_handle* fsm_hndl) {
292  auto beat_count = fsm_hndl->beat_count;
293  // SCCTRACE(SCMOD) << " " ;
294  auto size = axi::get_burst_size(*fsm_hndl->trans);
295  auto byte_offset = beat_count * size;
296  auto offset = (fsm_hndl->trans->get_address() + byte_offset) & (CFG::BUSWIDTH / 8 - 1);
297  typename CFG::data_t data{0};
298  if(offset && (size + offset) > (CFG::BUSWIDTH / 8)) { // un-aligned multi-beat access
299  if(beat_count == 0) {
300  auto dptr = fsm_hndl->trans->get_data_ptr();
301  for(size_t i = offset; i < size; ++i, ++dptr) {
302  auto bit_offs = i * 8;
303  data(bit_offs + 7, bit_offs) = *dptr;
304  }
305  } else {
306  auto beat_start_idx = byte_offset - offset;
307  auto data_len = fsm_hndl->trans->get_data_length();
308  auto dptr = fsm_hndl->trans->get_data_ptr() + beat_start_idx;
309  for(size_t i = offset; i < size && (beat_start_idx + i) < data_len; ++i, ++dptr) {
310  auto bit_offs = i * 8;
311  data(bit_offs + 7, bit_offs) = *dptr;
312  }
313  }
314  } else { // aligned or single beat access
315  auto dptr = fsm_hndl->trans->get_data_ptr() + byte_offset;
316  for(size_t i = 0; i < size; ++i, ++dptr) {
317  auto bit_offs = (offset + i) * 8;
318  data(bit_offs + 7, bit_offs) = *dptr;
319  }
320  }
321  return data;
322 }
323 
324 template <typename CFG> inline void axi::pin::ace_lite_initiator<CFG>::setup_callbacks(fsm_handle* fsm_hndl) {
325  fsm_hndl->fsm->cb[RequestPhaseBeg] = [this, fsm_hndl]() -> void {
326  if(fsm_hndl->is_snoop) {
327  SCCTRACE(SCMOD) << " for snoop in RequestPhaseBeg ";
328  } else {
329  fsm_hndl->beat_count = 0;
330  outstanding_cnt[fsm_hndl->trans->get_command()]++;
331  if(CFG::IS_LITE) {
332  auto offset = fsm_hndl->trans->get_address() % (CFG::BUSWIDTH / 8);
333  if(offset + fsm_hndl->trans->get_data_length() > CFG::BUSWIDTH / 8) {
334  SCCFATAL(SCMOD) << " transaction " << *fsm_hndl->trans << " is not AXI4Lite compliant";
335  }
336  }
337  }
338  };
339  fsm_hndl->fsm->cb[BegPartReqE] = [this, fsm_hndl]() -> void {
340  sc_assert(fsm_hndl->trans->is_write());
341  if(fsm_hndl->beat_count == 0) {
342  aw_fifo.push_back({fsm_hndl->trans.get(), false});
343  }
344  wdata_fifo.push_back({fsm_hndl->trans.get(), false, wdata_fifo.num_avail() > 0, fsm_hndl->beat_count});
345  if(pipelined_wrreq && !wdata_fifo.num_avail())
346  schedule(EndPartReqE, fsm_hndl->trans, sc_core::SC_ZERO_TIME);
347  };
348  fsm_hndl->fsm->cb[EndPartReqE] = [this, fsm_hndl]() -> void {
349  tlm::tlm_phase phase = axi::END_PARTIAL_REQ;
350  sc_core::sc_time t(clk_if ? ::scc::time_to_next_posedge(clk_if) - 1_ps : sc_core::SC_ZERO_TIME);
351  auto ret = tsckt->nb_transport_bw(*fsm_hndl->trans, phase, t);
352  fsm_hndl->beat_count++;
353  };
354  fsm_hndl->fsm->cb[BegReqE] = [this, fsm_hndl]() -> void {
355  switch(fsm_hndl->trans->get_command()) {
356  case tlm::TLM_READ_COMMAND:
357  ar_fifo.push_back({fsm_hndl->trans.get(), false});
358  break;
359  case tlm::TLM_WRITE_COMMAND:
360  if(fsm_hndl->beat_count == 0) {
361  aw_fifo.push_back({fsm_hndl->trans.get(), false});
362  }
363  /* for dataless trans, no data on wdata_t*/
364  if(!axi::is_dataless(fsm_hndl->trans->get_extension<ace_extension>())) {
365  wdata_fifo.push_back({fsm_hndl->trans.get(), true, wdata_fifo.num_avail() > 0, fsm_hndl->beat_count});
366  if(pipelined_wrreq && !wdata_fifo.num_avail())
367  schedule(EndReqE, fsm_hndl->trans, sc_core::SC_ZERO_TIME);
368  }
369  }
370  };
371  fsm_hndl->fsm->cb[EndReqE] = [this, fsm_hndl]() -> void {
372  auto id = axi::get_axi_id(*fsm_hndl->trans);
373  if(mask_axi_id.get_value())
374  id &= (1UL << CFG::IDWIDTH) - 1;
375  switch(fsm_hndl->trans->get_command()) {
376  case tlm::TLM_READ_COMMAND:
377  rd_resp_by_id[id].push_back(fsm_hndl);
378  break;
379  case tlm::TLM_WRITE_COMMAND:
380  wr_resp_by_id[id].push_back(fsm_hndl);
381  fsm_hndl->beat_count++;
382  }
383  tlm::tlm_phase phase = tlm::END_REQ;
384  sc_core::sc_time t(clk_if ? ::scc::time_to_next_posedge(clk_if) - 1_ps : sc_core::SC_ZERO_TIME);
385  auto ret = tsckt->nb_transport_bw(*fsm_hndl->trans, phase, t);
386  fsm_hndl->trans->set_response_status(tlm::TLM_OK_RESPONSE);
387  };
388 
389  fsm_hndl->fsm->cb[BegPartRespE] = [this, fsm_hndl]() -> void {
390  // scheduling the response
391  assert(fsm_hndl->trans->is_read());
392  tlm::tlm_phase phase = axi::BEGIN_PARTIAL_RESP;
393  sc_core::sc_time t(sc_core::SC_ZERO_TIME);
394  auto ret = tsckt->nb_transport_bw(*fsm_hndl->trans, phase, t);
395  };
396  fsm_hndl->fsm->cb[EndPartRespE] = [this, fsm_hndl]() -> void {
397  fsm_hndl->beat_count++;
398  r_end_resp_evt.notify();
399  };
400  fsm_hndl->fsm->cb[BegRespE] = [this, fsm_hndl]() -> void {
401  // scheduling the response
402  tlm::tlm_phase phase = tlm::BEGIN_RESP;
403  sc_core::sc_time t(sc_core::SC_ZERO_TIME);
404  auto ret = tsckt->nb_transport_bw(*fsm_hndl->trans, phase, t);
405  };
406  fsm_hndl->fsm->cb[EndRespE] = [this, fsm_hndl]() -> void {
407  if(fsm_hndl->trans->is_read()) {
408  rd_resp_by_id[axi::get_axi_id(*fsm_hndl->trans)].pop_front();
409  r_end_resp_evt.notify();
410  }
411  if(fsm_hndl->trans->is_write()) {
412  wr_resp_by_id[axi::get_axi_id(*fsm_hndl->trans)].pop_front();
413  w_end_resp_evt.notify();
414  }
415  };
416 }
417 
418 template <typename CFG> inline void axi::pin::ace_lite_initiator<CFG>::ar_t() {
419  this->ar_valid.write(false);
420  wait(sc_core::SC_ZERO_TIME);
421  while(true) {
422  auto val = ar_fifo.read();
423  write_ar(*val.gp);
424  this->ar_valid.write(true);
425  do {
426  wait(this->ar_ready.posedge_event() | clk_delayed);
427  if(this->ar_ready.read())
428  react(axi::fsm::protocol_time_point_e::EndReqE, val.gp);
429  } while(!this->ar_ready.read());
430  wait(clk_i.posedge_event());
431  this->ar_valid.write(false);
432  }
433 }
434 
435 template <typename CFG> inline void axi::pin::ace_lite_initiator<CFG>::r_t() {
436  this->r_ready.write(false);
437  wait(sc_core::SC_ZERO_TIME);
438  while(true) {
439  wait(clk_delayed);
440  while(!this->r_valid.read()) {
441  wait(this->r_valid.posedge_event());
442  wait(CLK_DELAY); // verilator might create spurious events
443  }
444  auto id = CFG::IS_LITE ? 0U : this->r_id->read().to_uint();
445  auto data = this->r_data.read();
446  auto resp = this->r_resp.read();
447  auto& q = rd_resp_by_id[id];
448  sc_assert(q.size() && "No transaction found for received id");
449  auto* fsm_hndl = q.front();
450  auto beat_count = fsm_hndl->beat_count;
451  auto size = axi::get_burst_size(*fsm_hndl->trans);
452  auto byte_offset = beat_count * size;
453  auto offset = (fsm_hndl->trans->get_address() + byte_offset) & (CFG::BUSWIDTH / 8 - 1);
454  if(offset && (size + offset) > (CFG::BUSWIDTH / 8)) { // un-aligned multi-beat access
455  if(beat_count == 0) {
456  auto dptr = fsm_hndl->trans->get_data_ptr();
457  if(dptr)
458  for(size_t i = offset; i < size; ++i, ++dptr) {
459  auto bit_offs = i * 8;
460  *dptr = data(bit_offs + 7, bit_offs).to_uint();
461  }
462  } else {
463  auto beat_start_idx = beat_count * size - offset;
464  auto data_len = fsm_hndl->trans->get_data_length();
465  auto dptr = fsm_hndl->trans->get_data_ptr() + beat_start_idx;
466  if(dptr)
467  for(size_t i = offset; i < size && (beat_start_idx + i) < data_len; ++i, ++dptr) {
468  auto bit_offs = i * 8;
469  *dptr = data(bit_offs + 7, bit_offs).to_uint();
470  }
471  }
472  } else { // aligned or single beat access
473  auto dptr = fsm_hndl->trans->get_data_ptr() + beat_count * size;
474  if(dptr)
475  for(size_t i = 0; i < size; ++i, ++dptr) {
476  auto bit_offs = (offset + i) * 8;
477  *dptr = data(bit_offs + 7, bit_offs).to_uint();
478  }
479  }
481  fsm_hndl->trans->get_extension(e);
482  e->set_cresp(resp); // TODO: check if correct
483  e->add_to_response_array(*e);
484  /* dataless trans * */
485  if(axi::is_dataless(e)) {
486  SCCTRACE(SCMOD) << " r_t() for Make/Clean/Barrier Trans" << *fsm_hndl->trans;
487  react(axi::fsm::protocol_time_point_e::BegRespE, fsm_hndl);
488  } else {
489  auto tp = CFG::IS_LITE || this->r_last->read() ? axi::fsm::protocol_time_point_e::BegRespE
490  : axi::fsm::protocol_time_point_e::BegPartRespE;
491  react(tp, fsm_hndl);
492  }
493  wait(r_end_resp_evt);
494  this->r_ready.write(true);
495  wait(clk_i.posedge_event());
496  this->r_ready.write(false);
497  }
498 }
499 
500 template <typename CFG> inline void axi::pin::ace_lite_initiator<CFG>::aw_t() {
501  this->aw_valid.write(false);
502  wait(sc_core::SC_ZERO_TIME);
503  while(true) {
504  auto val = aw_fifo.read();
505  write_aw(*val.gp);
506  this->aw_valid.write(true);
507  do {
508  wait(this->aw_ready.posedge_event() | clk_delayed);
509  } while(!this->aw_ready.read());
510  if(axi::is_dataless(val.gp->template get_extension<axi::ace_extension>()))
511  schedule(axi::fsm::protocol_time_point_e::EndReqE, val.gp, sc_core::SC_ZERO_TIME);
512  wait(clk_i.posedge_event());
513  this->aw_valid.write(false);
514  }
515 }
516 
517 template <typename CFG> inline void axi::pin::ace_lite_initiator<CFG>::wdata_t() {
518  this->w_valid.write(false);
519  wait(sc_core::SC_ZERO_TIME);
520  while(true) {
521  if(!CFG::IS_LITE)
522  this->w_last->write(false);
523  if(pipelined_wrreq) {
524  while(!wdata_fifo.num_avail()) {
525  wait(clk_i.posedge_event());
526  }
527  } else {
528  wait(wdata_fifo.data_written_event());
529  }
530  auto val = wdata_fifo.front();
531  wdata_fifo.pop_front();
532  write_wdata(*val.gp, val.beat_num);
533  if(pipelined_wrreq && val.needs_end_req) {
534  auto evt = CFG::IS_LITE || (val.last) ? axi::fsm::protocol_time_point_e::EndReqE : axi::fsm::protocol_time_point_e::EndPartReqE;
535  schedule(evt, val.gp, sc_core::SC_ZERO_TIME);
536  }
537  this->w_valid.write(true);
538  if(!CFG::IS_LITE)
539  this->w_last->write(val.last);
540  do {
541  wait(this->w_ready.posedge_event() | clk_delayed);
542  if(!pipelined_wrreq && this->w_ready.read()) {
543  auto evt = val.last ? axi::fsm::protocol_time_point_e::EndReqE : axi::fsm::protocol_time_point_e::EndPartReqE;
544  schedule(evt, val.gp, sc_core::SC_ZERO_TIME);
545  }
546  } while(!this->w_ready.read());
547  wait(clk_i.posedge_event());
548  this->w_valid.write(false);
549  }
550 }
551 
552 template <typename CFG> inline void axi::pin::ace_lite_initiator<CFG>::b_t() {
553  this->b_ready.write(false);
554  wait(sc_core::SC_ZERO_TIME);
555  while(true) {
556  wait(clk_delayed);
557  while(!this->b_valid.read()) {
558  wait(this->b_valid.posedge_event());
559  wait(CLK_DELAY); // verilator might create spurious events
560  }
561  auto id = !CFG::IS_LITE ? this->b_id->read().to_uint() : 0U;
562  auto resp = this->b_resp.read();
563  auto& q = wr_resp_by_id[id];
564  sc_assert(q.size());
565  auto* fsm_hndl = q.front();
567  fsm_hndl->trans->get_extension(e);
568  e->set_resp(axi::into<axi::resp_e>(resp));
569  react(axi::fsm::protocol_time_point_e::BegRespE, fsm_hndl);
570  wait(w_end_resp_evt);
571  this->b_ready.write(true);
572  wait(clk_i.posedge_event());
573  this->b_ready.write(false);
574  }
575 }
576 
577 #endif /* _BUS_AXI_PIN_ace_lite_INITIATOR_H_ */
T * get() const noexcept
Return the stored pointer.
Definition: tlm_gp_shared.h:91
TLM2.0 components modeling AHB.
Definition: axi_initiator.h:30
constexpr ULT to_int(E t)
Definition: axi_tlm.h:47
unsigned get_burst_size(const request &r)
Definition: axi_tlm.h:1202
tlm::tlm_fw_transport_if< TYPES > ace_fw_transport_if
alias declaration for the ACE forward interface
Definition: axi_tlm.h:958
void set_cresp(uint8_t)
set the coherent response status
Definition: axi_tlm.h:1603
void add_to_response_array(response &)
add a read response to the response array
Definition: axi_tlm.h:1670
base class of all AXITLM based adapters and interfaces.
Definition: base.h:43
tlm::tlm_sync_enum nb_fw(payload_type &trans, phase_type const &phase, sc_core::sc_time &t)
triggers the FSM based on TLM phases in the forward path. Should be called from np_transport_fw of th...
Definition: base.cpp:190
tlm::scc::tlm_gp_shared_ptr trans
pointer to the associated AXITLM payload
Definition: types.h:62
size_t beat_count
beat count of this transaction
Definition: types.h:64
AxiProtocolFsm *const fsm
pointer to the FSM
Definition: types.h:60
bool is_snoop
indicator if this is a snoop access
Definition: types.h:66
void set_resp(resp_e)
set the response status as POD
Definition: axi_tlm.h:1572