MatchLib
axi4.h
1 /*
2  * Copyright (c) 2017-2019, 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 <nvhls_connections.h>
22 #include <nvhls_assert.h>
23 #include <nvhls_message.h>
24 #include <nvhls_module.h>
25 
26 #include <UIntOrEmpty.h>
27 
28 #include <axi/axi4_encoding.h>
29 #include <axi/axi4_configs.h>
30 
35 namespace axi {
36 
57 template <typename Cfg>
58 class axi4 {
59  public:
60  typedef AXI4_Encoding Enc;
61 
62  enum {
63  DATA_WIDTH = Cfg::dataWidth,
64  ADDR_WIDTH = Cfg::addrWidth,
65  ID_WIDTH = Cfg::idWidth,
66  BID_WIDTH = (Cfg::useWriteResponses == 0 ? 0 : Cfg::idWidth),
67  ALEN_WIDTH =
68  (Cfg::useBurst != 0 ? nvhls::log2_ceil<Cfg::maxBurstSize>::val : 0),
69  ASIZE_WIDTH = (Cfg::useVariableBeatSize != 0 ? 3 : 0),
70  LAST_WIDTH = (Cfg::useLast != 0 ? 1 : 0),
71  CACHE_WIDTH = (Cfg::useCache != 0 ? Enc::ARCACHE::_WIDTH : 0),
72  BURST_WIDTH = ((Cfg::useBurst != 0 &&
73  (Cfg::useFixedBurst != 0 || Cfg::useWrapBurst != 0))
74  ? Enc::AXBURST::_WIDTH
75  : 0),
76  WSTRB_WIDTH = (Cfg::useWriteStrobes != 0 ? (DATA_WIDTH >> 3) : 0),
77  RESP_WIDTH = Enc::XRESP::_WIDTH,
78  // TODO - The B channel ought to disappear entirely if useWriteResponses is
79  // 0, but that will require substantial refactoring. For now we leave
80  // RESP_WIDTH so there is a data stub in the ready-valid interface.
81 
82  AUSER_WIDTH = Cfg::aUserWidth,
83  WUSER_WIDTH = Cfg::wUserWidth,
84  BUSER_WIDTH = (Cfg::useWriteResponses == 0 ? 0 : Cfg::bUserWidth),
85  RUSER_WIDTH = Cfg::rUserWidth,
86  };
87 
88  typedef NVUINTW(ADDR_WIDTH) Addr;
89  typedef NVUINTW(DATA_WIDTH) Data;
90  typedef typename nvhls::UIntOrEmpty<ID_WIDTH>::T Id;
91  typedef typename nvhls::UIntOrEmpty<BID_WIDTH>::T BId;
92  typedef typename nvhls::UIntOrEmpty<ALEN_WIDTH>::T BeatNum;
93  typedef typename nvhls::UIntOrEmpty<ASIZE_WIDTH>::T BeatSize;
94  typedef typename nvhls::UIntOrEmpty<LAST_WIDTH>::T Last;
95  typedef typename nvhls::UIntOrEmpty<WSTRB_WIDTH>::T Wstrb;
96  typedef typename nvhls::UIntOrEmpty<CACHE_WIDTH>::T Cache;
97  typedef typename nvhls::UIntOrEmpty<BURST_WIDTH>::T Burst;
98  typedef NVUINTW(RESP_WIDTH) Resp;
99 
100  typedef typename nvhls::UIntOrEmpty<AUSER_WIDTH>::T AUser;
101  typedef typename nvhls::UIntOrEmpty<WUSER_WIDTH>::T WUser;
102  typedef typename nvhls::UIntOrEmpty<BUSER_WIDTH>::T BUser;
103  typedef typename nvhls::UIntOrEmpty<RUSER_WIDTH>::T RUser;
104 
108  struct AddrPayload : public nvhls_message {
109  Id id;
110  Addr addr;
111  Burst burst;
112  BeatNum len; // A*LEN
113  BeatSize size; // A*SIZE
114  Cache cache;
115  AUser auser;
116 
117  static const unsigned int width = ADDR_WIDTH + ID_WIDTH + ALEN_WIDTH +
118  ASIZE_WIDTH + BURST_WIDTH + CACHE_WIDTH +
119  AUSER_WIDTH;
120 
121  AddrPayload() {
122  if(ID_WIDTH > 0)
123  id = 0;
124  addr = 0; // NVUINT, ADDR_WIDTH always > 0
125  if(ALEN_WIDTH > 0)
126  len = 0;
127  if(ASIZE_WIDTH > 0)
128  size = 0;
129  if(BURST_WIDTH > 0)
130  burst = 0;
131  if(CACHE_WIDTH > 0)
132  cache = 0;
133  if(AUSER_WIDTH > 0)
134  auser = 0;
135  }
136 
137  template <unsigned int Size>
138  void Marshall(Marshaller<Size> &m) {
139  m &id;
140  m &addr;
141  m &len;
142  m &size;
143  m &burst;
144  m &cache;
145  m &auser;
146  }
147 
148 #ifdef CONNECTIONS_SIM_ONLY
149  inline friend void sc_trace(sc_trace_file *tf, const AddrPayload& v, const std::string& NAME ) {
150  sc_trace(tf,v.id, NAME + ".id");
151  sc_trace(tf,v.addr, NAME + ".addr");
152  sc_trace(tf,v.len, NAME + ".len");
153  }
154 #endif
155 
156  inline friend std::ostream& operator<<(ostream& os, const AddrPayload& rhs)
157  {
158  if (ID_WIDTH > 0)
159  os << dec << "id:" << rhs.id << " ";
160  os << hex << "addr:" << rhs.addr << " ";
161  if (ALEN_WIDTH > 0)
162  os << dec << "len:" << rhs.len << " ";
163  if (ASIZE_WIDTH > 0)
164  os << dec << "size:" << rhs.size << " ";
165  if (BURST_WIDTH > 0)
166  os << dec << "burst:" << rhs.burst << " ";
167  if (CACHE_WIDTH > 0)
168  os << dec << "cache:" << rhs.cache << " ";
169  if (AUSER_WIDTH > 0)
170  os << hex << "auser:" << rhs.auser << " ";
171  return os;
172  }
173 
174  };
175 
180  struct ReadPayload : public nvhls_message {
181  Id id;
182  Data data;
183  Resp resp;
184  Last last;
185  RUser ruser;
186 
187  static const unsigned int width =
188  DATA_WIDTH + RESP_WIDTH + ID_WIDTH + LAST_WIDTH + RUSER_WIDTH;
189 
190  ReadPayload() {
191  if(ID_WIDTH > 0)
192  id = 0;
193  data = 0; // NVUINT, DATA_WIDTH always > 0
194  resp = 0; // NVUINT, RESP_WIDTH always > 0
195  if(LAST_WIDTH > 0)
196  last = 0;
197  if(RUSER_WIDTH > 0)
198  ruser = 0;
199  }
200 
201  template <unsigned int Size>
202  void Marshall(Marshaller<Size> &m) {
203  m &id;
204  m &data;
205  m &resp;
206  m &last;
207  m &ruser;
208  }
209 
210 #ifdef CONNECTIONS_SIM_ONLY
211  inline friend void sc_trace(sc_trace_file *tf, const ReadPayload& v, const std::string& NAME ) {
212  sc_trace(tf,v.id, NAME + ".id");
213  sc_trace(tf,v.data, NAME + ".data");
214  sc_trace(tf,v.last, NAME + ".last");
215  }
216 #endif
217 
218  inline friend std::ostream& operator<<(ostream& os, const ReadPayload& rhs)
219  {
220  if (ID_WIDTH > 0)
221  os << dec << "id:" << rhs.id << " ";
222  os << hex << "data:" << rhs.data << " ";
223  os << dec << "resp:" << rhs.resp << " ";
224  if (LAST_WIDTH > 0)
225  os << dec << "last:" << rhs.last << " ";
226  if (RUSER_WIDTH > 0)
227  os << hex << "user:" << rhs.ruser << " ";
228  return os;
229  }
230  };
231 
236  struct WRespPayload : public nvhls_message {
237  BId id;
238  Resp resp;
239  BUser buser;
240 
241  static const unsigned int width = RESP_WIDTH + BID_WIDTH + BUSER_WIDTH;
242 
243  WRespPayload() {
244  if(ID_WIDTH > 0)
245  id = 0;
246  resp = 0; // NVUINT, RESP_WIDTH always > 0
247  if(BUSER_WIDTH > 0)
248  buser = 0;
249  }
250 
251  template <unsigned int Size>
252  void Marshall(Marshaller<Size> &m) {
253  m &id;
254  m &resp;
255  m &buser;
256  }
257 
258 #ifdef CONNECTIONS_SIM_ONLY
259  inline friend void sc_trace(sc_trace_file *tf, const WRespPayload& v, const std::string& NAME ) {
260  sc_trace(tf,v.id, NAME + ".id");
261  sc_trace(tf,v.resp, NAME + ".resp");
262  }
263 #endif
264 
265  inline friend std::ostream& operator<<(ostream& os, const WRespPayload& rhs)
266  {
267  if (ID_WIDTH > 0)
268  os << dec << "id:" << rhs.id << " ";
269  os << dec << "resp:" << rhs.resp << " ";
270  if (BUSER_WIDTH > 0)
271  os << hex << "buser:" << rhs.buser << " ";
272  return os;
273  }
274  };
275 
279  struct WritePayload : public nvhls_message {
280  // no id here!
281  Data data;
282  Last last;
283  Wstrb wstrb;
284  WUser wuser;
285 
286  WritePayload() {
287  data = 0; // NVUINT, DATA_WIDTH always > 0
288  if(LAST_WIDTH > 0)
289  last = 0;
290  if(WSTRB_WIDTH > 0)
291  wstrb = ~0;
292  if(WUSER_WIDTH > 0)
293  wuser = 0;
294  }
295 
296  static const unsigned int width =
297  DATA_WIDTH + LAST_WIDTH + WSTRB_WIDTH + WUSER_WIDTH;
298 
299  template <unsigned int Size>
300  void Marshall(Marshaller<Size> &m) {
301  m &data;
302  m &last;
303  m &wstrb;
304  m &wuser;
305  }
306 
307 #ifdef CONNECTIONS_SIM_ONLY
308  inline friend void sc_trace(sc_trace_file *tf, const WritePayload& v, const std::string& NAME ) {
309  sc_trace(tf,v.data, NAME + ".data");
310  sc_trace(tf,v.last, NAME + ".last");
311  sc_trace(tf,v.wstrb, NAME + ".wstrb");
312  }
313 #endif
314 
315  inline friend std::ostream& operator<<(ostream& os, const WritePayload& rhs)
316  {
317  os << hex << "data:" << rhs.data << " ";
318  if (LAST_WIDTH > 0)
319  os << dec << "last:" << rhs.last << " ";
320  if (WSTRB_WIDTH > 0)
321  os << hex << "wstrb:" << rhs.wstrb << " ";
322  if (WUSER_WIDTH > 0)
323  os << hex << "wuser:" << rhs.wuser << " ";
324  return os;
325  }
326  };
327 
334  class read {
335  public:
339  template <Connections::connections_port_t PortType = AUTO_PORT>
340  class chan {
341  public:
342  typedef Connections::Combinational<AddrPayload, PortType> ARChan;
343  typedef Connections::Combinational<ReadPayload, PortType> RChan;
344 
345  ARChan ar; // master to slave
346  RChan r; // slave to master
347 
348  chan(const char *name)
349  : ar(nvhls_concat(name, "_ar")), r(nvhls_concat(name, "_r")){};
350 
351  // TODO: Implement AXI protocol checker
352  }; // read::chan
353 
357  template <Connections::connections_port_t PortType = AUTO_PORT>
358  class master {
359  public:
360  typedef Connections::Out<AddrPayload, PortType> ARPort;
361  typedef Connections::In<ReadPayload, PortType> RPort;
362 
363  ARPort ar;
364  RPort r;
365 
366  master(const char *name)
367  : ar(nvhls_concat(name, "_ar")), r(nvhls_concat(name, "_r")) {}
368 
369  void reset() {
370  ar.Reset();
371  r.Reset();
372  }
373 
374  ReadPayload query(const AddrPayload &addr) {
375  // TODO: add nb version with state
376  ar.Push(addr);
377  return r.Pop();
378  }
379 
380  template <class C>
381  void operator()(C &c) {
382  ar(c.ar);
383  r(c.r);
384  }
385  }; // read::master
386 
390  template <Connections::connections_port_t PortType = AUTO_PORT>
391  class slave {
392  public:
393  typedef Connections::In<AddrPayload, PortType> ARPort;
394  typedef Connections::Out<ReadPayload, PortType> RPort;
395 
396  ARPort ar;
397  RPort r;
398 
399  slave(const char *name)
400  : ar(nvhls_concat(name, "_ar")), r(nvhls_concat(name, "_r")) {}
401 
402  void reset() {
403  ar.Reset();
404  r.Reset();
405  }
406 
407  AddrPayload aread() { return ar.Pop(); }
408 
409  bool nb_aread(AddrPayload &addr) { return ar.PopNB(addr); }
410 
411  void rwrite(const ReadPayload &data) { r.Push(data); }
412 
413  bool nb_rwrite(const ReadPayload &data) { return r.PushNB(data); }
414 
415  template <class C>
416  void operator()(C &c) {
417  ar(c.ar);
418  r(c.r);
419  }
420  }; // read::slave
421  }; // read
422 
429  class write {
430  public:
434  template <Connections::connections_port_t PortType = AUTO_PORT>
435  class chan {
436  public:
437  typedef Connections::Combinational<AddrPayload, PortType> AWChan;
438  typedef Connections::Combinational<WritePayload, PortType> WChan;
439  typedef Connections::Combinational<WRespPayload, PortType> BChan;
440 
441  AWChan aw; // master to slave
442  WChan w; // master to slave
443  BChan b; // slave to master
444 
445  chan(const char *name)
446  : aw(nvhls_concat(name, "_aw")),
447  w(nvhls_concat(name, "_w")),
448  b(nvhls_concat(name, "_b")){};
449 
450  // TODO: Implement AXI protocol checker
451  }; // write::chan
452 
456  template <Connections::connections_port_t PortType = AUTO_PORT>
457  class master {
458  public:
459  typedef Connections::Out<AddrPayload, PortType> AWPort;
460  typedef Connections::Out<WritePayload, PortType> WPort;
461  typedef Connections::In<WRespPayload, PortType> BPort;
462 
463  AWPort aw;
464  WPort w;
465  BPort b;
466 
467  master(const char *name)
468  : aw(nvhls_concat(name, "_aw")),
469  w(nvhls_concat(name, "_w")),
470  b(nvhls_concat(name, "_b")) {}
471 
472  void reset() {
473  aw.Reset();
474  w.Reset();
475  b.Reset();
476  }
477 
478  WRespPayload write(const AddrPayload &addr, const WritePayload &data) {
479  // TODO: add nb version with state
480  aw.Push(addr);
481  w.Push(data);
482  return b.Pop();
483  }
484 
485  template <class C>
486  void operator()(C &c) {
487  aw(c.aw);
488  w(c.w);
489  b(c.b);
490  }
491  }; // write::master
492 
496  template <Connections::connections_port_t PortType = AUTO_PORT>
497  class slave {
498  public:
499  typedef Connections::In<AddrPayload, PortType> AWPort;
500  typedef Connections::In<WritePayload, PortType> WPort;
501  typedef Connections::Out<WRespPayload, PortType> BPort;
502 
503  AWPort aw;
504  WPort w;
505  BPort b;
506 
507  bool got_waddr;
508  AddrPayload stored_waddr;
509 
510  slave(const char *name)
511  : aw(nvhls_concat(name, "_aw")),
512  w(nvhls_concat(name, "_w")),
513  b(nvhls_concat(name, "_b")),
514  got_waddr(false) {}
515 
516  void reset() {
517  aw.Reset();
518  w.Reset();
519  b.Reset();
520  }
521 
522  void wread(AddrPayload &addr, WritePayload &data) {
523  addr = aw.Pop();
524  data = w.Pop();
525  }
526 
527  bool nb_wread(AddrPayload &addr, WritePayload &data) {
528  if (!got_waddr) {
529  if (!aw.PopNB(addr)) {
530  return false;
531  } else {
532  got_waddr = true;
533  stored_waddr = addr;
534  }
535  } else {
536  addr = stored_waddr;
537  }
538 
539  if (w.PopNB(data)) {
540  got_waddr = false;
541  return true;
542  } else {
543  return false;
544  }
545  }
546 
547  void bwrite(const WRespPayload &resp) { b.Push(resp); }
548 
549  bool nb_bwrite(const WRespPayload &resp) { return b.PushNB(resp); }
550 
551  template <class C>
552  void operator()(C &c) {
553  aw(c.aw);
554  w(c.w);
555  b(c.b);
556  }
557  }; // write::slave
558  }; // write
559 }; // axi4
560 }; // axi
561 
562 #endif
The AXI write class.
Definition: axi4.h:429
#define nvhls_concat(s1, s2)
nvhls_concat define: Concatenate two strings, separate with an underscore.Useful for concatenating tw...
Definition: nvhls_module.h:59
A struct composed of the signals associated with an AXI write response.
Definition: axi4.h:236
The AXI read channel, used for connecting an AXI master and AXI slave.
Definition: axi4.h:340
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
The AXI read slave port. This port has an AR request channel as input and an R response channel as ou...
Definition: axi4.h:391
The AXI write channel, used for connecting an AXI master and AXI slave.
Definition: axi4.h:435
A struct composed of the signals associated with an AXI read response.
Definition: axi4.h:180
The AXI write master port. This port has AW and W request channels as outputs and a B response channe...
Definition: axi4.h:457
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
The AXI read master port. This port has an AR request channel as output and an R response channel as ...
Definition: axi4.h:358
Hardcoded values associated with the AXI4 standard.
Definition: axi4_encoding.h:30
The AXI read class.
Definition: axi4.h:334
The AXI write slave port. This port has AW and W request channels as inputs and a B response channel ...
Definition: axi4.h:497
The axi namespace contains classes and definitions related to the AXI standard.
Definition: axi4.h:35