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

[P4Testgen] Refactor ProgramInfo to be initialized with CompilerResult instead of a IR::P4Program #4324

Merged
merged 1 commit into from
Jan 15, 2024
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
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;
vlstill marked this conversation as resolved.
Show resolved Hide resolved

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"
vlstill marked this conversation as resolved.
Show resolved Hide resolved
pvs-nested-struct.p4
)

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