From 72b874819bd0318f326a127785074f40d28e5465 Mon Sep 17 00:00:00 2001 From: Chris Dodd Date: Wed, 15 Feb 2017 11:44:34 -0800 Subject: [PATCH 1/2] Fixes for P4_14->16 conversion of externs --- frontends/p4-14/typecheck.cpp | 11 ++-- frontends/p4/def_use.cpp | 5 ++ frontends/p4/def_use.h | 1 + frontends/p4/fromv1.0/converters.cpp | 24 +++++++- frontends/p4/fromv1.0/converters.h | 1 + frontends/p4/fromv1.0/programStructure.cpp | 72 +++++++++++++++------- frontends/p4/fromv1.0/programStructure.h | 1 + 7 files changed, 85 insertions(+), 30 deletions(-) diff --git a/frontends/p4-14/typecheck.cpp b/frontends/p4-14/typecheck.cpp index c864dad3ae0..af3c4d9f6d4 100644 --- a/frontends/p4-14/typecheck.cpp +++ b/frontends/p4-14/typecheck.cpp @@ -34,16 +34,16 @@ class TypeCheck::Pass1 : public Transform { const Visitor::Context *prop_ctxt = nullptr; if (auto prop = findContext(prop_ctxt)) { if (auto bbox = prop_ctxt->parent->node->to()) { - auto bbox_type = bbox->type->to(); - auto attr = bbox_type->attributes.get(prop->name); - if (attr->locals && attr->locals->locals.count(ref->path->name)) { - return attr->locals->locals.at(ref->path->name); } } } + if (auto bbox_type = bbox->type->to()) { + auto attr = bbox_type->attributes.get(prop->name); + if (attr->locals && attr->locals->locals.count(ref->path->name)) { + return attr->locals->locals.at(ref->path->name); } } } } if (auto bbox = findContext()) { if (auto bbox_type = bbox->type->to()) { if (auto attr = bbox_type->attributes.get(ref->path->name)) return new IR::AttributeRef(ref->srcInfo, attr->type, bbox->name, bbox_type, attr); - } else { + } else if (global) { BUG("extern type is not extern_type?"); } } return ref; } const IR::Node *preorder(IR::Metadata *m) override { @@ -92,6 +92,7 @@ class TypeCheck::Pass1 : public Transform { const IR::Node *preorder(IR::Property *prop) override { if (auto di = findContext()) { auto ext = di->type->to(); + if (!ext && !global) return prop; BUG_CHECK(ext, "%s is not an extern", di); if (auto attr = ext->attributes[prop->name]) { if (attr->type->is()) diff --git a/frontends/p4/def_use.cpp b/frontends/p4/def_use.cpp index 673d358c9b5..cb749457693 100644 --- a/frontends/p4/def_use.cpp +++ b/frontends/p4/def_use.cpp @@ -409,6 +409,11 @@ bool ComputeWriteSet::setDefinitions(Definitions* defs, const IR::Node* node) { /// For expressions we maintain the write-set in the writes std::map +bool ComputeWriteSet::preorder(const IR::Expression* expression) { + set(expression, LocationSet::empty); + return false; +} + bool ComputeWriteSet::preorder(const IR::DefaultExpression* expression) { set(expression, LocationSet::empty); return false; diff --git a/frontends/p4/def_use.h b/frontends/p4/def_use.h index 8d6b355379f..8b3c5491adf 100644 --- a/frontends/p4/def_use.h +++ b/frontends/p4/def_use.h @@ -412,6 +412,7 @@ class ComputeWriteSet : public Inspector { bool preorder(const IR::Operation_Unary* expression) override; bool preorder(const IR::MethodCallExpression* expression) override; bool preorder(const IR::DefaultExpression* expression) override; + bool preorder(const IR::Expression* expression) override; // statements bool preorder(const IR::ParserState* state) override; bool preorder(const IR::P4Parser* parser) override; diff --git a/frontends/p4/fromv1.0/converters.cpp b/frontends/p4/fromv1.0/converters.cpp index 3043e4d3e65..140983e0d8c 100644 --- a/frontends/p4/fromv1.0/converters.cpp +++ b/frontends/p4/fromv1.0/converters.cpp @@ -126,10 +126,12 @@ const IR::Node* ExpressionConverter::postorder(IR::PathExpression *ref) { if (ref->path->name.name == "next") { return ref; } - auto fl = structure->field_lists.get(ref->path->name); - if (fl != nullptr) { + if (auto fl = structure->field_lists.get(ref->path->name)) { ExpressionConverter conv(structure); - return conv.convert(fl); + return conv.convert(fl); } + if (auto flc = structure->field_list_calculations.get(ref->path->name)) { + // FIXME -- what to do with the algorithm and width from flc? + return ExpressionConverter(structure).convert(flc->input_fields); } return ref; } @@ -169,6 +171,10 @@ const IR::Node* ExpressionConverter::postorder(IR::HeaderStackItemRef* ref) { return ref; } +const IR::Node* ExpressionConverter::postorder(IR::GlobalRef *ref) { + return new IR::PathExpression(new IR::Path(ref->srcInfo, ref->toString())); +} + const IR::Node* StatementConverter::preorder(IR::Apply* apply) { auto table = structure->tables.get(apply->name); auto newname = structure->tables.get(table); @@ -478,6 +484,18 @@ class ComputeCallGraph : public Inspector { structure->calledControls.calls(parent->name, name); } } + void postorder(const IR::GlobalRef *gref) override { + auto parent = findContext(); + BUG_CHECK(parent != nullptr, "%1%: GlobalRef not within action", gref); + if (auto ctr = gref->obj->to()) + structure->calledCounters.calls(parent->name, ctr->name.name); + else if (auto mtr = gref->obj->to()) + structure->calledMeters.calls(parent->name, mtr->name.name); + else if (auto reg = gref->obj->to()) + structure->calledRegisters.calls(parent->name, reg->name.name); + else if (auto ext = gref->obj->to()) + structure->calledExterns.calls(parent->name, ext->name.name); + } }; class Rewriter : public Transform { diff --git a/frontends/p4/fromv1.0/converters.h b/frontends/p4/fromv1.0/converters.h index afb9fd174ce..3ff4bf88db3 100644 --- a/frontends/p4/fromv1.0/converters.h +++ b/frontends/p4/fromv1.0/converters.h @@ -44,6 +44,7 @@ class ExpressionConverter : public Transform { const IR::Node* postorder(IR::PathExpression* ref) override; const IR::Node* postorder(IR::ConcreteHeaderRef* nhr) override; const IR::Node* postorder(IR::HeaderStackItemRef* ref) override; + const IR::Node* postorder(IR::GlobalRef *gr) override; const IR::Expression* convert(const IR::Node* node) { auto result = node->apply(*this); return result->to(); diff --git a/frontends/p4/fromv1.0/programStructure.cpp b/frontends/p4/fromv1.0/programStructure.cpp index 893c6471a17..65154086c2f 100644 --- a/frontends/p4/fromv1.0/programStructure.cpp +++ b/frontends/p4/fromv1.0/programStructure.cpp @@ -225,25 +225,54 @@ void ProgramStructure::createStructures() { declarations->push_back(headers); } -void ProgramStructure::createExterns() { - for (auto it : extern_types) { - auto type = it.first; - IR::Type_Extern *modified_type = nullptr; - if (type->name != it.second) { - auto annos = addNameAnnotation(type->name.name, type->annotations); - type = modified_type = new IR::Type_Extern(type->srcInfo, it.second, type->methods, - type->attributes, annos); } +class ProgramStructure::FixupExtern : public Modifier { + ProgramStructure &self; + cstring origname, extname; + const IR::TypeParameters *typeParams = nullptr; + + bool preorder(IR::Type_Extern *type) override { + BUG_CHECK(!origname, "Nested extern"); + origname = type->name; + return true; } + void postorder(IR::Type_Extern *type) override { + if (extname != type->name) { + type->annotations = self.addNameAnnotation(type->name.name, type->annotations); + type->name = extname; } // FIXME -- should create ctors based on attributes? For now just create a // FIXME -- 0-arg one if needed if (!type->lookupMethod(type->name, 0)) { - if (!modified_type) - type = modified_type = type->clone(); auto methods = type->methods->clone(); - modified_type->methods = methods; + type->methods = methods; methods->push_back(new IR::Method(type->name, new IR::Type_Method( - new IR::ParameterList()))); } - declarations->push_back(type); - } + new IR::ParameterList()))); } } + void postorder(IR::Method *meth) override { + if (meth->name == origname) meth->name = extname; } + // Convert extern methods that take a field_list_calculation to take a type param instead + bool preorder(IR::Type_MethodBase *mtype) override { + BUG_CHECK(!typeParams, "recursion failure"); + typeParams = mtype->typeParameters; + return true; } + bool preorder(IR::Parameter *param) override { + BUG_CHECK(typeParams, "recursion failure"); + if (param->type->is()) { + auto n = new IR::Type_Var(self.makeUniqueName("FL")); + param->type = n; + auto v = typeParams->parameters->clone(); + v->push_back(n); + typeParams = new IR::TypeParameters(v); } + return false; } + void postorder(IR::Type_MethodBase *mtype) override { + BUG_CHECK(typeParams, "recursion failure"); + mtype->typeParameters = typeParams; + typeParams = nullptr; } + + public: + FixupExtern(ProgramStructure &self, cstring n) : self(self), extname(n) {} +}; + +void ProgramStructure::createExterns() { + for (auto it : extern_types) + declarations->push_back(it.first->apply(FixupExtern(*this, it.second))); } const IR::Expression* ProgramStructure::paramReference(const IR::Parameter* param) { @@ -443,14 +472,13 @@ void ProgramStructure::include(cstring filename) { CompilerOptions options; options.langVersion = CompilerOptions::FrontendVersion::P4_16; options.file = path.toString(); - FILE* file = options.preprocess(); - if (::errorCount() || file == nullptr) - return; - auto std = parse_P4_16_file(options.file, file); - if (::errorCount() || std == nullptr) - return; - for (auto decl : *std->declarations) - declarations->push_back(decl); + if (FILE* file = options.preprocess()) { + if (!::errorCount()) { + if (auto std = parse_P4_16_file(options.file, file)) { + if (!::errorCount()) { + for (auto decl : *std->declarations) { + declarations->push_back(decl); } } } } + options.closeInput(file); } } void ProgramStructure::loadModel() { diff --git a/frontends/p4/fromv1.0/programStructure.h b/frontends/p4/fromv1.0/programStructure.h index 56c8e1bebcf..d6be474561a 100644 --- a/frontends/p4/fromv1.0/programStructure.h +++ b/frontends/p4/fromv1.0/programStructure.h @@ -89,6 +89,7 @@ class ProgramStructure { iterator begin() { return iterator(nameToObject.begin(), objectToNewName); } iterator end() { return iterator(nameToObject.end(), objectToNewName); } }; + class FixupExtern; public: ProgramStructure(); From 28f625524af4917de64de387d4588718f0805b18 Mon Sep 17 00:00:00 2001 From: Chris Dodd Date: Wed, 15 Feb 2017 16:36:35 -0800 Subject: [PATCH 2/2] misc cleanups --- backends/bmv2/bmv2stf.py | 6 +++++- frontends/common/options.cpp | 6 +++--- frontends/common/parseInput.cpp | 1 + frontends/p4/fromv1.0/programStructure.cpp | 4 ++-- frontends/p4/frontend.h | 1 + 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/backends/bmv2/bmv2stf.py b/backends/bmv2/bmv2stf.py index f2bc7cac907..1c6a680a728 100755 --- a/backends/bmv2/bmv2stf.py +++ b/backends/bmv2/bmv2stf.py @@ -363,7 +363,11 @@ def do_command(self, cmd): interface, data = nextWord(cmd) data = ''.join(data.split()) time.sleep(self.packetDelay) - self.interfaces[interface]._write_packet(HexToByte(data)) + try: + self.interfaces[interface]._write_packet(HexToByte(data)) + except ValueError: + reportError("Invalid packet data", data) + return FAILURE self.interfaces[interface].flush() self.packetDelay = 0 elif first == "expect": diff --git a/frontends/common/options.cpp b/frontends/common/options.cpp index 89790785ea5..90a8aeced1b 100644 --- a/frontends/common/options.cpp +++ b/frontends/common/options.cpp @@ -280,13 +280,13 @@ void CompilerOptions::dumpPass(const char* manager, unsigned seq, const char* pa P4::ToP4 toP4(stream, Log::verbose(), file); node->apply(toP4); } + break; } } } DebugHook CompilerOptions::getDebugHook() const { - auto dp = std::bind(&CompilerOptions::dumpPass, this, - std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3, std::placeholders::_4); + using namespace std::placeholders; + auto dp = std::bind(&CompilerOptions::dumpPass, this, _1, _2, _3, _4); return dp; } diff --git a/frontends/common/parseInput.cpp b/frontends/common/parseInput.cpp index 07c626b4c47..1c177738568 100644 --- a/frontends/common/parseInput.cpp +++ b/frontends/common/parseInput.cpp @@ -30,6 +30,7 @@ const IR::P4Program* parseP4File(CompilerOptions& options) { bool compiling10 = options.isv1(); if (compiling10) { P4V1::Converter converter; + converter.addDebugHook(options.getDebugHook()); converter.loadModel(); // Model is loaded before parsing the input file. // In this way the SourceInfo in the model comes first. diff --git a/frontends/p4/fromv1.0/programStructure.cpp b/frontends/p4/fromv1.0/programStructure.cpp index 65154086c2f..858007db5f5 100644 --- a/frontends/p4/fromv1.0/programStructure.cpp +++ b/frontends/p4/fromv1.0/programStructure.cpp @@ -474,9 +474,9 @@ void ProgramStructure::include(cstring filename) { options.file = path.toString(); if (FILE* file = options.preprocess()) { if (!::errorCount()) { - if (auto std = parse_P4_16_file(options.file, file)) { + if (auto code = parse_P4_16_file(options.file, file)) { if (!::errorCount()) { - for (auto decl : *std->declarations) { + for (auto decl : *code->declarations) { declarations->push_back(decl); } } } } options.closeInput(file); } } diff --git a/frontends/p4/frontend.h b/frontends/p4/frontend.h index d8587b037ce..e6d2652f00a 100644 --- a/frontends/p4/frontend.h +++ b/frontends/p4/frontend.h @@ -26,6 +26,7 @@ class FrontEnd { std::vector hooks; public: FrontEnd() = default; + explicit FrontEnd(DebugHook hook) { hooks.push_back(hook); } void addDebugHook(DebugHook hook) { hooks.push_back(hook); } const IR::P4Program* run(const CompilerOptions& options, const IR::P4Program* program); };