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"
28#include "lib/bitvec.h"
34 static constexpr int MAX_HASH_BITS = 52;
36 static int get_max_hash_bits() {
38 if (!BackendOptions().disable_gfm_parity)
return MAX_HASH_BITS - 1;
55 std::function<bool(
const IR::PathExpression *)> checkPath;
57 static const IR::Type_Extern *externType(
const IR::Type *type) {
58 if (
auto *spec = type->to<IR::Type_SpecializedCanonical>()) type = spec->baseType;
59 return type->to<IR::Type_Extern>();
63 auto *expr = n->
to<IR::Expression>();
64 BUG_CHECK(expr,
"CanBeIXBarExpr called on non-expression");
65 rv = expr->type->width_bits() <= get_max_hash_bits();
66 return Inspector::init_apply(n);
68 bool preorder(
const IR::Node *) {
return false; }
69 bool preorder(
const IR::PathExpression *pe) {
70 if (!checkPath(pe)) rv =
false;
73 bool preorder(
const IR::Constant *) {
return false; }
74 bool preorder(
const IR::Member *m) {
76 while ((m = base->to<IR::Member>())) base = m->expr;
77 if (
auto *pe = base->to<IR::PathExpression>()) {
78 if (!checkPath(pe)) rv =
false;
79 }
else if (base->is<IR::HeaderRef>() || base->is<IR::TempVar>()) {
86 bool preorder(
const IR::TempVar *) {
return false; }
87 bool preorder(
const IR::Slice *) {
return rv; }
88 bool preorder(
const IR::Concat *) {
return rv; }
89 bool preorder(
const IR::Cast *) {
return rv; }
90 bool preorder(
const IR::BFN::SignExtend *) {
return rv; }
91 bool preorder(
const IR::BFN::ReinterpretCast *) {
return rv; }
92 bool preorder(
const IR::BXor *) {
return rv; }
93 bool preorder(
const IR::BAnd *e) {
94 if (!e->left->is<IR::Constant>() && !e->right->is<IR::Constant>()) rv =
false;
97 bool preorder(
const IR::BOr *e) {
98 if (!e->left->is<IR::Constant>() && !e->right->is<IR::Constant>()) rv =
false;
101 bool preorder(
const IR::MethodCallExpression *mce) {
102 if (
auto *method = mce->method->to<IR::Member>()) {
103 if (
auto *ext = externType(method->type)) {
104 if (ext->name ==
"Hash" && method->member ==
"get") {
112 bool preorder(
const IR::Expression *) {
return rv =
false; }
115 explicit CanBeIXBarExpr(
116 const IR::Expression *e,
117 std::function<
bool(
const IR::PathExpression *)> checkPath =
118 [](
const IR::PathExpression *) ->
bool { BUG(
"Unexpected path expression"); })
119 : checkPath(checkPath) {
122 operator bool()
const {
return rv; }
126inline bitvec to_bitvec(big_int v) {
127 bitvec rv(
static_cast<uintptr_t
>(v));
128 v >>=
sizeof(uintptr_t) * CHAR_BIT;
129 if (v > 0) rv |= to_bitvec(v) << (
sizeof(uintptr_t) * CHAR_BIT);
139 bool preorder(
const IR::Annotation *) {
return false; }
140 bool preorder(
const IR::Type *) {
return false; }
141 bool preorder(
const IR::Member *) {
return false; }
142 bool preorder(
const IR::Constant *k) {
143 if (getParent<IR::BAnd>())
return false;
144 rv ^= to_bitvec((k->value >> slice.lo) & ((big_int(1) << slice.size()) - 1)) << shift;
147 bool preorder(
const IR::Concat *e) {
149 int rwidth = e->right->type->width_bits();
150 if (slice.lo < rwidth) {
151 slice = slice.intersectWith(0, rwidth - 1);
152 visit(e->right,
"right");
154 if (tmp.hi >= rwidth) {
158 slice = slice.shiftedByBits(-rwidth);
159 visit(e->left,
"left");
165 bool preorder(
const IR::StructExpression *fl) {
167 IR::ListExpression listExpr(*getListExprComponents(*fl));
168 return preorder(&listExpr);
170 bool preorder(
const IR::ListExpression *fl) {
172 auto old_shift = shift;
173 for (
auto *e : boost::adaptors::reverse(fl->components)) {
174 int width = e->type->width_bits();
175 if (slice.lo < width) {
177 slice = slice.intersectWith(0, width - 1);
181 if (slice.hi < width)
break;
182 slice = slice.shiftedByBits(-width);
189 bool preorder(
const IR::Slice *sl) {
191 slice = slice.shiftedByBits(-sl->getL());
192 int width = sl->getH() - sl->getL() + 1;
193 if (slice.size() > width) slice.hi = slice.lo + width - 1;
198 bool preorder(
const IR::MethodCallExpression *mce) {
199 BUG(
"MethodCallExpression not supported in IXBarExprSeed: %s", mce);
204 IXBarExprSeed(
const IR::Expression *e, le_bitrange sl) : slice(sl) { e->apply(*
this); }
205 operator bitvec()
const {
return rv >> slice.lo; }
210 le_bitrange hash_bits;
214 const IR::Expression *hash_gen_expr =
nullptr;
219 bool is_dynamic()
const {
220 bool rv = !dyn_hash_name.isNull();
223 BUG_CHECK(symmetrically_hashed_inputs.empty(),
224 "Dynamically hashed values cannot "
225 "have symmetric fields");
231 void slice(le_bitrange hash_slice);
232 cstring name()
const {
return is_dynamic() ? dyn_hash_name :
"static_hash"_cs; }
233 int size()
const {
return hash_bits.size(); }
238 void dbprint(std::ostream &out)
const;
265class BuildP4HashFunction :
public PassManager {
270 auto rv = PassManager::init_apply(node);
276 BuildP4HashFunction &self;
285 } state = State::OUTSIDE;
288 auto rv = MauInspector::init_apply(node);
291 state = State::OUTSIDE;
295 bool preorder(
const IR::MAU::HashGenExpression *)
override;
296 bool preorder(
const IR::MAU::FieldListExpression *)
override;
297 bool preorder(
const IR::Constant *)
override;
298 bool preorder(
const IR::Expression *)
override;
299 bool preorder(
const IR::MAU::ActionArg *)
override;
300 bool preorder(
const IR::Mask *)
override;
301 bool preorder(
const IR::Cast *)
override;
302 bool preorder(
const IR::Concat *)
override;
303 bool preorder(
const IR::StructExpression *)
override;
304 bool preorder(
const IR::ListExpression *)
override;
305 void postorder(
const IR::BFN::SignExtend *)
override;
306 void postorder(
const IR::MAU::HashGenExpression *)
override;
309 explicit InsideHashGenExpr(BuildP4HashFunction &s) : self(s) {}
313 BuildP4HashFunction &self;
314 bool preorder(
const IR::MAU::HashGenExpression *)
override;
315 void postorder(
const IR::Slice *)
override;
318 explicit OutsideHashGenExpr(BuildP4HashFunction &s) : self(s) {}
321 void end_apply()
override;
324 explicit BuildP4HashFunction(
const PhvInfo &p) : phv(p) {
325 addPasses({
new InsideHashGenExpr(*
this),
new OutsideHashGenExpr(*
this)});
332 bool preorder(IR::MAU::IXBarExpression *e)
override;
Definition ixbar_expr.h:331
Definition mau_visitor.h:29
Definition mau_visitor.h:45
Definition stringify.h:33
Definition ltbitmatrix.h:25
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
Definition hash_function.h:28
T * to() noexcept
Definition rtti.h:226
Definition ixbar_expr.h:208
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