Skip to content

Commit

Permalink
Step 2: Refactor ProgramInfo to be initialized with CompilerResult in…
Browse files Browse the repository at this point in the history
…stead of a IR::P4Program. (#4324)
  • Loading branch information
fruffy authored Jan 15, 2024
1 parent fc678e8 commit 4c547a3
Show file tree
Hide file tree
Showing 34 changed files with 182 additions and 95 deletions.
15 changes: 10 additions & 5 deletions backends/p4tools/modules/testgen/core/program_info.cpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
#include "backends/p4tools/modules/testgen/core/program_info.h"

#include "backends/p4tools/common/compiler/compiler_target.h"
#include "backends/p4tools/common/compiler/reachability.h"
#include "backends/p4tools/common/lib/arch_spec.h"
#include "backends/p4tools/common/lib/util.h"
#include "backends/p4tools/common/lib/variables.h"
#include "ir/id.h"
#include "ir/irutils.h"
#include "lib/cstring.h"
#include "lib/enumerator.h"
#include "lib/exceptions.h"
#include "midend/coverage.h"

Expand All @@ -17,18 +17,19 @@

namespace P4Tools::P4Testgen {

ProgramInfo::ProgramInfo(const IR::P4Program *program) : concolicMethodImpls({}), program(program) {
ProgramInfo::ProgramInfo(const CompilerResult &compilerResult)
: compilerResult(compilerResult), concolicMethodImpls({}) {
concolicMethodImpls.add(*Concolic::getCoreConcolicMethodImpls());
if (TestgenOptions::get().dcg || !TestgenOptions::get().pattern.empty()) {
// Create DCG.
auto *currentDCG = new NodesCallGraph("NodesCallGraph");
P4ProgramDCGCreator dcgCreator(currentDCG);
program->apply(dcgCreator);
compilerResult.getProgram().apply(dcgCreator);
dcg = currentDCG;
}
/// Collect coverage information about the program.
auto coverage = P4::Coverage::CollectNodes(TestgenOptions::get().coverageOptions);
program->apply(coverage);
compilerResult.getProgram().apply(coverage);
auto coveredNodes = coverage.getCoverableNodes();
coverableNodes.insert(coveredNodes.begin(), coveredNodes.end());
}
Expand Down Expand Up @@ -74,7 +75,7 @@ void ProgramInfo::produceCopyInOutCall(const IR::Parameter *param, size_t paramI
const auto *paramType = param->type;
// We need to resolve type names.
if (const auto *tn = paramType->to<IR::Type_Name>()) {
paramType = resolveProgramType(program, tn);
paramType = resolveProgramType(&getP4Program(), tn);
}
// Retrieve the identifier of the global architecture map using the parameter
// index.
Expand All @@ -101,4 +102,8 @@ void ProgramInfo::produceCopyInOutCall(const IR::Parameter *param, size_t paramI
}
}

const CompilerResult &ProgramInfo::getCompilerResult() const { return compilerResult.get(); }

const IR::P4Program &ProgramInfo::getP4Program() const { return getCompilerResult().getProgram(); }

} // namespace P4Tools::P4Testgen
18 changes: 13 additions & 5 deletions backends/p4tools/modules/testgen/core/program_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
#include <optional>
#include <vector>

#include "backends/p4tools/common/compiler/compiler_target.h"
#include "backends/p4tools/common/compiler/reachability.h"
#include "backends/p4tools/common/lib/arch_spec.h"
#include "ir/declaration.h"
#include "ir/ir.h"
#include "lib/castable.h"
#include "midend/coverage.h"
Expand All @@ -19,8 +19,13 @@ namespace P4Tools::P4Testgen {

/// Stores target-specific information about a P4 program.
class ProgramInfo : public ICastable {
private:
/// The program info object stores the results of the compilation, which includes the P4 program
/// and any information extracted from the program using static analysis.
std::reference_wrapper<const CompilerResult> compilerResult;

protected:
explicit ProgramInfo(const IR::P4Program *program);
explicit ProgramInfo(const CompilerResult &compilerResult);

/// The list of concolic methods implemented by the target. This list is assembled during
/// initialization.
Expand Down Expand Up @@ -49,9 +54,6 @@ class ProgramInfo : public ICastable {

~ProgramInfo() override = default;

/// The P4 program from which this object is derived.
const IR::P4Program *program;

/// The generated dcg.
const NodesCallGraph *dcg = nullptr;

Expand Down Expand Up @@ -98,6 +100,12 @@ class ProgramInfo : public ICastable {
/// Throws a BUG, if the name can not be found.
[[nodiscard]] cstring getCanonicalBlockName(cstring programBlockName) const;

/// @returns a reference to the compiler result that this program info object was initialized
/// with.
[[nodiscard]] const CompilerResult &getCompilerResult() const;

[[nodiscard]] const IR::P4Program &getP4Program() const;

/// Helper function to produce copy-in and copy-out helper calls.
/// Copy-in and copy-out is needed to correctly model the value changes of data when it is
/// copied in and out of a programmable block. In many cases, data is reset here or not even
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ SymbolicExecutor::StepResult SymbolicExecutor::step(ExecutionState &state) {
}

void SymbolicExecutor::run(const Callback &callBack) {
runImpl(callBack, ExecutionState::create(programInfo.program));
runImpl(callBack, ExecutionState::create(&programInfo.getP4Program()));
}

bool SymbolicExecutor::handleTerminalState(const Callback &callback,
Expand Down
20 changes: 11 additions & 9 deletions backends/p4tools/modules/testgen/core/target.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
#include <string>
#include <utility>

#include "backends/p4tools/common/compiler/compiler_target.h"
#include "backends/p4tools/common/core/target.h"
#include "ir/declaration.h"
#include "ir/ir.h"
#include "ir/node.h"
#include "lib/enumerator.h"
#include "lib/exceptions.h"
#include "lib/log.h"

#include "backends/p4tools/modules/testgen/core/program_info.h"

Expand All @@ -18,22 +18,24 @@ namespace P4Tools::P4Testgen {
TestgenTarget::TestgenTarget(std::string deviceName, std::string archName)
: Target("testgen", std::move(deviceName), std::move(archName)) {}

const ProgramInfo *TestgenTarget::initProgramImpl(const IR::P4Program *program) const {
const ProgramInfo *TestgenTarget::produceProgramInfoImpl(
const CompilerResult &compilerResult) const {
const auto &program = compilerResult.getProgram();
// Check that the program has at least one main declaration.
const auto mainCount = program->getDeclsByName(IR::P4Program::main)->count();
const auto mainCount = program.getDeclsByName(IR::P4Program::main)->count();
BUG_CHECK(mainCount > 0, "Program doesn't have a main declaration.");

// Resolve the program's main declaration instance and delegate to the version of
// initProgramImpl that takes the main declaration.
const auto *mainIDecl = program->getDeclsByName(IR::P4Program::main)->single();
BUG_CHECK(mainIDecl, "Program's main declaration not found: %1%", program->main);
// produceProgramInfoImpl that takes the main declaration.
const auto *mainIDecl = program.getDeclsByName(IR::P4Program::main)->single();
BUG_CHECK(mainIDecl, "Program's main declaration not found: %1%", program.main);

const auto *mainNode = mainIDecl->getNode();
const auto *mainDecl = mainIDecl->to<IR::Declaration_Instance>();
BUG_CHECK(mainDecl, "%1%: Program's main declaration is a %2%, not a Declaration_Instance",
mainNode, mainNode->node_type_name());

return initProgramImpl(program, mainDecl);
return produceProgramInfoImpl(compilerResult, mainDecl);
}

const TestgenTarget &TestgenTarget::get() { return Target::get<TestgenTarget>("testgen"); }
Expand All @@ -43,8 +45,8 @@ TestBackEnd *TestgenTarget::getTestBackend(const ProgramInfo &programInfo, Symbo
return get().getTestBackendImpl(programInfo, symbex, testPath);
}

const ProgramInfo *TestgenTarget::initProgram(const IR::P4Program *program) {
return get().initProgramImpl(program);
const ProgramInfo *TestgenTarget::produceProgramInfo(const CompilerResult &compilerResult) {
return get().produceProgramInfoImpl(compilerResult);
}

ExprStepper *TestgenTarget::getExprStepper(ExecutionState &state, AbstractSolver &solver,
Expand Down
18 changes: 8 additions & 10 deletions backends/p4tools/modules/testgen/core/target.h
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
#ifndef BACKENDS_P4TOOLS_MODULES_TESTGEN_CORE_TARGET_H_
#define BACKENDS_P4TOOLS_MODULES_TESTGEN_CORE_TARGET_H_

#include <cstdint>
#include <filesystem>
#include <optional>
#include <string>
#include <vector>

#include "backends/p4tools/common/compiler/compiler_target.h"
#include "backends/p4tools/common/core/target.h"
#include "backends/p4tools/common/lib/arch_spec.h"
#include "ir/ir.h"
#include "ir/solver.h"
#include "ir/vector.h"

#include "backends/p4tools/modules/testgen/core/program_info.h"
#include "backends/p4tools/modules/testgen/core/small_step/cmd_stepper.h"
Expand All @@ -30,7 +27,7 @@ class TestgenTarget : public Target {
/// Produces a @ProgramInfo for the given P4 program.
///
/// @returns nullptr if the program is not supported by this target.
static const ProgramInfo *initProgram(const IR::P4Program *program);
static const ProgramInfo *produceProgramInfo(const CompilerResult &compilerResult);

/// Returns the test back end associated with this P4Testgen target.
static TestBackEnd *getTestBackend(const ProgramInfo &programInfo, SymbolicExecutor &symbex,
Expand All @@ -45,12 +42,13 @@ class TestgenTarget : public Target {
const ProgramInfo &programInfo);

protected:
/// @see @initProgram.
const ProgramInfo *initProgramImpl(const IR::P4Program *program) const;
/// @see @produceProgramInfo.
[[nodiscard]] const ProgramInfo *produceProgramInfoImpl(
const CompilerResult &compilerResult) const;

/// @see @initProgram.
virtual const ProgramInfo *initProgramImpl(const IR::P4Program *program,
const IR::Declaration_Instance *mainDecl) const = 0;
/// @see @produceProgramInfo.
virtual const ProgramInfo *produceProgramInfoImpl(
const CompilerResult &compilerResult, const IR::Declaration_Instance *mainDecl) const = 0;

/// @see getTestBackend.
virtual TestBackEnd *getTestBackendImpl(const ProgramInfo &programInfo,
Expand Down
23 changes: 23 additions & 0 deletions backends/p4tools/modules/testgen/targets/bmv2/bmv2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@

namespace P4Tools::P4Testgen::Bmv2 {

BMv2V1ModelCompilerResult::BMv2V1ModelCompilerResult(const IR::P4Program &program,
P4::P4RuntimeAPI p4runtimeApi)
: CompilerResult(program), p4runtimeApi(p4runtimeApi) {}

const P4::P4RuntimeAPI &BMv2V1ModelCompilerResult::getP4RuntimeApi() const { return p4runtimeApi; }

Bmv2V1ModelCompilerTarget::Bmv2V1ModelCompilerTarget() : CompilerTarget("bmv2", "v1model") {}

void Bmv2V1ModelCompilerTarget::make() {
Expand All @@ -23,6 +29,23 @@ void Bmv2V1ModelCompilerTarget::make() {
}
}

CompilerResultOrError Bmv2V1ModelCompilerTarget::runCompilerImpl(
const IR::P4Program *program) const {
program = runFrontend(program);
if (program == nullptr) {
return std::nullopt;
}
/// After the front end, get the P4Runtime API for the V1model architecture.
auto p4runtimeApi = P4::P4RuntimeSerializer::get()->generateP4Runtime(program, "v1model");

program = runMidEnd(program);
if (program == nullptr) {
return std::nullopt;
}

return {*new BMv2V1ModelCompilerResult{*program, p4runtimeApi}};
}

MidEnd Bmv2V1ModelCompilerTarget::mkMidEnd(const CompilerOptions &options) const {
MidEnd midEnd(options);
auto *refMap = midEnd.getRefMap();
Expand Down
16 changes: 15 additions & 1 deletion backends/p4tools/modules/testgen/targets/bmv2/bmv2.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,27 @@

namespace P4Tools::P4Testgen::Bmv2 {

/// Extends the CompilerResult with the associated P4RuntimeApi
class BMv2V1ModelCompilerResult : public CompilerResult {
private:
/// The runtimeAPI inferred from this particular BMv2 V1Model P4 program.
P4::P4RuntimeAPI p4runtimeApi;

public:
explicit BMv2V1ModelCompilerResult(const IR::P4Program &program, P4::P4RuntimeAPI p4runtimeApi);

[[nodiscard]] const P4::P4RuntimeAPI &getP4RuntimeApi() const;
};

class Bmv2V1ModelCompilerTarget : public CompilerTarget {
public:
/// Registers this target.
static void make();

private:
MidEnd mkMidEnd(const CompilerOptions &options) const override;
[[nodiscard]] MidEnd mkMidEnd(const CompilerOptions &options) const override;

CompilerResultOrError runCompilerImpl(const IR::P4Program *program) const override;

Bmv2V1ModelCompilerTarget();
};
Expand Down
16 changes: 7 additions & 9 deletions backends/p4tools/modules/testgen/targets/bmv2/program_info.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
#include "backends/p4tools/modules/testgen/targets/bmv2/program_info.h"

#include <list>
#include <map>
#include <optional>
#include <string>
#include <utility>
#include <variant>
#include <vector>

#include <boost/multiprecision/cpp_int.hpp>
Expand Down Expand Up @@ -39,9 +36,10 @@ namespace P4Tools::P4Testgen::Bmv2 {
const IR::Type_Bits Bmv2V1ModelProgramInfo::PARSER_ERR_BITS = IR::Type_Bits(32, false);

Bmv2V1ModelProgramInfo::Bmv2V1ModelProgramInfo(
const IR::P4Program *program, ordered_map<cstring, const IR::Type_Declaration *> inputBlocks,
const CompilerResult &compilerResult,
ordered_map<cstring, const IR::Type_Declaration *> inputBlocks,
std::map<int, int> declIdToGress)
: ProgramInfo(program),
: ProgramInfo(compilerResult),
programmableBlocks(std::move(inputBlocks)),
declIdToGress(std::move(declIdToGress)) {
const auto &options = TestgenOptions::get();
Expand Down Expand Up @@ -82,10 +80,10 @@ Bmv2V1ModelProgramInfo::Bmv2V1ModelProgramInfo(
std::vector<std::vector<const IR::Expression *>> restrictionsVec;
// Defines all "entry_restriction" and then converts restrictions from string to IR
// expressions, and stores them in restrictionsVec to move targetConstraints further.
program->apply(AssertsParser::AssertsParser(restrictionsVec));
compilerResult.getProgram().apply(AssertsParser::AssertsParser(restrictionsVec));
// Defines all "refers_to" and then converts restrictions from string to IR expressions,
// and stores them in restrictionsVec to move targetConstraints further.
program->apply(RefersToParser::RefersToParser(restrictionsVec));
compilerResult.getProgram().apply(RefersToParser::RefersToParser(restrictionsVec));
for (const auto &element : restrictionsVec) {
for (const auto *restriction : element) {
constraint = new IR::LAnd(constraint, restriction);
Expand All @@ -94,7 +92,7 @@ Bmv2V1ModelProgramInfo::Bmv2V1ModelProgramInfo(
// Try to map all instances of direct externs to the table they are attached to.
// Save the map in @var directExternMap.
auto directExternMapper = MapDirectExterns();
program->apply(directExternMapper);
compilerResult.getProgram().apply(directExternMapper);
auto mappedDirectExterns = directExternMapper.getdirectExternMap();
directExternMap.insert(mappedDirectExterns.begin(), mappedDirectExterns.end());

Expand Down Expand Up @@ -235,7 +233,7 @@ const IR::PathExpression *Bmv2V1ModelProgramInfo::getBlockParam(cstring blockLab
const auto *paramType = param->type;
// For convenience, resolve type names.
if (const auto *tn = paramType->to<IR::Type_Name>()) {
paramType = resolveProgramType(program, tn);
paramType = resolveProgramType(&getP4Program(), tn);
}

const auto &archSpec = getArchSpec();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class Bmv2V1ModelProgramInfo : public ProgramInfo {
std::map<const IR::IDeclaration *, const IR::P4Table *> directExternMap;

public:
Bmv2V1ModelProgramInfo(const IR::P4Program *program,
Bmv2V1ModelProgramInfo(const CompilerResult &compilerResult,
ordered_map<cstring, const IR::Type_Declaration *> inputBlocks,
std::map<int, int> declIdToGress);

Expand Down
9 changes: 5 additions & 4 deletions backends/p4tools/modules/testgen/targets/bmv2/target.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,13 @@ void Bmv2V1ModelTestgenTarget::make() {
}
}

const Bmv2V1ModelProgramInfo *Bmv2V1ModelTestgenTarget::initProgramImpl(
const IR::P4Program *program, const IR::Declaration_Instance *mainDecl) const {
const Bmv2V1ModelProgramInfo *Bmv2V1ModelTestgenTarget::produceProgramInfoImpl(
const CompilerResult &compilerResult, const IR::Declaration_Instance *mainDecl) const {
// The blocks in the main declaration are just the arguments in the constructor call.
// Convert mainDecl->arguments into a vector of blocks, represented as constructor-call
// expressions.
const auto blocks = argumentsToTypeDeclarations(program, mainDecl->arguments);
const auto blocks =
argumentsToTypeDeclarations(&compilerResult.getProgram(), mainDecl->arguments);

// We should have six arguments.
BUG_CHECK(blocks.size() == 6, "%1%: The BMV2 architecture requires 6 pipes. Received %2%.",
Expand All @@ -64,7 +65,7 @@ const Bmv2V1ModelProgramInfo *Bmv2V1ModelTestgenTarget::initProgramImpl(
}
}

return new Bmv2V1ModelProgramInfo(program, programmableBlocks, declIdToGress);
return new Bmv2V1ModelProgramInfo(compilerResult, programmableBlocks, declIdToGress);
}

Bmv2TestBackend *Bmv2V1ModelTestgenTarget::getTestBackendImpl(
Expand Down
5 changes: 3 additions & 2 deletions backends/p4tools/modules/testgen/targets/bmv2/target.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ class Bmv2V1ModelTestgenTarget : public TestgenTarget {
static void make();

protected:
const Bmv2V1ModelProgramInfo *initProgramImpl(
const IR::P4Program *program, const IR::Declaration_Instance *mainDecl) const override;
const Bmv2V1ModelProgramInfo *produceProgramInfoImpl(
const CompilerResult &compilerResult,
const IR::Declaration_Instance *mainDecl) const override;

Bmv2TestBackend *getTestBackendImpl(const ProgramInfo &programInfo, SymbolicExecutor &symbex,
const std::filesystem::path &testPath) const override;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ p4tools_add_xfail_reason(
bmv2_assert.p4
)

p4tools_add_xfail_reason(
"testgen-p4c-bmv2-metadata"
"Unsupported type argument for Value Set"
pvs-nested-struct.p4
)

p4tools_add_xfail_reason(
"testgen-p4c-bmv2-metadata"
"Computations are not supported in update_checksum"
Expand Down
Loading

0 comments on commit 4c547a3

Please sign in to comment.