17 #ifndef _BUS_AXI_PIN_ACE_LITE_TARGET_H_
18 #define _BUS_AXI_PIN_ACE_LITE_TARGET_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 <util/ities.h>
33 using namespace axi::fsm;
35 template <
typename CFG>
39 public b_ace_lite<CFG, typename CFG::slave_types>,
46 using payload_type = axi::axi_protocol_types::tlm_payload_type;
47 using phase_type = axi::axi_protocol_types::tlm_phase_type;
49 sc_core::sc_in<bool> clk_i{
"clk_i"};
54 : sc_core::sc_module(nm)
56 ,
base(CFG::BUSWIDTH,
false) {
57 instance_name = name();
60 sensitive << clk_i.pos();
70 tlm::tlm_sync_enum nb_transport_bw(payload_type& trans, phase_type& phase, sc_core::sc_time& t)
override;
72 void invalidate_direct_mem_ptr(sc_dt::uint64 start_range, sc_dt::uint64 end_range)
override;
74 void end_of_elaboration()
override { clk_if =
dynamic_cast<sc_core::sc_clock*
>(clk_i.get_interface()); }
82 if(sc_core::sc_delta_count_at_current_time() < 5) {
83 clk_self.notify(sc_core::SC_ZERO_TIME);
84 next_trigger(clk_self);
86 clk_delayed.notify(sc_core::SC_ZERO_TIME );
88 clk_delayed.notify(axi::CLK_DELAY);
96 static typename CFG::data_t get_read_data_for_beat(
fsm::fsm_handle* fsm_hndl);
117 std::deque<axi::fsm::fsm_handle*> snp_resp_queue;
119 sc_core::sc_clock* clk_if{
nullptr};
120 sc_core::sc_event clk_delayed, clk_self, ar_end_req_evt, wdata_end_req_evt;
121 std::array<fsm_handle*, 3> active_req_beat{
nullptr,
nullptr,
nullptr};
122 std::array<fsm_handle*, 3> active_req{
nullptr,
nullptr,
nullptr};
123 std::array<fsm_handle*, 3> active_resp_beat{
nullptr,
nullptr,
nullptr};
131 template <
typename CFG>
133 auto ret = tlm::TLM_ACCEPTED;
134 SCCTRACE(SCMOD) <<
"nb_transport_bw with " << phase <<
" with delay= " << t <<
" of trans " << trans;
135 if(phase == END_PARTIAL_REQ || phase == tlm::END_REQ) {
136 schedule(phase == tlm::END_REQ ? EndReqE : EndPartReqE, &trans, t,
false);
137 }
else if(phase == axi::BEGIN_PARTIAL_RESP || phase == tlm::BEGIN_RESP) {
138 schedule(phase == tlm::BEGIN_RESP ? BegRespE : BegPartRespE, &trans, t,
false);
140 SCCFATAL(SCMOD) <<
"Illegal phase received: " << phase;
144 template <
typename CFG>
151 auto byte_offset = beat_count * size;
152 auto offset = (fsm_hndl->
trans->get_address() + byte_offset) & (CFG::BUSWIDTH / 8 - 1);
153 typename CFG::data_t data{0};
154 if(offset && (size + offset) > (CFG::BUSWIDTH / 8)) {
155 if(beat_count == 0) {
156 auto dptr = fsm_hndl->
trans->get_data_ptr();
157 for(
size_t i = offset; i < size; ++i, ++dptr) {
158 auto bit_offs = i * 8;
159 data(bit_offs + 7, bit_offs) = *dptr;
162 auto beat_start_idx = byte_offset - offset;
163 auto data_len = fsm_hndl->
trans->get_data_length();
164 auto dptr = fsm_hndl->
trans->get_data_ptr() + beat_start_idx;
165 for(
size_t i = offset; i < size && (beat_start_idx + i) < data_len; ++i, ++dptr) {
166 auto bit_offs = i * 8;
167 data(bit_offs + 7, bit_offs) = *dptr;
171 auto dptr = fsm_hndl->
trans->get_data_ptr() + byte_offset;
172 for(
size_t i = 0; i < size; ++i, ++dptr) {
173 auto bit_offs = (offset + i) * 8;
174 data(bit_offs + 7, bit_offs) = *dptr;
181 fsm_hndl->
fsm->cb[RequestPhaseBeg] = [
this, fsm_hndl]() ->
void { fsm_hndl->
beat_count = 0; };
182 fsm_hndl->
fsm->cb[BegPartReqE] = [
this, fsm_hndl]() ->
void {
183 sc_assert(fsm_hndl->
trans->get_command() == tlm::TLM_WRITE_COMMAND);
184 tlm::tlm_phase phase = axi::BEGIN_PARTIAL_REQ;
185 sc_core::sc_time t(sc_core::SC_ZERO_TIME);
186 auto ret = isckt->nb_transport_fw(*fsm_hndl->
trans, phase, t);
187 if(ret == tlm::TLM_UPDATED) {
188 schedule(EndPartReqE, fsm_hndl->
trans, t,
true);
191 fsm_hndl->
fsm->cb[EndPartReqE] = [
this, fsm_hndl]() ->
void {
192 wdata_end_req_evt.notify();
193 active_req_beat[tlm::TLM_WRITE_COMMAND] =
nullptr;
196 fsm_hndl->
fsm->cb[BegReqE] = [
this, fsm_hndl]() ->
void {
197 tlm::tlm_phase phase = tlm::BEGIN_REQ;
198 sc_core::sc_time t(sc_core::SC_ZERO_TIME);
199 auto ret = isckt->nb_transport_fw(*fsm_hndl->
trans, phase, t);
200 if(ret == tlm::TLM_UPDATED) {
201 schedule(EndReqE, fsm_hndl->
trans, t,
true);
204 fsm_hndl->
fsm->cb[EndReqE] = [
this, fsm_hndl]() ->
void {
205 switch(fsm_hndl->
trans->get_command()) {
206 case tlm::TLM_READ_COMMAND:
207 ar_end_req_evt.notify();
208 active_req_beat[tlm::TLM_READ_COMMAND] =
nullptr;
210 case tlm::TLM_WRITE_COMMAND:
211 wdata_end_req_evt.notify();
212 active_req_beat[tlm::TLM_WRITE_COMMAND] =
nullptr;
219 fsm_hndl->
fsm->cb[BegPartRespE] = [
this, fsm_hndl]() ->
void {
220 assert(fsm_hndl->
trans->is_read());
221 active_resp_beat[tlm::TLM_READ_COMMAND] = fsm_hndl;
222 rresp_vl.notify({1, fsm_hndl});
224 fsm_hndl->
fsm->cb[EndPartRespE] = [
this, fsm_hndl]() ->
void {
226 assert(fsm_hndl->
trans->is_read());
227 tlm::tlm_phase phase = axi::END_PARTIAL_RESP;
228 sc_core::sc_time t(sc_core::SC_ZERO_TIME);
229 auto ret = isckt->nb_transport_fw(*fsm_hndl->
trans, phase, t);
230 active_resp_beat[tlm::TLM_READ_COMMAND] =
nullptr;
233 fsm_hndl->
fsm->cb[BegRespE] = [
this, fsm_hndl]() ->
void {
234 SCCTRACE(SCMOD) <<
"processing event BegRespE for trans " << *fsm_hndl->
trans;
236 active_resp_beat[fsm_hndl->
trans->get_command()] = fsm_hndl;
237 switch(fsm_hndl->
trans->get_command()) {
238 case tlm::TLM_READ_COMMAND:
239 rresp_vl.notify({3, fsm_hndl});
241 case tlm::TLM_WRITE_COMMAND:
242 wresp_vl.notify({3, fsm_hndl});
248 fsm_hndl->
fsm->cb[EndRespE] = [
this, fsm_hndl]() ->
void {
250 tlm::tlm_phase phase = tlm::END_RESP;
251 sc_core::sc_time t(sc_core::SC_ZERO_TIME);
252 auto ret = isckt->nb_transport_fw(*fsm_hndl->
trans, phase, t);
253 SCCTRACE(SCMOD) <<
"EndResp of setup_cb with coherent = " << coherent;
254 fsm_hndl->
finish.notify();
255 active_resp_beat[fsm_hndl->
trans->get_command()] =
nullptr;
260 this->ar_ready.write(
false);
261 wait(sc_core::SC_ZERO_TIME);
265 auto data_len = (1 << arsize) * (arlen + 1);
267 wait(this->ar_valid.posedge_event() | clk_delayed);
268 if(this->ar_valid.read()) {
269 SCCTRACE(SCMOD) <<
"ARVALID detected for 0x" << std::hex << this->ar_addr.read();
270 arid = this->ar_id->read().to_uint();
271 arlen = this->ar_len->read().to_uint();
272 arsize = this->ar_size->read().to_uint();
273 data_len = (1 << arsize) * (arlen + 1);
275 gp->set_address(this->ar_addr.read());
276 gp->set_command(tlm::TLM_READ_COMMAND);
277 gp->set_streaming_width(data_len);
279 gp->get_extension(ext);
282 if(this->ar_lock->read())
285 ext->
set_burst(axi::into<axi::burst_e>(this->ar_burst->read()));
287 ext->
set_prot(this->ar_prot->read());
288 ext->
set_qos(this->ar_qos->read());
290 ext->
set_domain(axi::into<axi::domain_e>(this->ar_domain->read()));
291 ext->
set_snoop(axi::into<axi::snoop_e>(this->ar_snoop->read()));
292 ext->
set_barrier(axi::into<axi::bar_e>(this->ar_bar->read()));
294 active_req_beat[tlm::TLM_READ_COMMAND] = find_or_create(gp);
295 react(axi::fsm::protocol_time_point_e::BegReqE, active_req_beat[tlm::TLM_READ_COMMAND]);
296 wait(ar_end_req_evt);
297 this->ar_ready.write(
true);
298 wait(clk_i.posedge_event());
299 this->ar_ready.write(
false);
305 this->r_valid.write(
false);
306 wait(sc_core::SC_ZERO_TIME);
311 std::tie(val, fsm_hndl) = rresp_vl.get();
312 SCCTRACE(SCMOD) << __FUNCTION__ <<
" val = " << (uint16_t)val <<
" beat count = " << fsm_hndl->
beat_count;
313 SCCTRACE(SCMOD) << __FUNCTION__ <<
" got read response beat of trans " << *fsm_hndl->
trans;
315 this->r_data.write(get_read_data_for_beat(fsm_hndl));
317 this->r_valid.write(val & 0x1);
319 this->r_id->write(ext->
get_id());
320 this->r_last->write(val & 0x2);
323 wait(this->r_ready.posedge_event() | clk_delayed);
324 if(this->r_ready.read()) {
326 CFG::IS_LITE || (val & 0x2) ? axi::fsm::protocol_time_point_e::EndRespE : axi::fsm::protocol_time_point_e::EndPartRespE;
327 react(evt, active_resp_beat[tlm::TLM_READ_COMMAND]);
329 }
while(!this->r_ready.read());
330 SCCTRACE(SCMOD) <<
"finished read response beat of trans [" << fsm_hndl->
trans <<
"]";
331 wait(clk_i.posedge_event());
332 this->r_valid.write(
false);
334 this->r_last->write(
false);
339 this->aw_ready.write(
false);
340 wait(sc_core::SC_ZERO_TIME);
341 const auto awsize =
util::ilog2(CFG::BUSWIDTH / 8);
343 wait(this->aw_valid.posedge_event() | clk_delayed);
344 if(this->aw_valid.event() || (!active_req_beat[tlm::TLM_IGNORE_COMMAND] && this->aw_valid.read())) {
345 SCCTRACE(SCMOD) <<
"AWVALID detected for 0x" << std::hex << this->aw_addr.read();
347 aw_data awd = {CFG::IS_LITE ? 0U : this->aw_id->read().to_uint(),
348 this->aw_addr.read().to_uint64(),
349 this->aw_prot.read().to_uint(),
350 this->aw_size->read().to_uint(),
351 this->aw_cache->read().to_uint(),
352 this->aw_burst->read().to_uint(),
353 this->aw_qos->read().to_uint(),
354 this->aw_region->read().to_uint(),
355 this->aw_len->read().to_uint(),
356 this->aw_domain->read().to_uint(),
357 this->aw_snoop->read().to_uint(),
358 this->aw_bar->read().to_uint(),
359 this->aw_unique->read(),
360 this->aw_stashniden->read() ? 0U : this->aw_stashnid->read().to_uint(),
361 this->aw_stashlpiden->read()? 0U : this->aw_stashlpid->read().to_uint(),
362 this->aw_lock->read() ? true :
false,
366 this->aw_ready.write(
true);
367 wait(clk_i.posedge_event());
368 this->aw_ready.write(
false);
374 this->w_ready.write(
false);
375 wait(sc_core::SC_ZERO_TIME);
377 wait(this->w_valid.posedge_event() | clk_delayed);
378 this->w_ready.write(
false);
379 if(this->w_valid.event() || (!active_req_beat[tlm::TLM_WRITE_COMMAND] && this->w_valid.read())) {
380 if(!active_req[tlm::TLM_WRITE_COMMAND]) {
381 if(!aw_que.has_next())
382 wait(aw_que.event());
383 auto awd = aw_que.get();
384 auto data_len = (1 << awd.size) * (awd.len + 1);
386 gp->set_address(awd.addr);
387 gp->set_command(tlm::TLM_WRITE_COMMAND);
389 gp->get_extension(ext);
393 ext->
set_burst(axi::into<axi::burst_e>(awd.burst));
398 ext->
set_snoop(axi::into<axi::snoop_e>(awd.snoop));
405 ext->
set_user(axi::common::id_type::CTRL, awd.user);
406 active_req_beat[tlm::TLM_WRITE_COMMAND] = find_or_create(gp);
407 active_req[tlm::TLM_WRITE_COMMAND] = active_req_beat[tlm::TLM_WRITE_COMMAND];
409 auto* fsm_hndl = active_req[tlm::TLM_WRITE_COMMAND];
410 SCCTRACE(SCMOD) <<
"WDATA detected for 0x" << std::hex << this->ar_addr.read();
411 auto& gp = fsm_hndl->
trans;
412 auto data = this->w_data.read();
413 auto strb = this->w_strb.read();
414 auto last = this->w_last->read();
417 auto byte_offset = beat_count * size;
418 auto offset = (fsm_hndl->
trans->get_address() + byte_offset) & (CFG::BUSWIDTH / 8 - 1);
419 if(offset && (size + offset) > (CFG::BUSWIDTH / 8)) {
420 if(beat_count == 0) {
421 auto dptr = fsm_hndl->
trans->get_data_ptr();
422 auto beptr = fsm_hndl->
trans->get_byte_enable_ptr();
423 for(
size_t i = offset; i < size; ++i, ++dptr, ++beptr) {
424 auto bit_offs = i * 8;
425 *dptr = data(bit_offs + 7, bit_offs).to_uint();
426 *beptr = strb[i] ? 0xff : 0;
429 auto beat_start_idx = byte_offset - offset;
430 auto data_len = fsm_hndl->
trans->get_data_length();
431 auto dptr = fsm_hndl->
trans->get_data_ptr() + beat_start_idx;
432 auto beptr = fsm_hndl->
trans->get_byte_enable_ptr() + beat_start_idx;
433 for(
size_t i = 0; i < size && (beat_start_idx + i) < data_len; ++i, ++dptr, ++beptr) {
434 auto bit_offs = i * 8;
435 *dptr = data(bit_offs + 7, bit_offs).to_uint();
436 *beptr = strb[i] ? 0xff : 0;
440 auto dptr = fsm_hndl->
trans->get_data_ptr() + byte_offset;
441 auto beptr = fsm_hndl->
trans->get_byte_enable_ptr() + byte_offset;
442 for(
size_t i = 0; i < size; ++i, ++dptr, ++beptr) {
443 auto bit_offs = (offset + i) * 8;
444 *dptr = data(bit_offs + 7, bit_offs).to_uint();
445 *beptr = strb[offset + i] ? 0xff : 0;
449 auto strobe = strb.to_uint();
451 auto act_data_len = CFG::IS_LITE ? util::bit_count(strobe) : (beat_count + 1) * size;
457 gp->set_data_length(act_data_len);
458 gp->set_byte_enable_length(act_data_len);
459 gp->set_streaming_width(act_data_len);
461 auto tp = this->w_last->read() ? axi::fsm::protocol_time_point_e::BegReqE : axi::fsm::protocol_time_point_e::BegPartReqE;
464 wait(wdata_end_req_evt);
465 this->w_ready.write(
true);
466 wait(clk_i.posedge_event());
467 this->w_ready.write(
false);
469 active_req[tlm::TLM_WRITE_COMMAND] =
nullptr;
475 this->b_valid.write(
false);
476 wait(sc_core::SC_ZERO_TIME);
480 std::tie(val, fsm_hndl) = wresp_vl.get();
481 SCCTRACE(SCMOD) <<
"got write response of trans " << *fsm_hndl->
trans;
484 this->b_valid.write(
true);
486 this->b_id->write(ext->
get_id());
487 SCCTRACE(SCMOD) <<
"got write response";
489 wait(this->b_ready.posedge_event() | clk_delayed);
490 if(this->b_ready.read()) {
491 react(axi::fsm::protocol_time_point_e::EndRespE, active_resp_beat[tlm::TLM_WRITE_COMMAND]);
493 }
while(!this->b_ready.read());
494 SCCTRACE(SCMOD) <<
"finished write response of trans [" << fsm_hndl->
trans <<
"]";
495 wait(clk_i.posedge_event());
496 this->b_valid.write(
false);
payload_type * allocate()
get a plain tlm_payload_type without extensions
static tlm_mm & get()
accessor function of the singleton
TLM2.0 components modeling AHB.
tlm::tlm_bw_transport_if< TYPES > axi_bw_transport_if
alias declaration for the backward interface:
constexpr ULT to_int(E t)
unsigned get_burst_size(const request &r)
CONSTEXPR unsigned ilog2(uint32_t val)
uint8_t get_cresp() const
get the coherent response status
void set_barrier(bar_e)
set the AxBAR value
void set_domain(domain_e)
set the AxDOMAIN value
void set_snoop(snoop_e)
set the AxSNOOP value
void set_exclusive(bool=true)
get the exclusive bit of AxLOCK (AxLOCK[0])
void set_id(unsigned int value)
void set_user(id_type chnl, unsigned int value)
unsigned int get_id() const
base class of all AXITLM based adapters and interfaces.
tlm::scc::tlm_gp_shared_ptr trans
pointer to the associated AXITLM payload
sc_core::sc_event finish
event indicating the end of the transaction
size_t beat_count
beat count of this transaction
AxiProtocolFsm *const fsm
pointer to the FSM
void set_length(uint8_t)
set the AxLEN value of the transaction, the value denotes the burst length - 1
void set_qos(uint8_t)
set the AxQOS (quality of service) value
void set_cache(uint8_t)
set the AxCACHE value as POD, only value from 0..15 are allowed
void set_region(uint8_t)
set the AxREGION value
void set_stash_lpid(uint8_t)
set the raw AWSTASHLPID value
void set_burst(burst_e)
set the AxBURST value,
void set_size(uint8_t)
get the AxSIZE value of the transaction, the length is 2^size. It needs to be less than 10 (512 bit w...
void set_prot(uint8_t)
set the AxPROT value as POD, only values from 0...7 are allowed
void set_stash_nid(uint8_t)
set the raw AWSTASHNID value
resp_e get_resp() const
get the response status as POD