Skip to content

Commit

Permalink
start to add metadata handling (#8)
Browse files Browse the repository at this point in the history
Also fixes issues with decl handling and match types.
  • Loading branch information
Calin Cascaval authored and hanw committed May 3, 2017
1 parent b70d37e commit 4e57dc4
Show file tree
Hide file tree
Showing 8 changed files with 60 additions and 27 deletions.
3 changes: 3 additions & 0 deletions backends/bmv2/analyzer.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ class ProgramParts {
std::map<const IR::P4Action*, unsigned> ids;
// All local variables
std::vector<const IR::Declaration_Variable*> variables;
// All the parsers
std::vector<const IR::P4Parser *> parsers;

ProgramParts() {}
void analyze(const IR::ToplevelBlock* toplevel);
Expand All @@ -197,6 +199,7 @@ class DiscoverStructure : public Inspector {
void postorder(const IR::ParameterList* paramList) override;
void postorder(const IR::P4Action* action) override;
void postorder(const IR::Declaration_Variable* decl) override;
void postorder(const IR::P4Parser *p) override { structure->parsers.push_back(p); }
};

} // namespace BMV2
Expand Down
23 changes: 22 additions & 1 deletion backends/bmv2/backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,26 @@ void Backend::createActions(Util::JsonArray* actions) {
}
}

// stdMeta and userMeta seem to change when moving from one declared control to another
// and drive the expression converter to use the right parameter
// still have not figured out where the metadata is actually generated!!
void Backend::createMetadata() {
for ( auto parser : structure.parsers ) {
std::cerr << "Found " << parser << std::endl;
userMetadataParameter = parser->type->applyParams->getParameter(
v1model.parser.metadataParam.index);
stdMetadataParameter = parser->type->applyParams->getParameter(
v1model.parser.standardMetadataParam.index);
auto mdType = typeMap.getType(userMetadataParameter, true);
auto mt = mdType->to<IR::Type_Struct>();
if (mt == nullptr) {
::error("Expected metadata %1% to be a struct", mdType);
return;
}
// break; // we need only one??
}
}

