Skip to content

Commit

Permalink
Add an explicit optional match key type. (#3920)
Browse files Browse the repository at this point in the history
  • Loading branch information
fruffy authored Mar 14, 2023
1 parent 41fe038 commit 5306a43
Show file tree
Hide file tree
Showing 20 changed files with 456 additions and 428 deletions.
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

0 comments on commit 5306a43

Please sign in to comment.