Skip to content

Commit 10a91e5

Browse files
author
Chris Dodd
committed
P4_14 support for extern
1 parent 8b210ff commit 10a91e5

23 files changed

+253
-91
lines changed

backends/bmv2/jsonconverter.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1079,7 +1079,7 @@ Util::IJson* JsonConverter::convertIf(const CFG::IfNode* node, cstring) {
10791079
return result;
10801080
}
10811081

1082-
bool JsonConverter::handleTableImplementation(const IR::TableProperty* implementation,
1082+
bool JsonConverter::handleTableImplementation(const IR::Property* implementation,
10831083
const IR::Key* key,
10841084
Util::JsonObject* table) {
10851085
if (implementation == nullptr) {

backends/bmv2/jsonconverter.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ class JsonConverter final {
108108
Util::JsonArray* force_list) const;
109109
cstring convertHashAlgorithm(cstring algorithm) const;
110110
// Return 'true' if the table is 'simple'
111-
bool handleTableImplementation(const IR::TableProperty* implementation,
111+
bool handleTableImplementation(const IR::Property* implementation,
112112
const IR::Key* key,
113113
Util::JsonObject* table);
114114
void addToFieldList(const IR::Expression* expr, Util::JsonArray* fl);

frontends/p4-14/p4-14-lex.l

+11
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ static bool pragmaLine = false; // FIXME -- use a flex state (and state stack?)
6464
"bit" { yylval.str = yytext; BEGIN(NORMAL); return BIT; }
6565
"blackbox" { yylval.str = yytext; BEGIN(NORMAL); return BLACKBOX; }
6666
"blackbox_type" { yylval.str = yytext; BEGIN(NORMAL); return BLACKBOX_TYPE; }
67+
"block" { yylval.str = yytext; BEGIN(NORMAL); return BLOCK; }
6768
"calculated_field" {
6869
yylval.str = yytext; BEGIN(NORMAL); return CALCULATED_FIELD; }
6970
"control" { yylval.str = yytext; BEGIN(NORMAL); return CONTROL; }
@@ -77,6 +78,12 @@ static bool pragmaLine = false; // FIXME -- use a flex state (and state stack?)
7778
yylval.str = yytext; BEGIN(NORMAL);
7879
return DYNAMIC_ACTION_SELECTION; }
7980
"else" { yylval.str = yytext; BEGIN(NORMAL); return ELSE; }
81+
"extern" { yylval.str = yytext; BEGIN(NORMAL); return BLACKBOX; }
82+
"extern_type" { yylval.str = yytext; BEGIN(NORMAL); return BLACKBOX_TYPE; }
83+
"expression" { yylval.str = yytext; BEGIN(NORMAL); return EXPRESSION; }
84+
"expression_local_variables" {
85+
yylval.str = yytext; BEGIN(NORMAL);
86+
return EXPRESSION_LOCAL_VARIABLES; }
8087
"extract" { yylval.str = yytext; BEGIN(NORMAL); return EXTRACT; }
8188
"false" { yylval.str = yytext; BEGIN(NORMAL); return FALSE; }
8289
"field_list" { yylval.str = yytext; BEGIN(NORMAL); return FIELD_LIST; }
@@ -90,6 +97,7 @@ static bool pragmaLine = false; // FIXME -- use a flex state (and state stack?)
9097
"implementation" {yylval.str = yytext; BEGIN(NORMAL); return IMPLEMENTATION; }
9198
"input" { yylval.str = yytext; BEGIN(NORMAL); return INPUT; }
9299
"instance_count" {yylval.str = yytext; BEGIN(NORMAL); return INSTANCE_COUNT; }
100+
"in" { yylval.str = yytext; BEGIN(NORMAL); return IN; }
93101
"int" { yylval.str = yytext; BEGIN(NORMAL); return INT; }
94102
"latest" { yylval.str = yytext; BEGIN(NORMAL); return LATEST; }
95103
"layout" { yylval.str = yytext; BEGIN(NORMAL); return LAYOUT; }
@@ -105,6 +113,8 @@ static bool pragmaLine = false; // FIXME -- use a flex state (and state stack?)
105113
"min_width" { yylval.str = yytext; BEGIN(NORMAL); return MIN_WIDTH; }
106114
"not" { yylval.str = yytext; BEGIN(NORMAL); return NOT; }
107115
"or" { yylval.str = yytext; BEGIN(NORMAL); return OR; }
116+
"optional" { yylval.str = yytext; BEGIN(NORMAL); return OPTIONAL; }
117+
"out" { yylval.str = yytext; BEGIN(NORMAL); return OUT; }
108118
"output_width" { yylval.str = yytext; BEGIN(NORMAL); return OUTPUT_WIDTH; }
109119
"parse_error" { yylval.str = yytext; BEGIN(NORMAL); return PARSE_ERROR; }
110120
"parser" { yylval.str = yytext; BEGIN(NORMAL); return PARSER; }
@@ -127,6 +137,7 @@ static bool pragmaLine = false; // FIXME -- use a flex state (and state stack?)
127137
"signed" { yylval.str = yytext; BEGIN(NORMAL); return SIGNED; }
128138
"size" { yylval.str = yytext; BEGIN(NORMAL); return SIZE; }
129139
"static" { yylval.str = yytext; BEGIN(NORMAL); return STATIC; }
140+
"string" { yylval.str = yytext; BEGIN(NORMAL); return STRING; }
130141
"true" { yylval.str = yytext; BEGIN(NORMAL); return TRUE; }
131142
"table" { yylval.str = yytext; BEGIN(NORMAL); return TABLE; }
132143
"type" { yylval.str = yytext; BEGIN(NORMAL); return TYPE; }

frontends/p4-14/p4-14-parse.ypp

+111-36
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ static map<int, std::pair<std::string, int>> line_file_map;
3737
static IR::V1Program *global;
3838
static void yyerror(const char *fmt);
3939
static IR::Constant *constantFold(IR::Expression *);
40+
static IR::Vector<IR::Expression> make_expr_list(const IR::NameList *);
4041

4142
#define YYLTYPE Util::SourceInfo
4243
#define YYLLOC_DEFAULT(Cur, Rhs, N) \
@@ -62,19 +63,26 @@ static const IR::Annotations *getPragmas() {
6263
IR::ActionFunction *ActionFunction;
6364
IR::ActionProfile *ActionProfile;
6465
IR::ActionSelector *ActionSelector;
66+
IR::Annotations *Annotations;
6567
IR::Apply *Apply;
68+
IR::Attribute *Attribute;
6669
IR::CalculatedField *CalculatedField;
6770
IR::CaseEntry *CaseEntry;
6871
IR::Vector<IR::CaseEntry> *CaseEntryList;
6972
IR::Constant *Constant;
7073
IR::Counter *Counter;
74+
IR::Declaration_Instance *BBox;
75+
IR::Direction Direction;
7176
IR::Expression *Expression;
7277
IR::Vector<IR::Expression> *ExpressionList;
7378
IR::FieldList *FieldList;
7479
IR::FieldListCalculation *FieldListCalculation;
7580
IR::NameList *NameList;
7681
IR::Member *Member;
7782
IR::Meter *Meter;
83+
IR::Parameter *Parameter;
84+
IR::ParameterList *ParameterList;
85+
IR::IndexedVector<IR::Parameter> *ParameterVector;
7886
IR::V1Parser *Parser;
7987
IR::Register *Register;
8088
IR::V1Table *Table;
@@ -83,21 +91,26 @@ static const IR::Annotations *getPragmas() {
8391
IR::Vector<IR::Annotation> *annotations;
8492
IR::IndexedVector<IR::StructField> *fields;
8593
} HeaderType;
94+
struct {
95+
IR::Vector<IR::Method> *methods;
96+
IR::NameMap<IR::Attribute, ordered_map> *attribs;
97+
} BBoxType;
8698
}
8799

88100
%token<str> ACTION ACTIONS ACTION_PROFILE ACTION_SELECTOR ALGORITHM APPLY
89-
ATTRIBUTE ATTRIBUTES BIT BLACKBOX BLACKBOX_TYPE
101+
ATTRIBUTE ATTRIBUTES BIT BLACKBOX BLACKBOX_TYPE BLOCK
90102
CALCULATED_FIELD CONTROL COUNTER CURRENT DEFAULT DEFAULT_ACTION
91-
DIRECT DROP DYNAMIC_ACTION_SELECTION ELSE EXTRACT FALSE
103+
DIRECT DROP DYNAMIC_ACTION_SELECTION ELSE EXTRACT EXPRESSION
104+
EXPRESSION_LOCAL_VARIABLES FALSE
92105
FIELD_LIST FIELD_LIST_CALCULATION FIELDS HEADER HEADER_TYPE
93-
IF IMPLEMENTATION INPUT INSTANCE_COUNT INT LATEST LAYOUT LENGTH MASK
106+
IF IMPLEMENTATION IN INPUT INSTANCE_COUNT INT LATEST LAYOUT LENGTH MASK
94107
MAX_LENGTH MAX_SIZE MAX_WIDTH METADATA METER METHOD MIN_SIZE MIN_WIDTH NOT
95-
OUTPUT_WIDTH PARSE_ERROR PARSER PARSER_EXCEPTION PAYLOAD PRAGMA PREFIX
96-
PRE_COLOR PRIMITIVE_ACTION READS REGISTER RESULT RETURN SATURATING
108+
OPTIONAL OUT OUTPUT_WIDTH PARSE_ERROR PARSER PARSER_EXCEPTION PAYLOAD PRAGMA
109+
PREFIX PRE_COLOR PRIMITIVE_ACTION READS REGISTER RESULT RETURN SATURATING
97110
SELECT SELECTION_KEY SELECTION_MODE SELECTION_TYPE SET_METADATA
98-
SIGNED SIZE STATIC TABLE TRUE TYPE UPDATE VALID VERIFY WIDTH WRITES
111+
SIGNED SIZE STATIC STRING TABLE TRUE TYPE UPDATE VALID VERIFY WIDTH WRITES
99112

100-
%token<str> IDENTIFIER STRING
113+
%token<str> IDENTIFIER STRING_LITERAL
101114
%token<Constant> INTEGER
102115

103116
%printer { fprintf(yyoutput, "\"%s\"", $$.c_str()); } <str>
@@ -123,12 +136,17 @@ static const IR::Annotations *getPragmas() {
123136
%type<ActionFunction> action_function_body action_statement_list
124137
%type<ActionProfile> action_profile_body
125138
%type<ActionSelector> action_selector_body
139+
%type<Annotations> blackbox_method
126140
%type<Apply> apply_case_list
141+
%type<Attribute> blackbox_attribute
142+
%type<BBox> blackbox_config
143+
%type<BBoxType> blackbox_body
127144
%type<CalculatedField> update_verify_spec_list
128145
%type<CaseEntry> case_value_list
129146
%type<CaseEntryList> case_entry_list
130147
%type<Constant> const_expression
131148
%type<Counter> counter_spec_list
149+
%type<Direction> inout
132150
%type<Expression> expression header_ref header_or_field_ref field_or_masked_ref opt_condition
133151
pragma_operand
134152
%type<ExpressionList> expression_list opt_expression_list control_statement_list opt_else
@@ -139,6 +157,9 @@ static const IR::Annotations *getPragmas() {
139157
%type<HeaderType> header_dec_body field_declarations
140158
%type<NameList> action_list name_list opt_name_list field_list_list
141159
%type<Meter> meter_spec_list
160+
%type<Parameter> argument
161+
%type<ParameterList> opt_argument_list
162+
%type<ParameterVector> argument_list
142163
%type<Parser> parser_statement_list
143164
%type<Register> register_spec_list
144165
%type<Table> table_body
@@ -239,14 +260,24 @@ opt_max_length: /* epsilon */
239260
IR::Vector<IR::Expression>($3)); }
240261
;
241262

242-
type: INT '<' INTEGER '>'
263+
type: BIT { $$ = IR::Type::Bits::get(@1, 1); }
264+
| BIT '<' INTEGER '>'
243265
{ if (!$3->fitsInt())
244266
BUG("%1$: Value too large", @3);
245267
$$ = IR::Type::Bits::get(@3, $3->asInt()); }
246-
| BIT '<' INTEGER '>'
268+
| BLOCK { $$ = IR::Type_Block::get(); }
269+
| COUNTER { $$ = IR::Type_Counter::get(); }
270+
| EXPRESSION { $$ = IR::Type_Expression::get(); }
271+
| FIELD_LIST_CALCULATION { $$ = IR::Type_FieldListCalculation::get(); }
272+
| INT { $$ = new IR::Type_InfInt; }
273+
| INT '<' INTEGER '>'
247274
{ if (!$3->fitsInt())
248275
BUG("%1$: Value too large", @3);
249-
$$ = IR::Type::Bits::get(@3, $3->asInt()); }
276+
$$ = IR::Type::Bits::get(@3, $3->asInt(), true); }
277+
| METER { $$ = IR::Type_Meter::get(); }
278+
| STRING { $$ = IR::Type_String::get(); }
279+
| REGISTER { $$ = IR::Type_Register::get(); }
280+
| TABLE { $$ = IR::Type_AnyTable::get(); }
250281
;
251282

252283
/************************************/
@@ -603,7 +634,7 @@ table_body: /* epsilon */ { $$ = new IR::V1Table(getPragmas()); }
603634
$$->default_action_args = $6; }
604635
| table_body IDENTIFIER ':' expression ';'
605636
{ auto exp = new IR::ExpressionValue(@4, $4);
606-
auto prop = new IR::TableProperty(@2, IR::ID(@2, $2), IR::Annotations::empty, exp, false);
637+
auto prop = new IR::Property(@2, IR::ID(@2, $2), IR::Annotations::empty, exp, false);
607638
$1->addProperty(prop);
608639
$$ = $1; }
609640
| table_body error ';' { $$=$1; }
@@ -679,47 +710,83 @@ apply_case_list: /* epsilon */ { $$ = new IR::Apply; }
679710
/************/
680711

681712
blackbox_type_declaration: BLACKBOX_TYPE name '{' blackbox_body '}'
682-
{ current_pragmas.clear(); }
713+
{ global->add($2, new IR::Type_Extern(@1+@5, IR::ID(@2, $2), $4.methods,
714+
*$4.attribs, getPragmas())); }
683715
;
684716

685-
blackbox_body: /* epsilon */
717+
blackbox_body: /* epsilon */ {
718+
$$.methods = new IR::Vector<IR::Method>;
719+
$$.attribs = new IR::NameMap<IR::Attribute, ordered_map>; }
686720
| blackbox_body ATTRIBUTE name '{' blackbox_attribute '}'
721+
{ ($$=$1).attribs->addUnique($3, $5); }
687722
| blackbox_body METHOD name '(' opt_argument_list ')' ';'
723+
{ ($$=$1).methods->push_back(new IR::Method(@2+@3, $3,
724+
new IR::Type_Method(@4+@6, IR::Type::Void::get(), $5))); }
688725
| blackbox_body METHOD name '(' opt_argument_list ')' '{' blackbox_method '}'
726+
{ ($$=$1).methods->push_back(new IR::Method(@2+@3, $3,
727+
new IR::Type_Method(@4+@6, IR::Type::Void::get(), $5), $8)); }
689728
| blackbox_body error
690729
;
691730

692-
blackbox_attribute: /* epsilon */
693-
| blackbox_attribute name ':' name ';'
694-
| blackbox_attribute name ':' type ';'
695-
| blackbox_attribute name '{' opt_name_list '}'
696-
| blackbox_attribute name ';'
731+
blackbox_attribute: /* epsilon */ { $$ = new IR::Attribute(@-1, $<str>-1); }
732+
| blackbox_attribute TYPE ':' type ';' { ($$=$1)->type = $4; }
733+
| blackbox_attribute EXPRESSION_LOCAL_VARIABLES '{' opt_name_list '}'
734+
{ ($$=$1)->locals = $4; }
735+
| blackbox_attribute OPTIONAL ';'
736+
{ ($$=$1)->optional = true; }
697737
| blackbox_attribute error ';'
698738
| blackbox_attribute error
699739
;
700740

701-
blackbox_method: /* epsilon */
741+
blackbox_method: { $$ = new IR::Annotations; }
702742
| blackbox_method READS '{' opt_name_list '}'
743+
{ ($$=$1)->add(new IR::Annotation(@2, $2, make_expr_list($4))); }
703744
| blackbox_method WRITES '{' opt_name_list '}'
745+
{ ($$=$1)->add(new IR::Annotation(@2, $2, make_expr_list($4))); }
704746
;
705747

706-
opt_argument_list: /* epsilon */ | argument_list ;
748+
opt_argument_list:
749+
/* epsilon */ { $$ = new IR::ParameterList(new IR::IndexedVector<IR::Parameter>); }
750+
| argument_list { $$ = new IR::ParameterList($1); }
751+
;
707752

708-
argument_list: argument | argument_list ',' argument ;
753+
argument_list:
754+
argument { $$ = new IR::IndexedVector<IR::Parameter>($1); }
755+
| argument_list ',' argument { ($$=$1)->push_back($3); }
756+
;
709757

710-
argument: name | type | argument name | argument type;
758+
argument:
759+
inout type name
760+
{ $$ = new IR::Parameter(@3, $3, $1, $2); }
761+
| OPTIONAL argument
762+
{ ($$ = $2)->annotations = $2->annotations->add(new IR::Annotation(@1, $1, {})); }
763+
;
764+
765+
inout: IN { $$ = IR::Direction::In; } | OUT { $$ = IR::Direction::Out; } ;
711766

712767
blackbox_instantiation:
713768
BLACKBOX name name ';'
714-
{ current_pragmas.clear(); }
715-
| BLACKBOX name name '{' blackbox_config '}'
716-
{ current_pragmas.clear(); }
769+
{ global->add($3, new IR::Declaration_Instance(@3, $3, getPragmas(),
770+
new IR::Type_Name($2), new IR::Vector<IR::Expression>)); }
771+
| BLACKBOX name name '{'
772+
{ $<BBox>$ = new IR::Declaration_Instance(@3, $3, getPragmas(),
773+
new IR::Type_Name($2), new IR::Vector<IR::Expression>); }
774+
blackbox_config '}'
775+
{ global->add($3, $6); }
717776
;
718777

719-
blackbox_config: /* epsilon */
778+
blackbox_config: /* epsilon */ { $$ = $<BBox>0; }
720779
| blackbox_config name ':' expressions ';'
780+
{ const IR::PropertyValue *pv;
781+
if ($4->size() == 1)
782+
pv = new IR::ExpressionValue($4->front());
783+
else
784+
pv = new IR::ExpressionListValue(std::move(*$4));
785+
($$=$1)->properties.add($2, new IR::Property(@2+@4, $2, pv, false)); }
721786
| blackbox_config name '{' expressions '}'
722-
;
787+
{ auto *pv = new IR::ExpressionListValue(std::move(*$4));
788+
($$=$1)->properties.add($2, new IR::Property(@2+@4, $2, pv, false)); }
789+
;
723790

724791
expressions: /* epsilon */
725792
{ $$ = new IR::Vector<IR::Expression>; }
@@ -739,9 +806,9 @@ pragma_operands: /* epsilon */
739806

740807
pragma_operand:
741808
INTEGER { $$ = $1; }
742-
| STRING { $$ = new IR::StringLiteral($1); }
743-
| name { $$ = new IR::StringLiteral($1); }
744-
| name '.' name { $$ = new IR::StringLiteral($1 + '.' + $3); }
809+
| STRING_LITERAL { $$ = new IR::StringLiteral(@1, $1); }
810+
| name { $$ = new IR::StringLiteral(@1, $1); }
811+
| name '.' name { $$ = new IR::StringLiteral(@1+@3, $1 + '.' + $3); }
745812
;
746813

747814
/***************/
@@ -813,15 +880,16 @@ opt_expression_list: /* epsilon */ { $$ = nullptr; } | expression_list
813880

814881
name: IDENTIFIER
815882
| ACTION | ACTIONS | ACTION_PROFILE | ACTION_SELECTOR | ALGORITHM
816-
| ATTRIBUTE | ATTRIBUTES | BIT | BLACKBOX | BLACKBOX_TYPE
883+
| ATTRIBUTE | ATTRIBUTES | BIT | BLACKBOX | BLACKBOX_TYPE | BLOCK
817884
| CALCULATED_FIELD | CONTROL | COUNTER | DEFAULT_ACTION
818-
| DIRECT | DROP | DYNAMIC_ACTION_SELECTION | EXTRACT | FIELD_LIST
819-
| FIELD_LIST_CALCULATION | FIELDS | HEADER | HEADER_TYPE | IMPLEMENTATION
885+
| DIRECT | DROP | DYNAMIC_ACTION_SELECTION | EXPRESSION | EXPRESSION_LOCAL_VARIABLES
886+
| EXTRACT | FIELD_LIST
887+
| FIELD_LIST_CALCULATION | FIELDS | HEADER | HEADER_TYPE | IMPLEMENTATION | IN
820888
| INPUT | INSTANCE_COUNT | INT | LAYOUT | LENGTH | MASK | MAX_LENGTH | MAX_SIZE
821-
| MAX_WIDTH | METADATA | METER | METHOD | MIN_SIZE | MIN_WIDTH | OUTPUT_WIDTH
822-
| PARSER | PARSER_EXCEPTION | PRE_COLOR | PRIMITIVE_ACTION | READS
889+
| MAX_WIDTH | METADATA | METER | METHOD | MIN_SIZE | MIN_WIDTH | OPTIONAL | OUT
890+
| OUTPUT_WIDTH | PARSER | PARSER_EXCEPTION | PRE_COLOR | PRIMITIVE_ACTION | READS
823891
| REGISTER | RESULT | RETURN | SATURATING | SELECTION_KEY | SELECTION_MODE
824-
| SELECTION_TYPE | SET_METADATA | SIGNED | SIZE | STATIC | TABLE | TYPE
892+
| SELECTION_TYPE | SET_METADATA | SIGNED | SIZE | STATIC | STRING | TABLE | TYPE
825893
| UPDATE | VERIFY | WIDTH | WRITES
826894
;
827895

@@ -867,3 +935,10 @@ static IR::Constant *constantFold(IR::Expression *a) {
867935
auto rv = exp->apply(P4::DoConstantFolding(nullptr, nullptr))->to<IR::Constant>();
868936
return rv ? new IR::Constant(rv->type, rv->value, rv->base) : nullptr;
869937
}
938+
939+
static IR::Vector<IR::Expression> make_expr_list(const IR::NameList *list) {
940+
IR::Vector<IR::Expression> rv;
941+
for (auto &name :list->names)
942+
rv.push_back(new IR::StringLiteral(name));
943+
return rv;
944+
}

frontends/p4/createBuiltins.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ void CreateBuiltins::postorder(IR::ActionListElement* element) {
4949
void CreateBuiltins::postorder(IR::ExpressionValue* expression) {
5050
// convert a default_action = a; into
5151
// default_action = a();
52-
auto prop = findContext<IR::TableProperty>();
52+
auto prop = findContext<IR::Property>();
5353
if (prop != nullptr &&
5454
prop->name == IR::TableProperties::defaultActionPropertyName &&
5555
expression->expression->is<IR::PathExpression>())

frontends/p4/evaluator/evaluator.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ bool Evaluator::preorder(const IR::P4Table* table) {
252252
return false;
253253
}
254254

255-
bool Evaluator::preorder(const IR::TableProperty* prop) {
255+
bool Evaluator::preorder(const IR::Property* prop) {
256256
LOG1("Evaluating " << prop);
257257
visit(prop->value);
258258
auto value = getValue(prop->value);

frontends/p4/evaluator/evaluator.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ class Evaluator final : public Inspector, public IHasBlock {
6161
bool preorder(const IR::Declaration_Instance* inst) override;
6262
bool preorder(const IR::ConstructorCallExpression* inst) override;
6363
bool preorder(const IR::PathExpression* expression) override;
64-
bool preorder(const IR::TableProperty* prop) override;
64+
bool preorder(const IR::Property* prop) override;
6565
bool preorder(const IR::Member* expression) override;
6666
bool preorder(const IR::Constant* expression) override
6767
{ setValue(expression, expression); return false; }

0 commit comments

Comments
 (0)