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