35 struct CollectUsedFields :
public Inspector {
36 std::set<cstring> used_fields;
37 const IR::Type_Header *eg_intr_md =
nullptr;
39 bool preorder(
const IR::Type_Header *type)
override {
40 if (type->name ==
"egress_intrinsic_metadata_t") {
41 if (!eg_intr_md) eg_intr_md = type;
46 bool preorder(
const IR::Member *member)
override {
47 if (
auto hdr = member->expr->to<IR::PathExpression>()) {
48 if (
auto type = hdr->type->to<IR::Type_Header>()) {
49 if (type->name ==
"egress_intrinsic_metadata_t") {
50 used_fields.insert(member->member);
60 const CollectUsedFields &used_fields;
66 BUG_CHECK(used_fields.eg_intr_md,
"egress_intrinsic_metadata_t not found?");
68 const IR::StructField *prev =
nullptr;
69 const IR::Type *prev_type =
nullptr;
70 for (
auto field : used_fields.eg_intr_md->fields) {
71 if (used_fields.used_fields.count(field->name) || field->name ==
"egress_port") {
74 const IR::Type *canonicalType =
nullptr;
75 if (field->type->is<IR::Type_Name>())
76 canonicalType = typeMap->getTypeType(field->type,
true);
78 canonicalType = field->type;
79 if (canonicalType->width_bits() % 8) {
82 (canonicalType->width_bits() + prev_type->width_bits()) % 8 == 0,
83 "%1% not padded to be byte-aligned in %2%", field->name,
84 "egress_intrinsic_metadata_t");
85 new_fields.push_back(prev);
87 new_fields.push_back(field);
90 if (field->type->is<IR::Type_Name>())
91 prev_type = typeMap->getTypeType(field->type,
true);
93 prev_type = field->type;
96 unsigned total_size_in_bits = 0;
97 for (
auto field : new_fields) {
98 const IR::Type *canonicalType;
99 if (field->type->is<IR::Type_Name>())
100 canonicalType = typeMap->getTypeType(field->type,
true);
102 canonicalType = field->type;
103 auto bits = canonicalType->to<IR::Type_Bits>();
104 total_size_in_bits += bits->size;
107 BUG_CHECK(total_size_in_bits % 8 == 0,
108 "rewritten egress_intrinsic_metadata_t not byte-aligned?");
112 if (Device::currentDevice() == Device::JBAY) {
113 unsigned total_size_in_byte = total_size_in_bits / 8;
114 unsigned tofino2_pad = ((total_size_in_byte + 3) / 4) * 4 - total_size_in_byte;
115 if (total_size_in_byte + tofino2_pad < Device::egressIntrinsicMetadataMinLen())
116 tofino2_pad += Device::egressIntrinsicMetadataMinLen() -
117 (total_size_in_byte + tofino2_pad);
120 LOG4(
"tofino2 needs " << tofino2_pad <<
" bytes of padding");
122 const IR::StructField *tofino2_pad_field =
new IR::StructField(
123 "__tofino2_pad_", {
new IR::Annotation(
IR::ID(
"padding"), {})},
124 IR::Type::Bits::get(tofino2_pad * 8));
126 new_fields.push_back(tofino2_pad_field);
130 return Transform::init_apply(root);
133 IR::Node *preorder(IR::Type_Header *type)
override {
134 if (type->name ==
"egress_intrinsic_metadata_t") {
135 auto clone = type->clone();
136 clone->fields = new_fields;
137 LOG4(
"rewrite egress_intrinsic_metadata_t as:");
145 explicit RewriteHeader(
const CollectUsedFields &used,
P4::TypeMap *typeMap)
146 : used_fields(used), typeMap(typeMap) {}
151 auto collectUsedFields =
new CollectUsedFields;
155 new RewriteHeader(*collectUsedFields, typeMap),