1#include "ordered_target.h"
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) {
10#if SYSTEMC_VERSION < 20250221
11 SC_HAS_PROCESS(rate_limiting_buffer);
13 SC_METHOD(process_req2resp_fifos);
15 sensitive << clk_i.pos();
16 SC_THREAD(start_wr_resp_thread);
17 SC_THREAD(start_rd_resp_thread);
20void rate_limiting_buffer::end_of_elaboration() { clk_if =
dynamic_cast<sc_core::sc_clock*
>(clk_i.get_interface()); }
22void rate_limiting_buffer::start_of_simulation() {
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) {
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);
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);
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);
44 wr_req2resp_fifo.push_back(std::make_tuple(&trans, get_cci_randomized_value(
wr_resp_delay)));
45 else if(trans.is_read())
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));
55 std::get<1>(entry) -= 1;
56 rd_req2resp_fifo.push_back(entry);
58 rd_req2resp_fifo.pop_front();
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));
65 std::get<1>(entry) -= 1;
66 wr_req2resp_fifo.push_back(entry);
68 wr_req2resp_fifo.pop_front();
72void rate_limiting_buffer::start_rd_resp_thread() {
73 auto residual_clocks = 0.0;
75 wait(rd_resp_fifo.data_written_event());
76 while(rd_resp_fifo.avail())
77 if(
auto* trans = rd_resp_fifo.front()) {
79 if(time_per_byte_total.value()) {
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());
94 while(bw_o->transport(*trans) != 0)
95 wait(clk_i.posedge_event());
96 rd_resp_fifo.pop_front();
101void rate_limiting_buffer::start_wr_resp_thread() {
102 auto residual_clocks = 0.0;
104 wait(wr_resp_fifo.data_written_event());
105 while(wr_resp_fifo.avail())
106 if(
auto* trans = wr_resp_fifo.front()) {
108 if(time_per_byte_total.value()) {
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());
123 while(bw_o->transport(*trans) != 0)
124 wait(clk_i.posedge_event());
125 wr_resp_fifo.pop_front();
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.