void Backend::addErrors(Util::JsonArray* errors) {
for (const auto &p : errorCodesMap) {
auto name = p.first->getName().name.c_str();
Expand Down Expand Up @@ -409,13 +429,14 @@ void Backend::convert(const IR::ToplevelBlock* tb) {
externs = mkArrayField(&toplevel, "extern_instances");

// This visitor is used in multiple passes to convert expression to json
conv = new ExpressionConverter(&refMap, &typeMap, &structure, &errorCodesMap);
conv = new ExpressionConverter(this);

PassManager codegen_passes = {
new CopyAnnotations(this),
new VisitFunctor([this](){ addMetaInformation(); }),
new VisitFunctor([this](){ addEnums(enums); }),
new VisitFunctor([this](){ createScalars(); }),
new VisitFunctor([this](){ createMetadata(); }),
new ConvertHeaders(this),
new VisitFunctor([this](){ addLocals(); }),
new VisitFunctor([this](){ padScalars(); }),
Expand Down
4 changes: 4 additions & 0 deletions backends/bmv2/backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ class Backend : public PassManager {
const unsigned boolWidth = 1;
unsigned scalars_width = 0;
cstring scalarsName;
const IR::Parameter* userMetadataParameter;
const IR::Parameter* stdMetadataParameter;

// We place scalar user metadata fields (i.e., bit<>, bool)
// in the "scalars" metadata object, so we may need to rename
Expand All @@ -99,6 +101,7 @@ class Backend : public PassManager {
void convertActionBody(const IR::Vector<IR::StatOrDecl>* body, Util::JsonArray* result);
void createActions(Util::JsonArray* actions);
void createScalars();
void createMetadata();
void genExternMethod(Util::JsonArray* result, P4::ExternMethod *em);
void padScalars();

Expand All @@ -112,6 +115,7 @@ class Backend : public PassManager {
void serialize(std::ostream& out) const
{ toplevel.serialize(out); }
P4::P4CoreLibrary & getCoreLibrary() const { return corelib; }
ErrorCodesMap & getErrorCodesMap() { return errorCodesMap; }
ExpressionConverter * getExpressionConverter() { return conv; };
DirectCounterMap & getDirectCounterMap() { return directCounterMap; }
DirectMeterMap & getMeterMap() { return meterMap; }
Expand Down
3 changes: 2 additions & 1 deletion backends/bmv2/control.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ void Control::convertTableEntries(const IR::P4Table *table,
::error("%1% invalid range key expression", k);
}
} else {
::error("unkown key type %1% for key %2%", matchType, k);
::error("unkown key type '%1%' for key %2%", matchType, k);
}
matchKeys->append(key);
keyIndex++;
Expand Down Expand Up @@ -163,6 +163,7 @@ cstring Control::getKeyMatchType(const IR::KeyElement *ke) {
cstring match_type = "invalid";
if (mt->name.name == backend->getCoreLibrary().exactMatch.name ||
mt->name.name == backend->getCoreLibrary().ternaryMatch.name) {
match_type = mt->name.name;
if (expr->is<IR::MethodCallExpression>()) {
auto mi = P4::MethodInstance::resolve(expr->to<IR::MethodCallExpression>(),
&backend->getRefMap(), &backend->getTypeMap());
Expand Down
33 changes: 17 additions & 16 deletions backends/bmv2/expression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,15 +87,16 @@ void ExpressionConverter::postorder(const IR::BoolLiteral* expression) {
}

void ExpressionConverter::postorder(const IR::MethodCallExpression* expression) {
auto instance = P4::MethodInstance::resolve(expression, refMap, typeMap);
auto instance = P4::MethodInstance::resolve(expression,
&backend->getRefMap(), &backend->getTypeMap());
if (instance->is<P4::ExternMethod>()) {
auto em = instance->to<P4::ExternMethod>();
if (em->originalExternType->name == corelib.packetIn.name &&
em->method->name == corelib.packetIn.lookahead.name) {
BUG_CHECK(expression->typeArguments->size() == 1,
"Expected 1 type parameter for %1%", em->method);
auto targ = expression->typeArguments->at(0);
auto typearg = typeMap->getTypeType(targ, true);
auto typearg = backend->getTypeMap().getTypeType(targ, true);
int width = typearg->width_bits();
BUG_CHECK(width > 0, "%1%: unknown width", targ);
auto j = new Util::JsonObject();
Expand Down Expand Up @@ -175,11 +176,11 @@ const IR::Parameter* ExpressionConverter::enclosingParamReference(const IR::Expr
return nullptr;

auto pe = expression->to<IR::PathExpression>();
auto decl = refMap->getDeclaration(pe->path, true);
auto decl = backend->getRefMap().getDeclaration(pe->path, true);
auto param = decl->to<IR::Parameter>();
if (param == nullptr)
return param;
if (structure->nonActionParameters.count(param) > 0)
if (backend->getStructure().nonActionParameters.count(param) > 0)
return param;
return nullptr;
}
Expand All @@ -188,7 +189,7 @@ void ExpressionConverter::postorder(const IR::Member* expression) {
// TODO: deal with references that return bool
auto result = new Util::JsonObject();

auto parentType = typeMap->getType(expression->expr, true);
auto parentType = backend->getTypeMap().getType(expression->expr, true);
cstring fieldName = expression->member.name;
if (parentType->is<IR::Type_StructLike>()) {
auto st = parentType->to<IR::Type_StructLike>();
Expand All @@ -199,11 +200,11 @@ void ExpressionConverter::postorder(const IR::Member* expression) {
}

{
auto type = typeMap->getType(expression, true);
auto type = backend->getTypeMap().getType(expression, true);
if (type->is<IR::Type_Error>()) {
result->emplace("type", "hexstr");
auto decl = type->to<IR::Type_Error>()->getDeclByName(expression->member.name);
auto errorValue = errorCodesMap->at(decl);
auto errorValue = backend->getErrorCodesMap().at(decl);
result->emplace("value", Util::toString(errorValue));
map.emplace(expression, result);
return;
Expand All @@ -212,7 +213,7 @@ void ExpressionConverter::postorder(const IR::Member* expression) {

auto param = enclosingParamReference(expression->expr);
if (param != nullptr) {
auto type = typeMap->getType(expression, true);
auto type = backend->getTypeMap().getType(expression, true);
LOG1("Parameter: " << param);
//FIXME:
#if 0
Expand Down Expand Up @@ -256,7 +257,7 @@ void ExpressionConverter::postorder(const IR::Member* expression) {
if (expression->expr->is<IR::Member>()) {
// array.next.field => type: "stack_field", value: [ array, field ]
auto mem = expression->expr->to<IR::Member>();
auto memtype = typeMap->getType(mem->expr, true);
auto memtype = backend->getTypeMap().getType(mem->expr, true);
if (memtype->is<IR::Type_Stack>() && mem->member == IR::Type_Stack::last) {
auto l = get(mem->expr);
CHECK_NULL(l);
Expand Down Expand Up @@ -419,7 +420,7 @@ void ExpressionConverter::postorder(const IR::Operation_Unary* expression) {

void ExpressionConverter::postorder(const IR::PathExpression* expression) {
// This is useful for action bodies mostly
auto decl = refMap->getDeclaration(expression->path, true);
auto decl = backend->getRefMap().getDeclaration(expression->path, true);
if (auto param = decl->to<IR::Parameter>()) {
LOG1("Expression: " << param << " " << expression);
#if 0
Expand All @@ -432,20 +433,20 @@ void ExpressionConverter::postorder(const IR::PathExpression* expression) {
return;
}
#endif
if (structure->nonActionParameters.find(param) !=
structure->nonActionParameters.end()) {
if (backend->getStructure().nonActionParameters.find(param) !=
backend->getStructure().nonActionParameters.end()) {
map.emplace(expression, new Util::JsonValue(param->name.name));
return;
}
auto result = new Util::JsonObject();
result->emplace("type", "runtime_data");
unsigned paramIndex = ::get(structure->index, param);
unsigned paramIndex = ::get(&backend->getStructure().index, param);
result->emplace("value", paramIndex);
map.emplace(expression, result);
} else if (auto var = decl->to<IR::Declaration_Variable>()) {
LOG1("Variable to json " << var);
auto result = new Util::JsonObject();
auto type = typeMap->getType(var, true);
auto type = backend->getTypeMap().getType(var, true);
if (type->is<IR::Type_StructLike>()) {
result->emplace("type", "header");
result->emplace("value", var->name);
Expand Down Expand Up @@ -498,7 +499,7 @@ void ExpressionConverter::postorder(const IR::Expression* expression) {
Util::IJson* ExpressionConverter::convert(const IR::Expression* e, bool doFixup, bool wrap, bool convertBool) {
const IR::Expression *expr = e;
if (doFixup) {
ArithmeticFixup af(typeMap);
ArithmeticFixup af(&backend->getTypeMap());
auto r = e->apply(af);
CHECK_NULL(r);
expr = r->to<IR::Expression>();
Expand Down Expand Up @@ -543,7 +544,7 @@ Util::IJson* ExpressionConverter::convert(const IR::Expression* e, bool doFixup,
Util::IJson* ExpressionConverter::convertLeftValue(const IR::Expression* e) {
leftValue = true;
const IR::Expression *expr = e;
ArithmeticFixup af(typeMap);
ArithmeticFixup af(&backend->getTypeMap());
auto r = e->apply(af);
CHECK_NULL(r);
expr = r->to<IR::Expression>();
Expand Down
11 changes: 3 additions & 8 deletions backends/bmv2/expression.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,21 +44,16 @@ class ArithmeticFixup : public Transform {
};

class ExpressionConverter : public Inspector {
P4::ReferenceMap* refMap;
P4::TypeMap* typeMap;
Backend *backend;
P4::P4CoreLibrary& corelib;
ProgramParts* structure;
ErrorCodesMap* errorCodesMap;
cstring scalarsName = "scalars";

/// after translating an Expression to JSON, save the result to 'map'.
std::map<const IR::Expression*, Util::IJson*> map;
bool leftValue; // true if converting a left value
public:
explicit ExpressionConverter(P4::ReferenceMap* refMap, P4::TypeMap* typeMap,
ProgramParts* structure, ErrorCodesMap* errorCodesMap):
refMap(refMap), typeMap(typeMap), corelib(P4::P4CoreLibrary::instance),
structure(structure), errorCodesMap(errorCodesMap),
explicit ExpressionConverter(Backend *b) :
backend(b), corelib(P4::P4CoreLibrary::instance),
leftValue(false), simpleExpressionsOnly(false) {}
bool simpleExpressionsOnly; // if set we fail to convert complex expressions

Expand Down
7 changes: 6 additions & 1 deletion backends/bmv2/extern.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,12 @@ bool Extern::preorder(const IR::Declaration_Instance* decl) {
auto result = new Util::JsonObject();
result->emplace("name", decl->name);
result->emplace("id", nextId("extern_instances"));
result->emplace("type", decl->type->to<IR::Type_Specialized>()->baseType->toString());
if (decl->type->is<IR::Type_Specialized>())
result->emplace("type", decl->type->to<IR::Type_Specialized>()->baseType->toString());
else if (decl->type->is<IR::Type_Name>())
result->emplace("type", decl->type->to<IR::Type_Name>()->path->name.toString());
else
P4C_UNIMPLEMENTED("extern support for %1%", decl);
auto attributes = mkArrayField(result, "attribute_values");
addExternAttributes(decl, externBlock, attributes);
backend->externs->append(result);
Expand Down
3 changes: 3 additions & 0 deletions backends/bmv2/v1model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ using BMV2::nextId;

namespace P4V1 {

cstring jsonMetadataParameterName = "standard_metadata";



static void addToFieldList(BMV2::Backend *bmv2, const IR::Expression* expr,
Util::JsonArray* fl)
Expand Down

0 comments on commit 4e57dc4

Please sign in to comment.