MatchLib
Host.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 __AXIMG_T_HOST__
18 #define __AXIMG_T_HOST__
19 
20 #include <systemc.h>
21 #include <ac_reset_signal_is.h>
22 
23 #include <axi/axi4.h>
24 #include <nvhls_connections.h>
25 
26 #include <queue>
27 #include <deque>
28 
40 template <typename Cfg>
41 SC_MODULE(Host) {
42  public:
43  sc_in<bool> reset_bar;
44  sc_in<bool> clk;
45 
46  Connections::Out<WrRequest<Cfg> > wrRequestOut;
47  Connections::In<WrResp<Cfg> > wrRespIn;
48  Connections::Out<RdRequest<Cfg> > rdRequestOut;
49  Connections::In<RdResp<Cfg> > rdRespIn;
50 
51  static const int bytesPerBeat = Cfg::dataWidth >> 3;
52 
53  sc_out<bool> done_write;
54  sc_out<bool> done_read;
55 
56  static const int write_count = 400;
57  static const int read_count = 50;
58 
59  std::deque<unsigned int> read_ref;
60  std::queue<typename axi::axi4<Cfg>::Data> dataQ;
61 
62  SC_CTOR(Host) : reset_bar("reset_bar"), clk("clk") {
63  SC_THREAD(run_wr_source);
64  sensitive << clk.pos();
65  async_reset_signal_is(reset_bar, false);
66 
67  SC_THREAD(run_wr_sink);
68  sensitive << clk.pos();
69  async_reset_signal_is(reset_bar, false);
70 
71  SC_THREAD(run_rd_source);
72  sensitive << clk.pos();
73  async_reset_signal_is(reset_bar, false);
74 
75  SC_THREAD(run_rd_sink);
76  sensitive << clk.pos();
77  async_reset_signal_is(reset_bar, false);
78  }
79 
80  struct Data { // don't really need this except to test out gen_random_payload
81  static const int width = Cfg::dataWidth;
82  NVUINTW(width) d;
83 
84  template <unsigned int Size>
85  void Marshall(Marshaller<Size>& m) {
86  m& d;
87  }
88  };
89 
90  protected:
91  void run_wr_source() {
92  wrRequestOut.Reset();
93  int addr = 0;
94  int ctr = 0;
95 
96  wait(20); // If we start sending requests before resetting the ReorderBufs, bad things happen
97 
98  while (1) {
99  wait();
100 
101  if (ctr < write_count) {
102  WrRequest<Cfg> wrRequest;
103  wrRequest.addr = addr;
104 
105  int len = rand() % 6;
106 
107  wrRequest.len = len;
108  wrRequest.last = 0;
109 
110  for (int i = 0; i <= len; ++i) {
111  if (i == len) {
112  wrRequest.last = 1;
113  ctr++;
114  }
115  wrRequest.data = nvhls::gen_random_payload<Data>().d;
116  std::cout << "@" << sc_time_stamp()
117  << " write source initiated a request:"
118  << "\t addr = " << hex << wrRequest.addr
119  << "\t data = " << hex << wrRequest.data
120  << "\t len = " << dec << wrRequest.len
121  << std::endl;
122  wrRequestOut.Push(wrRequest);
123  dataQ.push(wrRequest.data);
124  addr += bytesPerBeat;
125  }
126  }
127  }
128  }
129 
130  void run_wr_sink() {
131  wrRespIn.Reset();
132  done_write = 0;
133  int ctr = 0;
134 
135  while (1) {
136  wait();
137  WrResp<Cfg> wrResp = wrRespIn.Pop();
138 
139  std::cout << "@" << sc_time_stamp() << " write sink received response:"
140  << "\t resp = " << dec << wrResp.resp
141  << std::endl;
142  if (++ctr == write_count) done_write = 1;
143  }
144  }
145 
146  void run_rd_source() {
147  rdRequestOut.Reset();
148  int addr = 0;
149  int ctr = 0;
150 
151  wait(2000); // Let writes run well ahead of reads
152 
153  while (1) {
154  wait();
155 
156  if (ctr < read_count) {
157  if (rand() % 5 == 0) { // Really need to pace ourselves here
158  RdRequest<Cfg> rdRequest;
159  rdRequest.addr = addr;
160  int len = rand() % 3;
161 
162  rdRequest.len = len;
163 
164  std::cout << "@" << sc_time_stamp() << " read source initiated a request:"
165  << "\t addr = " << hex << rdRequest.addr
166  << "\t len = " << dec << rdRequest.len
167  << std::endl;
168  rdRequestOut.Push(rdRequest);
169  addr += (len+1)*bytesPerBeat;
170  ctr++;
171  }
172  }
173  }
174  }
175 
176  void run_rd_sink() {
177  rdRespIn.Reset();
178  done_read = 0;
179  int ctr = 0;
180 
181  while (1) {
182  wait();
183  RdResp<Cfg> rdResp = rdRespIn.Pop();
184  typename axi::axi4<Cfg>::Data rd_data_expected = dataQ.front(); dataQ.pop();
185 
186  std::cout << "@" << sc_time_stamp() << " read sink received response:"
187  << "\t last = " << rdResp.last
188  << "\t data = " << hex << rdResp.data
189  << "\t expected = " << hex << rd_data_expected
190  << std::endl;
191  NVHLS_ASSERT_MSG(rdResp.data == rd_data_expected, "Read response data did not match expected value");
192 
193  if (rdResp.last == 1) ctr++;
194  if (ctr == read_count) done_read = 1;
195  }
196  }
197 };
198 
199 #endif
The struct for read responses for AxiMasterGate.
The struct for read requests for AxiMasterGate.
The struct for write requests for AxiMasterGate.
NVUINTW(Wrapped< T >::width) TypeToNVUINT(T in)
Convert Type to NVUINT.
Definition: TypeToBits.h:115
SC_MODULE(Host)
A testbench component to verify AxiMasterGate.
Definition: Host.h:41
The base axi4 class parameterized according a valid config.
Definition: axi4.h:58
The struct for write responses for AxiMasterGate.
#define NVHLS_ASSERT_MSG(X, MSG)
Definition: nvhls_assert.h:116