MatchLib
All Classes Namespaces Files Functions Modules Pages
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
40template <typename Cfg>
41SC_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)
#define CDCOUT(x, y)
Definition hls_globals.h:73
#define NVUINTW(width)
Definition nvhls_types.h:35
nvhls_t< W >::nvuint_t get_slc(type X, const unsigned int i)
Function that returns slice of bits.
Definition nvhls_int.h:437
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.