Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an explicit optional match key type. #3920

Merged
merged 3 commits into from
Mar 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 12 additions & 15 deletions backends/p4tools/modules/testgen/core/small_step/table_stepper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,7 @@
#include "backends/p4tools/modules/testgen/lib/execution_state.h"
#include "backends/p4tools/modules/testgen/lib/test_spec.h"

namespace P4Tools {

namespace P4Testgen {
namespace P4Tools::P4Testgen {

const ExecutionState *TableStepper::getExecutionState() { return &stepper->state; }

Expand Down Expand Up @@ -106,17 +104,18 @@ bool TableStepper::compareLPMEntries(const IR::Entry *leftIn, const IR::Entry *r
left->node_type_name(), right, right->node_type_name());
}

const IR::Expression *TableStepper::computeTargetMatchType(
ExecutionState *nextState, const KeyProperties &keyProperties,
std::map<cstring, const FieldMatch> *matches, const IR::Expression *hitCondition) {
const IR::Expression *TableStepper::computeTargetMatchType(ExecutionState *nextState,
const KeyProperties &keyProperties,
TableMatchMap *matches,
const IR::Expression *hitCondition) {
const IR::Expression *keyExpr = keyProperties.key->expression;
// Create a new zombie constant that corresponds to the key expression.
cstring keyName = properties.tableName + "_key_" + keyProperties.name;
const auto ctrlPlaneKey = nextState->createZombieConst(keyExpr->type, keyName);

if (keyProperties.matchType == P4Constants::MATCH_KIND_EXACT) {
hitCondition = new IR::LAnd(hitCondition, new IR::Equ(keyExpr, ctrlPlaneKey));
matches->emplace(keyProperties.name, Exact(keyProperties.key, ctrlPlaneKey));
matches->emplace(keyProperties.name, new Exact(keyProperties.key, ctrlPlaneKey));
return hitCondition;
}
if (keyProperties.matchType == P4Constants::MATCH_KIND_TERNARY) {
Expand All @@ -129,7 +128,8 @@ const IR::Expression *TableStepper::computeTargetMatchType(
} else {
ternaryMask = nextState->createZombieConst(keyExpr->type, maskName);
}
matches->emplace(keyProperties.name, Ternary(keyProperties.key, ctrlPlaneKey, ternaryMask));
matches->emplace(keyProperties.name,
new Ternary(keyProperties.key, ctrlPlaneKey, ternaryMask));
return new IR::LAnd(hitCondition, new IR::Equ(new IR::BAnd(keyExpr, ternaryMask),
new IR::BAnd(ctrlPlaneKey, ternaryMask)));
}
Expand All @@ -151,7 +151,7 @@ const IR::Expression *TableStepper::computeTargetMatchType(
} else {
lpmMask = new IR::Shl(IR::getConstant(keyType, maxReturn), prefix);
}
matches->emplace(keyProperties.name, LPM(keyProperties.key, ctrlPlaneKey, maskVar));
matches->emplace(keyProperties.name, new LPM(keyProperties.key, ctrlPlaneKey, maskVar));
return new IR::LAnd(
hitCondition,
new IR::LAnd(
Expand All @@ -164,8 +164,7 @@ const IR::Expression *TableStepper::computeTargetMatchType(
TESTGEN_UNIMPLEMENTED("Match type %s not implemented for table keys.", keyProperties.matchType);
}

const IR::Expression *TableStepper::computeHit(ExecutionState *nextState,
std::map<cstring, const FieldMatch> *matches) {
const IR::Expression *TableStepper::computeHit(ExecutionState *nextState, TableMatchMap *matches) {
const IR::Expression *hitCondition = IR::getBoolLiteral(!properties.resolvedKeys.empty());
for (auto keyProperties : properties.resolvedKeys) {
hitCondition = computeTargetMatchType(nextState, keyProperties, matches, hitCondition);
Expand Down Expand Up @@ -391,7 +390,7 @@ void TableStepper::evalTableControlEntries(
auto *nextState = new ExecutionState(stepper->state);

// First, we compute the hit condition to trigger this particular action call.
std::map<cstring, const FieldMatch> matches;
TableMatchMap matches;
const auto *hitCondition = computeHit(nextState, &matches);

// We get the control plane name of the action we are calling.
Expand Down Expand Up @@ -683,6 +682,4 @@ TableStepper::TableStepper(ExprStepper *stepper, const IR::P4Table *table)
properties.tableName = table->controlPlaneName();
}

} // namespace P4Testgen

} // namespace P4Tools
} // namespace P4Tools::P4Testgen
10 changes: 5 additions & 5 deletions backends/p4tools/modules/testgen/core/small_step/table_stepper.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,16 +138,16 @@ class TableStepper {
/// match or does not match at all. The table stepper first checks these custom match types. If
/// these do not match it steps through the default implementation. If it does not match either,
/// a P4C_UNIMPLEMENTED is thrown.
virtual const IR::Expression *computeTargetMatchType(
ExecutionState *nextState, const KeyProperties &keyProperties,
std::map<cstring, const FieldMatch> *matches, const IR::Expression *hitCondition);
virtual const IR::Expression *computeTargetMatchType(ExecutionState *nextState,
const KeyProperties &keyProperties,
TableMatchMap *matches,
const IR::Expression *hitCondition);

/// A helper function that computes whether a control-plane/table-key hits or not. This does not
/// handle constant entries, it is specialized for control plane entries.
/// The function also tracks the list of field matches created to achieve a hit. We later use
/// this to insert table entries using the STF/PTF framework.
const IR::Expression *computeHit(ExecutionState *nextState,
std::map<cstring, const FieldMatch> *matches);
const IR::Expression *computeHit(ExecutionState *nextState, TableMatchMap *matches);

/// Collects properties that may be set per table. Target back end may have different semantics
/// for table execution that need to be collect before evaluation the table.
Expand Down
51 changes: 8 additions & 43 deletions backends/p4tools/modules/testgen/lib/test_spec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@
#include "ir/irutils.h"
#include "lib/exceptions.h"

namespace P4Tools {

namespace P4Testgen {
namespace P4Tools::P4Testgen {

/* =========================================================================================
* Test Specification Objects
Expand Down Expand Up @@ -167,35 +165,6 @@ const LPM *LPM::evaluate(const Model &model) const {

cstring LPM::getObjectName() const { return "LPM"; }

Range::Range(const IR::KeyElement *key, const IR::Expression *low, const IR::Expression *high)
: TableMatch(key), low(low), high(high) {}

const IR::Constant *Range::getEvaluatedLow() const {
const auto *constant = low->to<IR::Constant>();
BUG_CHECK(constant,
"Variable is not a constant. It has type %1% instead. Has the test object %2% "
"been evaluated?",
low->type->node_type_name(), getObjectName());
return constant;
}

const IR::Constant *Range::getEvaluatedHigh() const {
const auto *constant = high->to<IR::Constant>();
BUG_CHECK(constant,
"Variable is not a constant. It has type %1% instead. Has the test object %2% "
"been evaluated?",
high->type->node_type_name(), getObjectName());
return constant;
}

const Range *Range::evaluate(const Model &model) const {
const auto *evaluatedLow = model.evaluate(low);
const auto *evaluatedHigh = model.evaluate(high);
return new Range(getKey(), evaluatedLow, evaluatedHigh);
}

cstring Range::getObjectName() const { return "Range"; }

Exact::Exact(const IR::KeyElement *key, const IR::Expression *val) : TableMatch(key), value(val) {}

const IR::Constant *Exact::getEvaluatedValue() const {
Expand All @@ -214,11 +183,10 @@ const Exact *Exact::evaluate(const Model &model) const {

cstring Exact::getObjectName() const { return "Exact"; }

TableRule::TableRule(std::map<cstring, const FieldMatch> matches, int priority, ActionCall action,
int ttl)
TableRule::TableRule(TableMatchMap matches, int priority, ActionCall action, int ttl)
: matches(std::move(matches)), priority(priority), action(std::move(action)), ttl(ttl) {}

const std::map<cstring, const FieldMatch> *TableRule::getMatches() const { return &matches; }
const TableMatchMap *TableRule::getMatches() const { return &matches; }

int TableRule::getPriority() const { return priority; }

Expand All @@ -229,14 +197,13 @@ int TableRule::getTTL() const { return ttl; }
cstring TableRule::getObjectName() const { return "TableRule"; }

const TableRule *TableRule::evaluate(const Model &model) const {
std::map<cstring, const FieldMatch> evaluatedMatches;
TableMatchMap evaluatedMatches;
for (const auto &matchTuple : matches) {
auto name = matchTuple.first;
auto match = matchTuple.second;
const auto &match = matchTuple.second;
// This is a lambda function that applies the visitor to each variant.
const auto evaluatedMatch = boost::apply_visitor(
[model](auto const &obj) -> FieldMatch { return *obj.evaluate(model); }, match);
evaluatedMatches.insert({name, evaluatedMatch});
const auto *evaluatedMatch = match->evaluate(model)->checkedTo<TableMatch>();
evaluatedMatches[name] = evaluatedMatch;
}
const auto *evaluatedAction = action.evaluate(model);
return new TableRule(evaluatedMatches, priority, *evaluatedAction, ttl);
Expand Down Expand Up @@ -340,6 +307,4 @@ std::map<cstring, const TestObject *> TestSpec::getTestObjectCategory(cstring ca
return {};
}

} // namespace P4Testgen

} // namespace P4Tools
} // namespace P4Tools::P4Testgen
44 changes: 7 additions & 37 deletions backends/p4tools/modules/testgen/lib/test_spec.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@
#include "lib/castable.h"
#include "lib/cstring.h"

namespace P4Tools {

namespace P4Testgen {
namespace P4Tools::P4Testgen {

/// This file defines a series of test objects which, in sum, produce an abstract test
/// specification.
Expand Down Expand Up @@ -148,6 +146,8 @@ class TableMatch : public TestObject {
const IR::KeyElement *getKey() const;
};

using TableMatchMap = std::map<cstring, const TableMatch *>;

class Ternary : public TableMatch {
private:
/// The actual match value.
Expand Down Expand Up @@ -202,31 +202,6 @@ class LPM : public TableMatch {
const IR::Constant *getEvaluatedPrefixLength() const;
};

class Range : public TableMatch {
private:
/// The inclusive start of the range.
const IR::Expression *low;

/// The inclusive end of the range.
const IR::Expression *high;

public:
explicit Range(const IR::KeyElement *key, const IR::Expression *low,
const IR::Expression *high);

const Range *evaluate(const Model &model) const override;

cstring getObjectName() const override;

/// @returns the inclusive start of the range. It is expected to be a constant at this point.
/// A BUG is thrown otherwise.
const IR::Constant *getEvaluatedLow() const;

/// @returns the inclusive end of the range. It is expected to be a constant at this point.
/// A BUG is thrown otherwise.
const IR::Constant *getEvaluatedHigh() const;
};

class Exact : public TableMatch {
private:
/// The value the key is matched with.
Expand All @@ -244,12 +219,10 @@ class Exact : public TableMatch {
const IR::Constant *getEvaluatedValue() const;
};

using FieldMatch = boost::variant<Exact, Ternary, LPM, Range>;

class TableRule : public TestObject {
private:
/// Each element in the map is the control plane name of the key paired with its match rule.
const std::map<cstring, const FieldMatch> matches;
const TableMatchMap matches;

/// The priority of this entry. This is required for STF back ends when matching ternary.
int priority;
Expand All @@ -259,15 +232,14 @@ class TableRule : public TestObject {
int ttl;

public:
TableRule(std::map<cstring, const FieldMatch> matches, int priority, ActionCall action,
int ttl);
TableRule(TableMatchMap matches, int priority, ActionCall action, int ttl);

const TableRule *evaluate(const Model &model) const override;

cstring getObjectName() const override;

/// @returns the list of keys that need to match to execute the action.
const std::map<cstring, const FieldMatch> *getMatches() const;
const TableMatchMap *getMatches() const;

/// @returns the priority of this entry.
int getPriority() const;
Expand Down Expand Up @@ -381,8 +353,6 @@ class TestSpec {
static constexpr int TTL = 0;
};

} // namespace P4Testgen

} // namespace P4Tools
} // namespace P4Tools::P4Testgen

#endif /* BACKENDS_P4TOOLS_MODULES_TESTGEN_LIB_TEST_SPEC_H_ */
Loading