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"
48#include "ir/namemap.h"
49#include "ir/pass_manager.h"
50#include "ir/visitor.h"
57 enum Arch_t { TNA, T2NA, PSA, V1MODEL, UNKNOWN };
60 inline static Arch_t architecture = Arch_t::UNKNOWN;
61 inline static cstring version =
"UNKNOWN"_cs;
62 inline static bool disabled_for_gtest =
false;
69 return Inspector::init_apply(node);
71 void end_apply()
override {
72 if (disabled_for_gtest)
return;
73 BUG_CHECK(found !=
false,
"No @pkginfo annotation found in the program");
75 bool preorder(
const IR::PackageBlock *pkg)
override;
76 static Arch_t toArchEnum(
cstring arch) {
77 if (arch ==
"TNA" || arch ==
"tna")
79 else if (arch ==
"T2NA" || arch ==
"t2na")
82 return Arch_t::UNKNOWN;
85 static Arch_t currentArchitecture() {
return architecture; }
86 static cstring currentArchitectureVersion() {
return version; }
89 static void init(
cstring arch) {
90 architecture = toArchEnum(arch);
91 disabled_for_gtest =
true;
95struct FindArchitecture :
public PassManager {
100 refMap.setIsV1(
true);
103 passes.emplace_back(typeChecking);
104 passes.emplace_back(evaluator);
106 auto toplevel = evaluator->getToplevelBlock();
107 auto main = toplevel->getMain();
108 ERROR_CHECK(main !=
nullptr, ErrorType::ERR_INVALID,
109 "program: does not instantiate `main`");
124 const IR::MethodCallStatement *preorder(IR::MethodCallStatement *call)
override {
125 auto *action = findContext<IR::P4Action>();
126 if (!action)
return call;
128 auto *callExpr = call->methodCall->to<IR::MethodCallExpression>();
129 BUG_CHECK(callExpr,
"Malformed method call IR: %1%", call);
131 auto *dontTranslate = action->getAnnotation(
"dont_translate_extern_method"_cs);
132 if (!dontTranslate)
return call;
133 for (
auto *excluded : dontTranslate->getExpr()) {
134 auto *excludedMethod = excluded->to<IR::StringLiteral>();
135 if (!excludedMethod) {
137 "Non-string argument to @dont_translate_extern_method: "
143 if (excludedMethod->value == callExpr->method->toString()) {
145 "Excluding method call from translation due to "
146 "@dont_translate_extern_method: %1%",
161 explicit GenerateTofinoProgram(
ProgramStructure *structure) : structure(structure) {
162 CHECK_NULL(structure);
163 setName(
"GenerateTofinoProgram");
166 const IR::Node *preorder(IR::P4Program *program)
override {
167 auto *rv = structure->create(program);
173class TranslationFirst :
public PassManager {
175 TranslationFirst() { setName(
"TranslationFirst"); }
179class TranslationLast :
public PassManager {
181 TranslationLast() { setName(
"TranslationLast"); }
190class ArchTranslation :
public PassManager {
196enum ArchBlock_t { PARSER = 0, MAU, DEPARSER, BLOCK_TYPE };
198static const std::map<Architecture::Arch_t, std::map<std::pair<ArchBlock_t, gress_t>,
int>>
201 {{{PARSER, INGRESS}, 0},
203 {{DEPARSER, INGRESS}, 2},
204 {{PARSER, EGRESS}, 3},
206 {{DEPARSER, EGRESS}, 5}}},
208 {{{PARSER, INGRESS}, 0},
210 {{DEPARSER, INGRESS}, 2},
211 {{PARSER, EGRESS}, 3},
213 {{DEPARSER, EGRESS}, 5},
240 auto p4_arch = Architecture::currentArchitecture();
241 BUG_CHECK(archBlockIndex.count(p4_arch) != 0,
"Unknown architecture %1%", p4_arch);
242 BUG_CHECK(archBlockIndex.at(p4_arch).find({block_type, gress}) !=
243 archBlockIndex.at(p4_arch).end(),
244 "Unknown block type %1% for architecture %2%",
block_type, p4_arch);
247 void dbprint(std::ostream &out) {
250 out <<
"gress " << gress <<
" ";
254 bool operator==(
const BlockInfo &other)
const {
256 gress == other.gress &&
block_index == other.block_index &&
259 bool operator<(
const BlockInfo &other)
const {
261 std::tie(other.pipe_index, other.pipe_name, other.gress, other.block_index,
269 std::vector<cstring> names;
273 std::vector<int> ids;
278 std::vector<const IR::Annotation *> pragmas;
281 Pipeline(
cstring name,
const IR::BFN::P4Thread *ingress,
const IR::BFN::P4Thread *egress,
282 const IR::BFN::P4Thread *ghost);
285 bool equiv(
const Pipeline &other)
const;
290 void insertPragmas(
const std::vector<const IR::Annotation *> &all_pragmas);
296 auto it = std::find_if(pipelines.begin(), pipelines.end(),
297 [&](
const auto &p) { return p.equiv(pipeline); });
298 if (it == pipelines.end()) {
299 it = pipelines.insert(pipelines.end(), pipeline);
301 pipeIdxToPipeline[pipe_idx] = std::distance(pipelines.begin(), it);
302 it->ids.push_back(pipe_idx);
303 it->names.push_back(name);
306 const Pipeline &getPipeline(
size_t pipe_idx)
const {
307 return pipelines.at(pipeIdxToPipeline.at(pipe_idx));
311 const std::vector<Pipeline> &getPipelines()
const {
return pipelines; }
313 size_t size()
const {
return pipeIdxToPipeline.size(); }
316 std::vector<Pipeline> pipelines;
321using BlockInfoMapping = std::multimap<const IR::Node *, BlockInfo>;
323using DefaultPortMap = std::map<int, std::vector<int>>;
327 const IR::PackageBlock *mainBlock =
nullptr;
337 void parseSingleParserPipeline(
const IR::PackageBlock *block,
unsigned index);
340 void parseMultipleParserInstances(
const IR::PackageBlock *block,
cstring pipe,
341 IR::BFN::P4Thread *thread, gress_t gress);
343 void parsePortMapAnnotation(
const IR::PackageBlock *block, DefaultPortMap &map);
345 bool preorder(
const IR::PackageBlock *block)
override;
349 BlockInfoMapping toBlockInfo;
350 bool hasMultiplePipes =
false;
351 bool hasMultipleParsers =
false;
357 BlockInfoMapping *block_info;
362 BlockInfoMapping *block_info)
363 : refMap(refMap), typeMap(typeMap), block_info(block_info) {}
364 const IR::Node *postorder(IR::P4Parser *node)
override;
365 const IR::Node *postorder(IR::P4Control *node)
override;
366 const IR::Node *postorder(IR::Declaration_Instance *node)
override;
368 block_name_map.clear();
369 return Transform::init_apply(node);
382struct RewriteControlAndParserBlocks :
public PassManager {
385 auto *parseTna =
new ParseTna(refMap, typeMap);
387 passes.push_back(evaluator);
389 auto *evaluated_program = root->to<IR::P4Program>();
390 auto *toplevel = evaluator->getToplevelBlock();
395 auto *main = toplevel->getMain();
396 ERROR_CHECK(main !=
nullptr, ErrorType::ERR_INVALID,
397 "program: does not instantiate `main`");
398 main->apply(*parseTna);
414 : options(options), refMap(refMap), typeMap(typeMap) {}
415 const IR::Node *postorder(IR::BFN::TnaControl *control)
override;
416 const IR::Node *postorder(IR::BFN::TnaParser *parser)
override;
417 const IR::Node *postorder(IR::BFN::TnaDeparser *deparser)
override;
430 std::map<cstring, unsigned> enum_encoding;
436 const IR::Node *postorder(IR::Type_Enum *node)
override {
437 if (node->name ==
"MeterColor_t") enum_encoding.emplace(node->name, 2);
441 const IR::Node *postorder(IR::Type_Name *node)
override {
442 auto name = node->path->name;
443 if (enum_encoding.count(name)) {
444 auto size = enum_encoding.at(name);
445 return IR::Type_Bits::get(size);
452class ApplyEvaluator :
public PassManager {
456 const IR::ToplevelBlock *toplevel =
nullptr;
461 refMap->setIsV1(
true);
466 new VisitFunctor([
this, evaluator]() { toplevel = evaluator->getToplevelBlock(); }),
471 : refMap(refMap), typeMap(typeMap) {
474 refMap->setIsV1(
true);
479 new VisitFunctor([
this, evaluator]() { toplevel = evaluator->getToplevelBlock(); }),
483 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 backends/common/programStructure.h:32
Class used to encode maps from paths to declarations.
Definition referenceMap.h:66
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:231
cstring pipe_name
The pipe name to generate a fully qualified name in case of multipipe scenarios.
Definition arch.h:222
std::vector< int > portmap
which port to configure using this impl.
Definition arch.h:225
int pipe_index
Index in the Pipeline invocation.
Definition arch.h:220
cstring parser_instance_name
used by multi-parser support
Definition arch.h:229
ArchBlock_t block_type
A block could be a parser, deparser or a mau.
Definition arch.h:227
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:122
void error(const char *format, Args &&...args)
Report an error with the given message.
Definition lib/error.h:58