MatchLib
ManagerFromFile.h
1 /*
2  * Copyright (c) 2017-2024, NVIDIA CORPORATION. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License")
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef __AXI_T_MANAGER_FROM_FILE__
18 #define __AXI_T_MANAGER_FROM_FILE__
19 
20 #include <nvhls_int.h>
21 #include <systemc.h>
22 #include <ac_reset_signal_is.h>
23 
24 #include <axi/axi4.h>
25 #include <axi/testbench/CSVFileReader.h>
26 #include <nvhls_connections.h>
27 #include <hls_globals.h>
28 
29 #include <queue>
30 #include <string>
31 #include <sstream>
32 #include <vector>
33 #include <math.h>
34 #include <boost/assert.hpp>
35 
60 // Allow an sc_in to be present only if a template parameter is enabled
61 template <typename T, bool enable> class sc_in_conditional : public sc_signal<T> {};
62 template <typename T> class sc_in_conditional <T,1> : public sc_in<T> {};
63 
64 template <typename axiCfg, bool enable_interrupts = false> class ManagerFromFile : public sc_module {
65  public:
66  static const int kDebugLevel = 1;
67  typedef axi::axi4<axiCfg> axi4_;
68 
69  typename axi4_::read::template manager<> if_rd;
70  typename axi4_::write::template manager<> if_wr;
71 
72  sc_in<bool> reset_bar;
73  sc_in<bool> clk;
74 
76 
77  static const int bytesPerBeat = axi4_::DATA_WIDTH >> 3;
78  static const int bytesPerWord = axi4_::DATA_WIDTH >> 3;
79  static const int axiAddrBitsPerWord = nvhls::log2_ceil<bytesPerWord>::val;
80 
81  std::queue< int > delay_q;
82  std::queue< int > req_q;
83  std::queue< typename axi4_::AddrPayload > raddr_q;
84  std::queue< typename axi4_::AddrPayload > waddr_q;
85  std::queue< typename axi4_::WritePayload > wdata_q;
86  std::queue<typename axi4_::Data> rresp_q;
87 
88  typename axi4_::AddrPayload addr_pld;
89  typename axi4_::WritePayload wr_data_pld;
90  typename axi4_::ReadPayload data_pld;
91  typename axi4_::AddrPayload wr_addr_pld;
92  typename axi4_::WRespPayload wr_resp_pld;
93 
94  int burst_inflight = 0;
95  sc_out<bool> done;
96 
97  SC_HAS_PROCESS(ManagerFromFile);
98 
99  ManagerFromFile(sc_module_name name_, std::string filename="requests.csv")
100  : sc_module(name_), if_rd("if_rd"), if_wr("if_wr"), reset_bar("reset_bar"), clk("clk") {
101 
102  CDCOUT("Reading file: " << filename << endl, kDebugLevel);
103  CSVFileReader reader(filename);
104  std::vector< std::vector<std::string> > dataList = reader.readCSV();
105  for (unsigned int i=0; i < dataList.size(); i++) {
106  std::vector<std::string> vec = dataList[i];
107  CMOD_ASSERT_MSG(vec.size() == 5, "Each request must have five elements");
108  if (!burst_inflight) delay_q.push(atoi(vec[0].c_str()));
109  if (vec[1] == "R") {
110  if (!burst_inflight) {
111  req_q.push(0);
112  std::stringstream ss;
113  sc_uint<axi4_::ADDR_WIDTH> addr;
114  ss << hex << vec[2];
115  ss >> addr;
116  std::stringstream ss_len;
117  addr_pld.addr = static_cast<typename axi4_::Addr>(addr);
118  sc_uint<axi4_::ALEN_WIDTH> len;
119  ss_len << hex << vec[4];
120  ss_len >> len;
121  if (len) CMOD_ASSERT_MSG(axiCfg::useBurst, "A burst transaction was requested but the AXI config does not support bursts");
122  CMOD_ASSERT_MSG(axiCfg::maxBurstSize >= len, "A burst transaction was requested that is longer than the maximum allowed by the AXI config");
123  addr_pld.len = 0;
124  addr_pld.len = static_cast<typename axi4_::BeatNum>(len);
125  raddr_q.push(addr_pld);
126  burst_inflight = int(len);
127  } else {
128  burst_inflight--;
129  }
130  std::stringstream ss_data;
131  sc_biguint<axi4_::DATA_WIDTH> data;
132  ss_data << hex << vec[3];
133  ss_data >> data;
134  rresp_q.push(TypeToNVUINT(data));
135  } else if (vec[1] == "W") {
136  if (!burst_inflight) {
137  req_q.push(1);
138  std::stringstream ss;
139  sc_uint<axi4_::ADDR_WIDTH> addr;
140  ss << hex << vec[2];
141  ss >> addr;
142  std::stringstream ss_len;
143  addr_pld.addr = static_cast<typename axi4_::Addr>(addr);
144  sc_uint<axi4_::ALEN_WIDTH> len;
145  ss_len << hex << vec[4];
146  ss_len >> len;
147  if (len) CMOD_ASSERT_MSG(axiCfg::useBurst, "A burst transaction was requested but the AXI config does not support bursts");
148  CMOD_ASSERT_MSG(axiCfg::maxBurstSize >= len, "A burst transaction was requested that is longer than the maximum allowed by the AXI config");
149  addr_pld.len = static_cast<typename axi4_::BeatNum>(len);
150  waddr_q.push(addr_pld);
151  burst_inflight = int(len);
152  } else {
153  burst_inflight--;
154  }
155  std::stringstream ss_data;
156  sc_biguint<axi4_::DATA_WIDTH> data;
157  ss_data << hex << vec[3];
158  ss_data >> data;
159  wr_data_pld.data = TypeToNVUINT(data);
160  wr_data_pld.wstrb = ~0;
161  if (!burst_inflight) {
162  wr_data_pld.last = 1;
163  } else {
164  wr_data_pld.last = 0;
165  }
166  wdata_q.push(wr_data_pld);
167  } else if (vec[1] == "Q") {
168  CMOD_ASSERT_MSG(enable_interrupts, "Interrupt command read, but interrupts are not enabled");
169  req_q.push(2);
170  } else {
171  CMOD_ASSERT_MSG(1, "Requests must be R or W or Q");
172  }
173  }
174 
175  SC_THREAD(run);
176  sensitive << clk.pos();
177  async_reset_signal_is(reset_bar, false);
178  }
179 
180  protected:
181  void run() {
182 
183  done = 0;
184 
185  if_rd.reset();
186  if_wr.reset();
187 
188  wait(20);
189 
190  while (!delay_q.empty()) {
191  int delay = delay_q.front();
192  if (delay > 0) wait(delay);
193  delay_q.pop();
194  if (req_q.front() == 2) {
195  CMOD_ASSERT_MSG(enable_interrupts,"Interrupt command found, but interrupts are not enabled");
196  CDCOUT(sc_time_stamp() << " " << name() << " Beginning wait for interrupt"
197  << endl, kDebugLevel);
198  while (interrupt.read() == 0) wait();
199  CDCOUT(sc_time_stamp() << " " << name() << " Interrupt received"
200  << endl, kDebugLevel);
201  } else if (req_q.front() == 1) {
202  addr_pld = waddr_q.front();
203  if_wr.aw.Push(addr_pld);
204  waddr_q.pop();
205  CDCOUT(sc_time_stamp() << " " << name() << " Sent write request:"
206  << " addr=[" << addr_pld << "]"
207  << endl, kDebugLevel);
208  do {
209  wr_data_pld = wdata_q.front();
210  if_wr.w.Push(wr_data_pld);
211  wdata_q.pop();
212  CDCOUT(sc_time_stamp() << " " << name() << " Sent write data:"
213  << " data=[" << wr_data_pld << "]"
214  << endl, kDebugLevel);
215  } while (!wr_data_pld.last);
216  if_wr.b.Pop();
217  } else if (req_q.front() == 0) {
218  addr_pld = raddr_q.front();
219  if_rd.ar.Push(addr_pld);
220  raddr_q.pop();
221  CDCOUT(sc_time_stamp() << " " << name() << " Sent read request: "
222  << " addr=[" << addr_pld << "]"
223  << endl, kDebugLevel);
224  do {
225  data_pld = if_rd.r.Pop();
226  CDCOUT(sc_time_stamp() << " " << name() << " Received read response: ["
227  << data_pld << "]"
228  << endl, kDebugLevel);
229  CMOD_ASSERT_MSG(data_pld.data == rresp_q.front(),"Read response did not match expected value");
230  rresp_q.pop();
231  } while (!data_pld.last);
232  } else {
233  CMOD_ASSERT_MSG(0,"Unexpected value in req_q");
234  }
235  req_q.pop();
236  }
237  done = 1;
238  }
239 };
240 
241 #endif
A helper class to read CSV files.
Definition: CSVFileReader.h:37
The base axi4 class parameterized according a valid config.
Definition: axi4.h:64
An AXI manager that generates traffic according to a file for use in testbenches.
#define CMOD_ASSERT_MSG(X, MSG)
Definition: nvhls_assert.h:166
#define CDCOUT(x, y)
Definition: hls_globals.h:73
A struct composed of the signals associated with AXI read and write requests.
Definition: axi4.h:114
A struct composed of the signals associated with an AXI read response.
Definition: axi4.h:157
A struct composed of the signals associated with an AXI write response.
Definition: axi4.h:190
A struct composed of the signals associated with AXI write data.
Definition: axi4.h:215
Compute Celing of log2 of a constant.
Definition: nvhls_int.h:174