17 #ifndef SC_INCLUDE_DYNAMIC_PROCESSES
18 #define SC_INCLUDE_DYNAMIC_PROCESSES
22 #include "protocol_fsm.h"
23 #include <scc/report.h>
25 #include <tlm/scc/tlm_id.h>
26 #include <tlm/scc/tlm_mm.h>
27 #include <scc/utilities.h>
29 using namespace sc_core;
34 fsm_handle::fsm_handle():fsm{new AxiProtocolFsm()} {
38 fsm_handle::~fsm_handle(){
43 base::base(
size_t transfer_width,
bool coherent, protocol_time_point_e wr_start)
44 : transfer_width_in_bytes(transfer_width / 8)
46 , coherent(coherent) {
47 assert(wr_start == RequestPhaseBeg || wr_start == WValidE);
50 sc_core::sc_spawn_options opts;
51 opts.dont_initialize();
53 opts.set_sensitivity(&fsm_event_queue.
event());
54 sc_core::sc_spawn(sc_bind(&
base::process_fsm_event,
this), sc_core::sc_gen_unique_name(
"fsm_event_method"), &opts);
55 fsm_clk_queue.set_avail_cb([
this]() {
56 if(fsm_clk_queue_hndl.valid())
57 fsm_clk_queue_hndl.enable();
59 fsm_clk_queue.set_empty_cb([
this]() {
60 if(fsm_clk_queue_hndl.valid())
61 fsm_clk_queue_hndl.disable();
66 auto it = active_fsm.find(gp);
67 if(!gp || it == active_fsm.end()) {
69 SCCTRACE(instance_name) <<
"creating fsm for trans " << *gp;
71 SCCTRACE(instance_name) <<
"creating fsm for new transaction";
73 if(idle_fsm.empty()) {
76 idle_fsm.push_back(fsm_hndl);
77 allocated_fsm.emplace_back(fsm_hndl);
79 auto fsm_hndl = idle_fsm.front();
88 active_fsm.insert(std::make_pair(fsm_hndl->trans.get(), fsm_hndl));
89 fsm_hndl->start = sc_time_stamp();
92 it->second->start = sc_time_stamp();
98 while(
auto e = fsm_event_queue.
get_next()) {
100 if(std::get<2>(entry))
101 schedule(std::get<0>(entry), std::get<1>(entry), 0);
103 react(std::get<0>(entry), std::get<1>(entry));
108 if(!fsm_clk_queue_hndl.valid())
109 fsm_clk_queue_hndl = sc_process_handle(sc_get_current_process_handle());
110 if(fsm_clk_queue.avail())
111 while(fsm_clk_queue.avail()) {
112 auto entry = fsm_clk_queue.front();
113 if(std::get<2>(entry) == 0) {
114 SCCTRACE(instance_name) <<
"processing event " << evt2str(std::get<0>(entry)) <<
" of trans "
115 << *std::get<1>(entry);
116 react(std::get<0>(entry), std::get<1>(entry));
118 std::get<2>(entry) -= 1;
119 fsm_clk_queue.push_back(entry);
121 fsm_clk_queue.pop_front();
125 fsm_clk_queue_hndl.disable();
129 SCCTRACE(instance_name)<<
"in react() base has coherent =" << coherent <<
" with event " << evt2str(event);
130 fsm_hndl->state=event;
133 fsm_hndl->
fsm->process_event(
WReq());
136 case RequestPhaseBeg:
165 SCCTRACE(instance_name)<<
"in EndResp of base() with coherent =" << coherent;
166 if(!coherent || fsm_hndl->
is_snoop) {
167 SCCTRACE(instance_name) <<
"freeing fsm for trans " << *fsm_hndl->
trans;
169 active_fsm.erase(fsm_hndl->
trans.
get());
170 fsm_hndl->
trans =
nullptr;
171 idle_fsm.push_back(fsm_hndl);
174 fsm_hndl->
fsm->process_event(EndRespNoAck());
178 SCCTRACE(instance_name) <<
"freeing fsm for trans " << *fsm_hndl->
trans;
179 fsm_hndl->
fsm->process_event(AckRecv());
180 active_fsm.erase(fsm_hndl->
trans.
get());
181 fsm_hndl->
trans =
nullptr;
182 idle_fsm.push_back(fsm_hndl);
186 SCCFATAL(instance_name) <<
"No valid protocol time point";
191 SCCTRACE(instance_name) <<
"base::nb_fw " << phase <<
" with delay = " << t <<
" of trans " << trans;
192 if(phase == BEGIN_PARTIAL_REQ || phase == BEGIN_REQ) {
194 if(!trans.is_read()) {
195 protocol_time_point_e evt = axi::fsm::RequestPhaseBeg;
196 if(fsm_hndl->
beat_count == 0 && wr_start != RequestPhaseBeg)
199 evt = phase == BEGIN_PARTIAL_REQ ? BegPartReqE : BegReqE;
200 if(t == SC_ZERO_TIME) {
206 if(t == SC_ZERO_TIME) {
207 react(BegReqE, &trans);
211 }
else if(phase == END_PARTIAL_RESP || phase == END_RESP) {
212 if(t == SC_ZERO_TIME) {
213 react(phase == END_RESP ? EndRespE : EndPartRespE, &trans);
215 schedule(phase == END_RESP ? EndRespE : EndPartRespE, &trans, t);
216 }
else if(phase == END_REQ) {
217 if(t == SC_ZERO_TIME) {
218 react(EndReqE, &trans);
221 }
else if(phase == BEGIN_PARTIAL_RESP || phase == BEGIN_RESP) {
222 if(t == SC_ZERO_TIME) {
223 react(phase == BEGIN_RESP ? BegRespE : BegPartRespE, &trans);
225 schedule(phase == BEGIN_RESP ? BegRespE : BegPartRespE, &trans, t);
226 }
else if(phase == axi::ACK) {
227 if(t == SC_ZERO_TIME) {
236 SCCTRACE(instance_name) <<
"base::nb_bw " << phase <<
" of trans " << trans;
237 if(phase == END_PARTIAL_REQ || phase == END_REQ) {
238 if(t == SC_ZERO_TIME) {
239 react(phase == END_REQ ? EndReqE : EndPartReqE, &trans);
241 schedule(phase == END_REQ ? EndReqE : EndPartReqE, &trans, t);
242 }
else if(phase == BEGIN_PARTIAL_RESP || phase == BEGIN_RESP) {
243 if(t == SC_ZERO_TIME) {
244 react(phase == BEGIN_RESP ? BegRespE : BegPartRespE, &trans);
246 schedule(phase == BEGIN_RESP ? BegRespE : BegPartRespE, &trans, t);
247 }
else if(phase == BEGIN_REQ) {
250 if(t == SC_ZERO_TIME) {
251 react(BegReqE, &trans);
254 }
else if(phase == END_PARTIAL_RESP || phase == END_RESP) {
255 if(t == SC_ZERO_TIME) {
256 react(phase == END_RESP ? EndRespE : EndPartRespE, &trans);
258 schedule(phase == END_RESP ? EndRespE : EndPartRespE, &trans, t);
tlm::tlm_generic_payload * get() const noexcept
Return the stored pointer.
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.
bool is_burst(const axi::axi_protocol_types::tlm_payload_type &trans)
void react(axi::fsm::protocol_time_point_e event, tlm::scc::tlm_gp_shared_ptr &trans)
triggers the FSM with event and given transaction
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...
virtual void setup_callbacks(axi::fsm::fsm_handle *)=0
this function is called to add the callbacks to the fsm handle during creation. Needs to be implement...
void schedule(axi::fsm::protocol_time_point_e e, tlm::scc::tlm_gp_shared_ptr &gp, unsigned cycles)
processes the fsm_sched_queue and propagates events to fsm_clk_queue. Should be registered as falling...
void process_fsm_clk_queue()
processes the fsm_clk_queue and triggers the FSM accordingly. Should be registered as rising-edge clo...
tlm::tlm_sync_enum nb_bw(payload_type &trans, phase_type const &phase, sc_core::sc_time &t)
triggers the FSM based on TLM phases in the backward path. Should be called from np_transport_bw of t...
axi::fsm::fsm_handle * find_or_create(payload_type *gp=nullptr, bool ace=false)
retrieve the FSM handle based on the transaction passed. If non exist one will be created
void process_fsm_event()
processes the fsm_event_queue and triggers FSM aligned
axi::axi_protocol_types::tlm_payload_type payload_type
aliases used in the class
virtual axi::fsm::fsm_handle * create_fsm_handle()=0
function to create a fsm_handle. Needs to be implemented by the derived class
tlm::scc::tlm_gp_shared_ptr trans
pointer to the associated AXITLM payload
size_t beat_count
beat count of this transaction
AxiProtocolFsm *const fsm
pointer to the FSM
bool is_snoop
indicator if this is a snoop access
boost::optional< TYPE > get_next()
non-blocking get
sc_core::sc_event & event()
get the available event