1#include "replay_target.h"
3#include <yaml-cpp/exceptions.h>
4#include <yaml-cpp/node/parse.h>
5#include <yaml-cpp/yaml.h>
10replay_buffer::replay_buffer(
const sc_core::sc_module_name& nm)
11: sc_core::sc_module(nm) {
13#if SYSTEMC_VERSION < 20250221
14 SC_HAS_PROCESS(replay_buffer);
16 SC_METHOD(process_req2resp_fifos);
18 sensitive << clk_i.pos();
19 SC_THREAD(start_wr_resp_thread);
20 SC_THREAD(start_rd_resp_thread);
23void replay_buffer::end_of_elaboration() { clk_if =
dynamic_cast<sc_core::sc_clock*
>(clk_i.get_interface()); }
25void replay_buffer::start_of_simulation() {
26 if(replay_file_name.get_value().length()) {
27 std::ifstream ifs(replay_file_name.get_value());
30 std::getline(ifs, line);
31 while(std::getline(ifs, 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);
48 SCCINFO(SCMOD) <<
"SEQ file name of replay target = " << replay_file_name.get_value();
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);
66 if(replay_file_name.get_value().length()) {
67 SCCWARN(SCMOD) <<
"No transaction in write sequence buffer for " << trans;
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])) {
76 rd_sequence[id].erase(it);
80 if(replay_file_name.get_value().length()) {
81 SCCWARN(SCMOD) <<
"No transaction in read sequence buffer for " << trans;
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));
93 std::get<1>(entry) -= 1;
94 rd_req2resp_fifo.push_back(entry);
96 rd_req2resp_fifo.pop_front();
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));
103 std::get<1>(entry) -= 1;
104 wr_req2resp_fifo.push_back(entry);
106 wr_req2resp_fifo.pop_front();
110void replay_buffer::start_rd_resp_thread() {
111 auto residual_clocks = 0.0;
113 wait(rd_resp_fifo.data_written_event());
114 while(rd_resp_fifo.avail())
115 if(
auto* trans = rd_resp_fifo.front()) {
117 if(time_per_byte_total.value()) {
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());
132 while(bw_o->transport(*trans) != 0)
133 wait(clk_i.posedge_event());
134 rd_resp_fifo.pop_front();
139void replay_buffer::start_wr_resp_thread() {
140 auto residual_clocks = 0.0;
142 wait(wr_resp_fifo.data_written_event());
143 while(wr_resp_fifo.avail())
144 if(
auto* trans = wr_resp_fifo.front()) {
146 if(time_per_byte_total.value()) {
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());
161 while(bw_o->transport(*trans) != 0)
162 wait(clk_i.posedge_event());
163 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)