24#ifndef BF_P4C_ARCH_ARCH_H_
25#define BF_P4C_ARCH_ARCH_H_
29#include <boost/algorithm/string.hpp>
31#include "backends/tofino/bf-p4c/arch/program_structure.h"
32#include "backends/tofino/bf-p4c/bf-p4c-options.h"
33#include "backends/tofino/bf-p4c/ir/gress.h"
34#include "backends/tofino/bf-p4c/lib/assoc.h"
35#include "backends/tofino/bf-p4c/midend/type_checker.h"
36#include "frontends/common/options.h"
37#include "frontends/common/resolveReferences/referenceMap.h"
38#include "frontends/common/resolveReferences/resolveReferences.h"
39#include "frontends/p4/cloner.h"
40#include "frontends/p4/coreLibrary.h"
41#include "frontends/p4/evaluator/evaluator.h"
42#include "frontends/p4/methodInstance.h"
43#include "frontends/p4/sideEffects.h"
44#include "frontends/p4/typeChecking/typeChecker.h"
45#include "frontends/p4/typeMap.h"
46#include "frontends/p4/uniqueNames.h"
47#include "ir/ir-generated.h"
49#include "ir/namemap.h"
50#include "ir/pass_manager.h"
51#include "ir/visitor.h"
58 enum Arch_t { TNA, T2NA, PSA, V1MODEL, UNKNOWN };
61 inline static Arch_t architecture = Arch_t::UNKNOWN;
62 inline static cstring version =
"UNKNOWN"_cs;
63 inline static bool disabled_for_gtest =
false;
70 return Inspector::init_apply(node);
72 void end_apply()
override {
73 if (disabled_for_gtest)
return;
74 BUG_CHECK(found !=
false,
"No @pkginfo annotation found in the program");
76 bool preorder(
const IR::PackageBlock *pkg)
override;
77 static Arch_t toArchEnum(
cstring arch) {
78 if (arch ==
"TNA" || arch ==
"tna")
80 else if (arch ==
"T2NA" || arch ==
"t2na")
83 return Arch_t::UNKNOWN;
86 static Arch_t currentArchitecture() {
return architecture; }
87 static cstring currentArchitectureVersion() {
return version; }
90 static void init(
cstring arch) {
91 architecture = toArchEnum(arch);
92 disabled_for_gtest =
true;
104 passes.emplace_back(typeChecking);
105 passes.emplace_back(evaluator);
107 auto toplevel = evaluator->getToplevelBlock();
108 auto main = toplevel->getMain();
109 ERROR_CHECK(main !=
nullptr, ErrorType::ERR_INVALID,
110 "program: does not instantiate `main`");
125 const IR::MethodCallStatement *preorder(IR::MethodCallStatement *call)
override {
126 auto *action = findContext<IR::P4Action>();
127 if (!action)
return call;
129 auto *callExpr = call->methodCall->to<IR::MethodCallExpression>();
130 BUG_CHECK(callExpr,
"Malformed method call IR: %1%", call);
132 auto *dontTranslate = action->getAnnotation(
"dont_translate_extern_method"_cs);
133 if (!dontTranslate)
return call;
134 for (
auto *excluded : dontTranslate->getExpr()) {
135 auto *excludedMethod = excluded->to<IR::StringLiteral>();
136 if (!excludedMethod) {
138 "Non-string argument to @dont_translate_extern_method: "
144 if (excludedMethod->value == callExpr->method->toString()) {
146 "Excluding method call from translation due to "
147 "@dont_translate_extern_method: %1%",
163 CHECK_NULL(structure);
164 setName(
"GenerateTofinoProgram");
167 const IR::Node *preorder(IR::P4Program *program)
override {
168 auto *rv = structure->create(program);
197enum ArchBlock_t { PARSER = 0, MAU, DEPARSER, BLOCK_TYPE };
199static const std::map<Architecture::Arch_t, std::map<std::pair<ArchBlock_t, gress_t>,
int>>
202 {{{PARSER, INGRESS}, 0},
204 {{DEPARSER, INGRESS}, 2},
205 {{PARSER, EGRESS}, 3},
207 {{DEPARSER, EGRESS}, 5}}},
209 {{{PARSER, INGRESS}, 0},
211 {{DEPARSER, INGRESS}, 2},
212 {{PARSER, EGRESS}, 3},
214 {{DEPARSER, EGRESS}, 5},
241 auto p4_arch = Architecture::currentArchitecture();
242 BUG_CHECK(archBlockIndex.count(p4_arch) != 0,
"Unknown architecture %1%", p4_arch);
243 BUG_CHECK(archBlockIndex.at(p4_arch).find({block_type, gress}) !=
244 archBlockIndex.at(p4_arch).end(),
245 "Unknown block type %1% for architecture %2%",
block_type, p4_arch);
248 void dbprint(std::ostream &out) {
251 out <<
"gress " << gress <<
" ";
255 bool operator==(
const BlockInfo &other)
const {
257 gress == other.gress &&
block_index == other.block_index &&
260 bool operator<(
const BlockInfo &other)
const {
262 std::tie(other.pipe_index, other.pipe_name, other.gress, other.block_index,
270 std::vector<cstring> names;
274 std::vector<int> ids;
279 std::vector<const IR::Annotation *> pragmas;
282 Pipeline(
cstring name,
const IR::BFN::P4Thread *ingress,
const IR::BFN::P4Thread *egress,
283 const IR::BFN::P4Thread *ghost);
286 bool equiv(
const Pipeline &other)
const;
291 void insertPragmas(
const std::vector<const IR::Annotation *> &all_pragmas);
297 auto it = std::find_if(pipelines.begin(), pipelines.end(),
298 [&](
const auto &p) { return p.equiv(pipeline); });
299 if (it == pipelines.end()) {
300 it = pipelines.insert(pipelines.end(), pipeline);
302 pipeIdxToPipeline[pipe_idx] = std::distance(pipelines.begin(), it);
303 it->ids.push_back(pipe_idx);
304 it->names.push_back(name);
307 const Pipeline &getPipeline(
size_t pipe_idx)
const {
308 return pipelines.at(pipeIdxToPipeline.at(pipe_idx));
312 const std::vector<Pipeline> &getPipelines()
const {
return pipelines; }
314 size_t size()
const {
return pipeIdxToPipeline.size(); }
317 std::vector<Pipeline> pipelines;
322using BlockInfoMapping = std::multimap<const IR::Node *, BlockInfo>;
324using DefaultPortMap = std::map<int, std::vector<int>>;
328 const IR::PackageBlock *mainBlock =
nullptr;
338 void parseSingleParserPipeline(
const IR::PackageBlock *block,
unsigned index);
341 void parseMultipleParserInstances(
const IR::PackageBlock *block,
cstring pipe,
342 IR::BFN::P4Thread *thread, gress_t gress);
344 void parsePortMapAnnotation(
const IR::PackageBlock *block, DefaultPortMap &map);
346 bool preorder(
const IR::PackageBlock *block)
override;
350 BlockInfoMapping toBlockInfo;
351 bool hasMultiplePipes =
false;
352 bool hasMultipleParsers =
false;
358 BlockInfoMapping *block_info;
363 BlockInfoMapping *block_info)
364 : refMap(refMap), typeMap(typeMap), block_info(block_info) {}
365 const IR::Node *postorder(IR::P4Parser *node)
override;
366 const IR::Node *postorder(IR::P4Control *node)
override;
367 const IR::Node *postorder(IR::Declaration_Instance *node)
override;
369 block_name_map.clear();
370 return Transform::init_apply(node);
386 auto *parseTna =
new ParseTna(refMap, typeMap);
388 passes.push_back(evaluator);
390 auto *evaluated_program = root->to<IR::P4Program>();
391 auto *toplevel = evaluator->getToplevelBlock();
396 auto *main = toplevel->getMain();
397 ERROR_CHECK(main !=
nullptr, ErrorType::ERR_INVALID,
398 "program: does not instantiate `main`");
399 main->apply(*parseTna);
415 : options(options), refMap(refMap), typeMap(typeMap) {}
416 const IR::Node *postorder(IR::BFN::TnaControl *control)
override;
417 const IR::Node *postorder(IR::BFN::TnaParser *parser)
override;
418 const IR::Node *postorder(IR::BFN::TnaDeparser *deparser)
override;
431 std::map<cstring, unsigned> enum_encoding;
437 const IR::Node *postorder(IR::Type_Enum *node)
override {
438 if (node->name ==
"MeterColor_t") enum_encoding.emplace(node->name, 2);
442 const IR::Node *postorder(IR::Type_Name *node)
override {
443 auto name = node->path->name;
444 if (enum_encoding.count(name)) {
445 auto size = enum_encoding.at(name);
446 return IR::Type_Bits::get(size);
457 const IR::ToplevelBlock *toplevel =
nullptr;
467 new VisitFunctor([
this, evaluator]() { toplevel = evaluator->getToplevelBlock(); }),
472 : refMap(refMap), typeMap(typeMap) {
480 new VisitFunctor([
this, evaluator]() { toplevel = evaluator->getToplevelBlock(); }),
484 const IR::ToplevelBlock *getToplevelBlock() {
return toplevel; }
Definition bf-p4c-options.h:28
static BFNContext & get()
Definition bf-p4c-options.cpp:777
void discoverPipes(const IR::P4Program *, const IR::ToplevelBlock *)
identify the pipelines in the program and setup the _pipes map
Definition bf-p4c-options.cpp:829
Definition evaluator.h:115
Definition ir/pass_manager.h:40
Definition backends/common/programStructure.h:32
Class used to encode maps from paths to declarations.
Definition referenceMap.h:66
void setIsV1(bool isv1)
Set boolean indicating whether map is for a P4_14 program to isV1.
Definition referenceMap.h:105
Definition typeChecker.h:55
Definition ir/pass_manager.h:184
Definition ordered_map.h:32
int block_index
Index of the constructor.
Definition arch.h:232
cstring pipe_name
The pipe name to generate a fully qualified name in case of multipipe scenarios.
Definition arch.h:223
std::vector< int > portmap
which port to configure using this impl.
Definition arch.h:226
int pipe_index
Index in the Pipeline invocation.
Definition arch.h:221
cstring parser_instance_name
used by multi-parser support
Definition arch.h:230
ArchBlock_t block_type
A block could be a parser, deparser or a mau.
Definition arch.h:228
PassManager that governs the normalization of variations in the architectures.
Definition arch.h:191
The namespace encapsulating Barefoot/Intel-specific stuff.
Definition add_t2na_meta.cpp:21
void warning(const char *format, Args &&...args)
Report a warning with the given message.
Definition lib/error.h:115
void error(const char *format, Args &&...args)
Report an error with the given message.
Definition lib/error.h:51