MatchLib
All Classes Namespaces Files Functions Modules Pages
axi4.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_AXI4_H_
18#define _AXI_AXI4_H_
19
20#include <systemc>
21#include <connections/connections.h>
22#include <connections/connections_utils.h>
23
24#include "auto_gen_fields.h"
25
26#include <nvhls_connections.h>
27#include <nvhls_assert.h>
28#include <nvhls_message.h>
29#include <nvhls_module.h>
30
31#include <UIntOrEmpty.h>
32
33#include <axi/axi4_encoding.h>
34#include <axi/axi4_configs.h>
35
36
41namespace axi {
42
63template <typename Cfg>
64class axi4 {
65 public:
66 typedef AXI4_Encoding Enc;
67
68 enum {
69 DATA_WIDTH = Cfg::dataWidth,
70 ADDR_WIDTH = Cfg::addrWidth,
71 ID_WIDTH = Cfg::idWidth,
72 BID_WIDTH = (Cfg::useWriteResponses == 0 ? 0 : Cfg::idWidth),
73 ALEN_WIDTH =
74 (Cfg::useBurst != 0 ? nvhls::log2_ceil<Cfg::maxBurstSize>::val : 0),
75 ASIZE_WIDTH = (Cfg::useVariableBeatSize != 0 ? 3 : 0),
76 LAST_WIDTH = (Cfg::useLast != 0 ? 1 : 0),
77 CACHE_WIDTH = (Cfg::useCache != 0 ? Enc::ARCACHE::_WIDTH : 0),
78 BURST_WIDTH = ((Cfg::useBurst != 0 &&
79 (Cfg::useFixedBurst != 0 || Cfg::useWrapBurst != 0))
80 ? Enc::AXBURST::_WIDTH
81 : 0),
82 WSTRB_WIDTH = (Cfg::useWriteStrobes != 0 ? (DATA_WIDTH >> 3) : 0),
83 RESP_WIDTH = Enc::XRESP::_WIDTH,
84 // TODO - The B channel ought to disappear entirely if useWriteResponses is
85 // 0, but that will require substantial refactoring. For now we leave
86 // RESP_WIDTH so there is a data stub in the ready-valid interface.
87
88 AUSER_WIDTH = Cfg::aUserWidth,
89 WUSER_WIDTH = Cfg::wUserWidth,
90 BUSER_WIDTH = (Cfg::useWriteResponses == 0 ? 0 : Cfg::bUserWidth),
91 RUSER_WIDTH = Cfg::rUserWidth,
92 };
93
94 typedef NVUINTW(ADDR_WIDTH) Addr;
95 typedef NVUINTW(DATA_WIDTH) Data;
96 typedef typename nvhls::UIntOrEmpty<ID_WIDTH>::T Id;
97 typedef typename nvhls::UIntOrEmpty<BID_WIDTH>::T BId;
98 typedef typename nvhls::UIntOrEmpty<ALEN_WIDTH>::T BeatNum;
99 typedef typename nvhls::UIntOrEmpty<ASIZE_WIDTH>::T BeatSize;
100 typedef typename nvhls::UIntOrEmpty<LAST_WIDTH>::T Last;
101 typedef typename nvhls::UIntOrEmpty<WSTRB_WIDTH>::T Wstrb;
102 typedef typename nvhls::UIntOrEmpty<CACHE_WIDTH>::T Cache;
103 typedef typename nvhls::UIntOrEmpty<BURST_WIDTH>::T Burst;
104 typedef NVUINTW(RESP_WIDTH) Resp;
105
106 typedef typename nvhls::UIntOrEmpty<AUSER_WIDTH>::T AUser;
107 typedef typename nvhls::UIntOrEmpty<WUSER_WIDTH>::T WUser;
108 typedef typename nvhls::UIntOrEmpty<BUSER_WIDTH>::T BUser;
109 typedef typename nvhls::UIntOrEmpty<RUSER_WIDTH>::T RUser;
110
114 struct AddrPayload : public nvhls_message {
115 Id id;
116 Addr addr;
117 Burst burst;
118 BeatNum len; // A*LEN
119 BeatSize size; // A*SIZE
120 Cache cache;
121 AUser auser;
122
123 AUTO_GEN_FIELD_METHODS(AddrPayload, ( \
124 id \
125 , addr \
126 , burst \
127 , len \
128 , size \
129 , cache \
130 , auser \
131 ) )
132 //
133
134
135 AddrPayload() {
136 if(ID_WIDTH > 0)
137 id = 0;
138 addr = 0; // NVUINT, ADDR_WIDTH always > 0
139 if(ALEN_WIDTH > 0)
140 len = 0;
141 if(ASIZE_WIDTH > 0)
142 size = 0;
143 if(BURST_WIDTH > 0)
144 burst = 0;
145 if(CACHE_WIDTH > 0)
146 cache = 0;
147 if(AUSER_WIDTH > 0)
148 auser = 0;
149 }
150
151 };
152
157 struct ReadPayload : public nvhls_message {
158 Id id;
159 Data data;
160 Resp resp;
161 Last last;
162 RUser ruser;
163
164 AUTO_GEN_FIELD_METHODS(ReadPayload, ( \
165 id \
166 , data \
167 , resp \
168 , last \
169 , ruser \
170 ) )
171 //
172
173
174 ReadPayload() {
175 if(ID_WIDTH > 0)
176 id = 0;
177 data = 0; // NVUINT, DATA_WIDTH always > 0
178 resp = 0; // NVUINT, RESP_WIDTH always > 0
179 if(LAST_WIDTH > 0)
180 last = 0;
181 if(RUSER_WIDTH > 0)
182 ruser = 0;
183 }
184 };
185
190 struct WRespPayload : public nvhls_message {
191 BId id;
192 Resp resp;
193 BUser buser;
194
195 AUTO_GEN_FIELD_METHODS(WRespPayload, ( \
196 id \
197 , resp \
198 , buser \
199 ) )
200 //
201
202 WRespPayload() {
203 if(ID_WIDTH > 0)
204 id = 0;
205 resp = 0; // NVUINT, RESP_WIDTH always > 0
206 if(BUSER_WIDTH > 0)
207 buser = 0;
208 }
209
210 };
211
215 struct WritePayload : public nvhls_message {
216 // no id here!
217 Data data;
218 Last last;
219 Wstrb wstrb;
220 WUser wuser;
221
222 AUTO_GEN_FIELD_METHODS(WritePayload, ( \
223 data \
224 , last \
225 , wstrb \
226 , wuser \
227 ) )
228 //
229
230 WritePayload() {
231 data = 0; // NVUINT, DATA_WIDTH always > 0
232 if(LAST_WIDTH > 0)
233 last = 0;
234 if(WSTRB_WIDTH > 0)
235 wstrb = ~0;
236 if(WUSER_WIDTH > 0)
237 wuser = 0;
238 }
239 };
240
247 class read {
248 public:
252 template <Connections::connections_port_t PortType = AUTO_PORT>
253 class chan {
254 public:
255 typedef Connections::Combinational<AddrPayload, PortType> ARChan;
256 typedef Connections::Combinational<ReadPayload, PortType> RChan;
257
258 ARChan ar; // manager to subordinate
259 RChan r; // subordinate to manager
260
261 chan(const char *name)
262 : ar(nvhls_concat(name, "_ar")), r(nvhls_concat(name, "_r")){};
263
264 // TODO: Implement AXI protocol checker
265 }; // read::chan
266
270 template <Connections::connections_port_t PortType = AUTO_PORT>
271 class manager {
272 public:
273 typedef Connections::Out<AddrPayload, PortType> ARPort;
274 typedef Connections::In<ReadPayload, PortType> RPort;
275
276 ARPort ar;
277 RPort r;
278
279 manager(const char *name)
280 : ar(nvhls_concat(name, "_ar")), r(nvhls_concat(name, "_r")) {}
281
282 void reset() {
283 ar.Reset();
284 r.Reset();
285 }
286
287 ReadPayload query(const AddrPayload &addr) {
288 // TODO: add nb version with state
289 ar.Push(addr);
290 return r.Pop();
291 }
292
293 template <class C>
294 void operator()(C &c) {
295 ar(c.ar);
296 r(c.r);
297 }
298 }; // read::manager
299
303 template <Connections::connections_port_t PortType = AUTO_PORT>
305 public:
306 typedef Connections::In<AddrPayload, PortType> ARPort;
307 typedef Connections::Out<ReadPayload, PortType> RPort;
308
309 ARPort ar;
310 RPort r;
311
312 subordinate(const char *name)
313 : ar(nvhls_concat(name, "_ar")), r(nvhls_concat(name, "_r")) {}
314
315 void reset() {
316 ar.Reset();
317 r.Reset();
318 }
319
320 AddrPayload aread() { return ar.Pop(); }
321
322 bool nb_aread(AddrPayload &addr) { return ar.PopNB(addr); }
323
324 void rwrite(const ReadPayload &data) { r.Push(data); }
325
326 bool nb_rwrite(const ReadPayload &data) { return r.PushNB(data); }
327
328 template <class C>
329 void operator()(C &c) {
330 ar(c.ar);
331 r(c.r);
332 }
333 }; // read::subordinate
334 }; // read
335
342 class write {
343 public:
347 template <Connections::connections_port_t PortType = AUTO_PORT>
348 class chan {
349 public:
350 typedef Connections::Combinational<AddrPayload, PortType> AWChan;
351 typedef Connections::Combinational<WritePayload, PortType> WChan;
352 typedef Connections::Combinational<WRespPayload, PortType> BChan;
353
354 AWChan aw; // manager to subordinate
355 WChan w; // manager to subordinate
356 BChan b; // subordinate to manager
357
358 chan(const char *name)
359 : aw(nvhls_concat(name, "_aw")),
360 w(nvhls_concat(name, "_w")),
361 b(nvhls_concat(name, "_b")){};
362
363 // TODO: Implement AXI protocol checker
364 }; // write::chan
365
369 template <Connections::connections_port_t PortType = AUTO_PORT>
370 class manager {
371 public:
372 typedef Connections::Out<AddrPayload, PortType> AWPort;
373 typedef Connections::Out<WritePayload, PortType> WPort;
374 typedef Connections::In<WRespPayload, PortType> BPort;
375
376 AWPort aw;
377 WPort w;
378 BPort b;
379
380 manager(const char *name)
381 : aw(nvhls_concat(name, "_aw")),
382 w(nvhls_concat(name, "_w")),
383 b(nvhls_concat(name, "_b")) {}
384
385 void reset() {
386 aw.Reset();
387 w.Reset();
388 b.Reset();
389 }
390
391 WRespPayload write(const AddrPayload &addr, const WritePayload &data) {
392 // TODO: add nb version with state
393 aw.Push(addr);
394 w.Push(data);
395 return b.Pop();
396 }
397
398 template <class C>
399 void operator()(C &c) {
400 aw(c.aw);
401 w(c.w);
402 b(c.b);
403 }
404 }; // write::manager
405
409 template <Connections::connections_port_t PortType = AUTO_PORT>
411 public:
412 typedef Connections::In<AddrPayload, PortType> AWPort;
413 typedef Connections::In<WritePayload, PortType> WPort;
414 typedef Connections::Out<WRespPayload, PortType> BPort;
415
416 AWPort aw;
417 WPort w;
418 BPort b;
419
420 bool got_waddr;
421 AddrPayload stored_waddr;
422
423 subordinate(const char *name)
424 : aw(nvhls_concat(name, "_aw")),
425 w(nvhls_concat(name, "_w")),
426 b(nvhls_concat(name, "_b")),
427 got_waddr(false) {}
428
429 void reset() {
430 aw.Reset();
431 w.Reset();
432 b.Reset();
433 }
434
435 void wread(AddrPayload &addr, WritePayload &data) {
436 addr = aw.Pop();
437 data = w.Pop();
438 }
439
440 bool nb_wread(AddrPayload &addr, WritePayload &data) {
441 if (!got_waddr) {
442 if (!aw.PopNB(addr)) {
443 return false;
444 } else {
445 got_waddr = true;
446 stored_waddr = addr;
447 }
448 } else {
449 addr = stored_waddr;
450 }
451
452 if (w.PopNB(data)) {
453 got_waddr = false;
454 return true;
455 } else {
456 return false;
457 }
458 }
459
460 void bwrite(const WRespPayload &resp) { b.Push(resp); }
461
462 bool nb_bwrite(const WRespPayload &resp) { return b.PushNB(resp); }
463
464 template <class C>
465 void operator()(C &c) {
466 aw(c.aw);
467 w(c.w);
468 b(c.b);
469 }
470 }; // write::subordinate
471 }; // write
472}; // axi4
473}; // axi
474
475#endif
476
Hardcoded values associated with the AXI4 standard.
The AXI read channel, used for connecting an AXI manager and AXI subordinate.
Definition axi4.h:253
The AXI read manager port. This port has an AR request channel as output and an R response channel as...
Definition axi4.h:271
The AXI read subordinate port. This port has an AR request channel as input and an R response channel...
Definition axi4.h:304
The AXI read class.
Definition axi4.h:247
The AXI write channel, used for connecting an AXI manager and AXI subordinate.
Definition axi4.h:348
The AXI write manager port. This port has AW and W request channels as outputs and a B response chann...
Definition axi4.h:370
The AXI write subordinate port. This port has AW and W request channels as inputs and a B response ch...
Definition axi4.h:410
The AXI write class.
Definition axi4.h:342
The base axi4 class parameterized according a valid config.
Definition axi4.h:64
#define NVUINTW(width)
Definition nvhls_types.h:35
#define nvhls_concat(s1, s2)
nvhls_concat define: Concatenate two strings, separate with an underscore.
The axi namespace contains classes and definitions related to the AXI standard.
Definition axi4.h:41
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