MatchLib
WHVCRouter.h
1 /*
2  * Copyright (c) 2016-2022, 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 __WHVCROUTER_H__
18 #define __WHVCROUTER_H__
19 
20 // WormHole router with virtual channel and Multicast support.
21 // -Source Routing is assumed.
22 // -First flit stores route information.
23 // -Multi-cast to 1 remote port and many local ports.
24 // -Changing the destination format and route computation can allow multi-cast
25 // to all ports without distinction between local and remote ports.
26 // -Port numbers: local ports are numbered 0 to L-1, remote ports are numbered
27 // L to L+R-1.
28 // -1 hot encoding for local destination - send flit to port i if dest[i]=1.
29 // -Destination format per hop <Remote Dst> <Local Dst> .
30 // -Destination Width per Hop = r_dest_port_width_per_hop +
31 // l_dest_port_width_per_hop
32 // -Remote destination width is log_num_rports
33 // -Local destination width is num_lports
34 // -First flit format: <Dest-N> ... <Dest-2> <Dest-1>
35 // -This implementation assumes that virtual channel information is specified
36 // at the LSBs of packet id.
37 // -Termination condition: if dest of next hop is 0
38 
39 #include <nvhls_packet.h>
40 #include <nvhls_vector.h>
41 #include <Arbiter.h>
42 #include <hls_globals.h>
43 #include <fifo.h>
44 #include <one_hot_to_bin.h>
45 #include <nvhls_assert.h>
46 #include <crossbar.h>
47 
48 template <int NumLPorts, int NumRports, int NumVchannels, int BufferSize,
49  typename FlitType = Flit<64, 0, 0, 0, FlitId2bit, WormHole> >
50 class WHVCRouterBase : public sc_module {
51 public:
52  static const int kDebugLevel = 2;
53  typedef FlitType Flit_t;
54  // Declare constants
55  enum {
56  num_lports = NumLPorts,
57  num_rports = NumRports,
58  num_ports = num_lports + num_rports,
59  num_vchannels = NumVchannels,
60  log_num_vchannels = nvhls::index_width<num_vchannels>::val,
61  log_num_lports = nvhls::index_width<num_lports>::val,
62  log_num_rports = nvhls::index_width<num_rports>::val,
63  log_num_ports = nvhls::index_width<num_ports>::val,
64  buffersize = BufferSize,
65  log_buffersize = nvhls::index_width<buffersize>::val,
66  log_buffersizeplus1 = nvhls::index_width<buffersize + 1>::val
67  };
68  typedef NVUINTW(log_buffersizeplus1) Credit_t;
69  typedef NVUINTW(1) Credit_ret_t;
70 
71  // Input / Output ports
72  Connections::In<Flit_t> in_port[num_ports];
73  Connections::Out<Flit_t> out_port[num_ports];
74 
75  // Credits
76  // Send out credit when buffer is popped
77  // Increment local credit when credits are read
78  // 1 credit counter per output port
79  Connections::In<Credit_ret_t> in_credit[num_ports * num_vchannels];
80  Connections::Out<Credit_ret_t> out_credit[num_ports * num_vchannels];
81  sc_in_clk clk;
82  sc_in<bool> rst;
83 
84  // Input FIFO Buffer
86 
87  // Credit registers to store credits for both producer and consumer
88  Credit_t credit_recv[num_ports * num_vchannels];
89  Credit_t credit_send[num_ports * num_vchannels];
90 
91  // Variable to register outputs
92  Flit_t flit_out[num_ports];
93 
94  // Constructor
95  SC_HAS_PROCESS(WHVCRouterBase);
96  WHVCRouterBase(sc_module_name name_) : sc_module(name_) {
97  SC_THREAD(process);
98  sensitive << clk.pos();
100  }
101 
102  // Function to receive credits from the consumers
103  void receive_credit() {
104  Credit_ret_t credit_in;
105 #pragma hls_unroll yes
106  for (int i = 0; i < num_ports * num_vchannels; i++) {
107  if (in_credit[i].PopNB(credit_in)) {
108  credit_recv[i] = credit_recv[i] + credit_in;
109  CDCOUT(sc_time_stamp() << ": " << name()
110  << " Read credit from credit port-"
111  << i << " " << credit_recv[i] << endl, kDebugLevel);
112  }
113  NVHLS_ASSERT_MSG(credit_recv[i] <= buffersize, "Total credits received cannot be larger than Buffer size");
114  }
115  }
116 
117  void send_credit() {
118 #pragma hls_unroll yes
119  for (int i = 0; i < num_ports * num_vchannels; i++) {
120  if (credit_send[i] > 0) {
121  Credit_ret_t credit_out = 1;
122  bool temp = out_credit[i].PushNB(credit_out);
123  if (temp) {
124  credit_send[i]--;
125  }
126  CDCOUT(sc_time_stamp() << ": " << name() << " Returning credit to port"
127  << i << " credit_send=" << credit_send[i]
128  << " Success: " << temp << endl, kDebugLevel);
129  }
130  }
131  }
132 
133  void fill_ififo() {
134  // Read input port if data is available and fill input buffers
135  Flit_t inflit[num_ports];
136 #pragma hls_unroll yes
137  for (int i = 0; i < num_ports; i++) {
138  if (in_port[i].PopNB(inflit[i])) {
139  CDCOUT(sc_time_stamp() << ": " << name() << " Read input from port-" << i
140  << endl, kDebugLevel);
141  if (num_vchannels > 1) {
142  NVUINTW(log_num_vchannels) vcin_tmp = inflit[i].get_packet_id();
143  NVHLS_ASSERT_MSG(!ififo.isFull(i * num_vchannels + vcin_tmp), "Input fifo is full");
144  ififo.push(inflit[i], i * num_vchannels + vcin_tmp);
145  } else {
146  NVHLS_ASSERT_MSG(!ififo.isFull(i), "Input fifo is full");
147  ififo.push(inflit[i], i);
148  }
149  }
150  }
151  }
152 
153  void peek_ififo(Flit_t flit_in[num_ports],
154  NVUINTW(log_num_vchannels) vcin[num_ports],
155  NVUINTW(num_ports) in_valid) {
156 
157 #pragma hls_unroll yes
158  for (int i = 0; i < num_ports; i++) { // Iterating through the inputs here
159  // FIFO Read
160  if (in_valid[i]) {
161  flit_in[i] = ififo.peek(i * num_vchannels + vcin[i]);
162  CDCOUT(sc_time_stamp()
163  << ": " << name() << hex << " Read from FIFO:"
164  << i * num_vchannels + vcin[i] << " Flit< " << flit_in[i].flit_id
165  << "," << flit_in[i].data.to_uint64() << ">" << dec << endl, kDebugLevel);
166  }
167  }
168  }
169 
170  void crossbar_traversal(Flit_t flit_in[num_ports], bool is_push[num_ports],
171  NVUINTW(log_num_ports) select_id[num_ports],
172  NVUINTW(log_num_vchannels) vcin[num_ports],
173  NVUINTW(log_num_vchannels) vcout[num_ports]) {
174 #pragma hls_unroll yes
175  for (int i = 0; i < num_ports; i++) { // Iterating through output ports here
176  if (is_push[i]) {
177  flit_out[i] = flit_in[select_id[i]];
178  vcout[i] = vcin[select_id[i]];
179  }
180  }
181  }
182 
183 
184  virtual void reset() { }
185  virtual void run() { }
186 
187  void process() {
188  for (int i = 0; i < num_ports; i++)
189  in_port[i].Reset();
190  for (int i = 0; i < num_ports; i++)
191  out_port[i].Reset();
192  for (int i = 0; i < num_ports * num_vchannels; i++)
193  out_credit[i].Reset();
194  for (int i = 0; i < num_ports * num_vchannels; i++)
195  in_credit[i].Reset();
196  ififo.reset();
197  reset();
198 
199  // Reset credit registers
200  for (int i = 0; i < num_ports * num_vchannels; i++) {
201  credit_send[i] = 0;
202  credit_recv[i] = buffersize;
203  }
204 
205  #pragma hls_pipeline_init_interval 1
206  while (1) {
207  wait();
208  run();
209  }
210  }
211 };
212 
213 // Specialization for SourceRouting
255 template <int NumLPorts, int NumRports, int NumVchannels, int BufferSize,
256  typename FlitType, int MaxHops>
257 class WHVCSourceRouter: public WHVCRouterBase<NumLPorts, NumRports, NumVchannels, BufferSize, FlitType> {
258 public:
259  // Declare constants
261  static const int kDebugLevel = 2;
262  typedef FlitType Flit_t;
263  enum {
264  num_lports = BaseClass::num_lports,
265  num_rports = BaseClass::num_rports,
266  num_ports = BaseClass::num_ports,
267  num_vchannels = BaseClass::num_vchannels,
268  log_num_rports = BaseClass::log_num_rports,
269  log_num_ports = BaseClass::log_num_ports,
270  log_num_vchannels = BaseClass::log_num_vchannels,
271  dest_width_per_hop = log_num_rports + num_lports,
272  dest_width = MaxHops * dest_width_per_hop,
273  };
274 
275  WHVCSourceRouter(sc_module_name name_): BaseClass(name_) {
276 
277  }
278 
279  Arbiter<num_ports> arbiter[num_ports];
280 
281  // Store output destination for each port per virtual channel with 1hot
282  // encoding
283  NVUINTW(num_ports) out_dest[num_ports][num_vchannels];
284 
285  // Variable to block output port until previous push is successful
286  NVUINTW(num_ports) out_stall;
287 
288  // Variable that indicates if the output port is available to get new packet
289  bool is_get_new_packet[num_ports * num_vchannels];
290 
291  void inputvc_arbiter(NVUINTW(log_num_vchannels) vcin[num_ports],
292  NVUINTW(num_ports) & in_valid) {
293 #pragma hls_unroll yes
294  for (int i = 0; i < num_ports; i++) { // Iterating through the inputs here
295  vcin[i] = 0;
296  // Doing static arbitration across input VCs here. VC0 has
297  // highest priority. We are assuming that input and output VCs
298  // are same.
299  if (num_vchannels > 1) {
300  NVUINTW(num_vchannels) vcin_valid = 0;
301  NVUINTW(log_num_vchannels) vcin_local = 0;
302 #pragma hls_unroll yes
303  for (int j = 0; j < num_vchannels; j++) {
304  if ((!this->ififo.isEmpty(i * num_vchannels + j))) {
305  vcin_valid[num_vchannels - j - 1] = 1;
306  in_valid[i] = 1;
307  }
308  }
309  if (in_valid[i] == 1) {
310  vcin_local =
311  nvhls::leading_ones<num_vchannels, NVUINTW(num_vchannels),
312  NVUINTW(log_num_vchannels)>(vcin_valid);
313  vcin[i] = num_vchannels - vcin_local - 1;
314  }
315  } else {
316 #pragma hls_unroll yes
317  for (int i = 0; i < num_ports; i++) {
318  vcin[i] = 0;
319  if (!this->ififo.isEmpty(i)) {
320  in_valid[i] = 1;
321  }
322  }
323  }
324 
325  }
326  }
327  void compute_route(Flit_t flit_in[num_ports],
328  NVUINTW(log_num_vchannels) vcin[num_ports],
329  NVUINTW(num_ports) in_valid) {
330 
331 #pragma hls_unroll yes
332  for (int i = 0; i < num_ports; i++) { // Iterating through the inputs here
333  if (in_valid[i]) {
334  // Route Computation: For source routing just copy from header flit
335  if (flit_in[i].flit_id.isHeader()) {
336  NVUINTW(dest_width)
337  route = nvhls::get_slc<dest_width>(flit_in[i].data, 0);
338  NVUINTW(dest_width_per_hop)
339  out_dest_local = nvhls::get_slc<dest_width_per_hop>(route, 0);
340  NVUINTW(dest_width) next_dests_local = route >> dest_width_per_hop;
341  flit_in[i].data =
342  nvhls::set_slc(flit_in[i].data, next_dests_local, 0);
343  NVUINTW(num_lports)
344  ldest = nvhls::get_slc<num_lports>(out_dest_local, 0);
345  NVUINTW(log_num_rports)
346  rdest = nvhls::get_slc<log_num_rports>(out_dest_local, num_lports);
347  NVUINTW(num_rports) rdest_1hot = 0;
348  if (next_dests_local != 0) {
349  rdest_1hot[rdest] = 1;
350  }
351  out_dest[i][vcin[i]] =
352  (static_cast<NVUINTW(num_ports)>(rdest_1hot) << num_lports) |
353  ldest;
354  }
355  }
356  }
357  }
358 
359  void flit_output(bool is_push[num_ports],
360  NVUINTW(log_num_vchannels) vcout[num_ports]) {
361 
362 #pragma hls_unroll yes
363  for (int i = 0; i < num_ports; i++) { // Iterating over outputs here
364  if (is_push[i] == true || out_stall[i] == 1) {
365  bool temp = this->out_port[i].PushNB(this->flit_out[i]);
366  if (this->flit_out[i].flit_id.isTail()) {
367  is_get_new_packet[i * num_vchannels + vcout[i]] = true;
368  } else {
369  is_get_new_packet[i * num_vchannels + vcout[i]] = false;
370  }
371  if (temp == 0)
372  out_stall[i] = 1;
373  else {
374  out_stall[i] = 0;
375  this->credit_recv[i * num_vchannels + vcout[i]]--;
376  }
377  CDCOUT(sc_time_stamp()
378  << ": " << this->name() << " OutPort " << i
379  << " Push success??: " << temp << " Decrementing Credit status "
380  << i * num_vchannels + vcout[i] << ": "
381  << this->credit_recv[i * num_vchannels + vcout[i]]
382  << " [Router] Out_stall: " << out_stall[i] << endl, kDebugLevel);
383  }
384  }
385  }
386 
387  void arbitration(Flit_t flit_in[num_ports], NVUINTW(num_ports) in_valid,
388  NVUINTW(log_num_vchannels) vcin[num_ports],
389  NVUINTW(num_ports) valid[num_ports],
390  NVUINTW(num_ports) select[num_ports],
391  NVUINTW(log_num_ports) select_id[num_ports]) {
392 
393 #pragma hls_unroll yes
394  for (int i = 0; i < num_ports; i++) { // Iterating through the outputs here
395  valid[i] = 0; // valid of ith output is set to 0 here
396  }
397 
398 #pragma hls_unroll yes
399  for (int i = 0; i < num_ports; i++) { // Iterating through the inputs here
400  if (in_valid[i]) {
401  bool not_head_flit = (!flit_in[i].flit_id.isHeader());
402 
403 #pragma hls_unroll yes
404  for (int k = 0; k < num_ports;
405  k++) { // Iterating through the outputs here
406  int out_idx = k * num_vchannels + vcin[i];
407 
408  // Set valid bit to 1 for local ports only if credits are available at
409  // the output port for the virtual channel chosen
410  // also make sure that the output is requested, and that it is not
411  // head flit, or output[vc] accepts new headers
412  valid[k][i] =
413  (((this->credit_recv[out_idx] != 0) && (out_dest[i][vcin[i]][k] == 1) &&
414  (is_get_new_packet[out_idx] || not_head_flit) &&
415  (out_stall[k] == 0))
416  ? 1
417  : 0);
418  CDCOUT(sc_time_stamp() << ": " << this->name() << " Input Port:" << i
419  << "Output port: " << k << " VC: " << vcin[i] << " valid: "
420  << valid[k][i] << " OutStall: " << out_stall[k]
421  << " Credit: " << this->credit_recv[out_idx] << " GetnewPacket: "
422  << is_get_new_packet[out_idx] << hex << " Flit " << " <"
423  << flit_in[i].flit_id << "," << flit_in[i].data.to_uint64()
424  << dec << ">" << endl, kDebugLevel);
425  }
426  }
427  }
428 
429 #ifdef ENABLE_MULTICAST
430  // For Multicast, supress local output valid if remote output is invalid
431  NVUINTW((num_ports * num_vchannels))
432  is_multicast = 0; // Store if an input is unicast or multicast
433  NVUINTW(log_num_ports) remote_portid[num_ports];
434  NVUINTW(log_num_lports) local_portid[num_ports];
435 
436 #pragma hls_unroll yes
437  for (int i = 0; i < num_ports; i++) { // Iterating through the inputs here
438 #pragma hls_unroll yes
439  for (int l = 0; l < num_lports;
440  l++) { // Iterating through the outputs here
441 #pragma hls_unroll yes
442  for (int r = num_lports; r < num_ports; r++) {
443  if (out_dest[i][vcin[i]][l] && out_dest[i][vcin[i]][r]) {
444  is_multicast[i * num_vchannels + vcin[i]] = 1;
445  remote_portid[i] = r;
446  local_portid[i] = l;
447  if (!(valid[l][i] && valid[r][i])) {
448  valid[l][i] = 0;
449  valid[r][i] = 0; // valid of local port is 1 only is valid of
450  // remote port is 1
451  CDCOUT(sc_time_stamp() << ": " << this->name() << " Input Port:" << i
452  << " Local port: " << l << " Remote port: " << r
453  << " VC: " << vcin[i] << " valid: "<< valid[l][i]
454  << " Multicast: " << is_multicast[i*num_vchannels + vcin[i]]
455  << endl, kDebugLevel);
456  }
457  }
458  }
459  }
460  }
461 #endif
462 
463 // Arbitrate for output port if it is header flit
464 #pragma hls_unroll yes
465  for (int i = 0; i < num_ports; i++) { // Iterating through the outputs here
466  select[i] = 0;
467  if (valid[i] != 0) { // There is an input waiting to send to output
468  // i, credits are available at output
469  select[i] = arbiter[i].pick(valid[i]);
470 
471  NVUINTW(num_ports) select_temp = select[i];
472  NVUINTW(log_num_ports) select_id_temp;
473  one_hot_to_bin<num_ports, log_num_ports>(select_temp, select_id_temp);
474  select_id[i] = select_id_temp;
475  CDCOUT(sc_time_stamp() << ": " << this->name() << hex << " Output Port:"
476  << i << " Valid: " << valid[i].to_uint64() << " Select : "
477  << select[i].to_int64() << dec
478 #ifdef ENABLE_MULTICAST
479  << "Multicast: " << is_multicast[(select_id[i]*num_vchannels+vcin[select_id[i]])]
480 #endif
481  << endl, kDebugLevel);
482  }
483  }
484 
485 #ifdef ENABLE_MULTICAST
486 // For Multicast, set remote select = local select
487 #pragma hls_unroll yes
488  for (int i = 0; i < num_lports;
489  i++) { // Iterating through the remote outputs here
490  if (select[i] != 0 &&
491  is_multicast[(select_id[i] * num_vchannels + vcin[select_id[i]])] &&
492  valid[remote_portid[select_id[i]]][select_id[i]]) {
493  select[remote_portid[select_id[i]]] = select[i];
494  select_id[remote_portid[select_id[i]]] = select_id[i];
495  CDCOUT(sc_time_stamp() << ": " << this->name() << " Output Port:" << i
496  << "Input port: " << select_id[i] << " Remote port: "
497  << remote_portid[select_id[i]] << " VC: "
498  << vcin[select_id[i]] << "Remote Select: "
499  << select[remote_portid[select_id[i]]] << " Local Select: "
500  << select[i] << endl, kDebugLevel);
501  }
502  }
503 // For Multicast, if remote port is selected and not local port, reset remote
504 // port
505 #pragma hls_unroll yes
506  for (int i = num_lports; i < num_ports;
507  i++) { // Iterating through the remote outputs here
508  if (select[i] != 0 &&
509  is_multicast[(select_id[i] * num_vchannels + vcin[select_id[i]])] &&
510  (valid[i][select_id[local_portid[select_id[i]]]] == 0)) {
511  select[i] = 0;
512  CDCOUT("Set Select = 0 for Output port: " << i << endl, kDebugLevel);
513  CDCOUT(sc_time_stamp() << ": " << this->name() << " Output Port:" << i
514  << "Input port: " << select_id[i] << " Remote port: "
515  << remote_portid[select_id[i]] << " VC: "
516  << vcin[select_id[i]] << "Remote Select: " << select[i]
517  << " Local Select: " << select[local_portid[select_id[i]]]
518  << endl, kDebugLevel);
519  }
520  }
521 #endif
522  }
523 
524  void reset() {
525  out_stall = 0;
526  for (int i = 0; i < num_ports * num_vchannels; i++) {
527  is_get_new_packet[i] = true;
528  }
529  }
530 
531 
532  void run() {
533  this->receive_credit();
534  this->fill_ififo();
535 
536  Flit_t flit_in[num_ports];
537  NVUINTW(log_num_vchannels) vcin[num_ports];
538  NVUINTW(num_ports) in_valid = 0;
539 
540  // pick a valid vc per input. VC0 has priority.
541  // output: vcin[x] - vc selcted for in port x, in_valid - bitmap of
542  // inports valid bits
543  inputvc_arbiter(vcin, in_valid);
544 
545  // read top flit for each selected vc per in port
546  // output: flit_in[x] - top flit on selected vc on port x
547  this->peek_ififo(flit_in, vcin, in_valid);
548 
549  // for each selected input, in case of valid header flit only, update
550  // out_dest[i][vcin[i]]
551  // side effect updating out_dest[x][vc] for each input port x with output
552  // port bitmap
553  compute_route(flit_in, vcin, in_valid);
554 
555  // Variable to hold valid input requests. Set valid[i][j] = 1 if input j
556  // is sending flit to output i
557  NVUINTW(num_ports) valid[num_ports], select[num_ports];
558  NVUINTW(log_num_ports) select_id[num_ports];
559 
560  // arbitrate for any top header flits on selected vcs
561  // outputs:
562  // valid[x] - bitmap of valid input ports to address output port x. valid
563  // means there is credit on output port(and vc), and no other packet in
564  // flight to that output vc
565  // select[x] - bitmap of selected input port (one hot) for output port x
566  // select_id[x] - selected input port for output port x
567  arbitration(flit_in, in_valid, vcin, valid, select, select_id);
568 
569  // decide which port is going to push data out
570  // side effect updating is_push[x] to indicate that output port x is going
571  // to push a flit out
572  NVUINTW(num_ports) is_popfifo = 0;
573  bool is_push[num_ports];
574 #pragma hls_unroll yes
575  for (int i = 0; i < num_ports;
576  i++) { // Iterating through output ports here
577  is_push[i] = false;
578  if (select[i] != 0) {
579  is_popfifo[select_id[i]] = 1;
580  is_push[i] = true;
581  CDCOUT(sc_time_stamp() << ": " << this->name() << " Port:" << i << "Select: "
582  << select[i] << " select_id " << select_id[i]
583  << " Valid:" << valid[i] << "PopFifo: " <<
584  is_popfifo[select_id[i]] << endl, kDebugLevel);
585  }
586  }
587 
588 // pop input fifos and prepare credits to be returned to sources
589 #pragma hls_unroll yes
590  for (int i = 0; i < num_ports; i++) { // Iterating over inputs here
591  if (is_popfifo[i] == 1) {
592  this->ififo.incrHead(i * num_vchannels + vcin[i]);
593  CDCOUT(sc_time_stamp() << ": " << this->name() << " Popped FIFO of port-"
594  << i << " VC-" << vcin[i] << endl, kDebugLevel);
595  this->credit_send[i * num_vchannels + vcin[i]]++;
596  NVHLS_ASSERT_MSG(this->credit_send[i * num_vchannels + vcin[i]] <= BaseClass::buffersize, "Total credits cannot be larger than buffer size");
597  }
598  }
599 
600  // fill_ififo();
601  this->send_credit();
602  NVUINTW(log_num_vchannels) vcout[num_ports];
603 
604  this->crossbar_traversal(flit_in, is_push, select_id, vcin, vcout);
605 
606  // sends out flits to be sent
607  // side effect: updating is_get_new_packet[x] when tail goes through port
608  // x
609  // and out_stall when push_nb fails
610  flit_output(is_push, vcout);
611  }
612 };
613 
614 #endif //__WHVCROUTER_H__
Wormhole Router with virtual channels.
Definition: WHVCRouter.h:257
#define NVHLS_ASSERT_MSG(X, MSG)
Definition: nvhls_assert.h:135
#define CDCOUT(x, y)
Definition: hls_globals.h:73
type1 set_slc(type1 X, type2 Y, const unsigned int i)
Function that replaces slice of bits.
Definition: nvhls_int.h:387
type2 leading_ones(type1 X)
LeadingOne Detector.
Definition: nvhls_int.h:561
#define NVHLS_NEG_RESET_SIGNAL_IS(port)
ENABLE_SYNC_RESET define: Select synchronous or asynchronous reset.
Definition: nvhls_module.h:39
Compute index width of a constant.
Definition: nvhls_int.h:285