scc 2025.09
SystemC components library
ordered_target.cpp
1#include "ordered_target.h"
2namespace axi {
3namespace pe {
4
5rate_limiting_buffer::rate_limiting_buffer(const sc_core::sc_module_name& nm, cci::cci_param<int>& rd_resp_delay,
6 cci::cci_param<int>& wr_resp_delay)
7: rd_resp_delay(rd_resp_delay)
8, wr_resp_delay(wr_resp_delay) {
9 fw_i.bind(*this);
10#if SYSTEMC_VERSION < 20250221
11 SC_HAS_PROCESS(rate_limiting_buffer);
12#endif
13 SC_METHOD(process_req2resp_fifos);
14 dont_initialize();
15 sensitive << clk_i.pos();
16 SC_THREAD(start_wr_resp_thread);
17 SC_THREAD(start_rd_resp_thread);
18}
19
20void rate_limiting_buffer::end_of_elaboration() { clk_if = dynamic_cast<sc_core::sc_clock*>(clk_i.get_interface()); }
21
22void rate_limiting_buffer::start_of_simulation() {
23 if(clk_if) {
24 if(total_bw_limit_byte_per_sec.get_value() > 0.0) {
25 time_per_byte_total = sc_core::sc_time(1.0 / total_bw_limit_byte_per_sec.get_value(), sc_core::SC_SEC);
26 if(rd_bw_limit_byte_per_sec.get_value() > 0.0 || wr_bw_limit_byte_per_sec.get_value() > 0.0) {
27 SCCWARN(SCMOD)
28 << "total bandwidth is specified, ignoring settings of rd_bw_limit_byte_per_sec and wr_bw_limit_byte_per_sec";
29 rd_bw_limit_byte_per_sec.set_value(-1);
30 wr_bw_limit_byte_per_sec.set_value(-1);
31 }
32 }
33 if(rd_bw_limit_byte_per_sec.get_value() > 0.0) {
34 time_per_byte_rd = sc_core::sc_time(1.0 / rd_bw_limit_byte_per_sec.get_value(), sc_core::SC_SEC);
35 }
36 if(wr_bw_limit_byte_per_sec.get_value() > 0.0) {
37 time_per_byte_wr = sc_core::sc_time(1.0 / wr_bw_limit_byte_per_sec.get_value(), sc_core::SC_SEC);
38 }
39 }
40}
41
42void rate_limiting_buffer::transport(tlm::tlm_generic_payload& trans, bool lt_transport) {
43 if(trans.is_write())
44 wr_req2resp_fifo.push_back(std::make_tuple(&trans, get_cci_randomized_value(wr_resp_delay)));
45 else if(trans.is_read())
46 rd_req2resp_fifo.push_back(std::make_tuple(&trans, get_cci_randomized_value(rd_resp_delay)));
47}
48
49void rate_limiting_buffer::process_req2resp_fifos() {
50 while(rd_req2resp_fifo.avail()) {
51 auto& entry = rd_req2resp_fifo.front();
52 if(std::get<1>(entry) == 0) {
53 rd_resp_fifo.push_back(std::get<0>(entry));
54 } else {
55 std::get<1>(entry) -= 1;
56 rd_req2resp_fifo.push_back(entry);
57 }
58 rd_req2resp_fifo.pop_front();
59 }
60 while(wr_req2resp_fifo.avail()) {
61 auto& entry = wr_req2resp_fifo.front();
62 if(std::get<1>(entry) == 0) {
63 wr_resp_fifo.push_back(std::get<0>(entry));
64 } else {
65 std::get<1>(entry) -= 1;
66 wr_req2resp_fifo.push_back(entry);
67 }
68 wr_req2resp_fifo.pop_front();
69 }
70}
71
72void rate_limiting_buffer::start_rd_resp_thread() {
73 auto residual_clocks = 0.0;
74 while(true) {
75 wait(rd_resp_fifo.data_written_event());
76 while(rd_resp_fifo.avail())
77 if(auto* trans = rd_resp_fifo.front()) {
78 if(clk_if) {
79 if(time_per_byte_total.value()) {
80 scc::ordered_semaphore::lock lck(total_arb);
81 auto clocks = trans->get_data_length() * time_per_byte_total / clk_if->period() + total_residual_clocks;
82 auto delay = static_cast<unsigned>(clocks);
83 total_residual_clocks = clocks - delay;
84 wait(delay * clk_if->period());
85 wait(clk_i.posedge_event());
86 } else if(time_per_byte_rd.value()) {
87 auto clocks = trans->get_data_length() * time_per_byte_rd / clk_if->period() + residual_clocks;
88 auto delay = static_cast<unsigned>(clocks);
89 residual_clocks = clocks - delay;
90 wait(delay * clk_if->period());
91 wait(clk_i.posedge_event());
92 }
93 }
94 while(bw_o->transport(*trans) != 0)
95 wait(clk_i.posedge_event());
96 rd_resp_fifo.pop_front();
97 }
98 }
99}
100
101void rate_limiting_buffer::start_wr_resp_thread() {
102 auto residual_clocks = 0.0;
103 while(true) {
104 wait(wr_resp_fifo.data_written_event());
105 while(wr_resp_fifo.avail())
106 if(auto* trans = wr_resp_fifo.front()) {
107 if(clk_if) {
108 if(time_per_byte_total.value()) {
109 scc::ordered_semaphore::lock lck(total_arb);
110 auto clocks = trans->get_data_length() * time_per_byte_total / clk_if->period() + total_residual_clocks;
111 auto delay = static_cast<unsigned>(clocks);
112 total_residual_clocks = clocks - delay;
113 wait(delay * clk_if->period());
114 wait(clk_i.posedge_event());
115 } else if(time_per_byte_rd.value()) {
116 auto clocks = trans->get_data_length() * time_per_byte_rd / clk_if->period() + residual_clocks;
117 auto delay = static_cast<unsigned>(clocks);
118 residual_clocks = clocks - delay;
119 wait(delay * clk_if->period());
120 wait(clk_i.posedge_event());
121 }
122 }
123 while(bw_o->transport(*trans) != 0)
124 wait(clk_i.posedge_event());
125 wr_resp_fifo.pop_front();
126 }
127 }
128}
129
130} // namespace pe
131} // namespace axi
cci::cci_param< int > & rd_resp_delay
the latency between request and response phase. Will be overwritten by the return of the callback fun...
scc::fifo_w_cb< std::tuple< tlm::tlm_generic_payload *, unsigned > > rd_req2resp_fifo
queues realizing the min latency
void transport(tlm::tlm_generic_payload &payload, bool lt_transport=false) override
cci::cci_param< int > & wr_resp_delay
the latency between request and response phase. Will be overwritten by the return of the callback fun...
protocol engine implementations
TLM2.0 components modeling AHB.
a lock for the semaphore