17 #ifndef _BUS_AXI_PIN_ACE_LITE_INITIATOR_H_
18 #define _BUS_AXI_PIN_ACE_LITE_INITIATOR_H_
20 #include <axi/axi_tlm.h>
21 #include <axi/fsm/base.h>
22 #include <axi/fsm/protocol_fsm.h>
23 #include <axi/signal_if.h>
25 #include <tlm/scc/tlm_mm.h>
26 #include <tlm_utils/peq_with_cb_and_phase.h>
33 template <
typename CFG>
35 public aw_ace_lite<CFG, typename CFG::master_types>,
37 public b_ace_lite<CFG, typename CFG::master_types>,
38 public ar_ace_lite<CFG, typename CFG::master_types>,
44 using payload_type = axi::axi_protocol_types::tlm_payload_type;
45 using phase_type = axi::axi_protocol_types::tlm_phase_type;
47 sc_core::sc_in<bool> clk_i{
"clk_i"};
52 : sc_core::sc_module(nm)
54 ,
base(CFG::BUSWIDTH,
false) {
55 instance_name = name();
58 sensitive << clk_i.pos();
67 void b_transport(payload_type& trans, sc_core::sc_time& t)
override {
68 trans.set_dmi_allowed(
false);
69 trans.set_response_status(tlm::TLM_OK_RESPONSE);
72 tlm::tlm_sync_enum nb_transport_fw(payload_type& trans, phase_type& phase, sc_core::sc_time& t)
override {
74 sc_core::sc_time delay;
75 fw_peq.notify(trans, phase, delay);
76 return tlm::TLM_ACCEPTED;
79 bool get_direct_mem_ptr(payload_type& trans, tlm::tlm_dmi& dmi_data)
override {
80 trans.set_dmi_allowed(
false);
84 unsigned int transport_dbg(payload_type& trans)
override {
return 0; }
86 void end_of_elaboration()
override { clk_if =
dynamic_cast<sc_core::sc_clock*
>(clk_i.get_interface()); }
92 void clk_delay() { clk_delayed.notify(axi::CLK_DELAY); }
106 static typename CFG::data_t get_cache_data_for_beat(
fsm::fsm_handle* fsm_hndl);
107 std::array<unsigned, 3> outstanding_cnt{0, 0, 0};
108 std::array<fsm_handle*, 3> active_req{
nullptr,
nullptr,
nullptr};
109 std::array<fsm_handle*, 3> active_resp{
nullptr,
nullptr,
nullptr};
110 sc_core::sc_clock* clk_if{
nullptr};
111 sc_core::sc_event clk_delayed, clk_self, r_end_resp_evt, w_end_resp_evt, aw_evt, ar_evt;
112 void nb_fw(payload_type& trans,
const phase_type& phase) {
113 auto t = sc_core::SC_ZERO_TIME;
116 tlm_utils::peq_with_cb_and_phase<ace_lite_initiator> fw_peq{
this, &ace_lite_initiator::nb_fw};
117 std::unordered_map<unsigned, std::deque<fsm_handle*>> rd_resp_by_id, wr_resp_by_id;
118 sc_core::sc_buffer<uint8_t> wdata_vl;
119 void write_ar(tlm::tlm_generic_payload& trans);
120 void write_aw(tlm::tlm_generic_payload& trans);
121 void write_wdata(tlm::tlm_generic_payload& trans,
unsigned beat,
bool last =
false);
128 sc_dt::sc_uint<CFG::ADDRWIDTH> addr = trans.get_address();
129 this->ar_addr.write(addr);
131 this->ar_id->write(sc_dt::sc_uint<CFG::IDWIDTH>(ext->get_id()));
132 this->ar_len->write(sc_dt::sc_uint<8>(ext->get_length()));
133 this->ar_size->write(sc_dt::sc_uint<3>(ext->get_size()));
134 this->ar_burst->write(sc_dt::sc_uint<2>(
axi::to_int(ext->get_burst())));
135 if(ext->is_exclusive())
136 this->ar_lock->write(
true);
137 this->ar_cache->write(sc_dt::sc_uint<4>(ext->get_cache()));
138 this->ar_prot.write(ext->get_prot());
139 this->ar_qos->write(ext->get_qos());
140 this->ar_region->write(ext->get_region());
141 this->ar_domain->write(sc_dt::sc_uint<2>((uint8_t)ext->get_domain()));
142 this->ar_snoop->write(sc_dt::sc_uint<4>((uint8_t)ext->get_snoop()));
143 this->ar_bar->write(sc_dt::sc_uint<2>((uint8_t)ext->get_barrier()));
144 this->ar_user->write(ext->get_user(axi::common::id_type::CTRL));
149 sc_dt::sc_uint<CFG::ADDRWIDTH> addr = trans.get_address();
150 this->aw_addr.write(addr);
152 this->aw_prot.write(ext->get_prot());
154 if(this->aw_id.get_interface())
155 this->aw_id->write(sc_dt::sc_uint<CFG::IDWIDTH>(ext->get_id()));
156 if(ext->is_exclusive())
157 this->aw_lock->write(
true);
158 this->aw_len->write(sc_dt::sc_uint<8>(ext->get_length()));
159 this->aw_size->write(sc_dt::sc_uint<3>(ext->get_size()));
160 this->aw_burst->write(sc_dt::sc_uint<2>(
axi::to_int(ext->get_burst())));
161 this->aw_cache->write(sc_dt::sc_uint<4>(ext->get_cache()));
162 this->aw_qos->write(sc_dt::sc_uint<4>(ext->get_qos()));
163 this->aw_region->write(sc_dt::sc_uint<4>(ext->get_region()));
164 this->aw_user->write(ext->get_user(axi::common::id_type::CTRL));
165 this->aw_domain->write(sc_dt::sc_uint<2>((uint8_t)ext->get_domain()));
166 this->aw_snoop->write(sc_dt::sc_uint<CFG::AWSNOOPWIDTH>((uint8_t)ext->get_snoop()));
167 this->aw_bar->write(sc_dt::sc_uint<2>((uint8_t)ext->get_barrier()));
170 if(ext->is_stash_nid_en()) {
171 this->aw_stashniden->write(
true);
172 this->aw_stashnid->write(sc_dt::sc_uint<11>(ext->get_stash_nid()));
174 if(ext->is_stash_lpid_en()) {
175 this->aw_stashlpiden->write(
true);
176 this->aw_stashlpid->write(sc_dt::sc_uint<5>(ext->get_stash_lpid()));
182 template <
typename CFG>
184 typename CFG::data_t data{0};
185 sc_dt::sc_uint<CFG::BUSWIDTH / 8> strb{0};
188 auto byte_offset = beat * size;
189 auto offset = (trans.get_address() + byte_offset) & (CFG::BUSWIDTH / 8 - 1);
190 auto beptr = trans.get_byte_enable_length() ? trans.get_byte_enable_ptr() + byte_offset :
nullptr;
191 if(offset && (size + offset) > (CFG::BUSWIDTH / 8)) {
193 auto dptr = trans.get_data_ptr();
195 for(
size_t i = offset; i < size; ++i, ++dptr) {
196 auto bit_offs = i * 8;
197 data(bit_offs + 7, bit_offs) = *dptr;
199 strb[i] = *beptr == 0xff;
205 auto beat_start_idx = byte_offset - offset;
206 auto data_len = trans.get_data_length();
207 auto dptr = trans.get_data_ptr() + beat_start_idx;
209 for(
size_t i = 0; i < size && (beat_start_idx + i) < data_len; ++i, ++dptr) {
210 auto bit_offs = i * 8;
211 data(bit_offs + 7, bit_offs) = *dptr;
213 strb[i] = *beptr == 0xff;
220 auto dptr = trans.get_data_ptr() + byte_offset;
222 for(
size_t i = 0; i < size; ++i, ++dptr) {
223 auto bit_offs = (offset + i) * 8;
224 data(bit_offs + 7, bit_offs) = *dptr;
226 strb[offset + i] = *beptr == 0xff;
229 strb[offset + i] =
true;
232 this->w_data.write(data);
233 this->w_strb.write(strb);
235 this->w_id->write(ext->get_id());
236 if(this->w_user.get_interface())
237 this->w_user->write(ext->get_user(axi::common::id_type::DATA));
242 auto beat_count = fsm_hndl->beat_count;
245 auto byte_offset = beat_count * size;
246 auto offset = (fsm_hndl->trans->get_address() + byte_offset) & (CFG::BUSWIDTH / 8 - 1);
247 typename CFG::data_t data{0};
248 if(offset && (size + offset) > (CFG::BUSWIDTH / 8)) {
249 if(beat_count == 0) {
250 auto dptr = fsm_hndl->trans->get_data_ptr();
251 for(
size_t i = offset; i < size; ++i, ++dptr) {
252 auto bit_offs = i * 8;
253 data(bit_offs + 7, bit_offs) = *dptr;
256 auto beat_start_idx = byte_offset - offset;
257 auto data_len = fsm_hndl->trans->get_data_length();
258 auto dptr = fsm_hndl->trans->get_data_ptr() + beat_start_idx;
259 for(
size_t i = offset; i < size && (beat_start_idx + i) < data_len; ++i, ++dptr) {
260 auto bit_offs = i * 8;
261 data(bit_offs + 7, bit_offs) = *dptr;
265 auto dptr = fsm_hndl->trans->get_data_ptr() + byte_offset;
266 for(
size_t i = 0; i < size; ++i, ++dptr) {
267 auto bit_offs = (offset + i) * 8;
268 data(bit_offs + 7, bit_offs) = *dptr;
275 fsm_hndl->fsm->cb[RequestPhaseBeg] = [
this, fsm_hndl]() ->
void {
276 if(fsm_hndl->is_snoop) {
277 SCCTRACE(SCMOD) <<
" for snoop in RequestPhaseBeg ";
279 fsm_hndl->beat_count = 0;
280 outstanding_cnt[fsm_hndl->trans->get_command()]++;
282 auto offset = fsm_hndl->trans->get_address() % (CFG::BUSWIDTH / 8);
283 if(offset + fsm_hndl->trans->get_data_length() > CFG::BUSWIDTH / 8) {
284 SCCFATAL(SCMOD) <<
" transaction " << *fsm_hndl->trans <<
" is not AXI4Lite compliant";
289 fsm_hndl->fsm->cb[BegPartReqE] = [
this, fsm_hndl]() ->
void {
290 sc_assert(fsm_hndl->trans->is_write());
291 if(fsm_hndl->beat_count == 0) {
292 write_aw(*fsm_hndl->trans);
293 aw_evt.notify(sc_core::SC_ZERO_TIME);
295 write_wdata(*fsm_hndl->trans, fsm_hndl->beat_count);
296 active_req[tlm::TLM_WRITE_COMMAND] = fsm_hndl;
299 fsm_hndl->fsm->cb[EndPartReqE] = [
this, fsm_hndl]() ->
void {
300 active_req[tlm::TLM_WRITE_COMMAND] =
nullptr;
301 tlm::tlm_phase phase = axi::END_PARTIAL_REQ;
302 sc_core::sc_time t = (clk_if ? clk_if->period() - axi::CLK_DELAY - 1_ps : sc_core::SC_ZERO_TIME);
303 auto ret = tsckt->nb_transport_bw(*fsm_hndl->trans, phase, t);
304 fsm_hndl->beat_count++;
306 fsm_hndl->fsm->cb[BegReqE] = [
this, fsm_hndl]() ->
void {
307 SCCTRACEALL(SCMOD) <<
"In BegReqE of setup_cb";
308 switch(fsm_hndl->trans->get_command()) {
309 case tlm::TLM_READ_COMMAND:
310 active_req[tlm::TLM_READ_COMMAND] = fsm_hndl;
311 write_ar(*fsm_hndl->trans);
312 ar_evt.notify(sc_core::SC_ZERO_TIME);
314 case tlm::TLM_WRITE_COMMAND:
315 active_req[tlm::TLM_WRITE_COMMAND] = fsm_hndl;
316 if(fsm_hndl->beat_count == 0) {
317 write_aw(*fsm_hndl->trans);
318 aw_evt.notify(sc_core::SC_ZERO_TIME);
321 auto ext = fsm_hndl->trans->get_extension<ace_extension>();
322 if(!axi::is_dataless(ext)) {
323 write_wdata(*fsm_hndl->trans, fsm_hndl->beat_count,
true);
328 fsm_hndl->fsm->cb[EndReqE] = [
this, fsm_hndl]() ->
void {
329 SCCTRACEALL(SCMOD) <<
"In EndReqE of setup_cb";
330 switch(fsm_hndl->trans->get_command()) {
331 case tlm::TLM_READ_COMMAND:
332 rd_resp_by_id[axi::get_axi_id(*fsm_hndl->trans)].push_back(fsm_hndl);
333 active_req[tlm::TLM_READ_COMMAND] =
nullptr;
335 case tlm::TLM_WRITE_COMMAND:
336 wr_resp_by_id[axi::get_axi_id(*fsm_hndl->trans)].push_back(fsm_hndl);
337 active_req[tlm::TLM_WRITE_COMMAND] =
nullptr;
338 fsm_hndl->beat_count++;
340 tlm::tlm_phase phase = tlm::END_REQ;
341 sc_core::sc_time t = (clk_if ? clk_if->period() - axi::CLK_DELAY - 1_ps : sc_core::SC_ZERO_TIME);
342 SCCTRACE(SCMOD) <<
" in EndReq before set_resp";
343 auto ret = tsckt->nb_transport_bw(*fsm_hndl->trans, phase, t);
344 fsm_hndl->trans->set_response_status(tlm::TLM_OK_RESPONSE);
347 fsm_hndl->fsm->cb[BegPartRespE] = [
this, fsm_hndl]() ->
void {
349 assert(fsm_hndl->trans->is_read());
350 tlm::tlm_phase phase = axi::BEGIN_PARTIAL_RESP;
351 sc_core::sc_time t(sc_core::SC_ZERO_TIME);
352 auto ret = tsckt->nb_transport_bw(*fsm_hndl->trans, phase, t);
354 fsm_hndl->fsm->cb[EndPartRespE] = [
this, fsm_hndl]() ->
void {
355 SCCTRACE(SCMOD) <<
"in EndPartRespE of setup_cb ";
356 fsm_hndl->beat_count++;
357 r_end_resp_evt.notify();
359 fsm_hndl->fsm->cb[BegRespE] = [
this, fsm_hndl]() ->
void {
361 tlm::tlm_phase phase = tlm::BEGIN_RESP;
362 sc_core::sc_time t(sc_core::SC_ZERO_TIME);
363 auto ret = tsckt->nb_transport_bw(*fsm_hndl->trans, phase, t);
365 fsm_hndl->fsm->cb[EndRespE] = [
this, fsm_hndl]() ->
void {
366 SCCTRACE(SCMOD) <<
"in EndResp of setup_cb ";
367 if(fsm_hndl->trans->is_read()) {
368 rd_resp_by_id[axi::get_axi_id(*fsm_hndl->trans)].pop_front();
369 r_end_resp_evt.notify();
371 if(fsm_hndl->trans->is_write()) {
372 wr_resp_by_id[axi::get_axi_id(*fsm_hndl->trans)].pop_front();
373 w_end_resp_evt.notify();
378 this->ar_valid.write(
false);
379 wait(sc_core::SC_ZERO_TIME);
382 this->ar_valid.write(
true);
384 wait(this->ar_ready.posedge_event() | clk_delayed);
385 if(this->ar_ready.read())
386 react(axi::fsm::protocol_time_point_e::EndReqE, active_req[tlm::TLM_READ_COMMAND]);
387 }
while(!this->ar_ready.read());
388 wait(clk_i.posedge_event());
389 this->ar_valid.write(
false);
394 this->r_ready.write(
false);
395 wait(sc_core::SC_ZERO_TIME);
397 wait(this->r_valid.posedge_event() | clk_delayed);
398 if(this->r_valid.event() || (!active_resp[tlm::TLM_READ_COMMAND] && this->r_valid.read())) {
399 wait(sc_core::SC_ZERO_TIME);
400 auto id = CFG::IS_LITE ? 0U : this->r_id->read().to_uint();
401 auto data = this->r_data.read();
402 auto resp = this->r_resp.read();
403 auto& q = rd_resp_by_id[id];
405 auto* fsm_hndl = q.front();
406 auto beat_count = fsm_hndl->beat_count;
408 auto byte_offset = beat_count * size;
409 auto offset = (fsm_hndl->trans->get_address() + byte_offset) & (CFG::BUSWIDTH / 8 - 1);
410 if(offset && (size + offset) > (CFG::BUSWIDTH / 8)) {
411 if(beat_count == 0) {
412 auto dptr = fsm_hndl->trans->get_data_ptr();
414 for(
size_t i = offset; i < size; ++i, ++dptr) {
415 auto bit_offs = i * 8;
416 *dptr = data(bit_offs + 7, bit_offs).to_uint();
419 auto beat_start_idx = beat_count * size - offset;
420 auto data_len = fsm_hndl->trans->get_data_length();
421 auto dptr = fsm_hndl->trans->get_data_ptr() + beat_start_idx;
423 for(
size_t i = offset; i < size && (beat_start_idx + i) < data_len; ++i, ++dptr) {
424 auto bit_offs = i * 8;
425 *dptr = data(bit_offs + 7, bit_offs).to_uint();
429 auto dptr = fsm_hndl->trans->get_data_ptr() + beat_count * size;
431 for(
size_t i = 0; i < size; ++i, ++dptr) {
432 auto bit_offs = (offset + i) * 8;
433 *dptr = data(bit_offs + 7, bit_offs).to_uint();
437 fsm_hndl->trans->get_extension(e);
441 if(axi::is_dataless(e)) {
442 SCCTRACE(SCMOD) <<
" r_t() for Make/Clean/Barrier Trans" << *fsm_hndl->trans;
443 react(axi::fsm::protocol_time_point_e::BegRespE, fsm_hndl);
445 auto tp = CFG::IS_LITE || this->r_last->read() ? axi::fsm::protocol_time_point_e::BegRespE
446 : axi::fsm::protocol_time_point_e::BegPartRespE;
451 wait(r_end_resp_evt);
452 this->r_ready->write(
true);
453 wait(clk_i.posedge_event());
454 this->r_ready.write(
false);
460 this->aw_valid.write(
false);
461 wait(sc_core::SC_ZERO_TIME);
464 this->aw_valid.write(
true);
466 wait(this->aw_ready.posedge_event() | clk_delayed);
467 }
while(!this->aw_ready.read());
468 auto* fsm_hndl = active_req[tlm::TLM_WRITE_COMMAND];
470 react(axi::fsm::protocol_time_point_e::EndReqE, fsm_hndl);
471 wait(clk_i.posedge_event());
472 this->aw_valid.write(
false);
477 this->w_valid.write(
false);
478 wait(sc_core::SC_ZERO_TIME);
481 this->w_last->write(
false);
482 wait(wdata_vl.default_event());
483 auto val = wdata_vl.read();
484 this->w_valid.write(val & 0x1);
486 this->w_last->write(val & 0x2);
488 wait(this->w_ready.posedge_event() | clk_delayed);
489 if(this->w_ready.read()) {
491 CFG::IS_LITE || (val & 0x2) ? axi::fsm::protocol_time_point_e::EndReqE : axi::fsm::protocol_time_point_e::EndPartReqE;
492 react(evt, active_req[tlm::TLM_WRITE_COMMAND]);
494 }
while(!this->w_ready.read());
495 wait(clk_i.posedge_event());
496 this->w_valid.write(
false);
501 this->b_ready.write(
false);
502 wait(sc_core::SC_ZERO_TIME);
504 wait(this->b_valid.posedge_event() | clk_delayed);
505 if(this->b_valid.event() || (!active_resp[tlm::TLM_WRITE_COMMAND] && this->b_valid.read())) {
506 SCCTRACEALL(SCMOD) <<
" b_t() received b_valid ";
507 auto id = !CFG::IS_LITE ? this->b_id->read().to_uint() : 0U;
508 auto resp = this->b_resp.read();
509 auto& q = wr_resp_by_id[id];
511 auto* fsm_hndl = q.front();
513 fsm_hndl->trans->get_extension(e);
514 e->
set_resp(axi::into<axi::resp_e>(resp));
515 react(axi::fsm::protocol_time_point_e::BegRespE, fsm_hndl);
517 wait(w_end_resp_evt);
518 this->b_ready.write(
true);
519 wait(clk_i.posedge_event());
520 this->b_ready.write(
false);
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
void set_cresp(uint8_t)
set the coherent response status
void add_to_response_array(response &)
add a read response to the response array
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...
base(size_t transfer_width, bool coherent=false, axi::fsm::protocol_time_point_e wr_start=axi::fsm::RequestPhaseBeg)
the constructor
uint8_t get_size() const
set the AxSIZE value of the transaction
void set_resp(resp_e)
set the response status as POD