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