scc  2024.06
SystemC components library
replay_target.cpp
1 #include "replay_target.h"
2 #include <yaml-cpp/exceptions.h>
3 #include <yaml-cpp/node/parse.h>
4 #include <yaml-cpp/yaml.h>
5 #include <fstream>
6 
7 namespace axi {
8 namespace pe {
9 
10 replay_buffer::replay_buffer(const sc_core::sc_module_name &nm):sc_core::sc_module(nm) {
11  fw_i.bind(*this);
12  SC_HAS_PROCESS(replay_buffer);
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 
20 void replay_buffer::end_of_elaboration() {
21  clk_if = dynamic_cast<sc_core::sc_clock*>(clk_i.get_interface());
22 }
23 
24 void replay_buffer::start_of_simulation() {
25  if(replay_file_name.get_value().length()) {
26  std::ifstream ifs(replay_file_name.get_value());
27  if(ifs.is_open()) {
28  std::string line;
29  std::getline(ifs, line);
30  while (std::getline(ifs, line)) {
31  auto token = util::split(line, ',');
32  auto addr = strtoull(token[1].c_str(), nullptr, 10);
33  auto id = strtoull(token[2].c_str(), nullptr, 10);
34  auto start_cycle = strtoull(token[3].c_str(), nullptr, 10);
35  auto req_resp_lat=strtoull(token[4].c_str(), nullptr, 10);
36  if(token[0]=="READ") {
37  if(id>=rd_sequence.size())
38  rd_sequence.resize(id+1);
39  rd_sequence[id].emplace_back(addr, req_resp_lat);
40  } else if(token[0]=="WRITE") {
41  if(id>=wr_sequence.size())
42  wr_sequence.resize(id+1);
43  wr_sequence[id].emplace_back(addr, req_resp_lat);
44  }
45  }
46  }
47  SCCINFO(SCMOD)<<"SEQ file name of replay target = "<<replay_file_name.get_value();
48  }
49 }
50 
51 void replay_buffer::transport(tlm::tlm_generic_payload &trans, bool lt_transport) {
52  auto id = axi::get_axi_id(trans);
53  auto addr = trans.get_address();
54  auto cycle = clk_if? sc_core::sc_time_stamp()/clk_if->period():0;
55  if(trans.is_write()) {
56  if(id<wr_sequence.size() && wr_sequence[id].size()) {
57  auto it = std::find_if(std::begin(wr_sequence[id]), std::end(wr_sequence[id]), [addr](entry_t const & e){
58  return std::get<0>(e) == addr;
59  });
60  if(it != std::end(wr_sequence[id])) {
61  wr_req2resp_fifo.push_back(std::make_tuple(&trans, std::get<1>(*it)));
62  wr_sequence[id].erase(it);
63  return;
64  }
65  }
66  if(replay_file_name.get_value().length()) {
67  SCCWARN(SCMOD)<<"No transaction in write sequence buffer for "<<trans;
68  }
69  wr_req2resp_fifo.push_back(std::make_tuple(&trans, 0));
70  } else if(trans.is_read()) {
71  if(id<rd_sequence.size() && rd_sequence[id].size()) {
72  auto it = std::find_if(std::begin(rd_sequence[id]), std::end(rd_sequence[id]), [addr](entry_t const & e){
73  return std::get<0>(e) == addr;
74  });
75  if(it != std::end(rd_sequence[id])) {
76  rd_req2resp_fifo.push_back(std::make_tuple(&trans, std::get<1>(*it)));
77  rd_sequence[id].erase(it);
78  return;
79  }
80  }
81  if(replay_file_name.get_value().length()) {
82  SCCWARN(SCMOD)<<"No transaction in read sequence buffer for "<<trans;
83  }
84  rd_req2resp_fifo.push_back(std::make_tuple(&trans, 0));
85  }
86 }
87 
88 void replay_buffer::process_req2resp_fifos() {
89  while(rd_req2resp_fifo.avail()) {
90  auto& entry = rd_req2resp_fifo.front();
91  if(std::get<1>(entry) == 0) {
92  rd_resp_fifo.push_back(std::get<0>(entry));
93  } else {
94  std::get<1>(entry) -= 1;
95  rd_req2resp_fifo.push_back(entry);
96  }
97  rd_req2resp_fifo.pop_front();
98  }
99  while(wr_req2resp_fifo.avail()) {
100  auto& entry = wr_req2resp_fifo.front();
101  if(std::get<1>(entry) == 0) {
102  wr_resp_fifo.push_back(std::get<0>(entry));
103  } else {
104  std::get<1>(entry) -= 1;
105  wr_req2resp_fifo.push_back(entry);
106  }
107  wr_req2resp_fifo.pop_front();
108  }
109 }
110 
111 void replay_buffer::start_rd_resp_thread() {
112  auto residual_clocks = 0.0;
113  while(true) {
114  wait(rd_resp_fifo.data_written_event());
115  while(rd_resp_fifo.avail())
116  if(auto* trans = rd_resp_fifo.front()){
117  if(clk_if) {
118  if(time_per_byte_total.value()) {
119  scc::ordered_semaphore::lock lck(total_arb);
120  auto clocks = trans->get_data_length() * time_per_byte_total / clk_if->period() + total_residual_clocks;
121  auto delay = static_cast<unsigned>(clocks);
122  total_residual_clocks = clocks - delay;
123  wait(delay*clk_if->period());
124  wait(clk_i.posedge_event());
125  } else if(time_per_byte_rd.value()) {
126  auto clocks = trans->get_data_length() * time_per_byte_rd / clk_if->period() + residual_clocks;
127  auto delay = static_cast<unsigned>(clocks);
128  residual_clocks = clocks - delay;
129  wait(delay*clk_if->period());
130  wait(clk_i.posedge_event());
131  }
132  }
133  while(bw_o->transport(*trans)!=0) wait(clk_i.posedge_event());
134  rd_resp_fifo.pop_front();
135  }
136  }
137 }
138 
139 void replay_buffer::start_wr_resp_thread() {
140  auto residual_clocks = 0.0;
141  while(true) {
142  wait(wr_resp_fifo.data_written_event());
143  while(wr_resp_fifo.avail())
144  if(auto* trans = wr_resp_fifo.front()){
145  if(clk_if) {
146  if(time_per_byte_total.value()) {
147  scc::ordered_semaphore::lock lck(total_arb);
148  auto clocks = trans->get_data_length() * time_per_byte_total / clk_if->period() + total_residual_clocks;
149  auto delay = static_cast<unsigned>(clocks);
150  total_residual_clocks = clocks - delay;
151  wait(delay*clk_if->period());
152  wait(clk_i.posedge_event());
153  } else if(time_per_byte_rd.value()) {
154  auto clocks = trans->get_data_length() * time_per_byte_rd / clk_if->period() + residual_clocks;
155  auto delay = static_cast<unsigned>(clocks);
156  residual_clocks = clocks - delay;
157  wait(delay*clk_if->period());
158  wait(clk_i.posedge_event());
159  }
160  }
161  while(bw_o->transport(*trans)!=0) wait(clk_i.posedge_event());
162  wr_resp_fifo.pop_front();
163  }
164  }
165 }
166 }
167 }
TLM2.0 components modeling AHB.
Definition: axi_initiator.h:30
std::vector< std::string > split(const std::string &s, char separator)
Definition: ities.h:223
a lock for the semaphore