1#include "replay_target.h"
6const unsigned int CATCH_ALL_SEQUENCE = 0;
8replay_buffer::replay_buffer(
const sc_core::sc_module_name& nm)
9: sc_core::sc_module(nm) {
11#if SYSTEMC_VERSION < 20250221
12 SC_HAS_PROCESS(replay_buffer);
14 SC_METHOD(process_req2resp_fifos);
16 sensitive << clk_i.pos();
17 SC_THREAD(start_wr_resp_thread);
18 SC_THREAD(start_rd_resp_thread);
21void replay_buffer::end_of_elaboration() { clk_if =
dynamic_cast<sc_core::sc_clock*
>(clk_i.get_interface()); }
23void replay_buffer::start_of_simulation() {
24 if(replay_file_name.get_value().length()) {
25 std::ifstream ifs(replay_file_name.get_value());
28 std::getline(ifs, line);
29 while(std::getline(ifs, line)) {
31 auto addr = strtoull(token[1].c_str(),
nullptr, 10);
32 auto id = CATCH_ALL_SEQUENCE;
33 if(token[2].c_str()[0] !=
'*') {
34 id = strtoull(token[2].c_str(),
nullptr, 10) + 1;
36 auto start_cycle = strtoull(token[3].c_str(),
nullptr, 10);
37 auto req_resp_lat = strtoull(token[4].c_str(),
nullptr, 10);
38 if(token[0] ==
"READ") {
39 if(
id >= rd_sequence.size())
40 rd_sequence.resize(
id + 1);
41 rd_sequence[id].emplace_back(addr, req_resp_lat);
42 }
else if(token[0] ==
"WRITE") {
43 if(
id >= wr_sequence.size())
44 wr_sequence.resize(
id + 1);
45 wr_sequence[id].emplace_back(addr, req_resp_lat);
47 SCCWARN(SCMOD) <<
"Illegal command in replay file: " << line;
51 SCCINFO(SCMOD) <<
"SEQ file name of replay target = " << replay_file_name.get_value();
56 auto id = axi::get_axi_id(trans) + 1;
57 auto addr = trans.get_address();
58 auto cycle = clk_if ? sc_core::sc_time_stamp() / clk_if->period() : 0;
61 auto it = std::find_if(std::begin(sequence), std::end(sequence), [addr](entry_t
const& e) {
return std::get<0>(e) == addr; });
62 if(it != std::end(sequence)) {
63 fifo.push_back(std::make_tuple(&trans, std::get<1>(*it)));
70 if(trans.is_write()) {
71 if(
id < wr_sequence.size() && wr_sequence[
id].size()) {
72 if(find_and_push(wr_sequence[
id], wr_req2resp_fifo)) {
76 if(wr_sequence.size() && find_and_push(wr_sequence[CATCH_ALL_SEQUENCE], wr_req2resp_fifo)) {
79 if(replay_file_name.get_value().length()) {
80 SCCWARN(SCMOD) <<
"No transaction in write sequence buffer for " << trans;
82 wr_req2resp_fifo.push_back(std::make_tuple(&trans, 0));
83 }
else if(trans.is_read()) {
84 if(
id < rd_sequence.size() && rd_sequence[
id].size()) {
89 if(rd_sequence.size() && find_and_push(rd_sequence[CATCH_ALL_SEQUENCE],
rd_req2resp_fifo)) {
92 if(replay_file_name.get_value().length()) {
93 SCCWARN(SCMOD) <<
"No transaction in read sequence buffer for " << trans;
99void replay_buffer::process_req2resp_fifos() {
100 while(rd_req2resp_fifo.avail()) {
101 auto& entry = rd_req2resp_fifo.front();
102 if(std::get<1>(entry) == 0) {
103 rd_resp_fifo.push_back(std::get<0>(entry));
105 std::get<1>(entry) -= 1;
106 rd_req2resp_fifo.push_back(entry);
108 rd_req2resp_fifo.pop_front();
110 while(wr_req2resp_fifo.avail()) {
111 auto& entry = wr_req2resp_fifo.front();
112 if(std::get<1>(entry) == 0) {
113 wr_resp_fifo.push_back(std::get<0>(entry));
115 std::get<1>(entry) -= 1;
116 wr_req2resp_fifo.push_back(entry);
118 wr_req2resp_fifo.pop_front();
122void replay_buffer::start_rd_resp_thread() {
123 auto residual_clocks = 0.0;
125 wait(rd_resp_fifo.data_written_event());
126 while(rd_resp_fifo.avail())
127 if(
auto* trans = rd_resp_fifo.front()) {
129 if(time_per_byte_total.value()) {
131 auto clocks = trans->get_data_length() * time_per_byte_total / clk_if->period() + total_residual_clocks;
132 auto delay =
static_cast<unsigned>(clocks);
133 total_residual_clocks = clocks - delay;
134 wait(delay * clk_if->period());
135 wait(clk_i.posedge_event());
136 }
else if(time_per_byte_rd.value()) {
137 auto clocks = trans->get_data_length() * time_per_byte_rd / clk_if->period() + residual_clocks;
138 auto delay =
static_cast<unsigned>(clocks);
139 residual_clocks = clocks - delay;
140 wait(delay * clk_if->period());
141 wait(clk_i.posedge_event());
144 while(bw_o->transport(*trans) != 0)
145 wait(clk_i.posedge_event());
146 rd_resp_fifo.pop_front();
151void replay_buffer::start_wr_resp_thread() {
152 auto residual_clocks = 0.0;
154 wait(wr_resp_fifo.data_written_event());
155 while(wr_resp_fifo.avail())
156 if(
auto* trans = wr_resp_fifo.front()) {
158 if(time_per_byte_total.value()) {
160 auto clocks = trans->get_data_length() * time_per_byte_total / clk_if->period() + total_residual_clocks;
161 auto delay =
static_cast<unsigned>(clocks);
162 total_residual_clocks = clocks - delay;
163 wait(delay * clk_if->period());
164 wait(clk_i.posedge_event());
165 }
else if(time_per_byte_wr.value()) {
166 auto clocks = trans->get_data_length() * time_per_byte_wr / clk_if->period() + residual_clocks;
167 auto delay =
static_cast<unsigned>(clocks);
168 residual_clocks = clocks - delay;
169 wait(delay * clk_if->period());
170 wait(clk_i.posedge_event());
173 while(bw_o->transport(*trans) != 0)
174 wait(clk_i.posedge_event());
175 wr_resp_fifo.pop_front();
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)