54 #ifndef BM_BM_SIM_CALCULATIONS_H_
55 #define BM_BM_SIM_CALCULATIONS_H_
62 #include <type_traits>
63 #include <unordered_map>
67 #include "boost/variant.hpp"
71 #include "phv_forward.h"
79 struct defines_functor_operator {
80 using yes = char (&)[1];
81 using no = char (&)[2];
85 static yes deduce(
char (*)[
sizeof(&U::operator())]);
87 template <
typename>
static no deduce(...);
89 static bool constexpr value =
sizeof(deduce<T>(0)) ==
sizeof(yes);
94 template <
class ReturnType,
class... Args>
95 struct callable_traits_base {
96 using return_type = ReturnType;
97 using argument_type = std::tuple<Args...>;
99 template<std::
size_t I>
100 using arg =
typename std::tuple_element<I, argument_type>::type;
107 struct callable_traits : callable_traits<decltype(&T::operator())> { };
110 template <
class ClassType,
class ReturnType,
class... Args>
111 struct callable_traits<ReturnType(ClassType::*)(Args...) const>
112 : detail::callable_traits_base<ReturnType, Args...> { };
115 template <
class ClassType,
class ReturnType,
class... Args>
116 struct callable_traits<ReturnType(ClassType::*)(Args...)>
117 : detail::callable_traits_base<ReturnType, Args...> { };
119 template <
bool functor,
typename H>
122 static bool constexpr valid_hash =
false;
129 template<
typename T,
typename Return>
130 struct check_functor_signature {
131 template<
typename U, Return (U::*)(const
char *,
size_t) const>
134 template<
typename U>
static char Test(SFINAE<U, &U::operator()>*);
135 template<
typename U>
static int Test(...);
136 static const bool value =
sizeof(Test<T>(0)) ==
sizeof(
char);
141 template <
typename H>
142 struct HashChecker<true, H> {
144 using return_type =
typename callable_traits<H>::return_type;
145 using argument_type =
typename callable_traits<H>::argument_type;
147 static bool constexpr v1 = std::is_unsigned<return_type>::value;
148 static bool constexpr v2 =
149 std::is_same<argument_type, std::tuple<const char *, size_t>>::value;
151 static_assert(v1,
"Invalid return type for HashFn");
152 static_assert(v2,
"Invalid parameters for HashFn");
154 static bool constexpr v3 = check_functor_signature<H, return_type>::value;
155 static_assert(!(v1 && v2) || v3,
"HashFn is not const");
158 static bool constexpr valid_hash = v1 && v2 && v3;
164 template <
typename U,
165 typename std::enable_if<std::is_unsigned<U>::value,
int>::type = 0>
166 class RawCalculationIface {
168 U output(
const char *buffer,
size_t s)
const {
169 return output_(buffer, s);
172 std::unique_ptr<RawCalculationIface<U> > clone()
const {
173 return std::unique_ptr<RawCalculationIface<U> > (clone_());
176 virtual ~RawCalculationIface() { }
179 virtual U output_(
const char *buffer,
size_t s)
const = 0;
181 virtual RawCalculationIface<U> *clone_()
const = 0;
185 template <
typename T,
typename HashFn,
186 typename std::enable_if<std::is_unsigned<T>::value,
int>::type = 0>
188 : HashChecker<defines_functor_operator<HashFn>::value, HashFn>,
189 public RawCalculationIface<T> {
193 std::unique_ptr<RawCalculation<T, HashFn> > clone()
const {
194 return std::unique_ptr<RawCalculation<T, HashFn> > (clone_());
197 HashFn &get_hash_fn() {
return hash; }
200 T output_(
const char *buffer,
size_t s)
const override {
201 return output__(buffer, s);
204 RawCalculation<T, HashFn> *clone_()
const override {
205 RawCalculation<T, HashFn> *ptr =
new RawCalculation<T, HashFn>();
209 using HC = HashChecker<defines_functor_operator<HashFn>::value, HashFn>;
211 static_assert(defines_functor_operator<HashFn>::value,
212 "HashFn needs to overload '()' operator");
214 template <
typename U = T,
215 typename std::enable_if<std::is_unsigned<U>::value,
int>::type = 0>
216 typename std::enable_if<HC::valid_hash, U>::type
217 output__(
const char *buffer,
size_t s)
const {
218 return static_cast<U
>(hash(buffer, s));
221 template <
typename U = T,
222 typename std::enable_if<std::is_unsigned<U>::value,
int>::type = 0>
223 typename std::enable_if<!HC::valid_hash, U>::type
224 output__(
const char *buffer,
size_t s)
const {
225 (void) buffer; (void) s;
226 return static_cast<U
>(0u);
235 void push_back_field(header_id_t header,
int field_offset);
236 void push_back_constant(
const ByteContainer &v,
size_t nbits);
237 void push_back_header(header_id_t header);
238 void append_payload();
240 void operator()(
const Packet &pkt, ByteContainer *buf)
const;
259 std::vector<boost::variant<field_t, constant_t, header_t> > entries{};
260 bool with_payload{
false};
264 template <
typename T,
265 typename std::enable_if<std::is_unsigned<T>::value,
int>::type = 0>
268 Calculation_(
const BufBuilder &builder,
269 std::unique_ptr<RawCalculationIface<T> > c)
270 : builder(builder), c(std::move(c)) { }
272 T output(
const Packet &pkt)
const {
273 static thread_local ByteContainer key;
275 return c->output(key.data(), key.size());
278 RawCalculationIface<T> *get_raw_calculation() {
return c.get(); }
285 std::unique_ptr<RawCalculationIface<T> > c;
289 class CalculationsMap {
291 using MyC = RawCalculationIface<uint64_t>;
293 static CalculationsMap *get_instance();
294 bool register_one(
const char *name, std::unique_ptr<MyC> c);
295 std::unique_ptr<MyC> get_copy(
const std::string &name);
298 std::unordered_map<std::string, std::unique_ptr<MyC> > map_{};
302 class Calculation :
public Calculation_<uint64_t> {
304 Calculation(
const BufBuilder &builder,
305 std::unique_ptr<RawCalculationIface<uint64_t> > c)
306 : Calculation_(builder, std::move(c)) { }
308 Calculation(
const BufBuilder &builder,
const std::string &hash_name)
310 builder, CalculationsMap::get_instance()->get_copy(hash_name)
315 class NamedCalculation :
public NamedP4Object,
public Calculation_<uint64_t> {
317 NamedCalculation(
const std::string &name, p4object_id_t
id,
318 const BufBuilder &builder,
319 std::unique_ptr<RawCalculationIface<uint64_t> > c)
320 : NamedP4Object(name, id),
321 Calculation_(builder, std::move(c)) { }
323 NamedCalculation(
const std::string &name, p4object_id_t
id,
324 const BufBuilder &builder,
const std::string &hash_name)
325 : NamedP4Object(name, id),
327 builder, CalculationsMap::get_instance()->get_copy(hash_name)
336 #define REGISTER_HASH(hash_name) \
337 bool hash_name##_create_ = \
338 bm::CalculationsMap::get_instance()->register_one( \
340 std::unique_ptr<bm::CalculationsMap::MyC>( \
341 new bm::RawCalculation<uint64_t, hash_name>()));
346 uint64_t xxh64(
const char *buffer,
size_t s);
351 enum class CustomCrcErrorCode {
353 INVALID_CALCULATION_NAME,
354 WRONG_TYPE_CALCULATION,
360 template <
typename T>
361 struct crc_config_t {
366 bool remainder_reflected;
369 template <
typename T>
370 std::ostream &operator<<(std::ostream &out,
const crc_config_t<T> &c);
378 template <
typename T>
381 using crc_config_t = detail::crc_config_t<T>;
383 static CustomCrcErrorCode update_config(NamedCalculation *calculation,
384 const crc_config_t &config);
386 static CustomCrcErrorCode update_config(RawCalculationIface<uint64_t> *c,
387 const crc_config_t &config);
390 enum class ToeplitzErrorCode {
392 INVALID_CALCULATION_NAME,
393 WRONG_TYPE_CALCULATION,
399 using key_t = ByteContainer;
401 static ToeplitzErrorCode update_key(NamedCalculation *calculation,
404 static ToeplitzErrorCode update_key(RawCalculationIface<uint64_t> *c,
410 #endif // BM_BM_SIM_CALCULATIONS_H_