16 #ifndef SC_INCLUDE_DYNAMIC_PROCESSES
17 #define SC_INCLUDE_DYNAMIC_PROCESSES
19 #include <atp/timing_params.h>
20 #include <axi/axi_tlm.h>
21 #include <axi/pe/axi_initiator.h>
22 #include <scc/report.h>
23 #include <tlm/scc/tlm_gp_shared.h>
25 using namespace sc_core;
32 uint8_t log2n(uint8_t siz) {
return ((siz > 1) ? 1 + log2n(siz >> 1) : 0); }
36 SC_HAS_PROCESS(axi_initiator_b);
38 axi_initiator_b::axi_initiator_b(sc_core::sc_module_name nm,
40 size_t transfer_width, flavor_e flavor)
43 , transfer_width_in_bytes(transfer_width / 8)
45 add_attribute(data_interleaving);
53 add_attribute(enable_id_serializing);
55 SC_METHOD(clk_counter);
56 sensitive << clk_i.pos();
58 if(flavor == flavor_e::AXI)
59 for(
auto i = 0u; i < 16; i++)
60 sc_core::sc_spawn([
this]() { snoop_thread(); });
63 axi_initiator_b::~axi_initiator_b() {
64 for(
auto& e : tx_state_by_tx)
68 void axi_initiator_b::end_of_elaboration() {
69 clk_if =
dynamic_cast<sc_core::sc_clock*
>(clk_i.get_interface());
70 for(
auto i = 0U; i < outstanding_snoops.value; ++i) {
71 sc_spawn(sc_bind(&axi_initiator_b::snoop_thread,
this));
75 void axi_initiator_b::b_snoop(payload_type& trans, sc_core::sc_time& t) {
76 if(bw_o.get_interface()) {
77 auto latency = bw_o->transport(trans);
78 if(latency < std::numeric_limits<unsigned>::max())
79 t += latency * clk_period;
83 tlm::tlm_sync_enum axi_initiator_b::nb_transport_bw(payload_type& trans, phase_type& phase, sc_core::sc_time& t) {
84 SCCTRACE(SCMOD) << __FUNCTION__ <<
" received with phase " << phase <<
" with delay = " << t <<
" with trans " << trans;
85 if(phase == tlm::BEGIN_REQ) {
86 snp_peq.notify(trans, t);
87 }
else if(phase == END_PARTIAL_RESP || phase == tlm::END_RESP) {
88 auto it = snp_state_by_id.find(&trans);
89 sc_assert(it != snp_state_by_id.end());
90 it->second->peq.notify(std::make_tuple(&trans, phase), t);
92 auto it = tx_state_by_tx.find(&trans);
93 sc_assert(it != tx_state_by_tx.end());
94 auto txs = it->second;
95 txs->peq.notify(std::make_tuple(&trans, phase), t);
97 return tlm::TLM_ACCEPTED;
100 void axi_initiator_b::invalidate_direct_mem_ptr(sc_dt::uint64 start_range, sc_dt::uint64 end_range) {}
102 tlm::tlm_phase axi_initiator_b::send(payload_type& trans, axi_initiator_b::tx_state* txs, tlm::tlm_phase phase) {
103 sc_core::sc_time delay;
104 SCCTRACE(SCMOD) <<
"Send " << phase <<
" of " << trans;
105 tlm::tlm_sync_enum ret = socket_fw->nb_transport_fw(trans, phase, delay);
106 if(ret == tlm::TLM_UPDATED) {
108 SCCTRACE(SCMOD) <<
"Received " << phase <<
" for " << trans;
111 auto waiting = txs->peq.has_next();
112 auto entry = txs->peq.get();
114 SCCFATAL(SCMOD) <<
"there is a waiting " << std::get<0>(entry) <<
" with phase " << std::get<1>(entry);
115 sc_assert(!txs->peq.has_next());
116 sc_assert(std::get<0>(entry) == &trans);
117 SCCTRACE(SCMOD) <<
"in send() Received " << std::get<1>(entry) <<
" for " << trans;
118 return std::get<1>(entry);
122 void axi_initiator_b::transport(payload_type& trans,
bool blocking) {
123 auto axi_id = get_axi_id(trans);
124 if(flavor == flavor_e::AXI) {
127 sc_assert(
ace &&
"No valid extension found in transaction");
131 trans.set_extension(
axi4);
135 sc_assert(trans.get_extension<
axi::ace_extension>() &&
"No ACE extension found in transaction");
137 SCCTRACE(SCMOD) <<
"got transport req for " << trans;
140 socket_fw->b_transport(trans, t);
142 auto it = tx_state_by_tx.find(&trans);
143 if(it == tx_state_by_tx.end()) {
145 std::tie(it, success) = tx_state_by_tx.insert(std::make_pair(&trans,
new tx_state()));
147 auto& txs = it->second;
148 auto timing_e = trans.set_auto_extension<atp::timing_params>(
nullptr);
150 if(enable_id_serializing.value) {
151 if(!id_mtx[axi_id]) {
154 id_mtx[axi_id]->wait();
156 txs->active_tx = &trans;
157 auto burst_length = 0;
159 burst_length = is_dataless(e) ? 1 : e->get_length() + 1;
161 burst_length = e->get_length() + 1;
163 burst_length = e->get_length() + 1;
165 SCCTRACE(SCMOD) <<
"start transport " << trans;
166 tlm::tlm_phase next_phase{tlm::UNINITIALIZED_PHASE};
167 if(!trans.is_read()) {
168 if(!data_interleaving
172 for(
unsigned i = 1; i < (timing_e ? timing_e->awtv : awtv.value); ++i) {
173 wait(clk_i.posedge_event());
175 SCCTRACE(SCMOD) <<
"starting " << burst_length <<
" write beats of " << trans;
176 for(
unsigned i = 0; i < burst_length - 1; ++i) {
177 if(protocol_cb[axi::fsm::BegPartReqE])
178 protocol_cb[axi::fsm::BegPartReqE](trans,
false);
179 auto res = send(trans, txs, axi::BEGIN_PARTIAL_REQ);
180 if(axi::END_PARTIAL_REQ != res)
181 SCCFATAL(SCMOD) <<
"target responded with " << res <<
" for the " << i <<
"th beat of "
182 << burst_length <<
" beats in transaction " << trans;
183 for(
unsigned i = 0; i < (timing_e ? timing_e->wbv : wbv.value); ++i)
184 wait(clk_i.posedge_event());
185 if(protocol_cb[axi::fsm::EndPartReqE])
186 protocol_cb[axi::fsm::EndPartReqE](trans,
false);
188 auto res = send(trans, txs, tlm::BEGIN_REQ);
189 if(res == axi::BEGIN_PARTIAL_RESP || res == tlm::BEGIN_RESP)
191 else if(res != tlm::END_REQ)
192 SCCERR(SCMOD) <<
"target did not repsond with END_REQ to a BEGIN_REQ";
193 wait(clk_i.posedge_event());
195 SCCTRACE(SCMOD) <<
"starting " << burst_length <<
" write beats of " << trans;
196 for(
unsigned i = 0; i < burst_length - 1; ++i) {
200 for(
unsigned i = 1; i < (timing_e ? timing_e->awtv : awtv.value); ++i)
201 wait(clk_i.posedge_event());
202 auto res = send(trans, txs, axi::BEGIN_PARTIAL_REQ);
203 sc_assert(axi::END_PARTIAL_REQ == res);
204 for(
unsigned i = 1; i < (timing_e ? timing_e->wbv : wbv.value); ++i)
205 wait(clk_i.posedge_event());
208 if(protocol_cb[axi::fsm::BegReqE])
209 protocol_cb[axi::fsm::BegReqE](trans,
false);
210 auto res = send(trans, txs, tlm::BEGIN_REQ);
211 if(res == axi::BEGIN_PARTIAL_RESP || res == tlm::BEGIN_RESP)
213 else if(res != tlm::END_REQ)
214 SCCERR(SCMOD) <<
"target did not repsond with END_REQ to a BEGIN_REQ";
215 wait(clk_i.posedge_event());
216 if(protocol_cb[axi::fsm::EndReqE])
217 protocol_cb[axi::fsm::EndReqE](trans,
false);
222 for(
unsigned i = 1; i < (timing_e ? timing_e->artv : artv.value); ++i)
223 wait(clk_i.posedge_event());
224 SCCTRACE(SCMOD) <<
"starting address phase of " << trans;
225 if(protocol_cb[axi::fsm::BegPartReqE])
226 protocol_cb[axi::fsm::BegPartReqE](trans,
false);
227 auto res = send(trans, txs, tlm::BEGIN_REQ);
228 if(res == axi::BEGIN_PARTIAL_RESP || res == tlm::BEGIN_RESP)
230 else if(res != tlm::END_REQ)
231 SCCERR(SCMOD) <<
"target did not repsond with END_REQ to a BEGIN_REQ";
232 wait(clk_i.posedge_event());
233 if(protocol_cb[axi::fsm::EndReqE])
234 protocol_cb[axi::fsm::EndReqE](trans,
false);
236 auto finished =
false;
237 if(!trans.is_read() || !trans.get_data_length())
239 const auto exp_burst_length = burst_length;
242 auto entry = next_phase == tlm::UNINITIALIZED_PHASE ? txs->peq.get() : std::make_tuple(&trans, next_phase);
243 next_phase = tlm::UNINITIALIZED_PHASE;
245 if(std::get<0>(entry) == &trans && std::get<1>(entry) == tlm::BEGIN_RESP) {
246 if(protocol_cb[axi::fsm::BegRespE])
247 protocol_cb[axi::fsm::BegRespE](trans,
false);
248 SCCTRACE(SCMOD) <<
"received last beat of " << trans;
249 auto delay_in_cycles = timing_e ? (trans.is_read() ? timing_e->rbr : timing_e->br) : br.value;
250 for(
unsigned i = 0; i < delay_in_cycles; ++i)
251 wait(clk_i.posedge_event());
253 tlm::tlm_phase phase = tlm::END_RESP;
254 sc_time delay = clk_if ? clk_if->period() - 1_ps : SC_ZERO_TIME;
255 socket_fw->nb_transport_fw(trans, phase, delay);
257 SCCWARN(SCMOD) <<
"got wrong number of burst beats, expected " << exp_burst_length <<
", got "
258 << exp_burst_length - burst_length;
259 wait(clk_i.posedge_event());
260 if(protocol_cb[axi::fsm::EndRespE])
261 protocol_cb[axi::fsm::EndRespE](trans,
false);
263 }
else if(std::get<0>(entry) == &trans &&
264 std::get<1>(entry) == axi::BEGIN_PARTIAL_RESP) {
265 SCCTRACE(SCMOD) <<
"received beat = "<< burst_length<<
" with trans " << trans;
266 auto delay_in_cycles = timing_e ? timing_e->rbr : rbr.value;
267 for(
unsigned i = 0; i < delay_in_cycles; ++i)
268 wait(clk_i.posedge_event());
270 if(protocol_cb[axi::fsm::BegPartRespE])
271 protocol_cb[axi::fsm::BegPartRespE](trans,
false);
272 tlm::tlm_phase phase = axi::END_PARTIAL_RESP;
273 sc_time delay = clk_if ? clk_if->period() - 1_ps : SC_ZERO_TIME;
274 auto res = socket_fw->nb_transport_fw(trans, phase, delay);
275 if(res == tlm::TLM_UPDATED) {
279 if(protocol_cb[axi::fsm::EndPartRespE])
280 protocol_cb[axi::fsm::EndPartRespE](trans,
false);
283 if(flavor == flavor_e::ACE) {
284 if(trans.is_read() && rla.value != std::numeric_limits<unsigned>::max()) {
285 for(
unsigned i = 0; i < rla.value; ++i)
286 wait(clk_i.posedge_event());
287 tlm::tlm_phase phase = axi::ACK;
288 sc_time delay = SC_ZERO_TIME;
289 socket_fw->nb_transport_fw(trans, phase, delay);
290 wait(clk_i.posedge_event());
292 }
else if(trans.is_write() && ba.value != std::numeric_limits<unsigned>::max()) {
293 for(
unsigned i = 0; i < ba.value; ++i)
294 wait(clk_i.posedge_event());
295 tlm::tlm_phase phase = axi::ACK;
296 sc_time delay = SC_ZERO_TIME;
297 socket_fw->nb_transport_fw(trans, phase, delay);
298 wait(clk_i.posedge_event());
301 SCCTRACE(SCMOD) <<
"finished non-blocking protocol";
302 if(enable_id_serializing.value) {
303 id_mtx[axi_id]->post();
305 txs->active_tx =
nullptr;
306 any_tx_finished.notify(SC_ZERO_TIME);
308 SCCTRACE(SCMOD) <<
"finished transport req for " << trans;
312 void axi_initiator_b::snoop_thread() {
315 while(!(trans = snp_peq.get_next_transaction())) {
316 wait(snp_peq.get_event());
319 SCCDEBUG(SCMOD) <<
"start snoop #" << snoops_in_flight;
320 auto req_ext = trans->get_extension<ace_extension>();
321 sc_assert(req_ext !=
nullptr);
323 auto it = snp_state_by_id.find(&trans);
324 if(it == snp_state_by_id.end()) {
326 std::tie(it, success) = snp_state_by_id.insert(std::make_pair(trans.get(),
new tx_state()));
329 sc_time delay = clk_if ? clk_if->period() - 1_ps : SC_ZERO_TIME;
330 tlm::tlm_phase phase = tlm::END_REQ;
333 if(protocol_cb[axi::fsm::BegReqE])
334 protocol_cb[axi::fsm::BegReqE](*trans,
true);
335 socket_fw->nb_transport_fw(*trans, phase, delay);
337 if(bw_o.get_interface())
338 cycles = bw_o->transport(*trans);
339 if(protocol_cb[axi::fsm::EndReqE])
340 protocol_cb[axi::fsm::EndReqE](*trans,
true);
341 if(cycles < std::numeric_limits<unsigned>::max()) {
343 for(
size_t i = 0; i <= cycles; ++i)
344 wait(clk_i.posedge_event());
348 SCCTRACE(SCMOD)<<
" finish snoop response, release gp_shared_ptr";
354 void axi_initiator_b::snoop_resp(payload_type& trans,
bool sync) {
355 auto it = snp_state_by_id.find(&trans);
356 sc_assert(it != snp_state_by_id.end());
357 auto& txs = it->second;
358 auto data_len=trans.get_data_length();
359 auto burst_length = data_len/transfer_width_in_bytes;
362 tlm::tlm_phase next_phase{tlm::UNINITIALIZED_PHASE};
363 auto delay_in_cycles = wbv.value;
369 SCCTRACE(SCMOD) <<
"starting snoop resp with " << burst_length <<
" beats of " << trans;
370 for(
unsigned i = 0; i < burst_length - 1; ++i) {
371 if(protocol_cb[axi::fsm::BegPartRespE])
372 protocol_cb[axi::fsm::BegPartRespE](trans,
true);
373 auto res = send(trans, txs, axi::BEGIN_PARTIAL_RESP);
374 sc_assert(axi::END_PARTIAL_RESP == res);
375 wait(clk_i.posedge_event());
376 if(protocol_cb[axi::fsm::EndPartRespE])
377 protocol_cb[axi::fsm::EndPartRespE](trans,
true);
378 for(
unsigned i = 1; i < delay_in_cycles; ++i)
379 wait(clk_i.posedge_event());
381 if(protocol_cb[axi::fsm::BegRespE])
382 protocol_cb[axi::fsm::BegRespE](trans,
true);
383 auto res = send(trans, txs, tlm::BEGIN_RESP);
384 if(res != tlm::END_RESP)
385 SCCERR(SCMOD) <<
"target did not respond with END_RESP to a BEGIN_RESP";
386 wait(clk_i.posedge_event());
387 if(protocol_cb[axi::fsm::EndRespE])
388 protocol_cb[axi::fsm::EndRespE](trans,
true);
The ordered_semaphore primitive channel class.
TLM2.0 components modeling AHB.
tlm::tlm_fw_transport_if< TYPES > axi_fw_transport_if
alias declaration for the forward interface