MatchLib
Arbiter.h
1 /*
2  * Copyright (c) 2017-2020, 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 
18 #ifndef __ARBITER_H__
19 #define __ARBITER_H__
20 
21 #include <systemc.h>
22 #include <nvhls_int.h>
23 #include <nvhls_assert.h>
24 
25 enum arbiter_type { Static, Roundrobin };
26 
27 
60 template <unsigned int size_, arbiter_type ArbiterType = Roundrobin>
61 class Arbiter {
62  public:
63  typedef NVUINTW(size_) Mask;
64 
65  protected:
66  enum _ {
67  UNROLLED_SIZE = 2 * size_ - 1,
68  log_unrolled_size = nvhls::log2_ceil<UNROLLED_SIZE>::val,
70  //-1 because there is no reason to duplicate LSB
71  };
72 
73  typedef NVUINTW(UNROLLED_SIZE) UnrolledMask;
74  Mask next;
75 
76  public:
77  Arbiter() { reset(); };
78 
79  // reset the state
80  inline void reset() { next = ~static_cast<Mask>(0); }
81 
82  // picks the next element
83  // input : valid mask
84  // output : select mask
85  // side effect : updates internal state of next select
86  Mask pick(const Mask& valid) {
87  if (valid == 0) {
88  return 0;
89  }
90  UnrolledMask unrolled_valid = static_cast<UnrolledMask>(0);
91  unrolled_valid =
92  nvhls::set_slc(unrolled_valid, nvhls::get_slc<size_ - 1>(valid, 1), 0) |
93  nvhls::set_slc(unrolled_valid, valid, size_ - 1);
94 
95  UnrolledMask unrolled_next = static_cast<UnrolledMask>(0);
96  NVUINTW(size_ - 1) temp = ~static_cast<NVUINTW(size_ - 1)>(0);
97  unrolled_next = nvhls::set_slc(unrolled_next, next, size_ - 1) |
98  nvhls::set_slc(unrolled_next, temp, 0);
99 
100  UnrolledMask priority(unrolled_next & unrolled_valid);
101 
102  NVUINTW(log_unrolled_size) first_one_idx, num_zeros;
103  UnrolledMask unrolled_choice = static_cast<UnrolledMask>(0);
104 
105  Mask choice = static_cast<Mask>(0);
106  Mask choice_temp = static_cast<Mask>(0);
107  if (priority != 0) {
108  first_one_idx = nvhls::leading_ones<UNROLLED_SIZE, UnrolledMask,
109  NVUINTW(log_unrolled_size)>(priority);
110  unrolled_choice[first_one_idx] = 1;
111  choice_temp[0] = unrolled_choice[size_ - 1];
112  NVUINTW(size_ - 1)
113  temp2 = (nvhls::get_slc<UNROLLED_SIZE - size_>(unrolled_choice, size_)) |
114  (nvhls::get_slc<size_ - 1>(unrolled_choice, 0));
115  choice = nvhls::set_slc(choice_temp, temp2, 1);
116 
117  if (first_one_idx != (size_ - 1)) {
118  next[size_ - 1] = 0;
119 #pragma hls_unroll yes
120  for (unsigned i = size_ - 2; i > 0; --i) {
121  next[i] = next[i + 1] | choice[i + 1];
122  }
123  } else {
124  next = ~static_cast<Mask>(0);
125  }
126  }
127  // assert valid!=0 => (valid&choice)!=0
128  //NVHLS_ASSERT_MSG(valid!=0, "Arbiter input is zero and output is non-zero");
129  return choice;
130  }
131 };
132 
137 template<>
138 class Arbiter<1, Roundrobin> {
139  public:
140  typedef NVUINT1 Mask;
141 
142  public:
143  Arbiter() { reset(); };
144 
145  // reset the state
146  inline void reset() { }
147 
148  // picks the next element
149  Mask pick(const Mask& valid) {
150  if (valid !=0) {
151  return static_cast<Mask>(1);
152  } else {
153  return static_cast<Mask>(0);
154  }
155  }
156 };
157 
158 
166 template <unsigned int size_>
167 class Arbiter<size_, Static> {
168  public:
169  typedef NVUINTW(size_) Mask;
170 
171  protected:
172  enum _ { log_size = nvhls::log2_ceil<size_>::val };
173 
174  public:
175  // picks the next element
176  // input : valid mask
177  // output : select mask
178  // side effect : updates internal state of next select
179  Mask pick(const Mask& valid) {
180  Mask select = static_cast<Mask>(0);
181  NVUINTW(log_size) first_one_idx;
182  if (valid != 0) {
183  first_one_idx =
184  nvhls::leading_ones<size_, Mask, NVUINTW(log_size)>(valid);
185  select[first_one_idx] = 1;
186  }
187  return select;
188  }
189 };
190 
191 
192 #endif // __ARBITER_H__
A generalized implementation of generic n-way roundrobin arbiter.
Definition: Arbiter.h:61
type1 set_slc(type1 X, type2 Y, const unsigned int i)
Function that replaces slice of bits.
Definition: nvhls_int.h:387
nvhls_t< W >::nvuint_t get_slc(type X, const unsigned int i)
Function that returns slice of bits.
Definition: nvhls_int.h:437
type2 leading_ones(type1 X)
LeadingOne Detector.
Definition: nvhls_int.h:561
Compute Celing of log2 of a constant.
Definition: nvhls_int.h:174