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_IGNORE_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 && snp_credit_sent.get() < 15 && snp_counter.get() < snp_req_credit_limit.get_value()) {
536 auto credit2send = std::min<unsigned>(15 - snp_credit_sent.get(), std::min<int>(0, snp_req_credit_limit.get_value() - snp_counter.get()));
537 grant_credit(credit2send);
538 snp_credit_sent += credit2send;
544 if(bw_o.get_interface()) {
545 auto latency = bw_o->transport(trans);
546 if(latency < std::numeric_limits<unsigned>::max())
547 t += latency * (clk_if ? clk_if->period() : clk_period);
553 sc_assert(req_ext !=
nullptr);
554 auto it = tx_state_by_trans.find(to_id(trans));
555 sc_assert(it != tx_state_by_trans.end());
556 auto* txs = it->second;
557 handle_snoop_response(trans, txs);
558 tx_state_pool.push_back(it->second);
559 tx_state_pool.back()->peq.clear();
560 tx_state_by_trans.erase(to_id(trans));
565tlm::tlm_sync_enum chi::pe::chi_rn_initiator_b::nb_transport_bw(payload_type& trans, phase_type& phase, sc_core::sc_time& t) {
567 if(phase == tlm::BEGIN_REQ) {
571 snp_peq.notify(trans, t);
572 if(snp_counter < snp_req_credit_limit.get_value()) {
578 auto it = tx_state_by_trans.find(to_id(trans));
579 sc_assert(it != tx_state_by_trans.end());
580 it->second->peq.notify(std::make_tuple(&trans, phase), t);
583 if(phase == tlm::BEGIN_REQ) {
584 if(
auto credit_ext = trans.get_extension<chi_credit_extension>()) {
585 if(credit_ext->type == credit_type_e::REQ) {
586 SCCTRACEALL(SCMOD) <<
"Received " << credit_ext->count <<
" req " << (credit_ext->count == 1 ?
"credit" :
"credits");
587 for(
auto i = 0U; i < credit_ext->count; ++i)
590 phase = tlm::END_RESP;
591 trans.set_response_status(tlm::TLM_OK_RESPONSE);
593 t += clk_if->period() - 1_ps;
594 return tlm::TLM_COMPLETED;
596 SCCFATAL(SCMOD) <<
"Illegal transaction received from HN";
599 auto it = tx_state_by_trans.find(to_id(trans));
600 sc_assert(it != tx_state_by_trans.end());
601 it->second->peq.notify(std::make_tuple(&trans, phase), t);
604 return tlm::TLM_ACCEPTED;
607void chi::pe::chi_rn_initiator_b::invalidate_direct_mem_ptr(sc_dt::uint64 start_range, sc_dt::uint64 end_range) {}
609void chi::pe::chi_rn_initiator_b::update_data_extension(chi::chi_data_extension* data_ext, payload_type& trans) {
610 auto req_e = trans.get_extension<chi::chi_ctrl_extension>();
611 sc_assert(req_e !=
nullptr);
612 switch(req_e->req.get_opcode()) {
613 case chi::req_optype_e::WriteNoSnpPtl:
614 case chi::req_optype_e::WriteNoSnpFull:
615 case chi::req_optype_e::WriteUniquePtl:
616 case chi::req_optype_e::WriteUniqueFull:
617 case chi::req_optype_e::WriteUniquePtlStash:
618 case chi::req_optype_e::WriteUniqueFullStash:
620 case chi::req_optype_e::WriteNoSnpFullCleanSh:
621 case chi::req_optype_e::WriteNoSnpFullCleanInv:
622 case chi::req_optype_e::WriteNoSnpFullCleanShPerSep:
623 case chi::req_optype_e::WriteUniqueFullCleanSh:
624 case chi::req_optype_e::WriteUniqueFullCleanShPerSep:
625 case chi::req_optype_e::WriteBackFullCleanShPerSep:
626 case chi::req_optype_e::WriteNoSnpPtlCleanSh:
627 case chi::req_optype_e::WriteNoSnpPtlCleanInv:
628 case chi::req_optype_e::WriteNoSnpPtlCleanShPerSep:
629 case chi::req_optype_e::WriteUniquePtlCleanSh:
630 case chi::req_optype_e::WriteUniquePtlCleanShPerSep:
631 data_ext->dat.set_opcode(chi::dat_optype_e::NonCopyBackWrData);
634 case chi::req_optype_e::WriteBackFull:
635 case chi::req_optype_e::WriteBackPtl:
636 case chi::req_optype_e::WriteCleanFull:
637 case chi::req_optype_e::WriteCleanPtl:
639 case chi::req_optype_e::WriteBackFullCleanSh:
640 case chi::req_optype_e::WriteBackFullCleanInv:
641 case chi::req_optype_e::WriteCleanFullCleanSh:
642 case chi::req_optype_e::WriteCleanFullCleanShPerSep:
643 case chi::req_optype_e::WriteEvictFull:
644 data_ext->dat.set_opcode(chi::dat_optype_e::CopyBackWrData);
647 case chi::req_optype_e::AtomicStoreAdd:
648 case chi::req_optype_e::AtomicStoreClr:
649 case chi::req_optype_e::AtomicStoreEor:
650 case chi::req_optype_e::AtomicStoreSet:
651 case chi::req_optype_e::AtomicStoreSmax:
652 case chi::req_optype_e::AtomicStoreSmin:
653 case chi::req_optype_e::AtomicStoreUmax:
654 case chi::req_optype_e::AtomicStoreUmin:
655 data_ext->dat.set_opcode(chi::dat_optype_e::NonCopyBackWrData);
657 case chi::req_optype_e::AtomicLoadAdd:
658 case chi::req_optype_e::AtomicLoadClr:
659 case chi::req_optype_e::AtomicLoadEor:
660 case chi::req_optype_e::AtomicLoadSet:
661 case chi::req_optype_e::AtomicLoadSmax:
662 case chi::req_optype_e::AtomicLoadSmin:
663 case chi::req_optype_e::AtomicLoadUmax:
664 case chi::req_optype_e::AtomicLoadUmin:
665 case chi::req_optype_e::AtomicSwap:
666 case chi::req_optype_e::AtomicCompare:
667 data_ext->dat.set_opcode(chi::dat_optype_e::NonCopyBackWrData);
670 SCCWARN(SCMOD) <<
" Unable to match req_opcode with data_opcode in write transaction ";
672 if(data_ext->dat.get_opcode() == chi::dat_optype_e::NonCopyBackWrData) {
673 data_ext->dat.set_resp(chi::dat_resptype_e::NonCopyBackWrData);
674 }
else if(data_ext->dat.get_opcode() == chi::dat_optype_e::NCBWrDataCompAck) {
675 data_ext->dat.set_resp(chi::dat_resptype_e::NCBWrDataCompAck);
676 }
else if(data_ext->dat.get_opcode() == chi::dat_optype_e::CopyBackWrData) {
677 auto cache_ext = trans.get_extension<::cache::cache_info>();
678 sc_assert(cache_ext !=
nullptr);
679 auto cache_state = cache_ext->get_state();
680 if(cache_state == ::cache::state::IX) {
681 data_ext->dat.set_resp(chi::dat_resptype_e::CopyBackWrData_I);
682 }
else if(cache_state == ::cache::state::UC) {
683 data_ext->dat.set_resp(chi::dat_resptype_e::CopyBackWrData_UC);
684 }
else if(cache_state == ::cache::state::SC) {
685 data_ext->dat.set_resp(chi::dat_resptype_e::CopyBackWrData_SC);
686 }
else if(cache_state == ::cache::state::UD) {
687 data_ext->dat.set_resp(chi::dat_resptype_e::CopyBackWrData_UD_PD);
688 }
else if(cache_state == ::cache::state::SD) {
689 data_ext->dat.set_resp(chi::dat_resptype_e::CopyBackWrData_SD_PD);
691 SCCWARN(SCMOD) <<
" Unable to match cache state with resptype ";
693 SCCWARN(SCMOD) <<
"Unable to match resptype with WriteData Responses";
696 auto db_id = req_e->resp.get_db_id();
697 data_ext->set_txn_id(db_id);
698 data_ext->set_src_id(req_e->resp.get_tgt_id());
699 data_ext->dat.set_tgt_id(req_e->get_src_id());
702void chi::pe::chi_rn_initiator_b::create_data_ext(payload_type& trans) {
703 auto data_ext =
new chi::chi_data_extension;
704 update_data_extension(data_ext, trans);
705 trans.set_auto_extension<chi::chi_data_extension>(data_ext);
708void chi::pe::chi_rn_initiator_b::send_packet(tlm::tlm_phase phase, payload_type& trans, chi::pe::chi_rn_initiator_b::tx_state* txs) {
709 if(protocol_cb[WDAT])
710 protocol_cb[WDAT](WDAT, trans);
711 sc_core::sc_time delay = sc_core::SC_ZERO_TIME;
712 tlm::tlm_sync_enum ret = socket_fw->nb_transport_fw(trans, phase, delay);
713 if(ret == tlm::TLM_UPDATED) {
714 if(phase == chi::END_PARTIAL_DATA || phase == chi::END_DATA) {
719 auto entry = txs->peq.
get();
720 sc_assert(std::get<0>(entry) == &trans && (std::get<1>(entry) == chi::END_PARTIAL_DATA || std::get<1>(entry) == chi::END_DATA));
722 auto timing_e = trans.get_extension<atp::timing_params>();
723 auto delay_in_cycles = (timing_e && timing_e->wbv) ? timing_e->wbv : 1;
724 while(delay_in_cycles) {
726 wait(clk_i.posedge_event());
730void chi::pe::chi_rn_initiator_b::send_wdata(payload_type& trans, chi::pe::chi_rn_initiator_b::tx_state* txs) {
731 sc_core::sc_time delay;
732 tlm::tlm_phase phase;
733 auto data_ext = trans.get_extension<chi::chi_data_extension>();
734 if(data_ext ==
nullptr) {
735 create_data_ext(trans);
736 data_ext = trans.get_extension<chi::chi_data_extension>();
739 auto beat_cnt = calculate_beats(trans);
740 SCCDEBUG(SCMOD) <<
"Starting transaction on channel WDAT : (opcode, cmd, addr, len) = (" <<
to_char(data_ext->dat.get_opcode()) <<
", "
741 << trans.get_command() <<
", " << std::hex << trans.get_address() <<
", " << trans.get_data_length() <<
")";
742 if(!data_interleaving.get_value()) {
743 auto e = trans.get_extension<atp::timing_params>();
745 sem_lock l(prio_wdat_chnl);
746 auto clock_count = sc_core::sc_time_stamp().value() / clk_if->period().value();
747 while(clock_count < e->start_soonest) {
748 wait(clk_i.negedge_event());
749 clock_count = sc_core::sc_time_stamp().value() / clk_if->period().value();
752 auto time_offset = sc_core::sc_time_stamp() % clk_if->period();
755 for(
auto i = 0U; i < beat_cnt; ++i) {
757 phase = chi::BEGIN_PARTIAL_DATA;
759 phase = chi::BEGIN_DATA;
762 data_ext->dat.set_data_id(i << (transfer_width_in_bytes * 8 / 128 - 1));
763 SCCTRACE(SCMOD) <<
"WDAT flit with txnid " << data_ext->cmn.
get_txn_id()
764 <<
" data_id = " << (
unsigned int)(data_ext->dat.get_data_id()) <<
" sent. Beat count: " << i <<
", addr: 0x"
765 << std::hex << trans.get_address() <<
", last=" << (i == (beat_cnt - 1));
766 send_packet(phase, trans, txs);
770 for(
auto i = 0U; i < beat_cnt; ++i) {
772 sem_lock lck(wdat_chnl);
774 phase = chi::BEGIN_PARTIAL_DATA;
776 phase = chi::BEGIN_DATA;
778 data_ext->dat.set_data_id(i << (transfer_width_in_bytes * 8 / 128 - 1));
779 SCCTRACE(SCMOD) <<
"WDAT flit with txnid " << data_ext->cmn.
get_txn_id()
780 <<
" data_id = " << (
unsigned int)(data_ext->dat.get_data_id()) <<
" sent. Beat count: " << i
781 <<
", addr: 0x" << std::hex << trans.get_address() <<
", last=" << (i == (beat_cnt - 1));
782 send_packet(phase, trans, txs);
789void chi::pe::chi_rn_initiator_b::send_comp_ack(payload_type& trans, tx_state*& txs) {
790 if(make_rsp_from_req(trans, chi::rsp_optype_e::CompAck)) {
791 sem_lock lck(sresp_chnl);
792 SCCDEBUG(SCMOD) <<
"Send the CompAck response on SRSP channel, addr: 0x" << std::hex << trans.get_address();
793 if(protocol_cb[SRSP])
794 protocol_cb[SRSP](SRSP, trans);
795 tlm::tlm_phase phase = chi::ACK;
796 auto delay = SC_ZERO_TIME;
797 auto ret = socket_fw->nb_transport_fw(trans, phase, delay);
798 if(ret == tlm::TLM_UPDATED && phase == chi::ACK) {
802 auto entry = txs->peq.get();
803 sc_assert(std::get<0>(entry) == &trans && std::get<1>(entry) == tlm::END_RESP);
805 wait(clk_i.posedge_event());
809bool expectCompCMO(chi::chi_ctrl_extension* ext) {
810 switch(ext->req.get_opcode()) {
811 case req_optype_e::WriteBackFullCleanSh:
812 case req_optype_e::WriteBackFullCleanInv:
813 case req_optype_e::WriteBackFullCleanShPerSep:
814 case req_optype_e::WriteCleanFullCleanSh:
815 case req_optype_e::WriteCleanFullCleanShPerSep:
816 case req_optype_e::WriteNoSnpFullCleanSh:
817 case req_optype_e::WriteNoSnpFullCleanInv:
818 case req_optype_e::WriteNoSnpFullCleanShPerSep:
819 case req_optype_e::WriteUniquePtlCleanSh:
820 case req_optype_e::WriteUniqueFullCleanSh:
821 case req_optype_e::WriteUniquePtlCleanShPerSep:
822 case req_optype_e::WriteUniqueFullCleanShPerSep:
829bool expectPersist(chi::chi_ctrl_extension* ext) {
830 switch(ext->req.get_opcode()) {
831 case req_optype_e::WriteBackFullCleanShPerSep:
832 case req_optype_e::WriteCleanFullCleanShPerSep:
833 case req_optype_e::WriteNoSnpFullCleanShPerSep:
834 case req_optype_e::WriteUniquePtlCleanShPerSep:
835 case req_optype_e::WriteUniqueFullCleanShPerSep:
836 case req_optype_e::CleanSharedPersistSep:
843enum { WAIT_CTRL = 0x1, WAIT_DATA = 0x2, WAIT_COMPCMO = 4, WAIT_PERSIST = 8 };
844void chi::pe::chi_rn_initiator_b::exec_read_write_protocol(
const unsigned int txn_id, payload_type& trans,
845 chi::pe::chi_rn_initiator_b::tx_state*& txs) {
847 sc_core::sc_time delay;
848 auto ctrl_ext = trans.get_extension<chi::chi_ctrl_extension>();
849 unsigned not_finish = WAIT_CTRL;
850 not_finish |= is_dataless(ctrl_ext) ? 0 : WAIT_DATA;
851 not_finish |= expectCompCMO(ctrl_ext) ? WAIT_COMPCMO : 0;
852 not_finish |= expectPersist(ctrl_ext) ? WAIT_PERSIST : 0;
853 auto exp_beat_cnt = calculate_beats(trans);
857 auto entry = txs->peq.
get();
858 sc_assert(std::get<0>(entry) == &trans);
859 auto phase = std::get<1>(entry);
860 if(phase == tlm::BEGIN_RESP) {
861 if(chi::is_dataless(ctrl_ext)) {
862 switch(ctrl_ext->resp.get_opcode()) {
863 case chi::rsp_optype_e::Comp:
864 if(ctrl_ext->req.get_opcode() == chi::req_optype_e::MakeReadUnique)
865 not_finish &= ~WAIT_CTRL;
867 switch(ctrl_ext->resp.get_resp()) {
868 case chi::rsp_resptype_e::Comp_I:
869 case chi::rsp_resptype_e::Comp_UC:
870 case chi::rsp_resptype_e::Comp_SC:
871 not_finish &= ~WAIT_CTRL;
877 case chi::rsp_optype_e::CompDBIDResp:
878 case chi::rsp_optype_e::CompPersist:
879 case chi::rsp_optype_e::CompCMO:
880 case chi::rsp_optype_e::CompStashDone:
881 not_finish &= ~WAIT_CTRL;
883 case chi::rsp_optype_e::Persist:
884 not_finish &= ~WAIT_PERSIST;
889 not_finish &= ~WAIT_DATA;
890 send_cresp_response(trans);
891 }
else if(trans.is_write()) {
892 switch(ctrl_ext->resp.get_opcode()) {
893 case chi::rsp_optype_e::CompCMO:
894 not_finish &= ~WAIT_COMPCMO;
895 send_cresp_response(trans);
897 case chi::rsp_optype_e::Persist:
898 not_finish &= ~WAIT_PERSIST;
899 send_cresp_response(trans);
901 case chi::rsp_optype_e::CompDBIDResp:
902 not_finish &= ~WAIT_CTRL;
904 case chi::rsp_optype_e::DBIDResp:
905 case chi::rsp_optype_e::DBIDRespOrd:
906 send_cresp_response(trans);
907 send_wdata(trans, txs);
908 not_finish &= ~WAIT_DATA;
910 case chi::rsp_optype_e::Comp:
911 not_finish &= ~WAIT_CTRL;
912 send_cresp_response(trans);
915 SCCFATAL(SCMOD) <<
"Illegal opcode received: " <<
to_char(ctrl_ext->resp.get_opcode());
917 }
else if(trans.is_read()) {
918 not_finish &= ~WAIT_CTRL;
919 send_cresp_response(trans);
921 }
else if(trans.is_read() && (phase == chi::BEGIN_PARTIAL_DATA || phase == chi::BEGIN_DATA)) {
922 SCCTRACE(SCMOD) <<
"RDAT flit received. Beat count: " << beat_cnt <<
", addr: 0x" << std::hex << trans.get_address();
923 if(protocol_cb[RDAT])
924 protocol_cb[RDAT](RDAT, trans);
925 phase = phase == chi::BEGIN_PARTIAL_DATA ? (tlm::tlm_phase)chi::END_PARTIAL_DATA : (tlm::tlm_phase)END_DATA;
926 delay = clk_if ? ::scc::time_to_next_posedge(clk_if) - 1_ps : SC_ZERO_TIME;
927 socket_fw->nb_transport_fw(trans, phase, delay);
929 if(phase == chi::END_DATA) {
930 not_finish &= ~(WAIT_CTRL | WAIT_DATA);
931 if(beat_cnt != exp_beat_cnt)
932 SCCERR(SCMOD) <<
"Wrong beat count, expected " << exp_beat_cnt <<
", got " << beat_cnt;
935 SCCFATAL(SCMOD) <<
"Illegal protocol state (maybe just not implemented?)";
940void chi::pe::chi_rn_initiator_b::send_cresp_response(payload_type& trans) {
941 auto resp_ext = trans.get_extension<chi::chi_ctrl_extension>();
942 sc_assert(resp_ext !=
nullptr);
943 if(is_request_order(resp_ext))
945 auto id = (unsigned)(resp_ext->get_txn_id());
946 SCCDEBUG(SCMOD) <<
"got cresp: src_id=" << (unsigned)resp_ext->get_src_id() <<
", tgt_id=" << (unsigned)resp_ext->resp.get_tgt_id()
947 <<
", txnid=0x" << std::hex <<
id <<
", " <<
to_char(resp_ext->resp.get_opcode())
948 <<
", resp=" <<
to_char(resp_ext->resp.get_resp()) <<
", db_id=" << (unsigned)resp_ext->resp.get_db_id() <<
", addr=0x"
949 << std::hex << trans.get_address() <<
")";
950 if(protocol_cb[CRSP])
951 protocol_cb[CRSP](CRSP, trans);
952 tlm::tlm_phase phase = tlm::END_RESP;
953 sc_core::sc_time delay = clk_if ? ::scc::time_to_next_posedge(clk_if) - 1_ps : SC_ZERO_TIME;
954 socket_fw->nb_transport_fw(trans, phase, delay);
955 wait(clk_i.posedge_event());
958void chi::pe::chi_rn_initiator_b::exec_atomic_protocol(
const unsigned int txn_id, payload_type& trans,
959 chi::pe::chi_rn_initiator_b::tx_state*& txs) {
960 sc_core::sc_time delay;
962 auto entry = txs->peq.
get();
963 sc_assert(std::get<0>(entry) == &trans);
964 auto phase = std::get<1>(entry);
965 if(phase == tlm::BEGIN_RESP) {
966 send_cresp_response(trans);
967 auto resp_ext = trans.get_extension<chi::chi_ctrl_extension>();
968 if(resp_ext->resp.get_opcode() == chi::rsp_optype_e::DBIDResp) {
969 SCCERR(SCMOD) <<
"CRESP illegal response opcode: " <<
to_char(resp_ext->resp.get_opcode());
972 SCCERR(SCMOD) <<
"Illegal protocol state (maybe just not implemented?) " << phase;
975 auto not_finish = 0b11U;
976 auto exp_beat_cnt = calculate_beats(trans);
977 auto input_beat_cnt = 0U;
978 auto output_beat_cnt = 0U;
980 sem_lock lck(wdat_chnl);
984 if(output_beat_cnt < exp_beat_cnt) {
986 if(
auto data_ext = trans.get_extension<chi::chi_data_extension>()) {
987 update_data_extension(data_ext, trans);
989 create_data_ext(trans);
992 SCCDEBUG(SCMOD) <<
"Atomic send data (txn_id,opcode,cmd,addr,len) = (" << txn_id <<
","
993 <<
to_char(trans.get_extension<chi::chi_data_extension>()->dat.get_opcode()) <<
", " << trans.get_command()
994 <<
",0x" << std::hex << trans.get_address() <<
"," << trans.get_data_length() <<
"), beat=" << output_beat_cnt
995 <<
"/" << exp_beat_cnt;
996 if(output_beat_cnt < exp_beat_cnt)
997 phase = chi::BEGIN_PARTIAL_DATA;
999 phase = chi::BEGIN_DATA;
1000 send_packet(phase, trans, txs);
1001 if(output_beat_cnt == exp_beat_cnt) {
1002 wait(clk_i.posedge_event());
1007 if(input_beat_cnt < exp_beat_cnt && txs->peq.has_next()) {
1010 auto entry = txs->peq.
get();
1011 sc_assert(std::get<0>(entry) == &trans);
1012 phase = std::get<1>(entry);
1014 if(phase == chi::BEGIN_PARTIAL_DATA || phase == chi::BEGIN_DATA) {
1015 auto data_ext = trans.get_extension<chi::chi_data_extension>();
1016 sc_assert(data_ext);
1018 SCCDEBUG(SCMOD) <<
"Atomic received data (txn_id,opcode,cmd,addr,len)=(" << txn_id <<
","
1019 <<
to_char(data_ext->dat.get_opcode()) <<
"," << trans.get_command() <<
",0x" << std::hex
1020 << trans.get_address() <<
"," << trans.get_data_length() <<
"), beat=" << input_beat_cnt <<
"/"
1022 if(protocol_cb[RDAT])
1023 protocol_cb[RDAT](RDAT, trans);
1024 phase = phase == chi::BEGIN_PARTIAL_DATA ? (tlm::tlm_phase)chi::END_PARTIAL_DATA : (tlm::tlm_phase)END_DATA;
1025 delay = clk_if ? ::scc::time_to_next_posedge(clk_if) - 1_ps : SC_ZERO_TIME;
1026 socket_fw->nb_transport_fw(trans, phase, delay);
1027 if(phase == chi::END_DATA) {
1029 if(input_beat_cnt != exp_beat_cnt)
1030 SCCERR(SCMOD) <<
"Wrong beat count, expected " << exp_beat_cnt <<
", got " << input_beat_cnt;
1033 SCCERR(SCMOD) <<
"Illegal protocol state: " << phase;
1035 }
else if(output_beat_cnt == exp_beat_cnt)
1036 wait(txs->peq.
event());
1041 SCCTRACE(SCMOD) <<
"got transport req";
1044 socket_fw->b_transport(trans, t);
1048 convert_axi4ace_to_chi(trans, name(), use_legacy_mapping.get_value());
1050 sc_assert(req_ext !=
nullptr);
1052 req_ext->set_src_id(src_id.get_value());
1053 req_ext->req.set_tgt_id(tgt_id.get_value());
1054 req_ext->req.set_max_flit(calculate_beats(trans) - 1);
1056 auto it = tx_state_by_trans.find(to_id(trans));
1057 if(it == tx_state_by_trans.end()) {
1058 if(!tx_state_pool.size())
1061 std::tie(it, success) = tx_state_by_trans.insert({to_id(trans), tx_state_pool.back()});
1062 tx_state_pool.pop_back();
1064 auto& txs = it->second;
1065 auto const txn_id = req_ext->get_txn_id();
1066 if(chi::is_request_order(req_ext)) {
1069 if(strict_income_order.get_value())
1070 strict_order_sem.wait();
1071 sem_lock txnlck(active_tx_by_id[txn_id]);
1074 if(strict_income_order.get_value())
1075 strict_order_sem.post();
1076 setExpCompAck(req_ext);
1078 auto timing_e = trans.get_extension<atp::timing_params>();
1079 if(timing_e !=
nullptr) {
1080 auto delay_in_cycles = trans.is_read() ? timing_e->artv : timing_e->awtv;
1081 auto current_count = get_clk_cnt();
1082 if(current_count - m_prev_clk_cnt < delay_in_cycles) {
1083 unsigned delta_cycles = delay_in_cycles - (current_count - m_prev_clk_cnt);
1084 while(delta_cycles) {
1086 wait(clk_i.posedge_event());
1091 sem_lock lck(req_chnl);
1096 SCCTRACE(SCMOD) <<
"starting transaction with txn_id=" << txn_id;
1097 m_prev_clk_cnt = get_clk_cnt();
1098 SCCTRACE(SCMOD) <<
"Send REQ, addr: 0x" << std::hex << trans.get_address() <<
", TxnID: 0x" << std::hex << txn_id;
1099 if(protocol_cb[REQ])
1100 protocol_cb[REQ](REQ, trans);
1101 tlm::tlm_phase phase = tlm::BEGIN_REQ;
1102 sc_core::sc_time delay;
1103 tlm::tlm_sync_enum ret = socket_fw->nb_transport_fw(trans, phase, delay);
1104 if(ret == tlm::TLM_UPDATED) {
1105 sc_assert(phase == tlm::END_REQ);
1108 auto entry = txs->peq.
get();
1109 sc_assert(std::get<0>(entry) == &trans && std::get<1>(entry) == tlm::END_REQ);
1112 wait(clk_i.posedge_event());
1114 if(credit_ext->type == credit_type_e::REQ) {
1115 SCCTRACEALL(SCMOD) <<
"Received " << credit_ext->count <<
" req " << (credit_ext->count == 1 ?
"credit" :
"credits");
1116 for(
auto i = 0U; i < credit_ext->count; ++i)
1123 if((req_optype_e::AtomicLoadAdd <= req_ext->req.get_opcode()) && (req_ext->req.get_opcode() <= req_optype_e::AtomicCompare))
1124 exec_atomic_protocol(txn_id, trans, txs);
1126 exec_read_write_protocol(txn_id, trans, txs);
1128 req_ext->req.get_opcode() >= req_optype_e::AtomicStoreAdd && req_ext->req.get_opcode() <= req_optype_e::AtomicCompare;
1129 bool compack_allowed =
true;
1130 switch(req_ext->req.get_opcode()) {
1131 case req_optype_e::WriteUniqueFullStash:
1132 case req_optype_e::WriteUniquePtlStash:
1133 case req_optype_e::StashOnceShared:
1134 case req_optype_e::StashOnceUnique:
1135 case req_optype_e::WriteBackPtl:
1136 case req_optype_e::WriteBackFull:
1137 case req_optype_e::WriteCleanFull:
1138 case req_optype_e::WriteCleanPtl:
1139 case req_optype_e::CleanSharedPersistSep:
1140 case req_optype_e::WriteEvictFull:
1141 case req_optype_e::WriteUniqueZero:
1142 case req_optype_e::WriteNoSnpZero:
1143 case req_optype_e::StashOnceSepShared:
1144 case req_optype_e::StashOnceSepUnique:
1145 case req_optype_e::WriteBackFullCleanSh:
1146 case req_optype_e::WriteBackFullCleanInv:
1147 case req_optype_e::WriteBackFullCleanShPerSep:
1148 case req_optype_e::WriteCleanFullCleanSh:
1149 case req_optype_e::WriteCleanFullCleanShPerSep:
1150 compack_allowed =
false;
1155 if(!is_atomic && compack_allowed && req_ext->req.is_exp_comp_ack())
1156 send_comp_ack(trans, txs);
1159 trans.set_response_status(tlm::TLM_OK_RESPONSE);
1160 wait(clk_i.posedge_event());
1161 tx_state_pool.push_back(it->second);
1162 tx_state_pool.back()->peq.clear();
1163 tx_state_by_trans.erase(it);
1164 SCCTRACE(SCMOD) <<
"finished non-blocking protocol";
1165 any_tx_finished.notify(SC_ZERO_TIME);
1172 tlm::tlm_phase phase;
1175 ext->set_src_id(src_id.get_value());
1176 send_wdata(trans, txs);
1182 sc_assert(snp_ext !=
nullptr);
1184 snp_ext->set_src_id(src_id.get_value());
1185 snp_ext->resp.set_tgt_id(snp_ext->get_src_id());
1186 snp_ext->resp.set_db_id(snp_ext->get_txn_id());
1188 phase = tlm::BEGIN_RESP;
1189 delay = SC_ZERO_TIME;
1190 auto not_finish = snp_ext->resp.get_data_pull() ? 0b11U : 0b10U;
1192 auto e = trans.get_extension<atp::timing_params>();
1194 sem_lock l(prio_sresp_chnl);
1195 while(get_clk_cnt() < e->start_soonest) {
1196 wait(clk_i.negedge_event());
1199 wait(clk_i.posedge_event());
1202 if(protocol_cb[SRSP])
1203 protocol_cb[SRSP](SRSP, trans);
1204 auto ret = socket_fw->nb_transport_fw(trans, phase, delay);
1205 if(ret == tlm::TLM_UPDATED) {
1206 sc_assert(phase == tlm::END_RESP);
1210 wait(clk_i.posedge_event());
1213 if(snp_ext->resp.get_data_pull() && trans.get_data_length() < 64) {
1214 delete[] trans.get_data_ptr();
1215 trans.set_data_ptr(
new uint8_t[64]);
1216 trans.set_data_length(64);
1218 auto exp_beat_cnt = calculate_beats(trans);
1222 auto entry = txs->peq.
get();
1223 sc_assert(std::get<0>(entry) == &trans);
1224 auto phase = std::get<1>(entry);
1225 if(phase == tlm::END_RESP) {
1227 }
else if(snp_ext->resp.get_data_pull() && (phase == chi::BEGIN_PARTIAL_DATA || phase == chi::BEGIN_DATA)) {
1228 SCCTRACE(SCMOD) <<
"RDAT packet received with phase " << phase <<
". Beat count: " << beat_cnt <<
", addr: 0x" << std::hex
1229 << trans.get_address();
1231 if(protocol_cb[WDAT])
1232 protocol_cb[WDAT](WDAT, trans);
1233 phase = phase == chi::BEGIN_PARTIAL_DATA ? (tlm::tlm_phase)chi::END_PARTIAL_DATA : (tlm::tlm_phase)END_DATA;
1234 delay = clk_if ? ::scc::time_to_next_posedge(clk_if) - 1_ps : SC_ZERO_TIME;
1235 socket_fw->nb_transport_fw(trans, phase, delay);
1237 if(phase == chi::END_DATA) {
1239 if(beat_cnt != exp_beat_cnt)
1240 SCCERR(SCMOD) <<
"Wrong beat count, expected " << exp_beat_cnt <<
", got " << beat_cnt;
1241 if(bw_o.get_interface())
1242 bw_o->transport(trans);
1246 SCCFATAL(SCMOD) <<
"Illegal protocol state (maybe just not implemented?)";
1250 wait(clk_i.posedge_event());
1251 if(snp_ext->resp.get_data_pull())
1252 send_comp_ack(trans, txs);
1256void chi::pe::chi_rn_initiator_b::snoop_dispatch() {
1257 sc_core::sc_spawn_options opts;
1258 opts.set_stack_size(0x10000);
1259 payload_type* trans{
nullptr};
1261 while(!(trans = snp_peq.get_next_transaction())) {
1262 wait(snp_peq.get_event());
1264 if(thread_avail == 0 && thread_active < 32) {
1267 payload_type* trans{
nullptr};
1271 while(!(trans = snp_dispatch_que.get_next_transaction()))
1272 wait(snp_dispatch_que.get_event());
1273 sc_assert(thread_avail > 0);
1275 this->snoop_handler(trans);
1281 snp_dispatch_que.notify(*trans);
1285void chi::pe::chi_rn_initiator_b::snoop_handler(payload_type* trans) {
1286 auto req_ext = trans->get_extension<chi_snp_extension>();
1287 sc_assert(req_ext !=
nullptr);
1288 auto const txn_id = req_ext->get_txn_id();
1290 SCCDEBUG(SCMOD) <<
"Received SNOOP request: (src_id, txn_id, opcode, command, address) = " << req_ext->get_src_id() <<
", " << txn_id
1291 <<
", " <<
to_char(req_ext->req.get_opcode()) <<
", " << (trans->is_read() ?
"READ" :
"WRITE") <<
", " << std::hex
1292 << trans->get_address() <<
")";
1294 auto it = tx_state_by_trans.find(to_id(trans));
1295 if(it == tx_state_by_trans.end()) {
1296 if(!tx_state_pool.size())
1297 tx_state_pool.push_back(
new tx_state(
util::strprintf(
"peq_%d", ++peq_cnt)));
1299 std::tie(it, success) = tx_state_by_trans.insert({to_id(trans), tx_state_pool.back()});
1300 tx_state_pool.pop_back();
1302 auto* txs = it->second;
1304 if(protocol_cb[SNP])
1305 protocol_cb[SNP](SNP, *trans);
1306 sc_time delay = clk_if ? ::scc::time_to_next_posedge(clk_if) - 1_ps : SC_ZERO_TIME;
1307 tlm::tlm_phase phase = tlm::END_REQ;
1308 socket_fw->nb_transport_fw(*trans, phase, delay);
1310 if(bw_o.get_interface())
1311 cycles = bw_o->transport(*trans);
1312 if(cycles < std::numeric_limits<unsigned>::max()) {
1316 auto clock_count = sc_core::sc_time_stamp().value() / clk_if->period().value();
1317 auto e =
new atp::timing_params(clock_count + cycles - 2);
1318 trans->set_auto_extension(e);
1320 handle_snoop_response(*trans, txs);
1321 tx_state_pool.push_back(it->second);
1322 tx_state_pool.back()->peq.clear();
1323 tx_state_by_trans.erase(to_id(trans));
1329void chi::pe::chi_rn_initiator_b::grant_credit(
unsigned amount) {
1330 tlm::tlm_phase ph = tlm::BEGIN_REQ;
1331 auto t = sc_core::SC_ZERO_TIME;
1333 auto ext = gp->template get_extension<chi_credit_extension>();
1334 ext->type = credit_type_e::REQ;
1335 ext->count = amount;
1336 socket_fw->nb_transport_fw(*gp, ph, t);
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
payload_type * allocate()
get a plain tlm_payload_type without extensions
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
static tlm_mm & get()
accessor function of the singleton