19#ifndef BF_P4C_MAU_IXBAR_EXPR_H_
20#define BF_P4C_MAU_IXBAR_EXPR_H_
22#include "backends/tofino/bf-p4c/bf-p4c-options.h"
23#include "backends/tofino/bf-p4c/common/utils.h"
24#include "backends/tofino/bf-p4c/mau/mau_visitor.h"
25#include "backends/tofino/bf-p4c/phv/phv_fields.h"
26#include "boost/range/adaptor/reversed.hpp"
27#include "ir/ir-generated.h"
29#include "lib/bitvec.h"
35 static constexpr int MAX_HASH_BITS = 52;
37 static int get_max_hash_bits() {
39 if (!BackendOptions().disable_gfm_parity)
return MAX_HASH_BITS - 1;
56 std::function<bool(
const IR::PathExpression *)> checkPath;
58 static const IR::Type_Extern *externType(
const IR::Type *type) {
59 if (
auto *spec = type->to<IR::Type_SpecializedCanonical>()) type = spec->baseType;
60 return type->to<IR::Type_Extern>();
64 auto *expr = n->
to<IR::Expression>();
65 BUG_CHECK(expr,
"CanBeIXBarExpr called on non-expression");
66 rv = expr->type->width_bits() <= get_max_hash_bits();
67 return Inspector::init_apply(n);
69 bool preorder(
const IR::Node *) {
return false; }
70 bool preorder(
const IR::PathExpression *pe) {
71 if (!checkPath(pe)) rv =
false;
74 bool preorder(
const IR::Constant *) {
return false; }
75 bool preorder(
const IR::Member *m) {
77 while ((m = base->to<IR::Member>())) base = m->expr;
78 if (
auto *pe = base->to<IR::PathExpression>()) {
79 if (!checkPath(pe)) rv =
false;
80 }
else if (base->is<IR::HeaderRef>() || base->is<IR::TempVar>()) {
87 bool preorder(
const IR::TempVar *) {
return false; }
88 bool preorder(
const IR::Slice *) {
return rv; }
89 bool preorder(
const IR::Concat *) {
return rv; }
90 bool preorder(
const IR::Cast *) {
return rv; }
91 bool preorder(
const IR::BFN::SignExtend *) {
return rv; }
92 bool preorder(
const IR::BFN::ReinterpretCast *) {
return rv; }
93 bool preorder(
const IR::BXor *) {
return rv; }
94 bool preorder(
const IR::BAnd *e) {
95 if (!e->left->is<IR::Constant>() && !e->right->is<IR::Constant>()) rv =
false;
98 bool preorder(
const IR::BOr *e) {
99 if (!e->left->is<IR::Constant>() && !e->right->is<IR::Constant>()) rv =
false;
102 bool preorder(
const IR::MethodCallExpression *mce) {
103 if (
auto *method = mce->method->to<IR::Member>()) {
104 if (
auto *ext = externType(method->type)) {
105 if (ext->name ==
"Hash" && method->member ==
"get") {
113 bool preorder(
const IR::Expression *) {
return rv =
false; }
117 const IR::Expression *e,
118 std::function<
bool(
const IR::PathExpression *)> checkPath =
119 [](
const IR::PathExpression *) ->
bool { BUG(
"Unexpected path expression"); })
120 : checkPath(checkPath) {
123 operator bool()
const {
return rv; }
127inline bitvec to_bitvec(big_int v) {
128 bitvec rv(
static_cast<uintptr_t
>(v));
129 v >>=
sizeof(uintptr_t) * CHAR_BIT;
130 if (v > 0) rv |= to_bitvec(v) << (
sizeof(uintptr_t) * CHAR_BIT);
140 bool preorder(
const IR::Annotation *) {
return false; }
141 bool preorder(
const IR::Type *) {
return false; }
142 bool preorder(
const IR::Member *) {
return false; }
143 bool preorder(
const IR::Constant *k) {
144 if (getParent<IR::BAnd>())
return false;
145 rv ^= to_bitvec((k->value >> slice.
lo) & ((big_int(1) << slice.
size()) - 1)) << shift;
148 bool preorder(
const IR::Concat *e) {
150 int rwidth = e->right->type->width_bits();
151 if (slice.
lo < rwidth) {
153 visit(e->right,
"right");
155 if (tmp.hi >= rwidth) {
160 visit(e->left,
"left");
166 bool preorder(
const IR::StructExpression *fl) {
168 IR::ListExpression listExpr(*getListExprComponents(*fl));
169 return preorder(&listExpr);
171 bool preorder(
const IR::ListExpression *fl) {
173 auto old_shift = shift;
174 for (
auto *e : boost::adaptors::reverse(fl->components)) {
175 int width = e->type->width_bits();
176 if (slice.
lo < width) {
182 if (slice.
hi < width)
break;
190 bool preorder(
const IR::Slice *sl) {
193 int width = sl->getH() - sl->getL() + 1;
194 if (slice.
size() > width) slice.
hi = slice.
lo + width - 1;
199 bool preorder(
const IR::MethodCallExpression *mce) {
200 BUG(
"MethodCallExpression not supported in IXBarExprSeed: %s", mce);
206 operator bitvec()
const {
return rv >> slice.
lo; }
215 const IR::Expression *hash_gen_expr =
nullptr;
220 bool is_dynamic()
const {
221 bool rv = !dyn_hash_name.isNull();
224 BUG_CHECK(symmetrically_hashed_inputs.empty(),
225 "Dynamically hashed values cannot "
226 "have symmetric fields");
233 cstring name()
const {
return is_dynamic() ? dyn_hash_name :
"static_hash"_cs; }
234 int size()
const {
return hash_bits.
size(); }
239 void dbprint(std::ostream &out)
const;
251 const IR::Annotations *annotations, gress_t gress,
271 auto rv = PassManager::init_apply(node);
286 } state = State::OUTSIDE;
289 auto rv = MauInspector::init_apply(node);
292 state = State::OUTSIDE;
296 bool preorder(
const IR::MAU::HashGenExpression *)
override;
297 bool preorder(
const IR::MAU::FieldListExpression *)
override;
298 bool preorder(
const IR::Constant *)
override;
299 bool preorder(
const IR::Expression *)
override;
300 bool preorder(
const IR::MAU::ActionArg *)
override;
301 bool preorder(
const IR::Mask *)
override;
302 bool preorder(
const IR::Cast *)
override;
303 bool preorder(
const IR::Concat *)
override;
304 bool preorder(
const IR::StructExpression *)
override;
305 bool preorder(
const IR::ListExpression *)
override;
306 void postorder(
const IR::BFN::SignExtend *)
override;
307 void postorder(
const IR::MAU::HashGenExpression *)
override;
315 bool preorder(
const IR::MAU::HashGenExpression *)
override;
316 void postorder(
const IR::Slice *)
override;
322 void end_apply()
override;
326 addPasses({
new InsideHashGenExpr(*
this),
new OutsideHashGenExpr(*
this)});
333 bool preorder(IR::MAU::IXBarExpression *e)
override;
Definition ixbar_expr.h:332
Definition ixbar_expr.h:266
Definition ixbar_expr.h:34
Definition ixbar_expr.h:135
Definition mau_visitor.h:29
Definition mau_visitor.h:45
Definition stringify.h:33
Definition ltbitmatrix.h:25
Definition ir/pass_manager.h:40
Definition safe_vector.h:27
Definition phv_fields.h:1095
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:24
HalfOpenRange< Unit, Order > intersectWith(ClosedRange a) const
Definition lib/bitrange.h:610
ClosedRange< RangeUnit::Bit, Order > shiftedByBits(int offset) const
Definition lib/bitrange.h:556
int lo
Definition lib/bitrange.h:694
ssize_t size() const
Definition lib/bitrange.h:539
int hi
Definition lib/bitrange.h:700
Definition hash_function.h:28
T * to() noexcept
Definition rtti.h:226
Definition ixbar_expr.h:209
bool overlap(const P4HashFunction *, le_bitrange *my_overlap, le_bitrange *hash_overlap) const
Definition ixbar_expr.cpp:71
bool equiv_inputs_alg(const P4HashFunction *func) const
Definition ixbar_expr.cpp:42
void slice(le_bitrange hash_slice)
Definition ixbar_expr.cpp:25