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