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