diff --git a/backends/p4tools/testgen/targets/bmv2/p4_asserts_parser.cpp b/backends/p4tools/testgen/targets/bmv2/p4_asserts_parser.cpp index 31c52e75e..e0f358ca0 100644 --- a/backends/p4tools/testgen/targets/bmv2/p4_asserts_parser.cpp +++ b/backends/p4tools/testgen/targets/bmv2/p4_asserts_parser.cpp @@ -11,6 +11,16 @@ namespace P4Tools { namespace AssertsParser { +static std::vector NAMES{ + "Priority", "Text", "True", "False", "LineStatementClose", + "Id", "Number", "Minus", "Plus", "Dot", + "FieldAcces", "MetadataAccess", "LeftParen", "RightParen", "Equal", + "NotEqual", "GreaterThan", "GreaterEqual", "LessThan", "LessEqual", + "LNot", "Colon", "Semicolon", "Conjunction", "Disjunction", + "Implication", "Slash", "Percent", "Shr", "Shl", + "Mul", "Comment", "Unknown", "EndString", "End", +}; + AssertsParser::AssertsParser(std::vector>& output) : restrictionsVec(output) { setName("Restrictions"); @@ -18,30 +28,39 @@ AssertsParser::AssertsParser(std::vector>& ou /// The function to get kind from token Token::Kind Token::kind() const noexcept { return m_kind; } + /// The function to replace the token kind with another kind void Token::kind(Token::Kind kind) noexcept { m_kind = kind; } + /// Kind comparison function. Allows you to compare token kind with the specified kind and return /// bool values, replacement for == bool Token::is(Token::Kind kind) const noexcept { return m_kind == kind; } + /// Kind comparison function. Allows you to compare token kind with the specified kind and return /// bool values, replacement for != bool Token::is_not(Token::Kind kind) const noexcept { return m_kind != kind; } + /// Functions for multiple comparison kind bool Token::is_one_of(Token::Kind k1, Token::Kind k2) const noexcept { return is(k1) || is(k2); } + template bool Token::is_one_of(Token::Kind k1, Token::Kind k2, Ts... ks) const noexcept { return is(k1) || is_one_of(k2, ks...); } + /// The function to get lexeme from token std::string_view Token::lexeme() const noexcept { return m_lexeme; } + /// The function to replace the token lexeme with another lexeme void Token::lexeme(std::string_view lexeme) noexcept { m_lexeme = lexeme; } /// Function to get the current character char Lexer::peek() const noexcept { return *m_beg; } + /// The function advances the iterator one index back and returns the character corresponding to the /// position of the iterator char Lexer::prev() noexcept { return *m_beg--; } + /// The function advances the iterator one index forward and returns the character corresponding to /// the position of the iterator char Lexer::get() noexcept { return *m_beg++; } @@ -58,16 +77,7 @@ bool isSpace(char c) noexcept { } std::ostream& operator<<(std::ostream& os, const Token::Kind& kind) { - static const char* const NAMES[]{ - "Priority", "Text", "True", "False", "LineStatementClose", - "Id", "Number", "Minus", "Plus", "Dot", - "FieldAcces", "MetadataAccess", "LeftParen", "RightParen", "Equal", - "NotEqual", "GreaterThan", "GreaterEqual", "LessThan", "LessEqual", - "LNot", "Colon", "Semicolon", "Conjunction", "Disjunction", - "Implication", "Slash", "Percent", "Shr", "Shl", - "Mul", "Comment", "Unknown", "EndString", "End", - }; - return os << NAMES[static_cast(kind)]; + return os << NAMES.at(static_cast(kind)); } /// The function combines IR expressions separated by the "or" ,"and" operators @@ -78,49 +88,49 @@ std::ostream& operator<<(std::ostream& os, const Token::Kind& kind) { /// equal to !IR::Expression || (IR::Expression && IR::Expression) const IR::Expression* makeSingleExpr(std::vector input) { const IR::Expression* expr = nullptr; - for (uint64_t i = 0; i < input.size(); i++) { - if (const auto* lOr = input[i]->to()) { + for (uint64_t idx = 0; idx < input.size(); idx++) { + if (const auto* lOr = input[idx]->to()) { if (lOr->right->toString() == "(tmp") { - if (i + 1 == input.size()) { + if (idx + 1 == input.size()) { break; } std::vector tmp; - uint64_t idx = i; - i++; - if (i + 1 == input.size()) { - expr = new IR::LOr(input[idx - 1], input[i]); + uint64_t jdx = idx; + idx++; + if (idx + 1 == input.size()) { + expr = new IR::LOr(input[jdx - 1], input[idx]); break; } - while (i < input.size()) { - tmp.push_back(input[i]); - i++; + while (idx < input.size()) { + tmp.push_back(input[idx]); + idx++; } if (expr == nullptr) { - expr = new IR::LOr(input[idx - 1], makeSingleExpr(tmp)); + expr = new IR::LOr(input[jdx - 1], makeSingleExpr(tmp)); } else { expr = new IR::LOr(expr, makeSingleExpr(tmp)); } break; } { - if (i + 1 == input.size()) { + if (idx + 1 == input.size()) { break; } if (expr == nullptr) { - expr = new IR::LOr(input[i - 1], input[i + 1]); + expr = new IR::LOr(input[idx - 1], input[idx + 1]); } else { - expr = new IR::LOr(expr, input[i + 1]); + expr = new IR::LOr(expr, input[idx + 1]); } } } - if (input[i]->is()) { - if (i + 1 == input.size()) { + if (input[idx]->is()) { + if (idx + 1 == input.size()) { break; } if (expr == nullptr) { - expr = new IR::LAnd(input[i - 1], input[i + 1]); + expr = new IR::LAnd(input[idx - 1], input[idx + 1]); } else { - expr = new IR::LAnd(expr, input[i + 1]); + expr = new IR::LAnd(expr, input[idx + 1]); } } } @@ -162,16 +172,16 @@ const IR::Expression* makeConstant(Token input, const IR::Vector } else if (keyType->is()) { type = IR::Type_Bits::get(1); } else { - BUG("Unexpected key type %s.", type->node_type_name()); + BUG("Unexpected key type %s.", keyType->node_type_name()); } return IRUtils::getZombieConst(type, 0, std::string(inputStr)); } } if (input.is(Token::Kind::Number)) { - if (leftType == nullptr) + if (leftType == nullptr) { return IRUtils::getConstant(IR::Type_Bits::get(32), static_cast(inputStr)); - else - return IRUtils::getConstant(leftType, static_cast(inputStr)); + } + return IRUtils::getConstant(leftType, static_cast(inputStr)); } // TODO: Is this the right solution for priorities? if (input.is(Token::Kind::Priority)) { @@ -186,12 +196,12 @@ const IR::Expression* makeConstant(Token input, const IR::Vector /// Determines the right side of the expression starting from the original position and returns a /// slice of tokens related to the right side and the index of the end of the right side. /// Returning the end index is necessary so that after moving from the end of the right side -std::pair, int> findRightPart(std::vector tokens, int index) { - int idx = index + 1; +std::pair, size_t> findRightPart(std::vector tokens, size_t index) { + size_t idx = index + 1; int endIdx = 0; bool flag = true; while (flag) { - if (idx == (int)tokens.size() || + if (idx == tokens.size() || tokens[idx].is_one_of(Token::Kind::Conjunction, Token::Kind::Disjunction, Token::Kind::RightParen)) { endIdx = idx; @@ -207,17 +217,64 @@ std::pair, int> findRightPart(std::vector tokens, int return std::make_pair(rightTokens, idx); } +/// Chose a binary expression that correlates to the token kind. +const IR::Expression* pickBinaryExpr(const Token& token, const IR::Expression* leftL, + const IR::Expression* rightL) { + if (token.is(Token::Kind::Minus)) { + return new IR::Sub(leftL, rightL); + } + if (token.is(Token::Kind::Plus)) { + return new IR::Add(leftL, rightL); + } + if (token.is(Token::Kind::Equal)) { + return new IR::Equ(leftL, rightL); + } + if (token.is(Token::Kind::NotEqual)) { + return new IR::Neq(leftL, rightL); + } + if (token.is(Token::Kind::GreaterThan)) { + return new IR::Grt(leftL, rightL); + } + if (token.is(Token::Kind::GreaterEqual)) { + return new IR::Geq(leftL, rightL); + } + if (token.is(Token::Kind::LessThan)) { + return new IR::Lss(leftL, rightL); + } + if (token.is(Token::Kind::LessEqual)) { + return new IR::Leq(leftL, rightL); + } + if (token.is(Token::Kind::Slash)) { + return new IR::Div(leftL, rightL); + } + if (token.is(Token::Kind::Percent)) { + return new IR::Mod(leftL, rightL); + } + if (token.is(Token::Kind::Shr)) { + return new IR::Shr(leftL, rightL); + } + if (token.is(Token::Kind::Shl)) { + return new IR::Shl(leftL, rightL); + } + if (token.is(Token::Kind::Mul)) { + return new IR::Mul(leftL, rightL); + } + if (token.is(Token::Kind::NotEqual)) { + return new IR::Neq(leftL, rightL); + } + BUG("Unsupported binary expression."); +} + /// Converts a vector of tokens into a single IR:Expression /// For example, at the input we have a vector of tokens: /// [key1(Text), ->(Implication), key2(Text), &&(Conjunction), key3(Text)] The result will be an /// IR::Expression equal to !IR::Expression || (IR::Expression && IR::Expression) const IR::Expression* getIR(std::vector tokens, const IR::Vector& keyElements) { - const IR::Expression* expr = nullptr; std::vector exprVec; - for (int i = 0; i < static_cast(tokens.size()); i++) { - auto token = tokens.at(i); + for (size_t idx = 0; idx < tokens.size(); idx++) { + auto token = tokens.at(idx); if (token.is_one_of( Token::Kind::Minus, Token::Kind::Plus, Token::Kind::Equal, Token::Kind::NotEqual, Token::Kind::GreaterThan, Token::Kind::GreaterEqual, Token::Kind::LessThan, @@ -225,75 +282,45 @@ const IR::Expression* getIR(std::vector tokens, Token::Kind::Shl, Token::Kind::Mul, Token::Kind::NotEqual)) { const IR::Expression* leftL = nullptr; const IR::Expression* rightL = nullptr; - leftL = makeConstant(tokens[i - 1], keyElements, nullptr); - if (tokens[i + 1].is_one_of(Token::Kind::Text, Token::Kind::Number)) { - rightL = makeConstant(tokens[i + 1], keyElements, leftL->type); + leftL = makeConstant(tokens[idx - 1], keyElements, nullptr); + if (tokens[idx + 1].is_one_of(Token::Kind::Text, Token::Kind::Number)) { + rightL = makeConstant(tokens[idx + 1], keyElements, leftL->type); if (const auto* constant = leftL->to()) { auto* clone = constant->clone(); clone->type = rightL->type; leftL = clone; } } else { - auto rightPart = findRightPart(tokens, i); + auto rightPart = findRightPart(tokens, idx); rightL = getIR(rightPart.first, keyElements); - i = rightPart.second; + idx = rightPart.second; } - if (i - 2 > 0 && tokens[i - 2].is(Token::Kind::LNot)) { + if (idx - 2 > 0 && tokens[idx - 2].is(Token::Kind::LNot)) { leftL = new IR::LNot(leftL); } - - if (tokens[i].is(Token::Kind::Minus)) expr = new IR::Sub(leftL, rightL); - - if (tokens[i].is(Token::Kind::Plus)) expr = new IR::Add(leftL, rightL); - - if (tokens[i].is(Token::Kind::Equal)) expr = new IR::Equ(leftL, rightL); - - if (tokens[i].is(Token::Kind::NotEqual)) expr = new IR::Neq(leftL, rightL); - - if (tokens[i].is(Token::Kind::GreaterThan)) expr = new IR::Grt(leftL, rightL); - - if (tokens[i].is(Token::Kind::GreaterEqual)) expr = new IR::Geq(leftL, rightL); - - if (tokens[i].is(Token::Kind::LessThan)) expr = new IR::Lss(leftL, rightL); - - if (tokens[i].is(Token::Kind::LessEqual)) expr = new IR::Leq(leftL, rightL); - - if (tokens[i].is(Token::Kind::Slash)) expr = new IR::Div(leftL, rightL); - - if (tokens[i].is(Token::Kind::Percent)) expr = new IR::Mod(leftL, rightL); - - if (tokens[i].is(Token::Kind::Shr)) expr = new IR::Shr(leftL, rightL); - - if (tokens[i].is(Token::Kind::Shl)) expr = new IR::Shl(leftL, rightL); - - if (tokens[i].is(Token::Kind::Mul)) expr = new IR::Mul(leftL, rightL); - - if (tokens[i].is(Token::Kind::NotEqual)) expr = new IR::Neq(leftL, rightL); - - exprVec.push_back(expr); - + exprVec.push_back(pickBinaryExpr(token, leftL, rightL)); } else if (token.is(Token::Kind::LNot)) { - if (!tokens[i + 1].is_one_of(Token::Kind::Text, Token::Kind::Number)) { - auto rightPart = findRightPart(tokens, i); + if (!tokens[idx + 1].is_one_of(Token::Kind::Text, Token::Kind::Number)) { + auto rightPart = findRightPart(tokens, idx); const IR::Expression* exprLNot = getIR(rightPart.first, keyElements); - i = rightPart.second; + idx = rightPart.second; exprVec.push_back(new IR::LNot(exprLNot)); } - } else if (tokens[i].is(Token::Kind::Implication)) { - auto tmp = exprVec[exprVec.size() - 1]; + } else if (token.is(Token::Kind::Implication)) { + const auto* tmp = exprVec[exprVec.size() - 1]; exprVec.pop_back(); - const IR::Expression* expr1 = new IR::PathExpression(new IR::Path(IR::ID("tmp"))); + const IR::Expression* expr1 = new IR::PathExpression(new IR::Path("tmp")); exprVec.push_back(new IR::LNot(tmp)); - const IR::Expression* expr2 = new IR::PathExpression(new IR::Path(IR::ID("(tmp"))); + const IR::Expression* expr2 = new IR::PathExpression(new IR::Path("(tmp")); exprVec.push_back(new IR::LOr(expr1, expr2)); - } else if (tokens[i].is(Token::Kind::Disjunction)) { - const IR::Expression* expr1 = new IR::PathExpression(new IR::Path(IR::ID("tmp"))); - const IR::Expression* expr2 = new IR::PathExpression(new IR::Path(IR::ID("tmp"))); + } else if (token.is(Token::Kind::Disjunction)) { + const IR::Expression* expr1 = new IR::PathExpression(new IR::Path("tmp")); + const IR::Expression* expr2 = new IR::PathExpression(new IR::Path("tmp")); exprVec.push_back(new IR::LOr(expr1, expr2)); - } else if (tokens[i].is(Token::Kind::Conjunction)) { - const IR::Expression* expr1 = new IR::PathExpression(new IR::Path(IR::ID("tmp"))); - const IR::Expression* expr2 = new IR::PathExpression(new IR::Path(IR::ID("tmp"))); + } else if (token.is(Token::Kind::Conjunction)) { + const IR::Expression* expr1 = new IR::PathExpression(new IR::Path("tmp")); + const IR::Expression* expr2 = new IR::PathExpression(new IR::Path("tmp")); exprVec.push_back(new IR::LAnd(expr1, expr2)); } } @@ -302,9 +329,7 @@ const IR::Expression* getIR(std::vector tokens, return exprVec[0]; } - expr = makeSingleExpr(exprVec); - - return expr; + return makeSingleExpr(exprVec); } /// Combines successive tokens into variable names. /// Returns a vector with tokens combined into names. @@ -345,7 +370,7 @@ std::vector combineTokensToNames(const std::vector& inputVector) { return result; } -/// Combines successive tokens into numbers. For converting boolean or Hex, Octal values ​​to +/// Combines successive tokens into numbers. For converting boolean or Hex, Octal values to /// numbers we must first use combineTokensToNames. Returns a vector with tokens combined into /// numbers. For example, at the input we have a vector of tokens: [a(Text),c(Text),b(text), /// +(Plus), 1(Number),2(number)] The result will be [a(Text),c(Text),b(text), +(Plus), 12(number)] @@ -395,7 +420,7 @@ std::vector combineTokensToNumbers(std::vector input) { } return result; } -/// Convert access tokens or keys into table keys. For converting access tokens or keys ​​to +/// Convert access tokens or keys into table keys. For converting access tokens or keys to /// table keys we must first use combineTokensToNames. Returns a vector with tokens converted into /// table keys. /// For example, at the input we have a vector of tokens: diff --git a/backends/p4tools/testgen/targets/bmv2/p4_refers_to_parser.cpp b/backends/p4tools/testgen/targets/bmv2/p4_refers_to_parser.cpp index dd212d8d0..aee3f97cc 100644 --- a/backends/p4tools/testgen/targets/bmv2/p4_refers_to_parser.cpp +++ b/backends/p4tools/testgen/targets/bmv2/p4_refers_to_parser.cpp @@ -19,12 +19,13 @@ void RefersToParser::createConstraint(bool table, cstring currentName, cstring c cstring destKeyName, cstring destTableName, const IR::Type* type) { cstring tmp = ""; - if (table) + if (table) { tmp = currentName + "_key_" + currentKeyName; - else + } else { tmp = currentName + currentKeyName; + } auto left = IRUtils::getZombieConst(type, 0, tmp); - std::string str = static_cast(currentName); + std::string str = currentName.c_str(); std::vector elems; std::stringstream ss(str); std::string item; @@ -32,12 +33,12 @@ void RefersToParser::createConstraint(bool table, cstring currentName, cstring c elems.push_back(item); } str = ""; - for (long unsigned int i = 0; i < elems.size() - 1; i++) { + for (uint64_t i = 0; i < elems.size() - 1; i++) { str += elems[i] + "."; } tmp = str + destTableName + "_key_" + destKeyName; auto right = IRUtils::getZombieConst(type, 0, tmp); - auto expr = new IR::Equ(left, right); + auto* expr = new IR::Equ(left, right); std::vector constraint; constraint.push_back(expr); restrictionsVec.push_back(constraint); @@ -46,15 +47,15 @@ void RefersToParser::createConstraint(bool table, cstring currentName, cstring c const IR::Node* RefersToParser::postorder(IR::Annotation* annotation) { const IR::P4Action* prevAction = nullptr; if (annotation->name.name == "refers_to") { - if (auto action = findOrigCtxt()) { + if (const auto* action = findOrigCtxt()) { if (prevAction != action) { actionVector.push_back(action); prevAction = action; } - } else if (auto keys = findOrigCtxt()) { - auto table = findOrigCtxt(); + } else if (const auto* keys = findOrigCtxt()) { + const auto* table = findOrigCtxt(); CHECK_NULL(table); - auto key = findOrigCtxt(); + const auto* key = findOrigCtxt(); CHECK_NULL(key); auto it = find(keys->keyElements.begin(), keys->keyElements.end(), key); if (it != keys->keyElements.end()) { @@ -67,10 +68,11 @@ const IR::Node* RefersToParser::postorder(IR::Annotation* annotation) { } return annotation; } + // Finds a P4Action in the actionVector according /// to the specified input argument which is an ActionListElement const IR::P4Action* RefersToParser::findAction(const IR::ActionListElement* input) { - for (auto element : actionVector) { + for (const auto* element : actionVector) { if (input->getName().name == element->name.name) { return element; } @@ -82,7 +84,7 @@ const IR::P4Action* RefersToParser::findAction(const IR::ActionListElement* inpu // The build starts at index 2 because 0 is the table name and 1 is ",". cstring buildName(IR::Vector input) { cstring result = ""; - for (long unsigned int i = 2; i < input.size(); i++) { + for (uint64_t i = 2; i < input.size(); i++) { result += input[i]->text; } return result; @@ -91,23 +93,23 @@ cstring buildName(IR::Vector input) { /// An intermediate function that determines the type for future variables and partially /// collects their names for them, after which it calls the createConstraint function, /// which completes the construction of the constraint -void RefersToParser::createRefersToConstraint(IR::Vector annotations, +void RefersToParser::createRefersToConstraint(const IR::Vector& annotations, const IR::Type* inputType, cstring controlPlaneName, int id, bool isParameter, cstring inputName) { cstring currentKeyName = inputName; const IR::Type* type = nullptr; - for (auto annotation : annotations) { + for (const auto* annotation : annotations) { if (annotation->name.name == "refers_to") { cstring destTableName = annotation->body[0]->text; cstring destKeyName = buildName(annotation->body); - if (auto bit = inputType->to()) { + if (const auto* bit = inputType->to()) { type = bit; - } else if (auto varbit = inputType->to()) { + } else if (const auto* varbit = inputType->to()) { type = varbit; - } else if (inputType->to()) { - type = IR::Type_Bits::get(32); - } else { + } else if (inputType->is()) { type = IR::Type_Bits::get(1); + } else { + BUG("Unexpected key type %s.", inputType->node_type_name()); } if (isParameter) { currentKeyName = "_param_" + inputName + std::to_string(id); @@ -122,18 +124,18 @@ void RefersToParser::createRefersToConstraint(IR::Vector annotat } const IR::Node* RefersToParser::postorder(IR::ActionListElement* action) { - auto findedAction = findAction(action); - if (!findedAction) { + const auto* actionCall = findAction(action); + if (actionCall == nullptr) { return action; } - if (auto table = findOrigCtxt()) { - if (findedAction->parameters) { + if (const auto* table = findOrigCtxt()) { + if (actionCall->parameters != nullptr) { int id = 0; - for (auto parameter : findedAction->parameters->parameters) { - if (parameter->annotations) { + for (const auto* parameter : actionCall->parameters->parameters) { + if (parameter->annotations != nullptr) { createRefersToConstraint(parameter->annotations->annotations, parameter->type, table->controlPlaneName(), id, true, - findedAction->controlPlaneName()); + actionCall->controlPlaneName()); } id++; } diff --git a/backends/p4tools/testgen/targets/bmv2/p4_refers_to_parser.h b/backends/p4tools/testgen/targets/bmv2/p4_refers_to_parser.h index 30c3c4b88..f852eb19c 100644 --- a/backends/p4tools/testgen/targets/bmv2/p4_refers_to_parser.h +++ b/backends/p4tools/testgen/targets/bmv2/p4_refers_to_parser.h @@ -15,21 +15,27 @@ namespace RefersToParser { class RefersToParser : public Transform { std::vector>& restrictionsVec; + std::vector actionVector; + /// Finds a P4Action in the actionVector according /// to the specified input argument which is an ActionListElement const IR::P4Action* findAction(const IR::ActionListElement* input); + /// An intermediate function that determines the type for future variables and partially /// collects their names for them, after which it calls the createConstraint function, /// which completes the construction of the constraint - void createRefersToConstraint(IR::Vector annotations, const IR::Type* inputType, - cstring controlPlaneName, int id, bool isParameter, - cstring inputName); + void createRefersToConstraint(const IR::Vector& annotations, + const IR::Type* inputType, cstring controlPlaneName, int id, + bool isParameter, cstring inputName); public: explicit RefersToParser(std::vector>& output); + const IR::Node* postorder(IR::ActionListElement* action) override; + const IR::Node* postorder(IR::Annotation* annotation) override; + /// Builds names for the zombie constant and then creates a zombie constant and builds the /// refers_to constraints based on them void createConstraint(bool table, cstring currentName, cstring currentKeyName, diff --git a/backends/p4tools/testgen/targets/bmv2/test/p4-programs/bmv2_restrictions.p4 b/backends/p4tools/testgen/targets/bmv2/test/p4-programs/bmv2_restrictions.p4 deleted file mode 100755 index 888c380c9..000000000 --- a/backends/p4tools/testgen/targets/bmv2/test/p4-programs/bmv2_restrictions.p4 +++ /dev/null @@ -1,94 +0,0 @@ -#include - -header ethernet_t { - bit<48> dst_addr; - bit<48> src_addr; - bit<16> eth_type; -} - -header H { - bit<8> a; - bit<8> a1; - bit<8> b; -} - -struct Headers { - ethernet_t eth_hdr; - H h; -} - -struct Meta { } - -parser p(packet_in pkt, out Headers h, inout Meta meta, inout standard_metadata_t stdmeta) { - state start { - pkt.extract(h.eth_hdr); - transition parse_h; - } - state parse_h { - pkt.extract(h.h); - transition accept; - } -} - -control vrfy(inout Headers h, inout Meta meta) { - apply { } -} - - -control ingress(inout Headers h, inout Meta m, inout standard_metadata_t s) { - - action MyAction1() { - h.h.b = 1; - } - - action MyAction2() { - h.h.b = 2; - } - - action MyAction3() { - h.h.b = 3; - } - @entry_restriction(" - h.h.a1::mask != 0 && h.h.a1::prefix_length != 64; - h.h.a1 != 0; - h.h.a != 0xFF; - ") - table ternary_table { - key = { - h.h.isValid() : exact @name("valid"); - h.h.a : exact; - h.h.a1 : ternary; - } - - actions = { - NoAction; - MyAction1; - MyAction2; - MyAction3; - } - - size = 1024; - default_action = NoAction(); - } - - apply { - ternary_table.apply(); - } -} - -control egress(inout Headers h, inout Meta m, inout standard_metadata_t s) { - apply { } -} - -control update(inout Headers h, inout Meta m) { - apply { } -} - -control deparser(packet_out pkt, in Headers h) { - apply { - pkt.emit(h); - } -} - - -V1Switch(p(), vrfy(), ingress(), egress(), update(), deparser()) main; \ No newline at end of file diff --git a/backends/p4tools/testgen/targets/bmv2/test/p4-programs/bmv2_restrictions_2.p4 b/backends/p4tools/testgen/targets/bmv2/test/p4-programs/bmv2_restrictions_2.p4 index af3628ee2..e4283a67b 100755 --- a/backends/p4tools/testgen/targets/bmv2/test/p4-programs/bmv2_restrictions_2.p4 +++ b/backends/p4tools/testgen/targets/bmv2/test/p4-programs/bmv2_restrictions_2.p4 @@ -37,8 +37,8 @@ control vrfy(inout Headers h, inout Meta meta) { control ingress(inout Headers h, inout Meta m, inout standard_metadata_t s) { - action MyAction1(@refers_to(table_1 , h.h.a) bit<8> input ) { - h.h.b = 1; + action MyAction1(@refers_to(table_1 , h.h.a) bit<8> input_val) { + h.h.b = input_val; } action MyAction2() { @@ -101,4 +101,4 @@ control deparser(packet_out pkt, in Headers h) { } -V1Switch(p(), vrfy(), ingress(), egress(), update(), deparser()) main; \ No newline at end of file +V1Switch(p(), vrfy(), ingress(), egress(), update(), deparser()) main; diff --git a/backends/p4tools/testgen/test/small-step/p4_asserts_parser_test.cpp b/backends/p4tools/testgen/test/small-step/p4_asserts_parser_test.cpp index 8290193e3..fbfef03c7 100644 --- a/backends/p4tools/testgen/test/small-step/p4_asserts_parser_test.cpp +++ b/backends/p4tools/testgen/test/small-step/p4_asserts_parser_test.cpp @@ -76,52 +76,61 @@ Restrictions loadExample(const char* curFile, bool flag) { P4Tools::MidEnd midEnd(options); program = program->apply(midEnd); Restrictions result; - if (flag) + if (flag) { program->apply(P4Tools::AssertsParser::AssertsParser(result)); - else + } else { program->apply(P4Tools::RefersToParser::RefersToParser(result)); + } return result; } TEST_F(P4AssertsParserTest, RestrictionCount) { Restrictions parsingResult = loadExample( - "backends/p4tools/testgen/targets/bmv2/test/p4-programs/bmv2_restrictions.p4", true); + "backends/p4tools/testgen/targets/bmv2/test/p4-programs/bmv2_restrictions_1.p4", true); ASSERT_EQ(parsingResult.size(), (unsigned long)1); ASSERT_EQ(parsingResult[0].size(), (unsigned long)3); } TEST_F(P4AssertsParserTest, Restrictions) { Restrictions parsingResult = loadExample( - "backends/p4tools/testgen/targets/bmv2/test/p4-programs/bmv2_restrictions.p4", true); + "backends/p4tools/testgen/targets/bmv2/test/p4-programs/bmv2_restrictions_1.p4", true); ASSERT_EQ(parsingResult.size(), (unsigned long)1); - auto expr1 = P4Tools::IRUtils::getZombieConst(IR::Type_Bits::get(8), 0, - "ingress.ternary_table_mask_h.h.a1"); - auto expr2 = P4Tools::IRUtils::getZombieConst(IR::Type_Bits::get(8), 0, - "ingress.ternary_table_lpm_prefix_h.h.a1"); - auto const1 = P4Tools::IRUtils::getConstant(IR::Type_Bits::get(8), 0); - auto const2 = P4Tools::IRUtils::getConstant(IR::Type_Bits::get(8), 64); - auto operation = new IR::LAnd(new IR::Neq(expr1, const1), new IR::Neq(expr2, const2)); - expr1 = P4Tools::IRUtils::getZombieConst(IR::Type_Bits::get(8), 0, - "ingress.ternary_table_key_h.h.a1"); - auto operation1 = new IR::Neq(expr1, const1); - expr1 = P4Tools::IRUtils::getZombieConst(IR::Type_Bits::get(8), 0, - "ingress.ternary_table_key_h.h.a"); - const2 = P4Tools::IRUtils::getConstant(IR::Type_Bits::get(8), 255); - auto operation2 = new IR::Neq(expr1, const2); - ASSERT_TRUE(parsingResult[0][0]->equiv(*operation)); - ASSERT_TRUE(parsingResult[0][1]->equiv(*operation1)); - ASSERT_TRUE(parsingResult[0][2]->equiv(*operation2)); + { + const auto& expr1 = P4Tools::IRUtils::getZombieConst(IR::Type_Bits::get(8), 0, + "ingress.ternary_table_mask_h.h.a1"); + const auto& expr2 = P4Tools::IRUtils::getZombieConst( + IR::Type_Bits::get(8), 0, "ingress.ternary_table_lpm_prefix_h.h.a1"); + const auto* const1 = P4Tools::IRUtils::getConstant(IR::Type_Bits::get(8), 0); + const auto* const2 = P4Tools::IRUtils::getConstant(IR::Type_Bits::get(8), 64); + const auto* operation = + new IR::LAnd(new IR::Neq(expr1, const1), new IR::Neq(expr2, const2)); + ASSERT_TRUE(parsingResult[0][0]->equiv(*operation)); + } + { + const auto& expr1 = P4Tools::IRUtils::getZombieConst(IR::Type_Bits::get(8), 0, + "ingress.ternary_table_key_h.h.a1"); + const auto* const1 = P4Tools::IRUtils::getConstant(IR::Type_Bits::get(8), 0); + const auto* operation1 = new IR::Neq(expr1, const1); + ASSERT_TRUE(parsingResult[0][1]->equiv(*operation1)); + } + { + const auto& expr1 = P4Tools::IRUtils::getZombieConst(IR::Type_Bits::get(8), 0, + "ingress.ternary_table_key_h.h.a"); + const auto* const2 = P4Tools::IRUtils::getConstant(IR::Type_Bits::get(8), 255); + const auto* operation2 = new IR::Neq(expr1, const2); + ASSERT_TRUE(parsingResult[0][2]->equiv(*operation2)); + } } TEST_F(P4AssertsParserTest, RestrictionMiddleblockReferToInTable) { Restrictions parsingResult = loadExample( "backends/p4tools/testgen/targets/bmv2/test/p4-programs/bmv2_restrictions_2.p4", false); ASSERT_EQ(parsingResult.size(), (unsigned long)2); - auto expr1 = + const auto& expr1 = P4Tools::IRUtils::getZombieConst(IR::Type_Bits::get(8), 0, "ingress.table_1_key_h.h.a"); - auto expr2 = + const auto& expr2 = P4Tools::IRUtils::getZombieConst(IR::Type_Bits::get(8), 0, "ingress.table_2_key_h.h.a"); - auto operation = new IR::Equ(expr1, expr2); + const auto* operation = new IR::Equ(expr1, expr2); ASSERT_TRUE(parsingResult[0][0]->equiv(*operation)); }