36 struct CollectUsedFields :
public Inspector {
37 std::set<cstring> used_fields;
38 const IR::Type_Header *eg_intr_md =
nullptr;
40 bool preorder(
const IR::Type_Header *type)
override {
41 if (type->name ==
"egress_intrinsic_metadata_t") {
42 if (!eg_intr_md) eg_intr_md = type;
47 bool preorder(
const IR::Member *member)
override {
48 if (
auto hdr = member->expr->to<IR::PathExpression>()) {
49 if (
auto type = hdr->type->to<IR::Type_Header>()) {
50 if (type->name ==
"egress_intrinsic_metadata_t") {
51 used_fields.insert(member->member);
61 const CollectUsedFields &used_fields;
67 BUG_CHECK(used_fields.eg_intr_md,
"egress_intrinsic_metadata_t not found?");
69 const IR::StructField *prev =
nullptr;
70 const IR::Type *prev_type =
nullptr;
71 for (
auto field : used_fields.eg_intr_md->fields) {
72 if (used_fields.used_fields.count(field->name) || field->name ==
"egress_port") {
75 const IR::Type *canonicalType =
nullptr;
76 if (field->type->is<IR::Type_Name>())
77 canonicalType = typeMap->getTypeType(field->type,
true);
79 canonicalType = field->type;
80 if (canonicalType->width_bits() % 8) {
83 (canonicalType->width_bits() + prev_type->width_bits()) % 8 == 0,
84 "%1% not padded to be byte-aligned in %2%", field->name,
85 "egress_intrinsic_metadata_t");
86 new_fields.push_back(prev);
88 new_fields.push_back(field);
91 if (field->type->is<IR::Type_Name>())
92 prev_type = typeMap->getTypeType(field->type,
true);
94 prev_type = field->type;
97 unsigned total_size_in_bits = 0;
98 for (
auto field : new_fields) {
99 const IR::Type *canonicalType;
100 if (field->type->is<IR::Type_Name>())
101 canonicalType = typeMap->getTypeType(field->type,
true);
103 canonicalType = field->type;
104 auto bits = canonicalType->to<IR::Type_Bits>();
105 total_size_in_bits += bits->size;
108 BUG_CHECK(total_size_in_bits % 8 == 0,
109 "rewritten egress_intrinsic_metadata_t not byte-aligned?");
113 if (Device::currentDevice() == Device::JBAY) {
114 unsigned total_size_in_byte = total_size_in_bits / 8;
115 unsigned tofino2_pad = ((total_size_in_byte + 3) / 4) * 4 - total_size_in_byte;
116 if (total_size_in_byte + tofino2_pad < Device::egressIntrinsicMetadataMinLen())
117 tofino2_pad += Device::egressIntrinsicMetadataMinLen() -
118 (total_size_in_byte + tofino2_pad);
121 LOG4(
"tofino2 needs " << tofino2_pad <<
" bytes of padding");
123 auto *annots =
new IR::Annotations({
new IR::Annotation(
IR::ID(
"padding"), {})});
125 const IR::StructField *tofino2_pad_field =
new IR::StructField(
126 "__tofino2_pad_", annots, IR::Type::Bits::get(tofino2_pad * 8));
128 new_fields.push_back(tofino2_pad_field);
132 return Transform::init_apply(root);
135 IR::Node *preorder(IR::Type_Header *type)
override {
136 if (type->name ==
"egress_intrinsic_metadata_t") {
137 auto clone = type->clone();
138 clone->fields = new_fields;
139 LOG4(
"rewrite egress_intrinsic_metadata_t as:");
147 explicit RewriteHeader(
const CollectUsedFields &used,
P4::TypeMap *typeMap)
148 : used_fields(used), typeMap(typeMap) {}
153 auto collectUsedFields =
new CollectUsedFields;
157 new RewriteHeader(*collectUsedFields, typeMap),