decaf : a deparser optimization of copy assigned fields
More...
decaf : a deparser optimization of copy assigned fields
Copyright (C) 2024 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
SPDX-License-Identifier: Apache-2.0
author: zhao ma
The observation is that there is a high degree of data movement in many common data-plane program patterns (e.g. tunneling, label switching), i.e. a large number of fields participate in copy assignment only. These are the fields whose final value is that of another such copied only field.
Based on this observation, we devise an optimization to resolve data copies directly in the deparser rather than using the MAU to move the data, costing normal PHV containers.
Consider the program below:
action a1() { modify_field(data.a, data.b); }
action a2() { modify_field(data.a, 0x0800); }
action a3() { modify_field(data.a, data.c); }
table t1 {
reads { data.m : exact; }
actions { a1; a2; a3; nop; }
}
action a4() { modify_field(data.b, data.a); }
action a5() { modify_field(data.b, 0x0866); }
table t2 {
reads { data.k : exact; }
actions { a4; a5; nop; }
}
control ingress {
apply(t1);
apply(t2);
}
The possible values for each field (and reaching action sequence) are:
data.a : v0: 0x0800: t1.a2 -> *
v1: data.b: t1.a1 -> *
v2: data.c: t1.a3 -> *
v3: data.a: t1.nop -> *
data.b : v0: 0x0800: t1.a2 -> t2.a4
v1: 0x0866: * -> t2.a5
v2: data.a: t1.nop -> t2.a4
v3: data.c: t1.a3 -> t2.a4
v4: data.b: t1.a1 -> t2.nop
data.c : data.c (read-only)
Let's assign a bit to each action, and another bit to each version for a field's final value. The function between the action bits and version bits can be represented as a truth table.
a1 a2 a3 a4 a5 | a_v0 a_v1 a_v2 a_v3 b_v0 b_v1 b_v2 b_v3 b_v4
-------------------------------------------------------------------
1 0 0 0 0 | 0 1 0 0 0 0 0 0 1
0 1 0 0 0 | 1 0 0 0 0 0 0 0 1
0 0 1 0 0 | 0 1 0 1 0 0 0 0 1
0 1 0 1 0 | 1 0 0 0 1 0 0 0 0
0 0 0 0 1 | 0 0 0 1 0 1 0 0 0
...
...
Conveniently, the truth table can be implemented in Tofino as a match action table (using static entries). The version bits are wired to the FD as POV bits for the deparser to disambiguate which version to use for each field to reconstruct final packet, and with each version allocated to its own FD entry. Finally, all versions of value can be parsed into tagalong containers.
TODO
Tagalong containers, though abundant, are not unlimited. In addition, other resources also need to be managed. The list below is all resources need to be managed in the order of scarcity (most scarce to least). We need to make sure we don't over-fit any of these. Given a list of fields that can be decaf'd, we need to establish a partial order between any two fields such that one requires less resource than the other.
- tagalong PHV space (2k bits, half of normal PHV)
- POV bits (128 bits per gress)
- Parser constant extract (each state has 4xB, 2xH, 2xW constant extract bandwidth)
- Table resources (logical ID, memory)
- FD entries (abundant)
◆ Assign
Public Member Functions |
| Assign (const IR::MAU::Instruction *instr, const PHV::Field *dst, const IR::Constant *src) |
|
| Assign (const IR::MAU::Instruction *instr, const PHV::Field *dst, const PHV::Field *src) |
|
std::string | print () const |
|
Public Attributes |
const PHV::Field * | dst |
|
const IR::MAU::Instruction * | instr = nullptr |
|
const Value * | src |
|
◆ AssignChain
Public Member Functions |
bool | contains (const IR::MAU::Instruction *instr) const |
|
void | push_front (const Assign *assign) |
|
◆ CollectHeaderValidity
struct CollectHeaderValidity |
Public Member Functions |
| CollectHeaderValidity (const PhvInfo &phv) |
|
void | dbprint (std::ostream &out) const |
|
void | end_apply () override |
|
const IR::Expression * | get_valid_bit_expr (const PHV::Field *f) const |
|
bool | preorder (const IR::BFN::Emit *emit) override |
|
bool | preorder (const IR::MAU::Instruction *instr) override |
|
const IR::Node * | apply_visitor (const IR::Node *, const char *name=0) override |
|
profile_t | init_apply (const IR::Node *root) override |
|
virtual void | loop_revisit (const IR::Node *) |
|
virtual void | postorder (const IR::Node *) |
|
virtual bool | preorder (const IR::Node *) |
|
virtual void | revisit (const IR::Node *) |
|
void | revisit_visited () |
|
bool | visit_in_progress (const IR::Node *n) const |
|
void | visitAgain () const override |
|
void | visitOnce () const override |
|
virtual bool | check_global (cstring) |
|
virtual void | clear_globals () |
|
virtual Visitor * | clone () const |
|
virtual ControlFlowVisitor * | controlFlowVisitor () |
|
virtual void | end_apply (const IR::Node *root) |
|
virtual void | erase_global (cstring) |
|
template<class T > |
const T * | findContext () const |
|
template<class T > |
const T * | findContext (const Context *&c) const |
|
template<class T > |
const T * | findOrigCtxt () const |
|
template<class T > |
const T * | findOrigCtxt (const Context *&c) const |
|
virtual Visitor & | flow_clone () |
|
virtual void | flow_merge (Visitor &) |
|
virtual bool | flow_merge_closure (Visitor &) |
|
virtual void | flow_merge_global_from (cstring) |
|
virtual void | flow_merge_global_to (cstring) |
|
const Context * | getChildContext () const |
|
int | getChildrenVisited () const |
|
const Context * | getContext () const |
|
int | getContextDepth () const |
|
const IR::Node * | getCurrentNode () const |
|
template<class T > |
const T * | getCurrentNode () const |
|
const IR::Node * | getOriginal () const |
|
template<class T > |
const T * | getOriginal () const |
|
template<class T > |
const T * | getParent () const |
|
virtual bool | has_flow_joins () const |
|
profile_t | init_apply (const IR::Node *root, const Context *parent_context) |
|
bool | isInContext (const IR::Node *n) const |
|
virtual const char * | name () const |
|
template<class T > |
void | parallel_visit (const IR::Vector< T > &v, const char *name, int cidx) |
|
template<class T > |
void | parallel_visit (const IR::Vector< T > &v, const char *name=0) |
|
template<class T > |
void | parallel_visit (IR::Vector< T > &v, const char *name, int cidx) |
|
template<class T > |
void | parallel_visit (IR::Vector< T > &v, const char *name=0) |
|
void | print_context () const |
|
const Visitor & | setCalledBy (const Visitor *visitor) |
|
void | setName (const char *name) |
|
void | visit (const IR::Node &n, const char *name, int cidx) |
|
void | visit (const IR::Node &n, const char *name=0) |
|
void | visit (const IR::Node *&n, const char *name, int cidx) |
|
void | visit (const IR::Node *&n, const char *name=0) |
|
void | visit (const IR::Node *const &n, const char *name, int cidx) |
|
void | visit (const IR::Node *const &n, const char *name=0) |
|
void | visit (IR::Node &n, const char *name, int cidx) |
|
void | visit (IR::Node &n, const char *name=0) |
|
void | visit (IR::Node *&, const char *=0, int=0) |
|
template<class T , typename = std::enable_if_t<Util::has_SourceInfo_v<T> && !std::is_pointer_v<T>>, class... Args> |
void | warn (const int kind, const char *format, const T &node, Args &&...args) |
| The const ref variant of the above.
|
|
template<class T , typename = std::enable_if_t<Util::has_SourceInfo_v<T>>, class... Args> |
void | warn (const int kind, const char *format, const T *node, Args &&...args) |
|
bool | warning_enabled (int warning_kind) const |
|
void | print () const |
|
Public Attributes |
assoc::map< const PHV::Field *, const IR::Expression * > | field_to_expr |
|
ordered_map< const PHV::Field *, const PHV::Field * > | field_to_valid_bit |
|
assoc::map< const PHV::Field *, ordered_set< const IR::MAU::Action * > > | invalidate_to_action |
|
const PhvInfo & | phv |
|
assoc::map< const PHV::Field *, ordered_set< const IR::MAU::Action * > > | validate_to_action |
|
assoc::map< const PHV::Field *, ordered_set< const IR::BFN::ParserState * > > | validate_to_extract |
|
const Visitor * | called_by = nullptr |
|
cstring | internalName |
|
SplitFlowVisit_base *& | split_link |
|
SplitFlowVisit_base * | split_link_mem = nullptr |
|
◆ dbprint()
void CollectHeaderValidity::dbprint |
( |
std::ostream & | out | ) |
const |
|
inlinevirtual |
◆ end_apply()
void CollectHeaderValidity::end_apply |
( |
| ) |
|
|
inlineoverridevirtual |
◆ CollectWeakFields
We categorize fields that are referenced in the control flow as either strong or weak. The strong fields are ones that participate in match, non-move instruction, action data bus read, or other reasons (non packet defs, is part of a checksum update or digest). The weak fields are, by exclusion, the ones that are not strong. Weak fields also shall not have a transitive strong source. All weak fields are then decaf candidates.
Public Member Functions |
| CollectWeakFields (const PhvInfo &phv, const PhvUse &uses, const FieldDefUse &defuse, const DependencyGraph &dg) |
|
void | dbprint (std::ostream &out) const |
|
const IR::MAU::Action * | get_action (const Assign *assign) const |
|
const IR::MAU::Table * | get_table (const Assign *assign) const |
|
std::string | print_assign (const Assign *assign) const |
|
std::string | print_assign_context (const Assign *assign) const |
|
void | remove_weak_field (const PHV::Field *field) |
|
const IR::Node * | apply_visitor (const IR::Node *, const char *name=0) override |
|
profile_t | init_apply (const IR::Node *root) override |
|
virtual void | loop_revisit (const IR::Node *) |
|
virtual void | postorder (const IR::Node *) |
|
virtual bool | preorder (const IR::Node *) |
|
virtual void | revisit (const IR::Node *) |
|
void | revisit_visited () |
|
bool | visit_in_progress (const IR::Node *n) const |
|
void | visitAgain () const override |
|
void | visitOnce () const override |
|
virtual void | end_apply (const IR::Node *root) |
|
template<class T > |
const T * | findContext () const |
|
template<class T > |
const T * | findContext (const Context *&c) const |
|
template<class T > |
const T * | findOrigCtxt () const |
|
template<class T > |
const T * | findOrigCtxt (const Context *&c) const |
|
virtual bool | flow_merge_closure (Visitor &) |
|
const Context * | getChildContext () const |
|
int | getChildrenVisited () const |
|
const Context * | getContext () const |
|
int | getContextDepth () const |
|
const IR::Node * | getCurrentNode () const |
|
template<class T > |
const T * | getCurrentNode () const |
|
const IR::Node * | getOriginal () const |
|
template<class T > |
const T * | getOriginal () const |
|
template<class T > |
const T * | getParent () const |
|
profile_t | init_apply (const IR::Node *root, const Context *parent_context) |
|
bool | isInContext (const IR::Node *n) const |
|
virtual const char * | name () const |
|
template<class T > |
void | parallel_visit (const IR::Vector< T > &v, const char *name, int cidx) |
|
template<class T > |
void | parallel_visit (const IR::Vector< T > &v, const char *name=0) |
|
template<class T > |
void | parallel_visit (IR::Vector< T > &v, const char *name, int cidx) |
|
template<class T > |
void | parallel_visit (IR::Vector< T > &v, const char *name=0) |
|
void | print_context () const |
|
const Visitor & | setCalledBy (const Visitor *visitor) |
|
void | setName (const char *name) |
|
void | visit (const IR::Node &n, const char *name, int cidx) |
|
void | visit (const IR::Node &n, const char *name=0) |
|
void | visit (const IR::Node *&n, const char *name, int cidx) |
|
void | visit (const IR::Node *&n, const char *name=0) |
|
void | visit (const IR::Node *const &n, const char *name, int cidx) |
|
void | visit (const IR::Node *const &n, const char *name=0) |
|
void | visit (IR::Node &n, const char *name, int cidx) |
|
void | visit (IR::Node &n, const char *name=0) |
|
void | visit (IR::Node *&, const char *=0, int=0) |
|
template<class T , typename = std::enable_if_t<Util::has_SourceInfo_v<T> && !std::is_pointer_v<T>>, class... Args> |
void | warn (const int kind, const char *format, const T &node, Args &&...args) |
| The const ref variant of the above.
|
|
template<class T , typename = std::enable_if_t<Util::has_SourceInfo_v<T>>, class... Args> |
void | warn (const int kind, const char *format, const T *node, Args &&...args) |
|
bool | warning_enabled (int warning_kind) const |
|
Public Attributes |
std::map< gress_t, ordered_set< const IR::Constant * > > | all_constants |
|
ordered_map< const PHV::Field *, ordered_set< const Assign * > > | field_to_weak_assigns |
|
FieldGroup | read_only_weak_fields |
|
const Visitor * | called_by = nullptr |
|
cstring | internalName |
|
SplitFlowVisit_base *& | split_link |
|
SplitFlowVisit_base * | split_link_mem = nullptr |
|
|
typedef Visitor_Context | Context |
|
static cstring | demangle (const char *) |
|
static bool | warning_enabled (const Visitor *visitor, int warning_kind) |
|
void | visit_children (const IR::Node *, std::function< void()> fn) |
|
bool | dontForwardChildrenBeforePreorder = false |
|
bool | joinFlows = false |
|
bool | visitDagOnce = true |
|
◆ dbprint()
void CollectWeakFields::dbprint |
( |
std::ostream & | out | ) |
const |
|
virtual |
◆ ComputeValuesAtDeparser
class ComputeValuesAtDeparser |
Perform copy/constant propagation for the weak fields on table dependency. For each weak field, what are the all possible values that are reachable at the deparser?
Public Member Functions |
| ComputeValuesAtDeparser (CollectWeakFields &weak_fields) |
|
bool | is_weak_assign (const IR::MAU::Instruction *instr) const |
|
std::string | print_assign_chain (const AssignChain &chain) const |
|
std::string | print_assign_chains (const ordered_set< AssignChain > &chains) const |
|
std::string | print_value_map (const FieldGroup &weak_field_group, const ordered_set< AssignChain > &all_chains_in_group) const |
|
const IR::Node * | apply_visitor (const IR::Node *, const char *name=0) override |
|
profile_t | init_apply (const IR::Node *root) override |
|
virtual void | loop_revisit (const IR::Node *) |
|
virtual void | postorder (const IR::Node *) |
|
virtual bool | preorder (const IR::Node *) |
|
virtual void | revisit (const IR::Node *) |
|
void | revisit_visited () |
|
bool | visit_in_progress (const IR::Node *n) const |
|
void | visitAgain () const override |
|
void | visitOnce () const override |
|
virtual bool | check_global (cstring) |
|
virtual void | clear_globals () |
|
virtual Visitor * | clone () const |
|
virtual ControlFlowVisitor * | controlFlowVisitor () |
|
virtual void | end_apply () |
|
virtual void | end_apply (const IR::Node *root) |
|
virtual void | erase_global (cstring) |
|
template<class T > |
const T * | findContext () const |
|
template<class T > |
const T * | findContext (const Context *&c) const |
|
template<class T > |
const T * | findOrigCtxt () const |
|
template<class T > |
const T * | findOrigCtxt (const Context *&c) const |
|
virtual Visitor & | flow_clone () |
|
virtual void | flow_merge (Visitor &) |
|
virtual bool | flow_merge_closure (Visitor &) |
|
virtual void | flow_merge_global_from (cstring) |
|
virtual void | flow_merge_global_to (cstring) |
|
const Context * | getChildContext () const |
|
int | getChildrenVisited () const |
|
const Context * | getContext () const |
|
int | getContextDepth () const |
|
const IR::Node * | getCurrentNode () const |
|
template<class T > |
const T * | getCurrentNode () const |
|
const IR::Node * | getOriginal () const |
|
template<class T > |
const T * | getOriginal () const |
|
template<class T > |
const T * | getParent () const |
|
virtual bool | has_flow_joins () const |
|
profile_t | init_apply (const IR::Node *root, const Context *parent_context) |
|
bool | isInContext (const IR::Node *n) const |
|
virtual const char * | name () const |
|
template<class T > |
void | parallel_visit (const IR::Vector< T > &v, const char *name, int cidx) |
|
template<class T > |
void | parallel_visit (const IR::Vector< T > &v, const char *name=0) |
|
template<class T > |
void | parallel_visit (IR::Vector< T > &v, const char *name, int cidx) |
|
template<class T > |
void | parallel_visit (IR::Vector< T > &v, const char *name=0) |
|
void | print_context () const |
|
const Visitor & | setCalledBy (const Visitor *visitor) |
|
void | setName (const char *name) |
|
void | visit (const IR::Node &n, const char *name, int cidx) |
|
void | visit (const IR::Node &n, const char *name=0) |
|
void | visit (const IR::Node *&n, const char *name, int cidx) |
|
void | visit (const IR::Node *&n, const char *name=0) |
|
void | visit (const IR::Node *const &n, const char *name, int cidx) |
|
void | visit (const IR::Node *const &n, const char *name=0) |
|
void | visit (IR::Node &n, const char *name, int cidx) |
|
void | visit (IR::Node &n, const char *name=0) |
|
void | visit (IR::Node *&, const char *=0, int=0) |
|
template<class T , typename = std::enable_if_t<Util::has_SourceInfo_v<T> && !std::is_pointer_v<T>>, class... Args> |
void | warn (const int kind, const char *format, const T &node, Args &&...args) |
| The const ref variant of the above.
|
|
template<class T , typename = std::enable_if_t<Util::has_SourceInfo_v<T>>, class... Args> |
void | warn (const int kind, const char *format, const T *node, Args &&...args) |
|
bool | warning_enabled (int warning_kind) const |
|
Public Attributes |
ordered_map< const PHV::Field *, ordered_map< Value, ordered_set< AssignChain > > > | value_to_chains |
|
std::vector< FieldGroup > | weak_field_groups |
|
CollectWeakFields & | weak_fields |
|
const Visitor * | called_by = nullptr |
|
cstring | internalName |
|
SplitFlowVisit_base *& | split_link |
|
SplitFlowVisit_base * | split_link_mem = nullptr |
|
◆ CreateConstants
Certain weak fields may have constant values. These constants need to be extracted by the parser in Tofino. In JBay, the deparser comes with 8 bytes of constants we can use, the rest still need to be extracted in the parser.
Public Member Functions |
| CreateConstants (const ComputeValuesAtDeparser &values_at_deparser) |
|
void | dbprint (std::ostream &out) const |
|
bool | is_inserted (const IR::TempVar *constant) const |
|
Public Attributes |
std::map< gress_t, ordered_map< uint8_t, const IR::TempVar * > > | byte_to_temp_var |
|
std::map< gress_t, ordered_map< const IR::Constant *, std::vector< uint8_t > > > | const_to_bytes |
|
std::map< gress_t, ordered_set< uint8_t > > | deparser_bytes |
|
◆ dbprint()
void CreateConstants::dbprint |
( |
std::ostream & | out | ) |
const |
|
virtual |
◆ DeparserCopyOpt
Public Member Functions |
| DeparserCopyOpt (const PhvInfo &phv, PhvUse &uses, const FieldDefUse &defuse, const DependencyGraph &dg) |
|
| PassManager (cstring logFilePrefix, Logging::Mode logMode=Logging::Mode::CREATE) |
|
| PassManager (const PassManager &)=default |
|
| PassManager (const std::initializer_list< VisitorRef > &init) |
|
| PassManager (PassManager &&)=default |
|
void | addDebugHook (DebugHook h, bool recursive=false) |
|
void | addDebugHooks (std::vector< DebugHook > hooks, bool recursive=false) |
|
void | addPasses (const std::initializer_list< VisitorRef > &init) |
|
const IR::Node * | apply_visitor (const IR::Node *, const char *=0) override |
|
bool | backtrack (trigger &trig) override |
|
PassManager * | clone () const override |
|
void | early_exit () |
|
void | listPasses (std::ostream &, cstring sep) const |
|
bool | never_backtracks () override |
|
void | removePasses (const std::vector< cstring > &exclude) |
|
void | setStopOnError (bool stop) |
|
virtual bool | check_clone (const Visitor *a) |
|
virtual bool | check_global (cstring) |
|
virtual void | clear_globals () |
|
virtual ControlFlowVisitor * | controlFlowVisitor () |
|
virtual void | end_apply (const IR::Node *root) |
|
virtual void | erase_global (cstring) |
|
template<class T > |
const T * | findContext () const |
|
template<class T > |
const T * | findContext (const Context *&c) const |
|
template<class T > |
const T * | findOrigCtxt () const |
|
template<class T > |
const T * | findOrigCtxt (const Context *&c) const |
|
virtual Visitor & | flow_clone () |
|
virtual void | flow_merge (Visitor &) |
|
virtual bool | flow_merge_closure (Visitor &) |
|
virtual void | flow_merge_global_from (cstring) |
|
virtual void | flow_merge_global_to (cstring) |
|
const Context * | getChildContext () const |
|
int | getChildrenVisited () const |
|
const Context * | getContext () const |
|
int | getContextDepth () const |
|
const IR::Node * | getCurrentNode () const |
|
template<class T > |
const T * | getCurrentNode () const |
|
const IR::Node * | getOriginal () const |
|
template<class T > |
const T * | getOriginal () const |
|
template<class T > |
const T * | getParent () const |
|
virtual bool | has_flow_joins () const |
|
profile_t | init_apply (const IR::Node *root, const Context *parent_context) |
|
bool | isInContext (const IR::Node *n) const |
|
virtual const char * | name () const |
|
template<class T > |
void | parallel_visit (const IR::Vector< T > &v, const char *name, int cidx) |
|
template<class T > |
void | parallel_visit (const IR::Vector< T > &v, const char *name=0) |
|
template<class T > |
void | parallel_visit (IR::Vector< T > &v, const char *name, int cidx) |
|
template<class T > |
void | parallel_visit (IR::Vector< T > &v, const char *name=0) |
|
void | print_context () const |
|
const Visitor & | setCalledBy (const Visitor *visitor) |
|
void | setName (const char *name) |
|
void | visit (const IR::Node &n, const char *name, int cidx) |
|
void | visit (const IR::Node &n, const char *name=0) |
|
void | visit (const IR::Node *&n, const char *name, int cidx) |
|
void | visit (const IR::Node *&n, const char *name=0) |
|
void | visit (const IR::Node *const &n, const char *name, int cidx) |
|
void | visit (const IR::Node *const &n, const char *name=0) |
|
void | visit (IR::Node &n, const char *name, int cidx) |
|
void | visit (IR::Node &n, const char *name=0) |
|
void | visit (IR::Node *&, const char *=0, int=0) |
|
template<class T , typename = std::enable_if_t<Util::has_SourceInfo_v<T> && !std::is_pointer_v<T>>, class... Args> |
void | warn (const int kind, const char *format, const T &node, Args &&...args) |
| The const ref variant of the above.
|
|
template<class T , typename = std::enable_if_t<Util::has_SourceInfo_v<T>>, class... Args> |
void | warn (const int kind, const char *format, const T *node, Args &&...args) |
|
bool | warning_enabled (int warning_kind) const |
|
Public Attributes |
RewriteDeparser | rewrite_deparser |
|
const Visitor * | called_by = nullptr |
|
cstring | internalName |
|
SplitFlowVisit_base *& | split_link |
|
SplitFlowVisit_base * | split_link_mem = nullptr |
|
◆ FieldGroup
Public Member Functions |
| FieldGroup (int i) |
|
| ordered_set (const ordered_set &a) |
|
| ordered_set (InputIt first, InputIt last) |
|
| ordered_set (ordered_set &&a)=default |
|
| ordered_set (std::initializer_list< const PHV::Field * > init) |
|
reference | back () const noexcept |
|
const_iterator | begin () const noexcept |
|
iterator | begin () noexcept |
|
const_iterator | cbegin () const noexcept |
|
const_iterator | cend () const noexcept |
|
void | clear () |
|
size_type | count (const const PHV::Field *&a) const |
|
const_reverse_iterator | crbegin () const noexcept |
|
const_reverse_iterator | crend () const noexcept |
|
std::pair< iterator, bool > | emplace (Args &&...args) |
|
std::pair< iterator, bool > | emplace_back (Args &&...args) |
|
bool | empty () const noexcept |
|
const_iterator | end () const noexcept |
|
iterator | end () noexcept |
|
size_type | erase (const const PHV::Field *&v) |
|
iterator | erase (const_iterator pos) |
|
iterator | find (const const PHV::Field *&a) |
|
const_iterator | find (const const PHV::Field *&a) const |
|
reference | front () const noexcept |
|
std::pair< iterator, bool > | insert (const const PHV::Field *&v) |
|
std::pair< iterator, bool > | insert (const PHV::Field *&&v) |
|
iterator | insert (const_iterator pos, const const PHV::Field *&v) |
|
iterator | insert (const_iterator pos, const PHV::Field *&&v) |
|
void | insert (ordered_set::const_iterator begin, ordered_set::const_iterator end) |
|
iterator | lower_bound (const const PHV::Field *&a) |
|
const_iterator | lower_bound (const const PHV::Field *&a) const |
|
size_type | max_size () const noexcept |
|
bool | operator!= (const ordered_set &a) const |
|
bool | operator< (const ordered_set &a) const |
|
ordered_set & | operator= (const ordered_set &a) |
|
ordered_set & | operator= (ordered_set &&a)=default |
|
bool | operator== (const ordered_set &a) const |
|
void | push_back (const const PHV::Field *&v) |
|
void | push_back (const PHV::Field *&&v) |
|
const_reverse_iterator | rbegin () const noexcept |
|
reverse_iterator | rbegin () noexcept |
|
const_reverse_iterator | rend () const noexcept |
|
reverse_iterator | rend () noexcept |
|
size_type | size () const noexcept |
|
sorted_iterator | sorted_begin () const noexcept |
|
sorted_iterator | sorted_end () const noexcept |
|
iterator | upper_bound (const const PHV::Field *&a) |
|
const_iterator | upper_bound (const const PHV::Field *&a) const |
|
Public Attributes |
int | id = -1 |
|
|
typedef std::allocator< const PHV::Field * > | allocator_type |
|
typedef list_type::const_iterator | const_iterator |
|
typedef const const PHV::Field *& | const_reference |
|
typedef std::reverse_iterator< const_iterator > | const_reverse_iterator |
|
typedef list_type::const_iterator | iterator |
|
typedef std::less< const PHV::Field * > | key_compare |
|
typedef const PHV::Field * | key_type |
|
typedef const const PHV::Field *& | reference |
|
typedef std::reverse_iterator< iterator > | reverse_iterator |
|
typedef map_type::size_type | size_type |
|
typedef std::less< const PHV::Field * > | value_compare |
|
typedef const PHV::Field * | value_type |
|
◆ RewriteDeparser
Rewrite deparser to insert new emits created for each of the weak field's reachable value at the deparser. Each value emit is predicated by the synthesized POV bit created in the SynthesizePovEncoder pass.
◆ RewriteWeakFieldWrites
class RewriteWeakFieldWrites |
Replace all move instructions that weak fields are involved in by a single bit set to the $ctl bits for each action that the move instructions are in. Typically, these are the tunnel encap/decap actions.
Public Member Functions |
| RewriteWeakFieldWrites (const ComputeValuesAtDeparser &values_at_deparser, const SynthesizePovEncoder &synth_pov_encoder) |
|
const IR::Node * | apply_visitor (const IR::Node *, const char *name=0) override |
|
profile_t | init_apply (const IR::Node *root) override |
|
virtual void | loop_revisit (const IR::Node *) |
|
virtual const IR::Node * | postorder (IR::Node *n) |
|
virtual const IR::Node * | preorder (IR::Node *n) |
|
void | prune () |
|
virtual void | revisit (const IR::Node *, const IR::Node *) |
|
void | revisit_visited () |
|
bool | visit_in_progress (const IR::Node *) const |
|
void | visitAgain () const override |
|
void | visitOnce () const override |
|
virtual bool | check_global (cstring) |
|
virtual void | clear_globals () |
|
virtual Visitor * | clone () const |
|
virtual ControlFlowVisitor * | controlFlowVisitor () |
|
virtual void | end_apply (const IR::Node *root) |
|
virtual void | erase_global (cstring) |
|
template<class T > |
const T * | findContext () const |
|
template<class T > |
const T * | findContext (const Context *&c) const |
|
template<class T > |
const T * | findOrigCtxt () const |
|
template<class T > |
const T * | findOrigCtxt (const Context *&c) const |
|
virtual Visitor & | flow_clone () |
|
virtual void | flow_merge (Visitor &) |
|
virtual bool | flow_merge_closure (Visitor &) |
|
virtual void | flow_merge_global_from (cstring) |
|
virtual void | flow_merge_global_to (cstring) |
|
const Context * | getChildContext () const |
|
int | getChildrenVisited () const |
|
const Context * | getContext () const |
|
int | getContextDepth () const |
|
const IR::Node * | getCurrentNode () const |
|
template<class T > |
const T * | getCurrentNode () const |
|
const IR::Node * | getOriginal () const |
|
template<class T > |
const T * | getOriginal () const |
|
template<class T > |
const T * | getParent () const |
|
virtual bool | has_flow_joins () const |
|
profile_t | init_apply (const IR::Node *root, const Context *parent_context) |
|
bool | isInContext (const IR::Node *n) const |
|
virtual const char * | name () const |
|
template<class T > |
void | parallel_visit (const IR::Vector< T > &v, const char *name, int cidx) |
|
template<class T > |
void | parallel_visit (const IR::Vector< T > &v, const char *name=0) |
|
template<class T > |
void | parallel_visit (IR::Vector< T > &v, const char *name, int cidx) |
|
template<class T > |
void | parallel_visit (IR::Vector< T > &v, const char *name=0) |
|
void | print_context () const |
|
const Visitor & | setCalledBy (const Visitor *visitor) |
|
void | setName (const char *name) |
|
void | visit (const IR::Node &n, const char *name, int cidx) |
|
void | visit (const IR::Node &n, const char *name=0) |
|
void | visit (const IR::Node *&n, const char *name, int cidx) |
|
void | visit (const IR::Node *&n, const char *name=0) |
|
void | visit (const IR::Node *const &n, const char *name, int cidx) |
|
void | visit (const IR::Node *const &n, const char *name=0) |
|
void | visit (IR::Node &n, const char *name, int cidx) |
|
void | visit (IR::Node &n, const char *name=0) |
|
void | visit (IR::Node *&, const char *=0, int=0) |
|
template<class T , typename = std::enable_if_t<Util::has_SourceInfo_v<T> && !std::is_pointer_v<T>>, class... Args> |
void | warn (const int kind, const char *format, const T &node, Args &&...args) |
| The const ref variant of the above.
|
|
template<class T , typename = std::enable_if_t<Util::has_SourceInfo_v<T>>, class... Args> |
void | warn (const int kind, const char *format, const T *node, Args &&...args) |
|
bool | warning_enabled (int warning_kind) const |
|
◆ SynthesizePovEncoder
class SynthesizePovEncoder |
Given a set of weak fields, and their reaching values/action chains at the deparser, we construct tables to synthesize the POV bits needed to deparse the right version at runtime.
Public Member Functions |
| SynthesizePovEncoder (const CollectHeaderValidity &pov_bits, const ComputeValuesAtDeparser &values_at_deparser) |
|
void | dbprint (std::ostream &out) const |
|
const IR::Node * | apply_visitor (const IR::Node *, const char *name=0) override |
|
profile_t | init_apply (const IR::Node *root) override |
|
virtual void | loop_revisit (const IR::Node *) |
|
virtual const IR::Node * | postorder (IR::Node *n) |
|
virtual const IR::Node * | preorder (IR::Node *n) |
|
void | prune () |
|
virtual void | revisit (const IR::Node *, const IR::Node *) |
|
void | revisit_visited () |
|
bool | visit_in_progress (const IR::Node *) const |
|
void | visitAgain () const override |
|
void | visitOnce () const override |
|
virtual bool | check_global (cstring) |
|
virtual void | clear_globals () |
|
virtual Visitor * | clone () const |
|
virtual ControlFlowVisitor * | controlFlowVisitor () |
|
virtual void | end_apply (const IR::Node *root) |
|
virtual void | erase_global (cstring) |
|
template<class T > |
const T * | findContext () const |
|
template<class T > |
const T * | findContext (const Context *&c) const |
|
template<class T > |
const T * | findOrigCtxt () const |
|
template<class T > |
const T * | findOrigCtxt (const Context *&c) const |
|
virtual Visitor & | flow_clone () |
|
virtual void | flow_merge (Visitor &) |
|
virtual bool | flow_merge_closure (Visitor &) |
|
virtual void | flow_merge_global_from (cstring) |
|
virtual void | flow_merge_global_to (cstring) |
|
const Context * | getChildContext () const |
|
int | getChildrenVisited () const |
|
const Context * | getContext () const |
|
int | getContextDepth () const |
|
const IR::Node * | getCurrentNode () const |
|
template<class T > |
const T * | getCurrentNode () const |
|
const IR::Node * | getOriginal () const |
|
template<class T > |
const T * | getOriginal () const |
|
template<class T > |
const T * | getParent () const |
|
virtual bool | has_flow_joins () const |
|
profile_t | init_apply (const IR::Node *root, const Context *parent_context) |
|
bool | isInContext (const IR::Node *n) const |
|
virtual const char * | name () const |
|
template<class T > |
void | parallel_visit (const IR::Vector< T > &v, const char *name, int cidx) |
|
template<class T > |
void | parallel_visit (const IR::Vector< T > &v, const char *name=0) |
|
template<class T > |
void | parallel_visit (IR::Vector< T > &v, const char *name, int cidx) |
|
template<class T > |
void | parallel_visit (IR::Vector< T > &v, const char *name=0) |
|
void | print_context () const |
|
const Visitor & | setCalledBy (const Visitor *visitor) |
|
void | setName (const char *name) |
|
void | visit (const IR::Node &n, const char *name, int cidx) |
|
void | visit (const IR::Node &n, const char *name=0) |
|
void | visit (const IR::Node *&n, const char *name, int cidx) |
|
void | visit (const IR::Node *&n, const char *name=0) |
|
void | visit (const IR::Node *const &n, const char *name, int cidx) |
|
void | visit (const IR::Node *const &n, const char *name=0) |
|
void | visit (IR::Node &n, const char *name, int cidx) |
|
void | visit (IR::Node &n, const char *name=0) |
|
void | visit (IR::Node *&, const char *=0, int=0) |
|
template<class T , typename = std::enable_if_t<Util::has_SourceInfo_v<T> && !std::is_pointer_v<T>>, class... Args> |
void | warn (const int kind, const char *format, const T &node, Args &&...args) |
| The const ref variant of the above.
|
|
template<class T , typename = std::enable_if_t<Util::has_SourceInfo_v<T>>, class... Args> |
void | warn (const int kind, const char *format, const T *node, Args &&...args) |
|
bool | warning_enabled (int warning_kind) const |
|
Public Attributes |
ordered_map< const IR::MAU::Action *, const IR::TempVar * > | action_to_ctl_bit |
|
ordered_map< const IR::MAU::Instruction *, const IR::TempVar * > | assign_to_version_bit |
|
ordered_map< const PHV::Field *, const IR::TempVar * > | default_pov_bit |
|
ordered_map< const PHV::Field *, ordered_map< Value, const IR::TempVar * > > | value_to_pov_bit |
|
const Visitor * | called_by = nullptr |
|
cstring | internalName |
|
SplitFlowVisit_base *& | split_link |
|
SplitFlowVisit_base * | split_link_mem = nullptr |
|
◆ dbprint()
void SynthesizePovEncoder::dbprint |
( |
std::ostream & | out | ) |
const |
|
virtual |
◆ Value
Public Member Functions |
| Value (const IR::Constant *c) |
|
| Value (const PHV::Field *f) |
|
| Value (const Value &other) |
|
bool | operator< (const Value &other) const |
|
Value & | operator= (const Value &other) |
|
bool | operator== (const Value &other) const |
|
std::string | print () const |
|
Public Attributes |
const IR::Constant * | constant = nullptr |
|
const PHV::Field * | field = nullptr |
|
◆ VersionMap