17#ifndef SC_INCLUDE_DYNAMIC_PROCESSES
18#define SC_INCLUDE_DYNAMIC_PROCESSES
20#include <atp/timing_params.h>
21#include <axi/axi_tlm.h>
22#include <cache/cache_info.h>
23#include <chi/pe/chi_rn_initiator.h>
24#include <scc/report.h>
25#include <tlm/scc/tlm_gp_shared.h>
26#include <tlm/scc/tlm_mm.h>
27#include <util/strprintf.h>
29using namespace sc_core;
31using namespace chi::pe;
35uint8_t log2n(uint8_t siz) {
return ((siz > 1) ? 1 + log2n(siz >> 1) : 0); }
36inline uintptr_t to_id(tlm::tlm_generic_payload& t) {
return reinterpret_cast<uintptr_t
>(&t); }
37inline uintptr_t to_id(tlm::tlm_generic_payload* t) {
return reinterpret_cast<uintptr_t
>(t); }
38void convert_axi4ace_to_chi(tlm::tlm_generic_payload& gp,
char const* name,
bool legacy_mapping =
false) {
39 if(gp.get_data_length() > 64) {
40 SCCWARN(__FUNCTION__) <<
"Data length of " << gp.get_data_length() <<
" is not supported by CHI, shortening payload";
41 gp.set_data_length(64);
47 sc_assert(ace_ext !=
nullptr || axi4_ext !=
nullptr);
49 bool is_ace = (ace_ext !=
nullptr);
57 chi_req_ext->set_txn_id(is_ace ? ace_ext->get_id() : axi4_ext->
get_id());
58 chi_req_ext->set_qos(is_ace ? ace_ext->get_qos() : axi4_ext->
get_qos());
59 SCCTRACE(name) <<
"chi_ctrl_extension set TxnID=0x" << std::hex << chi_req_ext->get_txn_id();
62 sc_assert(((gp.get_data_length() & (gp.get_data_length() - 1)) == 0) &&
63 "CHI data size is not a power of 2: Byte transfer: 0->1, 1->2, 2->4, 3->8, .. 6->64, 7->reserved");
64 uint8_t chi_size = log2n(gp.get_data_length());
65 SCCDEBUG(name) <<
"convert_axi4ace_to_chi: data length = " << gp.get_data_length()
66 <<
"; Converted data length to chi_size = " <<
static_cast<unsigned>(chi_size);
68 chi_req_ext->req.set_size(chi_size);
75 sc_assert(gp.is_read() || gp.is_write());
76 chi_req_ext->req.set_opcode(gp.is_read() ? chi::req_optype_e::ReadNoSnp : chi::req_optype_e::WriteNoSnpFull);
79 auto axi_gp_cmd = gp.get_command();
80 auto axi_snp = ace_ext->get_snoop();
81 auto axi_domain = ace_ext->get_domain();
82 auto axi_bar = ace_ext->get_barrier();
83 auto axi_atomic = ace_ext->get_atop();
85 auto cacheable = ace_ext->is_modifiable();
89 sc_assert(axi_snp == axi::snoop_e::BARRIER);
90 SCCERR(name) <<
"Barrier transaction has no mapping in CHI";
92 chi::req_optype_e opcode{chi::req_optype_e::ReqLCrdReturn};
95 SCCDEBUG(name) <<
"AWATOP value: " << std::hex << static_cast<unsigned>(axi_atomic);
96 auto atomic_opcode = (axi_atomic >> 4) & 3;
97 auto atomic_subcode = axi_atomic & 7;
99 if(atomic_opcode == 1) {
100 const std::array<chi::req_optype_e, 8> atomic_store_opcodes = {
101 chi::req_optype_e::AtomicStoreAdd, chi::req_optype_e::AtomicStoreClr, chi::req_optype_e::AtomicStoreEor,
102 chi::req_optype_e::AtomicStoreSet, chi::req_optype_e::AtomicStoreSmax, chi::req_optype_e::AtomicStoreSmin,
103 chi::req_optype_e::AtomicStoreUmax, chi::req_optype_e::AtomicStoreUmin};
104 opcode = atomic_store_opcodes[atomic_subcode];
105 }
else if(atomic_opcode == 2) {
106 const std::array<chi::req_optype_e, 8> atomic_load_opcodes = {
107 chi::req_optype_e::AtomicLoadAdd, chi::req_optype_e::AtomicLoadClr, chi::req_optype_e::AtomicLoadEor,
108 chi::req_optype_e::AtomicLoadSet, chi::req_optype_e::AtomicLoadSmax, chi::req_optype_e::AtomicLoadSmin,
109 chi::req_optype_e::AtomicLoadUmax, chi::req_optype_e::AtomicLoadUmin};
110 opcode = atomic_load_opcodes[atomic_subcode];
111 }
else if(axi_atomic == 0x30)
112 opcode = chi::req_optype_e::AtomicSwap;
113 else if(axi_atomic == 0x31)
114 opcode = chi::req_optype_e::AtomicCompare;
116 SCCERR(name) <<
"Can't handle AXI AWATOP value: " << axi_atomic;
118 chi_req_ext->req.set_opcode(opcode);
119 chi_req_ext->req.set_snp_attr(axi_snp != axi::snoop_e::READ_NO_SNOOP);
120 chi_req_ext->req.set_snoop_me(axi_snp != axi::snoop_e::READ_NO_SNOOP);
121 }
else if(gp.is_read()) {
123 case axi::snoop_e::READ_NO_SNOOP:
124 sc_assert(axi_domain == axi::domain_e::NON_SHAREABLE || axi_domain == axi::domain_e::SYSTEM);
125 opcode = chi::req_optype_e::ReadNoSnp;
127 case axi::snoop_e::READ_ONCE:
128 sc_assert(axi_domain == axi::domain_e::INNER_SHAREABLE || axi_domain == axi::domain_e::OUTER_SHAREABLE);
129 opcode = chi::req_optype_e::ReadOnce;
130 chi_req_ext->req.set_snp_attr(cacheable);
132 case axi::snoop_e::READ_SHARED:
133 opcode = chi::req_optype_e::ReadShared;
135 case axi::snoop_e::READ_CLEAN:
136 opcode = chi::req_optype_e::ReadClean;
138 case axi::snoop_e::READ_NOT_SHARED_DIRTY:
139 opcode = chi::req_optype_e::ReadNotSharedDirty;
141 case axi::snoop_e::READ_UNIQUE:
142 opcode = chi::req_optype_e::ReadUnique;
144 case axi::snoop_e::CLEAN_SHARED:
145 opcode = chi::req_optype_e::CleanShared;
146 gp.set_data_length(0);
148 case axi::snoop_e::CLEAN_INVALID:
149 opcode = chi::req_optype_e::CleanInvalid;
150 gp.set_data_length(0);
152 case axi::snoop_e::CLEAN_SHARED_PERSIST:
153 opcode = chi::req_optype_e::CleanSharedPersist;
154 gp.set_data_length(0);
156 case axi::snoop_e::CLEAN_UNIQUE:
157 opcode = chi::req_optype_e::CleanUnique;
158 gp.set_data_length(0);
160 case axi::snoop_e::MAKE_UNIQUE:
161 opcode = chi::req_optype_e::MakeUnique;
162 gp.set_data_length(0);
164 case axi::snoop_e::MAKE_INVALID:
165 opcode = chi::req_optype_e::MakeInvalid;
166 gp.set_data_length(0);
169 SCCWARN(name) <<
"unexpected read type";
172 chi_req_ext->req.set_opcode(opcode);
174 if(axi_snp != axi::snoop_e::READ_NO_SNOOP) {
175 chi_req_ext->req.set_snp_attr(cacheable);
177 if(opcode == chi::req_optype_e::StashOnceUnique || opcode == chi::req_optype_e::StashOnceShared) {
178 gp.set_data_length(0);
179 gp.set_command(tlm::TLM_WRITE_COMMAND);
180 if(ace_ext->is_stash_nid_en()) {
181 chi_req_ext->req.set_stash_n_id(ace_ext->get_stash_nid());
182 chi_req_ext->req.set_stash_n_id_valid(
true);
184 if(ace_ext->is_stash_lpid_en()) {
185 chi_req_ext->req.set_stash_lp_id(ace_ext->get_stash_lpid());
186 chi_req_ext->req.set_stash_lp_id_valid(
true);
189 }
else if(gp.is_write()) {
191 case axi::snoop_e::WRITE_NO_SNOOP:
192 sc_assert(axi_domain == axi::domain_e::NON_SHAREABLE || axi_domain == axi::domain_e::SYSTEM);
193 opcode = gp.get_data_length() == 64 ? chi::req_optype_e::WriteNoSnpFull : chi::req_optype_e::WriteNoSnpPtl;
195 case axi::snoop_e::WRITE_UNIQUE:
196 sc_assert(axi_domain == axi::domain_e::INNER_SHAREABLE || axi_domain == axi::domain_e::OUTER_SHAREABLE);
197 opcode = gp.get_data_length() == 64 ? chi::req_optype_e::WriteUniqueFull : chi::req_optype_e::WriteUniquePtl;
198 chi_req_ext->req.set_snp_attr(cacheable);
200 case axi::snoop_e::WRITE_LINE_UNIQUE:
201 opcode = chi::req_optype_e::WriteUniqueFull;
203 case axi::snoop_e::WRITE_CLEAN: {
205 for(
auto i = 0; i < gp.get_byte_enable_length(); ++i) {
206 if(gp.get_byte_enable_ptr()[i] == 0) {
212 opcode = chi::req_optype_e::WriteCleanPtl;
214 opcode = chi::req_optype_e::WriteCleanFull;
217 case axi::snoop_e::WRITE_BACK:
218 opcode = gp.get_data_length() == 64 ? chi::req_optype_e::WriteBackFull : chi::req_optype_e::WriteBackPtl;
220 case axi::snoop_e::EVICT:
221 opcode = chi::req_optype_e::Evict;
223 case axi::snoop_e::WRITE_EVICT:
224 opcode = chi::req_optype_e::WriteEvictFull;
226 case axi::snoop_e::WRITE_UNIQUE_PTL_STASH:
227 opcode = chi::req_optype_e::WriteUniquePtlStash;
229 case axi::snoop_e::WRITE_UNIQUE_FULL_STASH:
230 opcode = chi::req_optype_e::WriteUniqueFullStash;
232 case axi::snoop_e::STASH_ONCE_UNIQUE:
233 opcode = chi::req_optype_e::StashOnceUnique;
234 gp.set_data_length(0);
235 chi_req_ext->req.set_size(6);
237 case axi::snoop_e::STASH_ONCE_SHARED:
238 opcode = chi::req_optype_e::StashOnceShared;
239 gp.set_data_length(0);
240 chi_req_ext->req.set_size(6);
243 SCCWARN(name) <<
"unexpected snoop type " <<
axi::to_char(axi_snp) <<
" during write";
246 chi_req_ext->req.set_opcode(opcode);
248 if(axi_snp != axi::snoop_e::WRITE_NO_SNOOP) {
249 chi_req_ext->req.set_snp_attr(cacheable);
251 if(opcode == chi::req_optype_e::WriteUniquePtlStash || opcode == chi::req_optype_e::WriteUniqueFullStash ||
252 opcode == chi::req_optype_e::StashOnceUnique || opcode == chi::req_optype_e::StashOnceShared) {
253 if(ace_ext->is_stash_nid_en()) {
254 chi_req_ext->req.set_stash_n_id(ace_ext->get_stash_nid());
255 chi_req_ext->req.set_stash_n_id_valid(
true);
257 if(ace_ext->is_stash_lpid_en()) {
258 chi_req_ext->req.set_stash_lp_id(ace_ext->get_stash_lpid());
259 chi_req_ext->req.set_stash_lp_id_valid(
true);
264 SCCERR(name) <<
"Not yet implemented !!! ";
298 switch(ace_ext->get_cache()) {
313 mem_attr = gp.is_read() ? 0b1101 : 0b0101;
317 mem_attr = gp.is_read() ? 0b0101 : 0b1101;
324 SCCERR(name) <<
"Unexpected AxCACHE type";
328 auto allocate = (ace_ext->is_allocate());
329 auto cachable = ace_ext->is_cacheable();
330 auto ewa = ace_ext->is_bufferable();
331 auto device = ace_ext->get_cache() < 2;
332 mem_attr = (allocate ? 8 : 0) + (cachable ? 4 : 0) + (device ? 2 : 0) + (ewa ? 1 : 0);
337 case chi::req_optype_e::ReadNoSnp:
338 case chi::req_optype_e::ReadNoSnpSep:
339 case chi::req_optype_e::ReadOnce:
340 case chi::req_optype_e::ReadOnceCleanInvalid:
341 case chi::req_optype_e::ReadOnceMakeInvalid:
342 case chi::req_optype_e::WriteNoSnpPtl:
343 case chi::req_optype_e::WriteNoSnpFull:
344 case chi::req_optype_e::WriteUniquePtl:
345 case chi::req_optype_e::WriteUniqueFull:
346 case chi::req_optype_e::AtomicStoreAdd:
347 case chi::req_optype_e::AtomicStoreClr:
348 case chi::req_optype_e::AtomicStoreEor:
349 case chi::req_optype_e::AtomicStoreSet:
350 case chi::req_optype_e::AtomicStoreSmax:
351 case chi::req_optype_e::AtomicStoreSmin:
352 case chi::req_optype_e::AtomicStoreUmax:
353 case chi::req_optype_e::AtomicStoreUmin:
354 case chi::req_optype_e::AtomicLoadAdd:
355 case chi::req_optype_e::AtomicLoadClr:
356 case chi::req_optype_e::AtomicLoadEor:
357 case chi::req_optype_e::AtomicLoadSet:
358 case chi::req_optype_e::AtomicLoadSmax:
359 case chi::req_optype_e::AtomicLoadSmin:
360 case chi::req_optype_e::AtomicLoadUmax:
361 case chi::req_optype_e::AtomicLoadUmin:
362 case chi::req_optype_e::AtomicSwap:
363 case chi::req_optype_e::AtomicCompare:
364 chi_req_ext->req.set_order(0b00);
371 chi_req_ext->req.set_mem_attr(mem_attr);
373 if(
auto msg = chi::is_valid_msg(chi_req_ext))
374 SCCFATAL(__FUNCTION__) <<
"Conversion created an invalid chi request, pls. check the AXI/ACE settings: " << msg;
377 gp.set_auto_extension(chi_req_ext);
379 gp.set_extension(chi_req_ext);
385 gp.set_extension(ace_ext);
386 gp.set_extension(axi4_ext);
390 switch(req_e->req.get_opcode()) {
392 case chi::req_optype_e::ReadNoSnpSep:
394 case chi::req_optype_e::Evict:
395 case chi::req_optype_e::StashOnceUnique:
396 case chi::req_optype_e::StashOnceShared:
397 case chi::req_optype_e::CleanShared:
398 case chi::req_optype_e::CleanSharedPersist:
399 case chi::req_optype_e::CleanSharedPersistSep:
400 case chi::req_optype_e::CleanInvalid:
401 case chi::req_optype_e::MakeInvalid:
403 case chi::req_optype_e::WriteNoSnpZero:
404 case chi::req_optype_e::WriteNoSnpFull:
405 case chi::req_optype_e::WriteNoSnpPtl:
406 case chi::req_optype_e::WriteUniqueZero:
407 case chi::req_optype_e::WriteUniquePtl:
408 case chi::req_optype_e::WriteUniqueFull:
409 case chi::req_optype_e::WriteUniqueFullStash:
410 case chi::req_optype_e::WriteBackFull:
411 case chi::req_optype_e::WriteBackPtl:
412 case chi::req_optype_e::WriteCleanFull:
413 case chi::req_optype_e::WriteCleanPtl:
415 case chi::req_optype_e::AtomicStoreAdd:
416 case chi::req_optype_e::AtomicStoreClr:
417 case chi::req_optype_e::AtomicStoreEor:
418 case chi::req_optype_e::AtomicStoreSet:
419 case chi::req_optype_e::AtomicStoreSmax:
420 case chi::req_optype_e::AtomicStoreSmin:
421 case chi::req_optype_e::AtomicStoreUmax:
422 case chi::req_optype_e::AtomicStoreUmin:
423 case chi::req_optype_e::AtomicLoadAdd:
424 case chi::req_optype_e::AtomicLoadClr:
425 case chi::req_optype_e::AtomicLoadEor:
426 case chi::req_optype_e::AtomicLoadSet:
427 case chi::req_optype_e::AtomicLoadSmax:
428 case chi::req_optype_e::AtomicLoadSmin:
429 case chi::req_optype_e::AtomicLoadUmax:
430 case chi::req_optype_e::AtomicLoadUmin:
431 case chi::req_optype_e::AtomicCompare:
432 case chi::req_optype_e::AtomicSwap:
436 req_e->req.set_exp_comp_ack(
false);
440 case chi::req_optype_e::ReadNoSnp:
441 case chi::req_optype_e::ReadOnce:
442 case chi::req_optype_e::CleanUnique:
443 case chi::req_optype_e::MakeUnique:
444 req_e->req.set_exp_comp_ack(
true);
447 req_e->req.set_exp_comp_ack(
true);
452 if((req_e->req.get_opcode() == chi::req_optype_e::ReadNoSnp || req_e->req.get_opcode() == chi::req_optype_e::ReadOnce) &&
453 (req_e->req.get_order() == 0b10 || req_e->req.get_order() == 0b11)) {
454 req_e->req.set_exp_comp_ack(
true);
458 if((req_e->req.get_opcode() >= chi::req_optype_e::WriteEvictFull &&
459 req_e->req.get_opcode() <= chi::req_optype_e::WriteUniquePtlStash) &&
460 (req_e->req.get_order() == 0b10 || req_e->req.get_order() == 0b11)) {
461 req_e->req.set_exp_comp_ack(
true);
465bool make_rsp_from_req(tlm::tlm_generic_payload& gp, chi::rsp_optype_e rsp_opcode) {
467 if(rsp_opcode == chi::rsp_optype_e::CompAck) {
468 if(is_dataless(ctrl_e) || gp.is_write()) {
469 ctrl_e->resp.set_tgt_id(ctrl_e->req.get_tgt_id());
470 ctrl_e->resp.set_trace_tag(ctrl_e->req.is_trace_tag());
471 if(ctrl_e->req.get_opcode() == chi::req_optype_e::MakeReadUnique) {
472 ctrl_e->set_txn_id(ctrl_e->resp.get_db_id());
476 ctrl_e->req.set_tgt_id(dat_e->dat.get_home_n_id());
477 ctrl_e->set_src_id(dat_e->get_src_id());
478 ctrl_e->set_qos(dat_e->get_qos());
479 ctrl_e->set_txn_id(dat_e->dat.get_db_id());
480 ctrl_e->resp.set_tgt_id(dat_e->dat.get_tgt_id());
481 ctrl_e->resp.set_trace_tag(dat_e->dat.is_trace_tag());
483 ctrl_e->resp.set_opcode(rsp_opcode);
486 ctrl_e->resp.set_opcode(rsp_opcode);
488 snp_e->resp.set_opcode(rsp_opcode);
489 if(rsp_opcode == chi::rsp_optype_e::CompAck) {
491 snp_e->set_src_id(dat_e->get_src_id());
492 snp_e->set_qos(dat_e->get_qos());
493 snp_e->set_txn_id(dat_e->dat.get_db_id());
494 snp_e->resp.set_tgt_id(dat_e->dat.get_tgt_id());
495 snp_e->resp.set_trace_tag(dat_e->dat.is_trace_tag());
505#if SYSTEMC_VERSION < 20250221
508chi::pe::chi_rn_initiator_b::chi_rn_initiator_b(sc_core::sc_module_name nm,
510 size_t transfer_width)
513, transfer_width_in_bytes(transfer_width / 8) {
516 SC_METHOD(clk_counter);
517 sensitive << clk_i.pos();
518 SC_THREAD(snoop_dispatch);
521chi::pe::chi_rn_initiator_b::~chi_rn_initiator_b() {
522 if(tx_state_by_trans.size()) {
523 for(
auto& e : tx_state_by_trans)
524 SCCDEBUG(SCMOD) <<
"unfinished transaction with ptr: " << e.first <<
" with access address = 0x" << std::hex
525 << ((tlm::tlm_generic_payload*)e.first)->get_address();
526 SCCWARN(SCMOD) <<
"is still waiting for unfinished transactions with number = " << tx_state_by_trans.size();
528 for(
auto& e : tx_state_by_trans)
530 for(
auto p : tx_state_pool)
534void chi::pe::chi_rn_initiator_b::clk_counter() {
535 if(m_clock_counter > 1) {
536 if(m_clock_counter < 3 && ProvidedSnpCreditCounter.get() < 15 && snp_counter.get() < snp_req_limit.get_value()) {
537 auto possible_snp_credits = snp_req_limit.get_value() - snp_counter.get() - ProvidedSnpCreditCounter.get();
538 auto max_allowed_credits = std::min(snp_req_credit_limit.get_value(), 15u);
539 auto credit2send = std::min<unsigned>(max_allowed_credits - ProvidedSnpCreditCounter.get(), possible_snp_credits);
541 grant_credit(credit_type_e::REQ, credit2send);
542 ProvidedSnpCreditCounter += credit2send;
545 auto cresp_send_limit = std::min(15u, cresp_req_credit_limit.get_value());
546 if(ProvidedCrespCreditCounter.get() < cresp_send_limit) {
547 auto credit2send = cresp_send_limit - ProvidedCrespCreditCounter;
549 grant_credit(credit_type_e::RESP, credit2send);
550 ProvidedCrespCreditCounter += credit2send;
553 auto rdat_send_limit = std::min(15u, rdat_req_credit_limit.get_value());
554 if(ProvidedRdatCreditCounter.get() < rdat_send_limit) {
555 auto credit2send = rdat_send_limit - ProvidedRdatCreditCounter;
557 grant_credit(credit_type_e::DATA, credit2send);
558 ProvidedRdatCreditCounter += credit2send;
566 if(bw_o.get_interface()) {
567 auto latency = bw_o->transport(trans);
568 if(latency < std::numeric_limits<unsigned>::max())
569 t += latency * (clk_if ? clk_if->period() : clk_period);
575 sc_assert(req_ext !=
nullptr);
576 auto it = tx_state_by_trans.find(to_id(trans));
577 sc_assert(it != tx_state_by_trans.end());
578 auto* txs = it->second;
579 handle_snoop_response(trans, txs);
580 tx_state_pool.push_back(it->second);
581 tx_state_pool.back()->peq.clear();
582 tx_state_by_trans.erase(to_id(trans));
587tlm::tlm_sync_enum chi::pe::chi_rn_initiator_b::nb_transport_bw(payload_type& trans, phase_type& phase, sc_core::sc_time& t) {
589 if(phase == tlm::BEGIN_REQ) {
592 ProvidedSnpCreditCounter--;
593 snp_peq.notify(trans, t);
595 auto it = tx_state_by_trans.find(to_id(trans));
596 sc_assert(it != tx_state_by_trans.end());
597 it->second->peq.notify(std::make_tuple(&trans, phase), t);
600 if(phase == tlm::BEGIN_REQ || phase == tlm::END_REQ || phase == tlm::END_RESP || phase == chi::END_PARTIAL_DATA ||
601 phase == chi::END_DATA) {
603 if(
auto ext = trans.get_extension<chi_credit_extension<credit_type_e::REQ>>()) {
604 for(
auto i = 0U; i < ext->count; ++i)
605 ReceivedReqCreditCounter.post();
606 SCCDEBUG(SCMOD) <<
"got " << ext->count <<
" REQ credits, snp_crd_counter=" << ReceivedReqCreditCounter.get_value();
608 }
else if(
auto ext = trans.get_extension<chi_credit_extension<credit_type_e::RESP>>()) {
609 for(
auto i = 0U; i < ext->count; ++i)
610 ReceivedSrespCreditCounter.post();
611 SCCDEBUG(SCMOD) <<
"got " << ext->count <<
" SResp credits, sresp_crd_counter=" << ReceivedSrespCreditCounter.get_value();
613 }
else if(
auto ext = trans.get_extension<chi_credit_extension<credit_type_e::DATA>>()) {
615 for(
auto i = 0U; i < ext->count; ++i)
616 ReceivedWdatCreditCounter.post();
617 SCCDEBUG(SCMOD) <<
"got " << ext->count <<
" WDat credits, rdat_crd_counter=" << ReceivedWdatCreditCounter.get_value();
621 if(phase == tlm::BEGIN_REQ) {
622 phase = tlm::END_RESP;
623 trans.set_response_status(tlm::TLM_OK_RESPONSE);
625 t += clk_if->period() - 1_ps;
626 return tlm::TLM_COMPLETED;
629 auto it = tx_state_by_trans.find(to_id(trans));
630 sc_assert(it != tx_state_by_trans.end());
631 if(phase == tlm::BEGIN_RESP) {
632 ProvidedCrespCreditCounter--;
633 }
else if(phase == chi::BEGIN_PARTIAL_DATA || phase == chi::BEGIN_DATA) {
634 ProvidedRdatCreditCounter--;
636 it->second->peq.notify(std::make_tuple(&trans, phase), t);
638 return tlm::TLM_ACCEPTED;
641void chi::pe::chi_rn_initiator_b::invalidate_direct_mem_ptr(sc_dt::uint64 start_range, sc_dt::uint64 end_range) {}
643void chi::pe::chi_rn_initiator_b::update_data_extension(chi::chi_data_extension* data_ext, payload_type& trans) {
644 auto req_e = trans.get_extension<chi::chi_ctrl_extension>();
645 sc_assert(req_e !=
nullptr);
646 switch(req_e->req.get_opcode()) {
647 case chi::req_optype_e::WriteNoSnpPtl:
648 case chi::req_optype_e::WriteNoSnpFull:
649 case chi::req_optype_e::WriteUniquePtl:
650 case chi::req_optype_e::WriteUniqueFull:
651 case chi::req_optype_e::WriteUniquePtlStash:
652 case chi::req_optype_e::WriteUniqueFullStash:
654 case chi::req_optype_e::WriteNoSnpFullCleanSh:
655 case chi::req_optype_e::WriteNoSnpFullCleanInv:
656 case chi::req_optype_e::WriteNoSnpFullCleanShPerSep:
657 case chi::req_optype_e::WriteUniqueFullCleanSh:
658 case chi::req_optype_e::WriteUniqueFullCleanShPerSep:
659 case chi::req_optype_e::WriteBackFullCleanShPerSep:
660 case chi::req_optype_e::WriteNoSnpPtlCleanSh:
661 case chi::req_optype_e::WriteNoSnpPtlCleanInv:
662 case chi::req_optype_e::WriteNoSnpPtlCleanShPerSep:
663 case chi::req_optype_e::WriteUniquePtlCleanSh:
664 case chi::req_optype_e::WriteUniquePtlCleanShPerSep:
665 data_ext->dat.set_opcode(chi::dat_optype_e::NonCopyBackWrData);
668 case chi::req_optype_e::WriteBackFull:
669 case chi::req_optype_e::WriteBackPtl:
670 case chi::req_optype_e::WriteCleanFull:
671 case chi::req_optype_e::WriteCleanPtl:
673 case chi::req_optype_e::WriteBackFullCleanSh:
674 case chi::req_optype_e::WriteBackFullCleanInv:
675 case chi::req_optype_e::WriteCleanFullCleanSh:
676 case chi::req_optype_e::WriteCleanFullCleanShPerSep:
677 case chi::req_optype_e::WriteEvictFull:
678 data_ext->dat.set_opcode(chi::dat_optype_e::CopyBackWrData);
681 case chi::req_optype_e::AtomicStoreAdd:
682 case chi::req_optype_e::AtomicStoreClr:
683 case chi::req_optype_e::AtomicStoreEor:
684 case chi::req_optype_e::AtomicStoreSet:
685 case chi::req_optype_e::AtomicStoreSmax:
686 case chi::req_optype_e::AtomicStoreSmin:
687 case chi::req_optype_e::AtomicStoreUmax:
688 case chi::req_optype_e::AtomicStoreUmin:
689 data_ext->dat.set_opcode(chi::dat_optype_e::NonCopyBackWrData);
691 case chi::req_optype_e::AtomicLoadAdd:
692 case chi::req_optype_e::AtomicLoadClr:
693 case chi::req_optype_e::AtomicLoadEor:
694 case chi::req_optype_e::AtomicLoadSet:
695 case chi::req_optype_e::AtomicLoadSmax:
696 case chi::req_optype_e::AtomicLoadSmin:
697 case chi::req_optype_e::AtomicLoadUmax:
698 case chi::req_optype_e::AtomicLoadUmin:
699 case chi::req_optype_e::AtomicSwap:
700 case chi::req_optype_e::AtomicCompare:
701 data_ext->dat.set_opcode(chi::dat_optype_e::NonCopyBackWrData);
704 SCCWARN(SCMOD) <<
" Unable to match req_opcode with data_opcode in write transaction ";
706 if(data_ext->dat.get_opcode() == chi::dat_optype_e::NonCopyBackWrData) {
707 data_ext->dat.set_resp(chi::dat_resptype_e::NonCopyBackWrData);
708 }
else if(data_ext->dat.get_opcode() == chi::dat_optype_e::NCBWrDataCompAck) {
709 data_ext->dat.set_resp(chi::dat_resptype_e::NCBWrDataCompAck);
710 }
else if(data_ext->dat.get_opcode() == chi::dat_optype_e::CopyBackWrData) {
711 auto cache_ext = trans.get_extension<::cache::cache_info>();
712 sc_assert(cache_ext !=
nullptr);
713 auto cache_state = cache_ext->get_state();
714 if(cache_state == ::cache::state::IX) {
715 data_ext->dat.set_resp(chi::dat_resptype_e::CopyBackWrData_I);
716 }
else if(cache_state == ::cache::state::UC) {
717 data_ext->dat.set_resp(chi::dat_resptype_e::CopyBackWrData_UC);
718 }
else if(cache_state == ::cache::state::SC) {
719 data_ext->dat.set_resp(chi::dat_resptype_e::CopyBackWrData_SC);
720 }
else if(cache_state == ::cache::state::UD) {
721 data_ext->dat.set_resp(chi::dat_resptype_e::CopyBackWrData_UD_PD);
722 }
else if(cache_state == ::cache::state::SD) {
723 data_ext->dat.set_resp(chi::dat_resptype_e::CopyBackWrData_SD_PD);
725 SCCWARN(SCMOD) <<
" Unable to match cache state with resptype ";
727 SCCWARN(SCMOD) <<
"Unable to match resptype with WriteData Responses";
730 auto db_id = req_e->resp.get_db_id();
731 data_ext->set_txn_id(db_id);
732 data_ext->set_src_id(req_e->resp.get_tgt_id());
733 data_ext->dat.set_tgt_id(req_e->get_src_id());
736void chi::pe::chi_rn_initiator_b::create_data_ext(payload_type& trans) {
737 auto data_ext =
new chi::chi_data_extension;
738 update_data_extension(data_ext, trans);
739 trans.set_auto_extension<chi::chi_data_extension>(data_ext);
742void chi::pe::chi_rn_initiator_b::send_packet(tlm::tlm_phase phase, payload_type& trans, chi::pe::chi_rn_initiator_b::tx_state* txs) {
743 if(protocol_cb[WDAT])
744 protocol_cb[WDAT](WDAT, trans);
745 ReceivedWdatCreditCounter.wait();
746 sc_core::sc_time delay = sc_core::SC_ZERO_TIME;
747 tlm::tlm_sync_enum ret = socket_fw->nb_transport_fw(trans, phase, delay);
748 if(ret == tlm::TLM_UPDATED) {
749 if(phase == chi::END_PARTIAL_DATA || phase == chi::END_DATA) {
750 if(
auto ext = trans.get_extension<chi::chi_credit_extension<credit_type_e::DATA>>()) {
751 for(
auto i = 0u; i < ext->count; ++i)
752 ReceivedWdatCreditCounter.post();
753 trans.set_auto_extension<chi_credit_extension<credit_type_e::DATA>>(
nullptr);
759 auto entry = txs->peq.
get();
760 sc_assert(std::get<0>(entry) == &trans && (std::get<1>(entry) == chi::END_PARTIAL_DATA || std::get<1>(entry) == chi::END_DATA));
762 auto timing_e = trans.get_extension<atp::timing_params>();
763 auto delay_in_cycles = (timing_e && timing_e->wbv) ? timing_e->wbv : 1;
764 while(delay_in_cycles) {
766 wait(clk_i.posedge_event());
770void chi::pe::chi_rn_initiator_b::send_wdata(payload_type& trans, chi::pe::chi_rn_initiator_b::tx_state* txs) {
771 sc_core::sc_time delay;
772 tlm::tlm_phase phase;
773 auto data_ext = trans.get_extension<chi::chi_data_extension>();
774 if(data_ext ==
nullptr) {
775 create_data_ext(trans);
776 data_ext = trans.get_extension<chi::chi_data_extension>();
779 auto beat_cnt = calculate_beats(trans);
780 SCCDEBUG(SCMOD) <<
"Starting transaction on channel WDAT : (opcode, cmd, addr, len) = (" <<
to_char(data_ext->dat.get_opcode()) <<
", "
781 << trans.get_command() <<
", " << std::hex << trans.get_address() <<
", " << trans.get_data_length() <<
")";
782 if(!data_interleaving.get_value()) {
783 auto e = trans.get_extension<atp::timing_params>();
785 sem_lock l(prio_wdat_chnl);
786 auto clock_count = sc_core::sc_time_stamp().value() / clk_if->period().value();
787 while(clock_count < e->start_soonest) {
788 wait(clk_i.negedge_event());
789 clock_count = sc_core::sc_time_stamp().value() / clk_if->period().value();
792 auto time_offset = sc_core::sc_time_stamp() % clk_if->period();
795 for(
auto i = 0U; i < beat_cnt; ++i) {
797 phase = chi::BEGIN_PARTIAL_DATA;
799 phase = chi::BEGIN_DATA;
802 data_ext->dat.set_data_id(i << (transfer_width_in_bytes * 8 / 128 - 1));
803 SCCTRACE(SCMOD) <<
"WDAT flit with txnid " << data_ext->cmn.
get_txn_id()
804 <<
" data_id = " << (
unsigned int)(data_ext->dat.get_data_id()) <<
" sent. Beat count: " << i <<
", addr: 0x"
805 << std::hex << trans.get_address() <<
", last=" << (i == (beat_cnt - 1));
806 send_packet(phase, trans, txs);
810 for(
auto i = 0U; i < beat_cnt; ++i) {
812 sem_lock lck(wdat_chnl);
814 phase = chi::BEGIN_PARTIAL_DATA;
816 phase = chi::BEGIN_DATA;
818 data_ext->dat.set_data_id(i << (transfer_width_in_bytes * 8 / 128 - 1));
819 SCCTRACE(SCMOD) <<
"WDAT flit with txnid " << data_ext->cmn.
get_txn_id()
820 <<
" data_id = " << (
unsigned int)(data_ext->dat.get_data_id()) <<
" sent. Beat count: " << i
821 <<
", addr: 0x" << std::hex << trans.get_address() <<
", last=" << (i == (beat_cnt - 1));
822 send_packet(phase, trans, txs);
829void chi::pe::chi_rn_initiator_b::send_comp_ack(payload_type& trans, tx_state*& txs) {
830 if(make_rsp_from_req(trans, chi::rsp_optype_e::CompAck)) {
831 sem_lock lck(sresp_chnl);
832 SCCDEBUG(SCMOD) <<
"Send the CompAck response on SRSP channel, addr: 0x" << std::hex << trans.get_address();
833 if(protocol_cb[SRSP])
834 protocol_cb[SRSP](SRSP, trans);
835 ReceivedSrespCreditCounter.wait();
836 tlm::tlm_phase phase = chi::ACK;
837 auto delay = SC_ZERO_TIME;
838 auto ret = socket_fw->nb_transport_fw(trans, phase, delay);
839 if(phase == chi::ACK) {
840 if(
auto ext = trans.get_extension<chi::chi_credit_extension<credit_type_e::RESP>>())
841 for(
auto i = 0u; i < ext->count; ++i)
842 ReceivedSrespCreditCounter.post();
846 auto entry = txs->peq.get();
847 sc_assert(std::get<0>(entry) == &trans && std::get<1>(entry) == tlm::END_RESP);
849 wait(clk_i.posedge_event());
853bool expectCompCMO(chi::chi_ctrl_extension* ext) {
854 switch(ext->req.get_opcode()) {
855 case req_optype_e::WriteBackFullCleanSh:
856 case req_optype_e::WriteBackFullCleanInv:
857 case req_optype_e::WriteBackFullCleanShPerSep:
858 case req_optype_e::WriteCleanFullCleanSh:
859 case req_optype_e::WriteCleanFullCleanShPerSep:
860 case req_optype_e::WriteNoSnpFullCleanSh:
861 case req_optype_e::WriteNoSnpFullCleanInv:
862 case req_optype_e::WriteNoSnpFullCleanShPerSep:
863 case req_optype_e::WriteUniquePtlCleanSh:
864 case req_optype_e::WriteUniqueFullCleanSh:
865 case req_optype_e::WriteUniquePtlCleanShPerSep:
866 case req_optype_e::WriteUniqueFullCleanShPerSep:
873bool expectPersist(chi::chi_ctrl_extension* ext) {
874 switch(ext->req.get_opcode()) {
875 case req_optype_e::WriteBackFullCleanShPerSep:
876 case req_optype_e::WriteCleanFullCleanShPerSep:
877 case req_optype_e::WriteNoSnpFullCleanShPerSep:
878 case req_optype_e::WriteUniquePtlCleanShPerSep:
879 case req_optype_e::WriteUniqueFullCleanShPerSep:
880 case req_optype_e::CleanSharedPersistSep:
887enum { WAIT_CTRL = 0x1, WAIT_DATA = 0x2, WAIT_COMPCMO = 4, WAIT_PERSIST = 8 };
888void chi::pe::chi_rn_initiator_b::exec_read_write_protocol(
const unsigned int txn_id, payload_type& trans,
889 chi::pe::chi_rn_initiator_b::tx_state*& txs) {
891 sc_core::sc_time delay;
892 auto ctrl_ext = trans.get_extension<chi::chi_ctrl_extension>();
893 unsigned not_finish = WAIT_CTRL;
894 not_finish |= is_dataless(ctrl_ext) ? 0 : WAIT_DATA;
895 not_finish |= expectCompCMO(ctrl_ext) ? WAIT_COMPCMO : 0;
896 not_finish |= expectPersist(ctrl_ext) ? WAIT_PERSIST : 0;
897 auto exp_beat_cnt = calculate_beats(trans);
901 auto entry = txs->peq.
get();
902 sc_assert(std::get<0>(entry) == &trans);
903 auto phase = std::get<1>(entry);
904 if(phase == tlm::BEGIN_RESP) {
905 if(chi::is_dataless(ctrl_ext)) {
906 switch(ctrl_ext->resp.get_opcode()) {
907 case chi::rsp_optype_e::Comp:
908 if(ctrl_ext->req.get_opcode() == chi::req_optype_e::MakeReadUnique)
909 not_finish &= ~WAIT_CTRL;
911 switch(ctrl_ext->resp.get_resp()) {
912 case chi::rsp_resptype_e::Comp_I:
913 case chi::rsp_resptype_e::Comp_UC:
914 case chi::rsp_resptype_e::Comp_SC:
915 not_finish &= ~WAIT_CTRL;
921 case chi::rsp_optype_e::CompDBIDResp:
922 case chi::rsp_optype_e::CompPersist:
923 case chi::rsp_optype_e::CompCMO:
924 case chi::rsp_optype_e::CompStashDone:
925 not_finish &= ~WAIT_CTRL;
927 case chi::rsp_optype_e::Persist:
928 not_finish &= ~WAIT_PERSIST;
933 not_finish &= ~WAIT_DATA;
934 finish_cresp_response(trans);
935 }
else if(trans.is_write()) {
936 switch(ctrl_ext->resp.get_opcode()) {
937 case chi::rsp_optype_e::CompCMO:
938 not_finish &= ~WAIT_COMPCMO;
939 finish_cresp_response(trans);
941 case chi::rsp_optype_e::Persist:
942 not_finish &= ~WAIT_PERSIST;
943 finish_cresp_response(trans);
945 case chi::rsp_optype_e::CompDBIDResp:
946 not_finish &= ~WAIT_CTRL;
948 case chi::rsp_optype_e::DBIDResp:
949 case chi::rsp_optype_e::DBIDRespOrd:
950 finish_cresp_response(trans);
951 send_wdata(trans, txs);
952 not_finish &= ~WAIT_DATA;
954 case chi::rsp_optype_e::Comp:
955 not_finish &= ~WAIT_CTRL;
956 finish_cresp_response(trans);
959 SCCFATAL(SCMOD) <<
"Illegal opcode received: " <<
to_char(ctrl_ext->resp.get_opcode());
961 }
else if(trans.is_read()) {
962 not_finish &= ~WAIT_CTRL;
963 finish_cresp_response(trans);
965 }
else if(trans.is_read() && (phase == chi::BEGIN_PARTIAL_DATA || phase == chi::BEGIN_DATA)) {
966 SCCTRACE(SCMOD) <<
"RDAT flit received. Beat count: " << beat_cnt <<
", addr: 0x" << std::hex << trans.get_address();
967 phase = phase == chi::BEGIN_PARTIAL_DATA ? (tlm::tlm_phase)chi::END_PARTIAL_DATA : (tlm::tlm_phase)END_DATA;
968 delay = clk_if ? ::scc::time_to_next_posedge(clk_if) - 1_ps : SC_ZERO_TIME;
969 socket_fw->nb_transport_fw(trans, phase, delay);
970 if(protocol_cb[RDAT])
971 protocol_cb[RDAT](RDAT, trans);
973 if(phase == chi::END_DATA) {
974 not_finish &= ~(WAIT_CTRL | WAIT_DATA);
975 if(beat_cnt != exp_beat_cnt)
976 SCCERR(SCMOD) <<
"Wrong beat count, expected " << exp_beat_cnt <<
", got " << beat_cnt;
979 SCCFATAL(SCMOD) <<
"Illegal protocol state (maybe just not implemented?)";
984void chi::pe::chi_rn_initiator_b::finish_cresp_response(payload_type& trans) {
985 auto resp_ext = trans.get_extension<chi::chi_ctrl_extension>();
986 sc_assert(resp_ext !=
nullptr);
987 if(is_request_order(resp_ext))
989 auto id = (unsigned)(resp_ext->get_txn_id());
990 SCCDEBUG(SCMOD) <<
"got cresp: src_id=" << (unsigned)resp_ext->get_src_id() <<
", tgt_id=" << (unsigned)resp_ext->resp.get_tgt_id()
991 <<
", txnid=0x" << std::hex <<
id <<
", " <<
to_char(resp_ext->resp.get_opcode())
992 <<
", resp=" <<
to_char(resp_ext->resp.get_resp()) <<
", db_id=" << (unsigned)resp_ext->resp.get_db_id() <<
", addr=0x"
993 << std::hex << trans.get_address() <<
")";
994 tlm::tlm_phase phase = tlm::END_RESP;
995 sc_core::sc_time delay = clk_if ? ::scc::time_to_next_posedge(clk_if) - 1_ps : SC_ZERO_TIME;
996 socket_fw->nb_transport_fw(trans, phase, delay);
997 wait(clk_i.posedge_event());
998 if(protocol_cb[CRSP])
999 protocol_cb[CRSP](CRSP, trans);
1002void chi::pe::chi_rn_initiator_b::exec_atomic_protocol(
const unsigned int txn_id, payload_type& trans,
1003 chi::pe::chi_rn_initiator_b::tx_state*& txs) {
1004 sc_core::sc_time delay;
1006 auto entry = txs->peq.
get();
1007 sc_assert(std::get<0>(entry) == &trans);
1008 auto phase = std::get<1>(entry);
1009 if(phase == tlm::BEGIN_RESP) {
1010 finish_cresp_response(trans);
1011 auto resp_ext = trans.get_extension<chi::chi_ctrl_extension>();
1012 if(resp_ext->resp.get_opcode() == chi::rsp_optype_e::DBIDResp) {
1013 SCCERR(SCMOD) <<
"CRESP illegal response opcode: " <<
to_char(resp_ext->resp.get_opcode());
1016 SCCERR(SCMOD) <<
"Illegal protocol state (maybe just not implemented?) " << phase;
1019 auto not_finish = 0b11U;
1020 auto exp_beat_cnt = calculate_beats(trans);
1021 auto input_beat_cnt = 0U;
1022 auto output_beat_cnt = 0U;
1024 sem_lock lck(wdat_chnl);
1028 if(output_beat_cnt < exp_beat_cnt) {
1030 if(
auto data_ext = trans.get_extension<chi::chi_data_extension>()) {
1031 update_data_extension(data_ext, trans);
1033 create_data_ext(trans);
1036 SCCDEBUG(SCMOD) <<
"Atomic send data (txn_id,opcode,cmd,addr,len) = (" << txn_id <<
","
1037 <<
to_char(trans.get_extension<chi::chi_data_extension>()->dat.get_opcode()) <<
", " << trans.get_command()
1038 <<
",0x" << std::hex << trans.get_address() <<
"," << trans.get_data_length() <<
"), beat=" << output_beat_cnt
1039 <<
"/" << exp_beat_cnt;
1040 if(output_beat_cnt < exp_beat_cnt)
1041 phase = chi::BEGIN_PARTIAL_DATA;
1043 phase = chi::BEGIN_DATA;
1044 send_packet(phase, trans, txs);
1045 if(output_beat_cnt == exp_beat_cnt) {
1046 wait(clk_i.posedge_event());
1051 if(input_beat_cnt < exp_beat_cnt && txs->peq.has_next()) {
1054 auto entry = txs->peq.
get();
1055 sc_assert(std::get<0>(entry) == &trans);
1056 phase = std::get<1>(entry);
1058 if(phase == chi::BEGIN_PARTIAL_DATA || phase == chi::BEGIN_DATA) {
1059 auto data_ext = trans.get_extension<chi::chi_data_extension>();
1060 sc_assert(data_ext);
1062 SCCDEBUG(SCMOD) <<
"Atomic received data (txn_id,opcode,cmd,addr,len)=(" << txn_id <<
","
1063 <<
to_char(data_ext->dat.get_opcode()) <<
"," << trans.get_command() <<
",0x" << std::hex
1064 << trans.get_address() <<
"," << trans.get_data_length() <<
"), beat=" << input_beat_cnt <<
"/"
1066 phase = phase == chi::BEGIN_PARTIAL_DATA ? (tlm::tlm_phase)chi::END_PARTIAL_DATA : (tlm::tlm_phase)END_DATA;
1067 delay = clk_if ? ::scc::time_to_next_posedge(clk_if) - 1_ps : SC_ZERO_TIME;
1068 auto rdat_send_limit = std::min(15u, rdat_req_credit_limit.get_value());
1069 chi::chi_credit_extension<credit_type_e::DATA> ext;
1070 if(ProvidedRdatCreditCounter.get() < rdat_send_limit) {
1071 ext.count = rdat_send_limit - ProvidedRdatCreditCounter;
1072 trans.set_extension(&ext);
1073 ProvidedRdatCreditCounter += ext.count;
1075 socket_fw->nb_transport_fw(trans, phase, delay);
1076 trans.set_extension<chi::chi_credit_extension<credit_type_e::DATA>>(
nullptr);
1077 if(phase == chi::END_DATA) {
1079 if(input_beat_cnt != exp_beat_cnt)
1080 SCCERR(SCMOD) <<
"Wrong beat count, expected " << exp_beat_cnt <<
", got " << input_beat_cnt;
1082 if(protocol_cb[RDAT])
1083 protocol_cb[RDAT](RDAT, trans);
1085 SCCERR(SCMOD) <<
"Illegal protocol state: " << phase;
1087 }
else if(output_beat_cnt == exp_beat_cnt)
1088 wait(txs->peq.
event());
1093 SCCTRACE(SCMOD) <<
"got transport req";
1096 socket_fw->b_transport(trans, t);
1100 convert_axi4ace_to_chi(trans, name(), use_legacy_mapping.get_value());
1102 sc_assert(req_ext !=
nullptr);
1104 req_ext->set_src_id(src_id.get_value());
1105 req_ext->req.set_tgt_id(tgt_id.get_value());
1106 req_ext->req.set_max_flit(calculate_beats(trans) - 1);
1108 auto it = tx_state_by_trans.find(to_id(trans));
1109 if(it == tx_state_by_trans.end()) {
1110 if(!tx_state_pool.size())
1113 std::tie(it, success) = tx_state_by_trans.insert({to_id(trans), tx_state_pool.back()});
1114 tx_state_pool.pop_back();
1116 auto& txs = it->second;
1117 auto const txn_id = req_ext->get_txn_id();
1118 if(chi::is_request_order(req_ext)) {
1121 if(strict_income_order.get_value())
1122 strict_order_sem.wait();
1123 sem_lock txnlck(active_tx_by_id[txn_id]);
1126 if(strict_income_order.get_value())
1127 strict_order_sem.post();
1128 setExpCompAck(req_ext);
1130 auto timing_e = trans.get_extension<atp::timing_params>();
1131 if(timing_e !=
nullptr) {
1132 auto delay_in_cycles = trans.is_read() ? timing_e->artv : timing_e->awtv;
1133 auto current_count = get_clk_cnt();
1134 if(current_count - m_prev_clk_cnt < delay_in_cycles) {
1135 unsigned delta_cycles = delay_in_cycles - (current_count - m_prev_clk_cnt);
1136 while(delta_cycles) {
1138 wait(clk_i.posedge_event());
1143 sem_lock lck(req_chnl);
1145 ReceivedReqCreditCounter.wait();
1148 SCCTRACE(SCMOD) <<
"starting transaction with txn_id=" << txn_id;
1149 m_prev_clk_cnt = get_clk_cnt();
1150 SCCTRACE(SCMOD) <<
"Send REQ, addr: 0x" << std::hex << trans.get_address() <<
", TxnID: 0x" << std::hex << txn_id;
1151 tlm::tlm_phase phase = tlm::BEGIN_REQ;
1152 sc_core::sc_time delay;
1153 tlm::tlm_sync_enum ret = socket_fw->nb_transport_fw(trans, phase, delay);
1154 if(ret == tlm::TLM_UPDATED) {
1155 sc_assert(phase == tlm::END_REQ);
1157 SCCTRACEALL(SCMOD) <<
"Received " << credit_ext->count <<
" req " << (credit_ext->count == 1 ?
"credit" :
"credits");
1158 for(
auto i = 0U; i < credit_ext->count; ++i)
1159 ReceivedReqCreditCounter.post();
1164 auto entry = txs->peq.
get();
1165 sc_assert(std::get<0>(entry) == &trans && std::get<1>(entry) == tlm::END_REQ);
1167 if(protocol_cb[REQ])
1168 protocol_cb[REQ](REQ, trans);
1169 wait(clk_i.posedge_event());
1172 if((req_optype_e::AtomicLoadAdd <= req_ext->req.get_opcode()) && (req_ext->req.get_opcode() <= req_optype_e::AtomicCompare))
1173 exec_atomic_protocol(txn_id, trans, txs);
1175 exec_read_write_protocol(txn_id, trans, txs);
1177 req_ext->req.get_opcode() >= req_optype_e::AtomicStoreAdd && req_ext->req.get_opcode() <= req_optype_e::AtomicCompare;
1178 bool compack_allowed =
true;
1179 switch(req_ext->req.get_opcode()) {
1180 case req_optype_e::WriteUniqueFullStash:
1181 case req_optype_e::WriteUniquePtlStash:
1182 case req_optype_e::StashOnceShared:
1183 case req_optype_e::StashOnceUnique:
1184 case req_optype_e::WriteBackPtl:
1185 case req_optype_e::WriteBackFull:
1186 case req_optype_e::WriteCleanFull:
1187 case req_optype_e::WriteCleanPtl:
1188 case req_optype_e::CleanSharedPersistSep:
1189 case req_optype_e::WriteEvictFull:
1190 case req_optype_e::WriteUniqueZero:
1191 case req_optype_e::WriteNoSnpZero:
1192 case req_optype_e::StashOnceSepShared:
1193 case req_optype_e::StashOnceSepUnique:
1194 case req_optype_e::WriteBackFullCleanSh:
1195 case req_optype_e::WriteBackFullCleanInv:
1196 case req_optype_e::WriteBackFullCleanShPerSep:
1197 case req_optype_e::WriteCleanFullCleanSh:
1198 case req_optype_e::WriteCleanFullCleanShPerSep:
1199 compack_allowed =
false;
1204 if(!is_atomic && compack_allowed && req_ext->req.is_exp_comp_ack())
1205 send_comp_ack(trans, txs);
1208 trans.set_response_status(tlm::TLM_OK_RESPONSE);
1209 wait(clk_i.posedge_event());
1210 tx_state_pool.push_back(it->second);
1211 tx_state_pool.back()->peq.clear();
1212 tx_state_by_trans.erase(it);
1213 SCCTRACE(SCMOD) <<
"finished non-blocking protocol";
1214 any_tx_finished.notify(SC_ZERO_TIME);
1221 tlm::tlm_phase phase;
1224 ext->set_src_id(src_id.get_value());
1225 send_wdata(trans, txs);
1231 sc_assert(snp_ext !=
nullptr);
1233 snp_ext->set_src_id(src_id.get_value());
1234 snp_ext->resp.set_tgt_id(snp_ext->get_src_id());
1235 snp_ext->resp.set_db_id(snp_ext->get_txn_id());
1237 phase = tlm::BEGIN_RESP;
1238 delay = SC_ZERO_TIME;
1239 auto not_finish = snp_ext->resp.get_data_pull() ? 0b11U : 0b10U;
1241 auto e = trans.get_extension<atp::timing_params>();
1243 sem_lock l(prio_sresp_chnl);
1244 while(get_clk_cnt() < e->start_soonest) {
1245 wait(clk_i.negedge_event());
1248 wait(clk_i.posedge_event());
1251 if(protocol_cb[SRSP])
1252 protocol_cb[SRSP](SRSP, trans);
1253 ReceivedSrespCreditCounter.wait();
1254 auto ret = socket_fw->nb_transport_fw(trans, phase, delay);
1255 if(ret == tlm::TLM_UPDATED) {
1256 sc_assert(phase == tlm::END_RESP);
1257 if(
auto ext = trans.get_extension<chi::chi_credit_extension<credit_type_e::RESP>>()) {
1258 for(
auto i = 0u; i < ext->count; ++i)
1259 ReceivedSrespCreditCounter.post();
1260 trans.set_auto_extension<chi_credit_extension<credit_type_e::RESP>>(
nullptr);
1265 wait(clk_i.posedge_event());
1268 if(snp_ext->resp.get_data_pull() && trans.get_data_length() < 64) {
1269 delete[] trans.get_data_ptr();
1270 trans.set_data_ptr(
new uint8_t[64]);
1271 trans.set_data_length(64);
1273 auto exp_beat_cnt = calculate_beats(trans);
1277 auto entry = txs->peq.
get();
1278 sc_assert(std::get<0>(entry) == &trans);
1279 auto phase = std::get<1>(entry);
1280 if(phase == tlm::END_RESP) {
1282 }
else if(snp_ext->resp.get_data_pull() && (phase == chi::BEGIN_PARTIAL_DATA || phase == chi::BEGIN_DATA)) {
1283 SCCTRACE(SCMOD) <<
"RDAT packet received with phase " << phase <<
". Beat count: " << beat_cnt <<
", addr: 0x" << std::hex
1284 << trans.get_address();
1286 if(protocol_cb[RDAT])
1287 protocol_cb[RDAT](RDAT, trans);
1288 phase = phase == chi::BEGIN_PARTIAL_DATA ? (tlm::tlm_phase)chi::END_PARTIAL_DATA : (tlm::tlm_phase)END_DATA;
1290 delay = clk_if ? ::scc::time_to_next_posedge(clk_if) - 1_ps : SC_ZERO_TIME;
1291 socket_fw->nb_transport_fw(trans, phase, delay);
1293 if(phase == chi::END_DATA) {
1295 if(beat_cnt != exp_beat_cnt)
1296 SCCERR(SCMOD) <<
"Wrong beat count, expected " << exp_beat_cnt <<
", got " << beat_cnt;
1297 if(bw_o.get_interface())
1298 bw_o->transport(trans);
1302 SCCFATAL(SCMOD) <<
"Illegal protocol state (maybe just not implemented?)";
1306 wait(clk_i.posedge_event());
1307 if(snp_ext->resp.get_data_pull())
1308 send_comp_ack(trans, txs);
1312void chi::pe::chi_rn_initiator_b::snoop_dispatch() {
1313 sc_core::sc_spawn_options opts;
1314 opts.set_stack_size(0x10000);
1315 payload_type* trans{
nullptr};
1317 while(!(trans = snp_peq.get_next_transaction())) {
1318 wait(snp_peq.get_event());
1320 if(thread_avail == 0 && thread_active < 32) {
1323 payload_type* trans{
nullptr};
1327 while(!(trans = snp_dispatch_que.get_next_transaction()))
1328 wait(snp_dispatch_que.get_event());
1329 sc_assert(thread_avail > 0);
1331 this->snoop_handler(trans);
1337 snp_dispatch_que.notify(*trans);
1341void chi::pe::chi_rn_initiator_b::snoop_handler(payload_type* trans) {
1342 auto req_ext = trans->get_extension<chi_snp_extension>();
1343 sc_assert(req_ext !=
nullptr);
1344 auto const txn_id = req_ext->get_txn_id();
1346 SCCDEBUG(SCMOD) <<
"Received SNOOP request: (src_id, txn_id, opcode, command, address) = " << req_ext->get_src_id() <<
", " << txn_id
1347 <<
", " <<
to_char(req_ext->req.get_opcode()) <<
", " << (trans->is_read() ?
"READ" :
"WRITE") <<
", " << std::hex
1348 << trans->get_address() <<
")";
1350 auto it = tx_state_by_trans.find(to_id(trans));
1351 if(it == tx_state_by_trans.end()) {
1352 if(!tx_state_pool.size())
1353 tx_state_pool.push_back(
new tx_state(
util::strprintf(
"peq_%d", ++peq_cnt)));
1355 std::tie(it, success) = tx_state_by_trans.insert({to_id(trans), tx_state_pool.back()});
1356 tx_state_pool.pop_back();
1358 auto* txs = it->second;
1359 sc_time delay = clk_if ? ::scc::time_to_next_posedge(clk_if) - 1_ps : SC_ZERO_TIME;
1360 tlm::tlm_phase phase = tlm::END_REQ;
1362 chi::chi_credit_extension<credit_type_e::REQ> ext;
1363 if(snp_counter.get() < snp_req_limit.get_value() && ProvidedSnpCreditCounter.get() < std::min(snp_req_credit_limit.get_value(), 15u)) {
1364 trans->set_extension(&ext);
1365 ProvidedSnpCreditCounter++;
1367 socket_fw->nb_transport_fw(*trans, phase, delay);
1368 trans->set_extension<chi::chi_credit_extension<credit_type_e::REQ>>(
nullptr);
1369 if(protocol_cb[SNP])
1370 protocol_cb[SNP](SNP, *trans);
1372 if(bw_o.get_interface())
1373 cycles = bw_o->transport(*trans);
1374 if(cycles < std::numeric_limits<unsigned>::max()) {
1376 auto clock_count = sc_core::sc_time_stamp().value() / clk_if->period().value();
1377 auto e =
new atp::timing_params(clock_count + cycles - 2);
1378 trans->set_auto_extension(e);
1380 handle_snoop_response(*trans, txs);
1381 tx_state_pool.push_back(it->second);
1382 tx_state_pool.back()->peq.clear();
1383 tx_state_by_trans.erase(to_id(trans));
1389void chi::pe::chi_rn_initiator_b::grant_credit(credit_type_e type,
unsigned amount) {
1390 tlm::tlm_phase ph = tlm::BEGIN_REQ;
1391 auto t = sc_core::SC_ZERO_TIME;
1392 tlm::tlm_generic_payload gp;
1394 case credit_type_e::REQ:
1395 gp.set_extension(
new chi_credit_extension<credit_type_e::REQ>(amount));
1397 case credit_type_e::RESP:
1398 gp.set_extension(
new chi_credit_extension<credit_type_e::RESP>(amount));
1400 case credit_type_e::DATA:
1401 gp.set_extension(
new chi_credit_extension<credit_type_e::DATA>(amount));
1406 socket_fw->nb_transport_fw(gp, ph, t);
1420 unsigned chi::pe::chi_rn_initiator_b::get_credit_count(channel_e e) {
1424 return ReceivedReqCreditCounter.get_value();
1426 return ReceivedWdatCreditCounter.get_value();
1428 return ReceivedSrespCreditCounter.get_value();
1430 return ProvidedCrespCreditCounter;
1432 return ProvidedRdatCreditCounter;
1434 return ProvidedSnpCreditCounter;
void transport(payload_type &trans, bool blocking) override
The forward transport function. It behaves blocking and is re-entrant.
void snoop_resp(payload_type &trans, bool sync=false) override
triggers a non-blocking snoop response if the snoop callback does not do so.
void b_snoop(payload_type &trans, sc_core::sc_time &t) override
snoop access to a snooped master
const char * to_char(E t)
@ MEMORY_BARRIER
Normal access, respecting barriers.
TLM2.0 components modeling CHI.
tlm::tlm_fw_transport_if< TYPES > chi_fw_transport_if
alias declaration for the forward interface
const char * to_char(E t)
std::string strprintf(const std::string format,...)
allocate and print to a string buffer
unsigned int get_id() const
uint8_t get_qos() const
get the AxQOS (quality of service) value
unsigned int get_txn_id() const
sc_core::sc_event & event()
get the available event