17 #ifndef _BUS_AXI_PIN_ACE_INITIATOR_H_
18 #define _BUS_AXI_PIN_ACE_INITIATOR_H_
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>
27 #include <tlm/scc/tlm_mm.h>
28 #include <tlm_utils/peq_with_cb_and_phase.h>
35 using namespace axi::fsm;
37 template <
typename CFG>
39 public aw_ace<CFG, typename CFG::master_types>,
40 public wdata_ace<CFG, typename CFG::master_types>,
41 public b_ace<CFG, typename CFG::master_types>,
42 public ar_ace<CFG, typename CFG::master_types>,
43 public rresp_ace<CFG, typename CFG::master_types>,
45 public ac_ace<CFG, typename CFG::master_types>,
46 public cr_ace<CFG, typename CFG::master_types>,
47 public cd_ace<CFG, typename CFG::master_types>,
53 enum { CACHELINE_SZ = 64 };
55 using payload_type = axi::axi_protocol_types::tlm_payload_type;
56 using phase_type = axi::axi_protocol_types::tlm_phase_type;
58 sc_core::sc_in<bool> clk_i{
"clk_i"};
62 cci::cci_param<bool> pipelined_wrreq{
"pipelined_wrreq",
false};
64 cci::cci_param<bool> mask_axi_id{
"mask_axi_id",
false};
66 ace_initiator(sc_core::sc_module_name
const& nm,
bool pipelined_wrreq =
false)
67 : sc_core::sc_module(nm)
69 ,
base(CFG::BUSWIDTH,
true)
70 , pipelined_wrreq(
"pipelined_wrreq", pipelined_wrreq) {
71 instance_name = name();
74 sensitive << clk_i.pos();
88 void b_transport(payload_type& trans, sc_core::sc_time& t)
override {
89 trans.set_dmi_allowed(
false);
90 trans.set_response_status(tlm::TLM_OK_RESPONSE);
93 tlm::tlm_sync_enum nb_transport_fw(payload_type& trans, phase_type& phase, sc_core::sc_time& t)
override {
95 sc_core::sc_time delay;
96 fw_peq.notify(trans, phase, delay);
97 return tlm::TLM_ACCEPTED;
100 bool get_direct_mem_ptr(payload_type& trans, tlm::tlm_dmi& dmi_data)
override {
101 trans.set_dmi_allowed(
false);
105 unsigned int transport_dbg(payload_type& trans)
override {
return 0; }
107 void end_of_elaboration()
override { clk_if =
dynamic_cast<sc_core::sc_clock*
>(clk_i.get_interface()); }
113 void clk_delay() { clk_delayed.notify(axi::CLK_DELAY); }
138 static typename CFG::data_t get_cache_data_for_beat(
fsm::fsm_handle* fsm_hndl);
139 unsigned int SNOOP = 3;
142 std::array<unsigned, 3> outstanding_cnt{0, 0, 0};
143 std::array<fsm_handle*, 3> active_req{
nullptr,
nullptr,
nullptr};
144 std::array<fsm_handle*, 4> active_resp_beat{
nullptr,
nullptr,
nullptr};
145 sc_core::sc_clock* clk_if{
nullptr};
146 sc_core::sc_event clk_delayed, clk_self, r_end_resp_evt, w_end_resp_evt, ac_end_req_evt;
147 void nb_fw(payload_type& trans,
const phase_type& phase) {
148 auto t = sc_core::SC_ZERO_TIME;
151 tlm_utils::peq_with_cb_and_phase<ace_initiator> fw_peq{
this, &ace_initiator::nb_fw};
152 std::unordered_map<unsigned, std::deque<fsm_handle*>> rd_resp_by_id, wr_resp_by_id;
154 tlm::tlm_generic_payload* gp =
nullptr;
156 bool needs_end_req =
false;
158 fifo_entry(tlm::tlm_generic_payload* gp,
bool last,
bool needs_end_req,
size_t beat_num)
161 , needs_end_req(needs_end_req)
162 , beat_num(beat_num) {
166 fifo_entry(tlm::tlm_generic_payload* gp,
bool needs_end_req)
168 , needs_end_req(needs_end_req) {
172 fifo_entry(fifo_entry
const& o)
175 , needs_end_req(o.needs_end_req)
176 , beat_num(o.beat_num) {
177 if(gp && gp->has_mm())
180 fifo_entry& operator=(
const fifo_entry& o) {
183 needs_end_req = o.needs_end_req;
184 beat_num = o.beat_num;
188 if(gp && gp->has_mm())
195 sc_core::sc_event rack_vl;
196 sc_core::sc_event wack_vl;
197 void write_ar(tlm::tlm_generic_payload& trans);
198 void write_aw(tlm::tlm_generic_payload& trans);
199 void write_wdata(tlm::tlm_generic_payload& trans,
unsigned beat);
206 sc_dt::sc_uint<CFG::ADDRWIDTH> addr = trans.get_address();
207 this->ar_addr.write(addr);
209 this->ar_prot.write(ext->get_prot());
211 auto id = ext->get_id();
212 if(!mask_axi_id.get_value() &&
id >= (1 << CFG::IDWIDTH))
213 SCCERR(SCMOD) <<
"AWID value larger than signal awid with width=" << CFG::IDWIDTH <<
" can carry";
214 this->ar_id->write(sc_dt::sc_uint<CFG::IDWIDTH>(
id));
215 this->ar_len->write(sc_dt::sc_uint<8>(ext->get_length()));
216 this->ar_size->write(sc_dt::sc_uint<3>(ext->get_size()));
217 this->ar_burst->write(sc_dt::sc_uint<2>(
axi::to_int(ext->get_burst())));
218 this->ar_lock->write(ext->is_exclusive());
219 this->ar_cache->write(sc_dt::sc_uint<4>(ext->get_cache()));
220 this->ar_prot.write(ext->get_prot());
221 this->ar_qos->write(ext->get_qos());
222 this->ar_region->write(ext->get_region());
223 this->ar_domain->write(sc_dt::sc_uint<2>((uint8_t)ext->get_domain()));
224 this->ar_snoop->write(sc_dt::sc_uint<4>((uint8_t)ext->get_snoop()));
225 this->ar_bar->write(sc_dt::sc_uint<2>((uint8_t)ext->get_barrier()));
226 this->ar_user->write(ext->get_user(axi::common::id_type::CTRL));
231 sc_dt::sc_uint<CFG::ADDRWIDTH> addr = trans.get_address();
232 this->aw_addr.write(addr);
234 this->aw_prot.write(ext->get_prot());
235 this->aw_lock->write(ext->is_exclusive());
236 auto id = ext->get_id();
237 if(!mask_axi_id.get_value() &&
id >= (1 << CFG::IDWIDTH))
238 SCCERR(SCMOD) <<
"AWID value larger than signal awid with width=" << CFG::IDWIDTH <<
" can carry";
239 this->aw_id->write(sc_dt::sc_uint<CFG::IDWIDTH>(
id));
240 this->aw_len->write(sc_dt::sc_uint<8>(ext->get_length()));
241 this->aw_size->write(sc_dt::sc_uint<3>(ext->get_size()));
242 this->aw_burst->write(sc_dt::sc_uint<2>(
axi::to_int(ext->get_burst())));
243 this->aw_cache->write(sc_dt::sc_uint<4>(ext->get_cache()));
244 this->aw_qos->write(sc_dt::sc_uint<4>(ext->get_qos()));
245 this->aw_region->write(sc_dt::sc_uint<4>(ext->get_region()));
246 this->aw_user->write(ext->get_user(axi::common::id_type::CTRL));
247 this->aw_domain->write(sc_dt::sc_uint<2>((uint8_t)ext->get_domain()));
248 this->aw_snoop->write(sc_dt::sc_uint<CFG::AWSNOOPWIDTH>((uint8_t)ext->get_snoop()));
249 this->aw_bar->write(sc_dt::sc_uint<2>((uint8_t)ext->get_barrier()));
250 this->aw_unique->write(ext->get_unique());
256 typename CFG::data_t data{0};
257 typename CFG::strb_t strb{0};
259 auto size = 1u << ext->get_size();
260 auto byte_offset = beat * size;
261 auto offset = (trans.get_address() + byte_offset) & (CFG::BUSWIDTH / 8 - 1);
262 auto beptr = trans.get_byte_enable_length() ? trans.get_byte_enable_ptr() + byte_offset :
nullptr;
263 if(offset && (size + offset) > (CFG::BUSWIDTH / 8)) {
265 auto dptr = trans.get_data_ptr();
267 for(
size_t i = offset; i < size; ++i, ++dptr) {
268 auto bit_offs = i * 8;
269 data(bit_offs + 7, bit_offs) = *dptr;
271 strb[i] = *beptr == 0xff;
277 auto beat_start_idx = byte_offset - offset;
278 auto data_len = trans.get_data_length();
279 auto dptr = trans.get_data_ptr() + beat_start_idx;
281 for(
size_t i = 0; i < size && (beat_start_idx + i) < data_len; ++i, ++dptr) {
282 auto bit_offs = i * 8;
283 data(bit_offs + 7, bit_offs) = *dptr;
285 strb[i] = *beptr == 0xff;
292 auto dptr = trans.get_data_ptr() + byte_offset;
294 for(
size_t i = 0; i < size; ++i, ++dptr) {
295 auto bit_offs = (offset + i) * 8;
296 data(bit_offs + 7, bit_offs) = *dptr;
298 strb[offset + i] = *beptr == 0xff;
301 strb[offset + i] =
true;
304 this->w_data.write(data);
305 this->w_strb.write(strb);
307 this->w_id->write(ext->get_id());
308 if(this->w_user.get_interface())
309 this->w_user->write(ext->get_user(axi::common::id_type::DATA));
317 auto byte_offset = beat_count * size;
318 auto offset = (fsm_hndl->
trans->get_address() + byte_offset) & (CFG::BUSWIDTH / 8 - 1);
319 typename CFG::data_t data{0};
320 if(offset && (size + offset) > (CFG::BUSWIDTH / 8)) {
321 if(beat_count == 0) {
322 auto dptr = fsm_hndl->
trans->get_data_ptr();
323 for(
size_t i = offset; i < size; ++i, ++dptr) {
324 auto bit_offs = i * 8;
325 data(bit_offs + 7, bit_offs) = *dptr;
328 auto beat_start_idx = byte_offset - offset;
329 auto data_len = fsm_hndl->
trans->get_data_length();
330 auto dptr = fsm_hndl->
trans->get_data_ptr() + beat_start_idx;
331 for(
size_t i = offset; i < size && (beat_start_idx + i) < data_len; ++i, ++dptr) {
332 auto bit_offs = i * 8;
333 data(bit_offs + 7, bit_offs) = *dptr;
337 auto dptr = fsm_hndl->
trans->get_data_ptr() + byte_offset;
338 for(
size_t i = 0; i < size; ++i, ++dptr) {
339 auto bit_offs = (offset + i) * 8;
340 data(bit_offs + 7, bit_offs) = *dptr;
347 fsm_hndl->
fsm->cb[RequestPhaseBeg] = [
this, fsm_hndl]() ->
void {
349 SCCTRACE(SCMOD) <<
" for snoop in RequestPhaseBeg ";
352 outstanding_cnt[fsm_hndl->
trans->get_command()]++;
354 auto offset = fsm_hndl->
trans->get_address() % (CFG::BUSWIDTH / 8);
355 if(offset + fsm_hndl->
trans->get_data_length() > CFG::BUSWIDTH / 8) {
356 SCCFATAL(SCMOD) <<
" transaction " << *fsm_hndl->
trans <<
" is not AXI4Lite compliant";
361 fsm_hndl->
fsm->cb[BegPartReqE] = [
this, fsm_hndl]() ->
void {
362 sc_assert(fsm_hndl->
trans->is_write());
364 aw_fifo.push_back({fsm_hndl->
trans.
get(),
false});
366 wdata_fifo.push_back({fsm_hndl->
trans.
get(),
false, wdata_fifo.num_avail() > 0, fsm_hndl->
beat_count});
367 if(pipelined_wrreq && !wdata_fifo.num_avail())
368 schedule(EndPartReqE, fsm_hndl->
trans, sc_core::SC_ZERO_TIME);
370 fsm_hndl->
fsm->cb[EndPartReqE] = [
this, fsm_hndl]() ->
void {
371 tlm::tlm_phase phase = axi::END_PARTIAL_REQ;
372 sc_core::sc_time t(clk_if ? ::scc::time_to_next_posedge(clk_if) - 1_ps : sc_core::SC_ZERO_TIME);
373 auto ret = tsckt->nb_transport_bw(*fsm_hndl->
trans, phase, t);
376 fsm_hndl->
fsm->cb[BegReqE] = [
this, fsm_hndl]() ->
void {
378 sc_core::sc_time t(sc_core::SC_ZERO_TIME);
379 tlm::tlm_phase phase = tlm::BEGIN_REQ;
380 auto ret = tsckt->nb_transport_bw(*fsm_hndl->
trans, phase, t);
382 switch(fsm_hndl->
trans->get_command()) {
383 case tlm::TLM_READ_COMMAND:
384 ar_fifo.push_back({fsm_hndl->
trans.
get(),
false});
386 case tlm::TLM_WRITE_COMMAND:
388 aw_fifo.push_back({fsm_hndl->
trans.
get(),
false});
391 if(!axi::is_dataless(fsm_hndl->
trans->get_extension<ace_extension>())) {
392 wdata_fifo.push_back({fsm_hndl->
trans.
get(),
true, wdata_fifo.num_avail() > 0, fsm_hndl->
beat_count});
393 if(pipelined_wrreq && !wdata_fifo.num_avail())
394 schedule(EndReqE, fsm_hndl->
trans, sc_core::SC_ZERO_TIME);
399 fsm_hndl->
fsm->cb[EndReqE] = [
this, fsm_hndl]() ->
void {
401 active_req[SNOOP] =
nullptr;
402 ac_end_req_evt.notify();
404 auto id = axi::get_axi_id(*fsm_hndl->
trans);
405 if(mask_axi_id.get_value())
406 id &= (1UL << CFG::IDWIDTH) - 1;
407 switch(fsm_hndl->
trans->get_command()) {
408 case tlm::TLM_READ_COMMAND:
409 rd_resp_by_id[id].push_back(fsm_hndl);
411 case tlm::TLM_WRITE_COMMAND:
412 wr_resp_by_id[id].push_back(fsm_hndl);
415 tlm::tlm_phase phase = tlm::END_REQ;
416 sc_core::sc_time t(clk_if ? ::scc::time_to_next_posedge(clk_if) - 1_ps : sc_core::SC_ZERO_TIME);
417 auto ret = tsckt->nb_transport_bw(*fsm_hndl->
trans, phase, t);
418 fsm_hndl->
trans->set_response_status(tlm::TLM_OK_RESPONSE);
421 fsm_hndl->
fsm->cb[BegPartRespE] = [
this, fsm_hndl]() ->
void {
423 active_resp_beat[SNOOP] = fsm_hndl;
424 cd_vl.notify({1, fsm_hndl});
428 assert(fsm_hndl->
trans->is_read());
429 tlm::tlm_phase phase = axi::BEGIN_PARTIAL_RESP;
430 sc_core::sc_time t(sc_core::SC_ZERO_TIME);
431 auto ret = tsckt->nb_transport_bw(*fsm_hndl->
trans, phase, t);
434 fsm_hndl->
fsm->cb[EndPartRespE] = [
this, fsm_hndl]() ->
void {
436 tlm::tlm_phase phase = axi::END_PARTIAL_RESP;
437 sc_core::sc_time t(sc_core::SC_ZERO_TIME);
438 auto ret = tsckt->nb_transport_bw(*fsm_hndl->
trans, phase, t);
440 active_resp_beat[SNOOP] =
nullptr;
444 r_end_resp_evt.notify();
447 fsm_hndl->
fsm->cb[BegRespE] = [
this, fsm_hndl]() ->
void {
449 active_resp_beat[SNOOP] = fsm_hndl;
450 cd_vl.notify({3, fsm_hndl});
451 cr_resp_vl.notify({3, fsm_hndl});
455 tlm::tlm_phase phase = tlm::BEGIN_RESP;
456 sc_core::sc_time t(sc_core::SC_ZERO_TIME);
457 auto ret = tsckt->nb_transport_bw(*fsm_hndl->
trans, phase, t);
460 fsm_hndl->
fsm->cb[EndRespE] = [
this, fsm_hndl]() ->
void {
462 sc_core::sc_time t(sc_core::SC_ZERO_TIME);
463 tlm::tlm_phase phase = tlm::END_RESP;
464 auto ret = tsckt->nb_transport_bw(*fsm_hndl->
trans, phase, t);
465 active_resp_beat[SNOOP] =
nullptr;
467 fsm_hndl->
finish.notify();
469 if(fsm_hndl->
trans->is_read()) {
470 rd_resp_by_id[axi::get_axi_id(*fsm_hndl->
trans)].pop_front();
471 r_end_resp_evt.notify();
472 }
else if(fsm_hndl->
trans->is_write()) {
473 wr_resp_by_id[axi::get_axi_id(*fsm_hndl->
trans)].pop_front();
474 w_end_resp_evt.notify();
478 fsm_hndl->
fsm->cb[Ack] = [
this, fsm_hndl]() ->
void {
479 SCCTRACE(SCMOD) <<
"in ACK of setup_cb for " << *fsm_hndl->
trans;
480 if(fsm_hndl->
trans->is_read()) {
481 rack_vl.notify(sc_core::SC_ZERO_TIME);
483 if(fsm_hndl->
trans->is_write()) {
484 wack_vl.notify(sc_core::SC_ZERO_TIME);
490 this->r_ack.write(
false);
491 wait(sc_core::SC_ZERO_TIME);
494 this->r_ack.write(
true);
495 wait(clk_i.posedge_event());
496 this->r_ack.write(
false);
501 this->w_ack.write(
false);
502 wait(sc_core::SC_ZERO_TIME);
505 this->w_ack.write(
true);
506 wait(clk_i.posedge_event());
507 this->w_ack.write(
false);
512 this->ar_valid.write(
false);
513 wait(sc_core::SC_ZERO_TIME);
515 auto val = ar_fifo.read();
517 this->ar_valid.write(
true);
519 wait(this->ar_ready.posedge_event() | clk_delayed);
520 if(this->ar_ready.read())
521 react(axi::fsm::protocol_time_point_e::EndReqE, val.gp);
522 }
while(!this->ar_ready.read());
523 wait(clk_i.posedge_event());
524 this->ar_valid.write(
false);
529 this->r_ready.write(
false);
530 wait(sc_core::SC_ZERO_TIME);
533 while(!this->r_valid.read()) {
534 wait(this->r_valid.posedge_event());
537 auto id = CFG::IS_LITE ? 0U : this->r_id->read().to_uint();
538 auto data = this->r_data.read();
539 auto resp = this->r_resp.read();
540 auto& q = rd_resp_by_id[id];
541 sc_assert(q.size() &&
"No transaction found for received id");
542 auto* fsm_hndl = q.front();
545 auto byte_offset = beat_count * size;
546 auto offset = (fsm_hndl->
trans->get_address() + byte_offset) & (CFG::BUSWIDTH / 8 - 1);
547 if(offset && (size + offset) > (CFG::BUSWIDTH / 8)) {
548 if(beat_count == 0) {
549 auto dptr = fsm_hndl->
trans->get_data_ptr();
551 for(
size_t i = offset; i < size; ++i, ++dptr) {
552 auto bit_offs = i * 8;
553 *dptr = data(bit_offs + 7, bit_offs).to_uint();
556 auto beat_start_idx = beat_count * size - offset;
557 auto data_len = fsm_hndl->
trans->get_data_length();
558 auto dptr = fsm_hndl->
trans->get_data_ptr() + beat_start_idx;
560 for(
size_t i = 0; i < size && (beat_start_idx + i) < data_len; ++i, ++dptr) {
561 auto bit_offs = i * 8;
562 *dptr = data(bit_offs + 7, bit_offs).to_uint();
566 auto dptr = fsm_hndl->
trans->get_data_ptr() + beat_count * size;
568 for(
size_t i = 0; i < size; ++i, ++dptr) {
569 auto bit_offs = (offset + i) * 8;
570 *dptr = data(bit_offs + 7, bit_offs).to_uint();
574 fsm_hndl->
trans->get_extension(e);
579 if(axi::is_dataless(e)) {
580 SCCTRACE(SCMOD) <<
" r_t() for Make/Clean/Barrier Trans" << *fsm_hndl->
trans;
581 react(axi::fsm::protocol_time_point_e::BegRespE, fsm_hndl);
583 auto tp = CFG::IS_LITE || this->r_last->read() ? axi::fsm::protocol_time_point_e::BegRespE
584 : axi::fsm::protocol_time_point_e::BegPartRespE;
587 wait(r_end_resp_evt);
588 this->r_ready.write(
true);
589 wait(clk_i.posedge_event());
590 this->r_ready.write(
false);
595 this->aw_valid.write(
false);
596 wait(sc_core::SC_ZERO_TIME);
598 auto val = aw_fifo.read();
600 this->aw_valid.write(
true);
602 wait(this->aw_ready.posedge_event() | clk_delayed);
603 }
while(!this->aw_ready.read());
604 if(axi::is_dataless(val.gp->template get_extension<axi::ace_extension>()))
605 schedule(axi::fsm::protocol_time_point_e::EndReqE, val.gp, sc_core::SC_ZERO_TIME);
606 wait(clk_i.posedge_event());
607 this->aw_valid.write(
false);
612 this->w_valid.write(
false);
613 wait(sc_core::SC_ZERO_TIME);
616 this->w_last->write(
false);
617 if(pipelined_wrreq) {
618 while(!wdata_fifo.num_avail()) {
619 wait(clk_i.posedge_event());
622 wait(wdata_fifo.data_written_event());
624 auto val = wdata_fifo.front();
625 wdata_fifo.pop_front();
626 write_wdata(*val.gp, val.beat_num);
627 if(pipelined_wrreq && val.needs_end_req) {
628 auto evt = CFG::IS_LITE || (val.last) ? axi::fsm::protocol_time_point_e::EndReqE : axi::fsm::protocol_time_point_e::EndPartReqE;
629 schedule(evt, val.gp, sc_core::SC_ZERO_TIME);
631 this->w_valid.write(
true);
633 this->w_last->write(val.last);
635 wait(this->w_ready.posedge_event() | clk_delayed);
636 if(!pipelined_wrreq && this->w_ready.read()) {
637 auto evt = val.last ? axi::fsm::protocol_time_point_e::EndReqE : axi::fsm::protocol_time_point_e::EndPartReqE;
638 schedule(evt, val.gp, sc_core::SC_ZERO_TIME);
640 }
while(!this->w_ready.read());
641 wait(clk_i.posedge_event());
642 this->w_valid.write(
false);
647 this->b_ready.write(
false);
648 wait(sc_core::SC_ZERO_TIME);
651 while(!this->b_valid.read()) {
652 wait(this->b_valid.posedge_event());
655 auto id = !CFG::IS_LITE ? this->b_id->read().to_uint() : 0U;
656 auto resp = this->b_resp.read();
657 auto& q = wr_resp_by_id[id];
659 auto* fsm_hndl = q.front();
661 fsm_hndl->
trans->get_extension(e);
662 e->
set_resp(axi::into<axi::resp_e>(resp));
663 react(axi::fsm::protocol_time_point_e::BegRespE, fsm_hndl);
664 wait(w_end_resp_evt);
665 this->b_ready.write(
true);
666 wait(clk_i.posedge_event());
667 this->b_ready.write(
false);
672 this->ac_ready.write(
false);
673 wait(sc_core::SC_ZERO_TIME);
677 auto arlen = ((CACHELINE_SZ - 1) / CFG::BUSWIDTH / 8);
680 auto data_len = (1 << arsize) * (arlen + 1);
683 while(!this->ac_valid.read()) {
684 wait(this->ac_valid.posedge_event());
687 SCCTRACE(SCMOD) <<
"ACVALID detected, for address 0x" << std::hex << this->ac_addr.read();
688 SCCTRACE(SCMOD) <<
"in ac_t(), create snoop trans with data_len= " << data_len;
690 gp->set_address(this->ac_addr.read());
691 gp->set_command(tlm::TLM_READ_COMMAND);
692 gp->set_streaming_width(data_len);
694 gp->get_extension(ext);
696 if(data_len == (CFG::BUSWIDTH / 8))
700 ext->
set_snoop(axi::into<axi::snoop_e>(this->ac_snoop->read()));
701 ext->
set_prot(this->ac_prot->read());
706 active_req[SNOOP] = find_or_create(gp,
true);
707 active_req[SNOOP]->is_snoop =
true;
708 react(axi::fsm::protocol_time_point_e::RequestPhaseBeg, active_req[SNOOP]);
710 wait(ac_end_req_evt);
711 this->ac_ready.write(
true);
712 wait(clk_i.posedge_event());
713 this->ac_ready.write(
false);
718 this->cd_valid.write(
false);
719 wait(sc_core::SC_ZERO_TIME);
724 std::tie(val, fsm_hndl) = cd_vl.get();
725 SCCTRACE(SCMOD) << __FUNCTION__ <<
" val = " << (uint16_t)val <<
" beat_count = " << fsm_hndl->
beat_count;
726 SCCTRACE(SCMOD) << __FUNCTION__ <<
" got snoop beat of trans " << *fsm_hndl->
trans;
729 this->cd_data.write(get_cache_data_for_beat(fsm_hndl));
730 this->cd_valid.write(val & 0x1);
731 SCCTRACE(SCMOD) << __FUNCTION__ <<
"() write cd_valid high ";
732 this->cd_last->write(val & 0x2);
734 wait(this->cd_ready.posedge_event() | clk_delayed);
735 if(this->cd_ready.read()) {
737 CFG::IS_LITE || (val & 0x2) ? axi::fsm::protocol_time_point_e::EndRespE : axi::fsm::protocol_time_point_e::EndPartRespE;
741 SCCTRACE(SCMOD) << __FUNCTION__ <<
"() receives cd_ready high, schedule evt " << evt2str(evt);
742 react(evt, active_resp_beat[SNOOP]);
745 }
while(!this->cd_ready.read());
746 SCCTRACE(SCMOD) << __FUNCTION__ <<
" finished snoop beat of trans [" << fsm_hndl->
trans <<
"]";
747 wait(clk_i.posedge_event());
748 this->cd_valid.write(
false);
750 this->cd_last->write(
false);
754 this->cr_valid.write(
false);
755 wait(sc_core::SC_ZERO_TIME);
760 std::tie(val, fsm_hndl) = cr_resp_vl.get();
761 SCCTRACE(SCMOD) << __FUNCTION__ <<
" (), generate snoop response in cr channel, val = " << (uint16_t)val
762 <<
" total beat_num = " << fsm_hndl->
beat_count;
766 this->cr_valid.write(
true);
768 wait(this->cr_ready.posedge_event() | clk_delayed);
769 if(this->cr_ready.read()) {
770 auto evt = axi::fsm::protocol_time_point_e::EndRespE;
771 SCCTRACE(SCMOD) << __FUNCTION__ <<
"(), schedule EndRespE ";
772 react(evt, active_resp_beat[SNOOP]);
774 }
while(!this->cr_ready.read());
775 SCCTRACE(SCMOD) <<
"finished snoop response ";
776 wait(clk_i.posedge_event());
777 this->cr_valid.write(
false);
payload_type * allocate()
get a plain tlm_payload_type without extensions
T * get() const noexcept
Return the stored pointer.
TLM2.0 components modeling AHB.
constexpr ULT to_int(E t)
unsigned get_burst_size(const request &r)
tlm::tlm_fw_transport_if< TYPES > ace_fw_transport_if
alias declaration for the ACE forward interface
CONSTEXPR unsigned ilog2(uint32_t val)
snoop address(AC) channel signals
void set_cresp(uint8_t)
set the coherent response status
uint8_t get_cresp() const
get the coherent response status
void set_snoop(snoop_e)
set the AxSNOOP value
void add_to_response_array(response &)
add a read response to the response array
snoop data(cd) channel signals
snoop response(cr) channel signals
base class of all AXITLM based adapters and interfaces.
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...
tlm::scc::tlm_gp_shared_ptr trans
pointer to the associated AXITLM payload
sc_core::sc_event finish
event indicating the end of the transaction
size_t beat_count
beat count of this transaction
AxiProtocolFsm *const fsm
pointer to the FSM
bool is_snoop
indicator if this is a snoop access
void set_length(uint8_t)
set the AxLEN value of the transaction, the value denotes the burst length - 1
void set_burst(burst_e)
set the AxBURST value,
void set_size(uint8_t)
get the AxSIZE value of the transaction, the length is 2^size. It needs to be less than 10 (512 bit w...
void set_prot(uint8_t)
set the AxPROT value as POD, only values from 0...7 are allowed
void set_resp(resp_e)
set the response status as POD
static tlm_mm & get()
accessor function of the singleton