MatchLib
MasterFromFile.h
1 /*
2  * Copyright (c) 2017-2020, 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_MASTER_FROM_FILE__
18 #define __AXI_T_MASTER_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 
53 // Allow an sc_in to be present only if a template parameter is enabled
54 template <typename T, bool enable> class sc_in_conditional : public sc_signal<T> {};
55 template <typename T> class sc_in_conditional <T,1> : public sc_in<T> {};
56 
57 template <typename axiCfg, bool enable_interrupts = false> class MasterFromFile : public sc_module {
58  public:
59  static const int kDebugLevel = 0;
60  typedef axi::axi4<axiCfg> axi4_;
61 
62  typename axi4_::read::template master<> if_rd;
63  typename axi4_::write::template master<> if_wr;
64 
65  sc_in<bool> reset_bar;
66  sc_in<bool> clk;
67 
69 
70  static const int bytesPerBeat = axi4_::DATA_WIDTH >> 3;
71  static const int bytesPerWord = axi4_::DATA_WIDTH >> 3;
72  static const int axiAddrBitsPerWord = nvhls::log2_ceil<bytesPerWord>::val;
73 
74  std::queue< int > delay_q;
75  std::queue< int > req_q;
76  std::queue< typename axi4_::AddrPayload > raddr_q;
77  std::queue< typename axi4_::AddrPayload > waddr_q;
78  std::queue< typename axi4_::WritePayload > wdata_q;
79  std::queue<typename axi4_::Data> rresp_q;
80 
81  typename axi4_::AddrPayload addr_pld;
82  typename axi4_::WritePayload wr_data_pld;
83  typename axi4_::ReadPayload data_pld;
84  typename axi4_::AddrPayload wr_addr_pld;
85  typename axi4_::WRespPayload wr_resp_pld;
86 
87  sc_out<bool> done;
88 
89  SC_HAS_PROCESS(MasterFromFile);
90 
91  MasterFromFile(sc_module_name name_, std::string filename="requests.csv")
92  : sc_module(name_), if_rd("if_rd"), if_wr("if_wr"), reset_bar("reset_bar"), clk("clk") {
93 
94  CDCOUT("Reading file: " << filename << endl, kDebugLevel);
95  CSVFileReader reader(filename);
96  std::vector< std::vector<std::string> > dataList = reader.readCSV();
97  for (unsigned int i=0; i < dataList.size(); i++) {
98  std::vector<std::string> vec = dataList[i];
99  NVHLS_ASSERT_MSG(vec.size() == 4, "Each request must have four elements");
100  delay_q.push(atoi(vec[0].c_str()));
101  if (vec[1] == "R") {
102  req_q.push(0);
103  std::stringstream ss;
104  sc_uint<axi4_::ADDR_WIDTH> addr;
105  ss << hex << vec[2];
106  ss >> addr;
107  addr_pld.addr = static_cast<typename axi4_::Addr>(addr);
108  addr_pld.len = 0;
109  raddr_q.push(addr_pld);
110  std::stringstream ss_data;
111  sc_biguint<axi4_::DATA_WIDTH> data;
112  ss_data << hex << vec[3];
113  ss_data >> data;
114  rresp_q.push(TypeToNVUINT(data));
115  } else if (vec[1] == "W") {
116  req_q.push(1);
117  std::stringstream ss;
118  sc_uint<axi4_::ADDR_WIDTH> addr;
119  ss << hex << vec[2];
120  ss >> addr;
121  addr_pld.addr = static_cast<typename axi4_::Addr>(addr);
122  addr_pld.len = 0;
123  waddr_q.push(addr_pld);
124  std::stringstream ss_data;
125  sc_biguint<axi4_::DATA_WIDTH> data;
126  ss_data << hex << vec[3];
127  ss_data >> data;
128  wr_data_pld.data = TypeToNVUINT(data);
129  wr_data_pld.wstrb = ~0;
130  wr_data_pld.last = 1;
131  wdata_q.push(wr_data_pld);
132  } else if (vec[1] == "Q") {
133  NVHLS_ASSERT_MSG(enable_interrupts,"Interrupt command read, but interrupts are not enabled");
134  req_q.push(2);
135  } else {
136  NVHLS_ASSERT_MSG(1,"Requests must be R or W or Q");
137  }
138  }
139 
140  SC_THREAD(run);
141  sensitive << clk.pos();
142  async_reset_signal_is(reset_bar, false);
143  }
144 
145  protected:
146  void run() {
147 
148  done = 0;
149 
150  if_rd.reset();
151  if_wr.reset();
152 
153  wait(20);
154 
155  while (!delay_q.empty()) {
156  int delay = delay_q.front();
157  if (delay > 0) wait(delay);
158  delay_q.pop();
159  if (req_q.front() == 2) {
160  NVHLS_ASSERT_MSG(enable_interrupts,"Interrupt command found, but interrupts are not enabled");
161  CDCOUT(sc_time_stamp() << " " << name() << " Beginning wait for interrupt"
162  << endl, kDebugLevel);
163  while (interrupt.read() == 0) wait();
164  CDCOUT(sc_time_stamp() << " " << name() << " Interrupt received"
165  << endl, kDebugLevel);
166  } else if (req_q.front() == 1) {
167  addr_pld = waddr_q.front();
168  if_wr.aw.Push(addr_pld);
169  waddr_q.pop();
170  wr_data_pld = wdata_q.front();
171  if_wr.w.Push(wr_data_pld);
172  wdata_q.pop();
173  if_wr.b.Pop();
174  CDCOUT(sc_time_stamp() << " " << name() << " Sent write request:"
175  << " addr=[" << addr_pld << "]"
176  << " data=[" << wr_data_pld << "]"
177  << endl, kDebugLevel);
178  } else {
179  addr_pld = raddr_q.front();
180  if_rd.ar.Push(addr_pld);
181  raddr_q.pop();
182  CDCOUT(sc_time_stamp() << " " << name() << " Sent read request: "
183  << addr_pld
184  << endl, kDebugLevel);
185  data_pld = if_rd.r.Pop();
186  CDCOUT(sc_time_stamp() << " " << name() << " Received read response: ["
187  << data_pld << "]"
188  << endl, kDebugLevel);
189  NVHLS_ASSERT_MSG(data_pld.data == rresp_q.front(),"Read response did not match expected value");
190  rresp_q.pop();
191  }
192  req_q.pop();
193  }
194  done = 1;
195  }
196 };
197 
198 #endif
A struct composed of the signals associated with an AXI write response.
Definition: axi4.h:236
A struct composed of the signals associated with AXI write data.
Definition: axi4.h:279
A struct composed of the signals associated with AXI read and write requests.
Definition: axi4.h:108
A struct composed of the signals associated with an AXI read response.
Definition: axi4.h:180
#define CDCOUT(x, y)
Definition: hls_globals.h:73
The base axi4 class parameterized according a valid config.
Definition: axi4.h:58
Compute Celing of log2 of a constant.
Definition: nvhls_int.h:174
An AXI master that generates traffic according to a file for use in testbenches.
#define NVHLS_ASSERT_MSG(X, MSG)
Definition: nvhls_assert.h:116
A helper class to read CSV files.
Definition: CSVFileReader.h:37