P4C
The P4 Compiler
|
#include <action_phv_constraints.h>
Classes | |
struct | ActionSources |
Public Member Functions | |
ActionPhvConstraints (const PhvInfo &p, const PhvUse &u, const PackConflicts &c, const MapTablesToActions &m, const DependencyGraph &d) | |
ordered_set< const PHV::Field * > | actionReads (const IR::MAU::Action *act) const |
const ordered_set< PHV::FieldSlice > & | actionReadsSlices (const IR::MAU::Action *act) const |
ordered_set< const IR::MAU::Action * > | actions_reading_fields (const PHV::Field *f) const |
ordered_set< const IR::MAU::Action * > | actions_writing_fields (const PHV::AllocSlice &slice) const |
ordered_set< const IR::MAU::Action * > | actions_writing_fields (const PHV::Field *f) const |
ordered_set< const PHV::Field * > | actionWrites (const IR::MAU::Action *act) const |
const ordered_set< PHV::FieldSlice > | actionWritesSlices (const IR::MAU::Action *act) const |
bool | all_field_slices_written_together (const PHV::Allocation::MutuallyLiveSlices &container_state, const PHV::ActionSet &set_of_actions, const PHV::Allocation::LiveRangeShrinkingMap &initActions) const |
CanPackReturnType | can_pack (const PHV::Allocation &alloc, const std::vector< PHV::AllocSlice > &slices, const PHV::Allocation::MutuallyLiveSlices &original_container_state, const PHV::Allocation::LiveRangeShrinkingMap &initActions) const |
bool | can_pack_pov (const PHV::SuperCluster::SliceList *slice_list, const PHV::Field *f) const |
CanPackErrorV2 | can_pack_v2 (const PHV::Allocation &alloc, const std::vector< PHV::AllocSlice > &slices) const |
can_pack_v2 checks whether allocating slices will violate any action constraints. | |
bool | cannot_initialize (const PHV::Container &c, const IR::MAU::Action *action, const PHV::Allocation &alloc) const |
CanPackErrorCode | check_ara_move_constraints (const PHV::Allocation &alloc, const PHV::Allocation::MutuallyLiveSlices &container_state, const PHV::Container &c, const PHV::Allocation::LiveRangeShrinkingMap &initActions) const |
CanPackErrorV2 | check_bitwise_and_basic_move_constraints (const PHV::ActionSet &actions, const PHV::Allocation::MutuallyLiveSlices &container_state, const ActionPropertyMap *action_props) const |
CanPackErrorV2 | check_move_constraints (const PHV::Allocation &alloc, const IR::MAU::Action *action, const std::vector< PHV::AllocSlice > &slices, const PHV::Allocation::MutuallyLiveSlices &container_state, const PHV::Container &c, const PHV::Allocation::LiveRangeShrinkingMap &initActions) const |
CanPackErrorV2 | check_move_constraints_from_read (const PHV::Allocation &alloc, const std::vector< PHV::AllocSlice > &candidates, const PHV::Allocation::LiveRangeShrinkingMap &initActions) const |
CanPackErrorV2 | check_read_action_move_constraints (const PHV::Allocation &alloc, const std::vector< PHV::AllocSlice > &candidates, const IR::MAU::Action *action, const PHV::Allocation::LiveRangeShrinkingMap &initActions) const |
CanPackErrorV2 | check_read_action_num_source_constraints (const PHV::Allocation &alloc, const std::vector< PHV::AllocSlice > &candidates, const IR::MAU::Action *action) const |
bool | checkBridgedPackingConstraints (const ordered_set< const PHV::Field * > &packing) const |
ordered_map< const PHV::Field *, int > | compute_sources_first_order (const ordered_map< const PHV::Field *, std::vector< PHV::FieldSlice > > &fields) const |
int | count_bitmasked_set_instructions (const std::vector< PHV::AllocSlice > &slices, const PHV::Allocation::LiveRangeShrinkingMap &initActions) const |
bool | creates_container_conflicts (const PHV::Allocation::MutuallyLiveSlices &container_state, const PHV::Allocation::LiveRangeShrinkingMap &initActions, const MapTablesToActions &tableActionsMap) const |
void | dest_first_sort (std::vector< const PHV::SuperCluster::SliceList * > &slice_list) const |
bool | diagnoseSuperCluster (const ordered_set< const PHV::SuperCluster::SliceList * > &sc, const ordered_map< PHV::FieldSlice, unsigned > &fieldAlignments, std::stringstream &error_msg) const |
std::optional< const PHV::Field * > | field_destination (const PHV::Field *f, const IR::MAU::Action *action) const |
ActionSources | getActionSources (const IR::MAU::Action *act, const PHV::Container &c, ordered_set< PHV::AllocSlice > &new_slices, const PHV::Allocation &alloc) const |
bool | hasPackConflict (const PHV::FieldSlice fs1, const PHV::FieldSlice fs2) const |
bool | hasSpecialityReads (const PHV::Field *f) const |
bool | is_bitmasked_set (const std::vector< PHV::AllocSlice > &container_state, const ordered_set< PHV::AllocSlice > &fields_not_written_to) const |
bool | is_in_action_to_writes (const IR::MAU::Action *, cstring) const |
bool | is_in_field_writes_to_actions (cstring, const IR::MAU::Action *) const |
bool | is_in_write_to_reads (cstring, const IR::MAU::Action *, cstring) const |
bool | is_meter_color_destination (const PHV::Field *f) const |
Track all the meter color destination to prioritize 8-bit PHV for such field. | |
bool | is_meter_color_destination_8bit (const PHV::Field *f) const |
ordered_set< const PHV::Field * > & | meter_color_dests () |
const ordered_set< const PHV::Field * > & | meter_color_dests () const |
ordered_set< const PHV::Field * > & | meter_color_dests_8bit () |
const ordered_set< const PHV::Field * > & | meter_color_dests_8bit () const |
bool | move_only_operations (const PHV::Field *f) const |
bool | pack_conflicts_present (const PHV::Allocation::MutuallyLiveSlices &container_state, const std::vector< PHV::AllocSlice > &slices) const |
bool | parser_constant_extract_satisfied (const PHV::Container &c, const PHV::Allocation::MutuallyLiveSlices &container_state) const |
ordered_set< const PHV::Field * > | slices_destinations (const PHV::Field *src, const std::vector< PHV::FieldSlice > &slices) const |
ordered_set< const PHV::Field * > | slices_sources (const PHV::Field *dest, const std::vector< PHV::FieldSlice > &slices) const |
void | sort (std::list< const PHV::SuperCluster::SliceList * > &slice_list) const |
void | sort (std::vector< PHV::FieldSlice > &slice_list) const |
bool | written_by_ad_constant (const PHV::Field *f, const IR::MAU::Action *act) const |
bool | written_in (const PHV::AllocSlice &slice, const IR::MAU::Action *act) const |
bool | written_in (const PHV::Field *f, const IR::MAU::Action *act) const |
Public Member Functions inherited from P4::Inspector | |
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 |
Public Member Functions inherited from P4::Visitor | |
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 |
Friends | |
std::ostream & | operator<< (std::ostream &out, const ActionPhvConstraints::ClassifiedSource &src) |
std::ostream & | operator<< (std::ostream &out, const ActionPhvConstraints::OperandInfo &info) |
std::ostream & | operator<< (std::ostream &out, const safe_vector< ActionPhvConstraints::OperandInfo > &info) |
Additional Inherited Members | |
Public Types inherited from P4::Visitor | |
typedef Visitor_Context | Context |
Static Public Member Functions inherited from P4::Visitor | |
static cstring | demangle (const char *) |
static bool | warning_enabled (const Visitor *visitor, int warning_kind) |
Public Attributes inherited from P4::Visitor | |
const Visitor * | called_by = nullptr |
cstring | internalName |
SplitFlowVisit_base *& | split_link |
SplitFlowVisit_base * | split_link_mem = nullptr |
Protected Member Functions inherited from P4::Visitor | |
virtual void | init_join_flows (const IR::Node *) |
virtual bool | join_flows (const IR::Node *) |
virtual void | post_join_flows (const IR::Node *, const IR::Node *) |
void | visit_children (const IR::Node *, std::function< void()> fn) |
Protected Attributes inherited from P4::Visitor | |
bool | dontForwardChildrenBeforePreorder = false |
bool | joinFlows = false |
bool | visitDagOnce = true |
This class is meant to gather action information as well as provide information to PHV analysis through function calls. Methods in AllocatePHV query the information contained in class members here to determine constraints on packing induced by MAU actions.
struct ActionPhvConstraints::ActionSources |
Class Members | ||
---|---|---|
bitvec | dest_bits | |
bool | has_ad = false | |
bool | has_const = false | |
ordered_set< Container > | phv | |
int | unalloc = 0 |
ordered_set< const PHV::Field * > ActionPhvConstraints::actionReads | ( | const IR::MAU::Action * | act | ) | const |
act
|
inline |
f
.
|
inline |
f
. ordered_set< const PHV::Field * > ActionPhvConstraints::actionWrites | ( | const IR::MAU::Action * | act | ) | const |
act
bool ActionPhvConstraints::all_field_slices_written_together | ( | const PHV::Allocation::MutuallyLiveSlices & | container_state, |
const PHV::ActionSet & | set_of_actions, | ||
const PHV::Allocation::LiveRangeShrinkingMap & | initActions ) const |
container_state
, if an action a in set_of_actions
writes that slice, then all other slices in container_state
are also written by a; and if an action b in set_of_actions
does not write slice s, then all other slices in container_state
are also not written by action b. CanPackReturnType ActionPhvConstraints::can_pack | ( | const PHV::Allocation & | alloc, |
const std::vector< PHV::AllocSlice > & | slices, | ||
const PHV::Allocation::MutuallyLiveSlices & | original_container_state, | ||
const PHV::Allocation::LiveRangeShrinkingMap & | initActions ) const |
Checks whether packing slices
into a container will violate MAU action constraints. initActions
is the map of fields to the actions where those fields must be initialized to enable metadata overlay.
TODO: Right now, the packing constraints generated by can_pack() have one limitation. Suppose there are n sources related to moves for a container in a particular action, and 2 of the sources (s1 and s2) are already allocated. In that case, valid packing requires the remaining n-2 sources to be packed with either s1 or s2. Right now, s1, s2, and all the other sources are put in the same set in the UnionFind. The allocator needs to be aware of this case.
check and generate conditional constraints.
bool ActionPhvConstraints::can_pack_pov | ( | const PHV::SuperCluster::SliceList * | slice_list, |
const PHV::Field * | f ) const |
f
can be packed in the same container and the next position in slice_list
. CanPackErrorV2 ActionPhvConstraints::can_pack_v2 | ( | const PHV::Allocation & | alloc, |
const std::vector< PHV::AllocSlice > & | slices ) const |
can_pack_v2 checks whether allocating slices
will violate any action constraints.
TODO: checks inherited from legacy code does not have detailed error message. For example, pack_conflicts_present, stateful_destinations_constraints_violated and ...
bool ActionPhvConstraints::cannot_initialize | ( | const PHV::Container & | c, |
const IR::MAU::Action * | action, | ||
const PHV::Allocation & | alloc ) const |
c
at action action
. CanPackErrorCode ActionPhvConstraints::check_ara_move_constraints | ( | const PHV::Allocation & | alloc, |
const PHV::Allocation::MutuallyLiveSlices & | container_state, | ||
const PHV::Container & | c, | ||
const PHV::Allocation::LiveRangeShrinkingMap & | initActions ) const |
Besides actual actions, we need to check always run actions: (1) always run action does not overwrite other fields. For example, if we have two sources to one destination in one ARA, we need verify there's no other field in destination that are not mutex. (2) TODO: always run action can be synthesized: we cannot do it now because we don't have a way to get all ARA instructions for a specific point, and because we do table placement after PHV, it's always possible to have any ARA, so the check here is trying to avoid introducing new dependencies. table placement will add new stages when multiple instruction cannot be synthesized in one always run action.
CanPackErrorV2 ActionPhvConstraints::check_bitwise_and_basic_move_constraints | ( | const PHV::ActionSet & | actions, |
const PHV::Allocation::MutuallyLiveSlices & | container_state, | ||
const ActionPropertyMap * | action_props ) const |
returns an eroor when any action constraint of actions
are violated if the destination container has slices in container_state
.
CanPackErrorV2 ActionPhvConstraints::check_move_constraints | ( | const PHV::Allocation & | alloc, |
const IR::MAU::Action * | action, | ||
const std::vector< PHV::AllocSlice > & | slices, | ||
const PHV::Allocation::MutuallyLiveSlices & | container_state, | ||
const PHV::Container & | c, | ||
const PHV::Allocation::LiveRangeShrinkingMap & | initActions ) const |
Checks whether packing slices
into a container will violate MAU action constraints for all move-based instructions, using an action move constraint solver for normal container destination. For mocha and dark container, check basic constraints that: (1) mocha container can only be written in whole by ad/constant/container. (2) dark container can only be written in while by container.
CanPackErrorV2 ActionPhvConstraints::check_move_constraints_from_read | ( | const PHV::Allocation & | alloc, |
const std::vector< PHV::AllocSlice > & | candidates, | ||
const PHV::Allocation::LiveRangeShrinkingMap & | initActions ) const |
Check action move constraints when a source slice is allocated in slices
. It will iterate over all actions that has read any in slices
and run move constraint checker on its destination container, with fields during the action.
CanPackErrorV2 ActionPhvConstraints::check_read_action_move_constraints | ( | const PHV::Allocation & | alloc, |
const std::vector< PHV::AllocSlice > & | candidates, | ||
const IR::MAU::Action * | action, | ||
const PHV::Allocation::LiveRangeShrinkingMap & | initActions ) const |
Use action constraint solver to check move-based instruction constraints from reader-side, i.e., candidates
are sources of instructions.
CanPackErrorV2 ActionPhvConstraints::check_read_action_num_source_constraints | ( | const PHV::Allocation & | alloc, |
const std::vector< PHV::AllocSlice > & | candidates, | ||
const IR::MAU::Action * | action ) const |
action
, when we allocate sources candidates
to alloc
. bool ActionPhvConstraints::checkBridgedPackingConstraints | ( | const ordered_set< const PHV::Field * > & | packing | ) | const |
packing
satisfies action constraints ordered_map< const PHV::Field *, int > ActionPhvConstraints::compute_sources_first_order | ( | const ordered_map< const PHV::Field *, std::vector< PHV::FieldSlice > > & | fields | ) | const |
compute_sources_first_order returns a mapping from field to an integer which represents the priority (lower number higher priority) if we need to allocate source fields first. Because fields can form a strongly connected component, i.e. a loop, in terms of writes, e.g. two fields write to each other, we will run a Tarjan algorithm first to replace those SCCs with a single node and then we run a topological sort. For example, Assume a <- b represents b writes to a, and we have
a <- b <- c <-> e ^ | d
will be converted to, a <- b <- {c, e} ^ | d
and the output will be, d, c, e: 1 b: 2 a: 3
i.e. we encounter a loop, convert that loop into one node.
int ActionPhvConstraints::count_bitmasked_set_instructions | ( | const std::vector< PHV::AllocSlice > & | slices, |
const PHV::Allocation::LiveRangeShrinkingMap & | initActions ) const |
Counts the number of bitmasked-set instructions corresponding to slices
in container c
and allocation object alloc
.
bool ActionPhvConstraints::creates_container_conflicts | ( | const PHV::Allocation::MutuallyLiveSlices & | container_state, |
const PHV::Allocation::LiveRangeShrinkingMap & | initActions, | ||
const MapTablesToActions & | tableActionsMap ) const |
void ActionPhvConstraints::dest_first_sort | ( | std::vector< const PHV::SuperCluster::SliceList * > & | slice_list | ) | const |
sort slice_lists
by
last destination
) of the list.bool ActionPhvConstraints::diagnoseSuperCluster | ( | const ordered_set< const PHV::SuperCluster::SliceList * > & | sc, |
const ordered_map< PHV::FieldSlice, unsigned > & | fieldAlignments, | ||
std::stringstream & | error_msg ) const |
Diagnose PHV allocation failure for supercluster sc
containing field slices in slice lists with alignment sliceAlignments
.
error_msg
with the appropriate error message. std::optional< const PHV::Field * > ActionPhvConstraints::field_destination | ( | const PHV::Field * | f, |
const IR::MAU::Action * | action ) const |
f
in action action
. f
is not written in action
. ActionPhvConstraints::ActionSources ActionPhvConstraints::getActionSources | ( | const IR::MAU::Action * | act, |
const PHV::Container & | c, | ||
ordered_set< PHV::AllocSlice > & | new_slices, | ||
const PHV::Allocation & | alloc ) const |
Find all sources of an action that write to a given container
act | action for which to find the sources |
c | destination container of interest for the action |
new_slices | slices to be added to the allocation |
alloc | current Allocation object containing allocated slices |
FIXME: This function can be made non-public once live range shrinking/dark overlay functionality is merged and all initialization points are correctly exposed.
|
inline |
fs1
and fs2
have a pack conflict.
|
inline |
f
is written using a speciality read (METER_ALU, HASH_DIST, RANDOM, or METER_COLOR). bool ActionPhvConstraints::is_bitmasked_set | ( | const std::vector< PHV::AllocSlice > & | container_state, |
const ordered_set< PHV::AllocSlice > & | fields_not_written_to ) const |
container_state
in a particular container, where slices in fields_not_written_to
are not written in the given action, would result in the synthesis of a bitmasked-set instruction. bool ActionPhvConstraints::is_in_action_to_writes | ( | const IR::MAU::Action * | action, |
cstring | write ) const |
For GTest function. Checks if the action_to_writes ordered_map entry is valid or not
bool ActionPhvConstraints::is_in_field_writes_to_actions | ( | cstring | write, |
const IR::MAU::Action * | action ) const |
For GTest function. Checks if the field_writes_to_actions ordered_map entry is valid or not
bool ActionPhvConstraints::is_in_write_to_reads | ( | cstring | write, |
const IR::MAU::Action * | act, | ||
cstring | read ) const |
For GTest function. Checks if the write_to_reads_per_action ordered_map entry is valid or not
|
inline |
[Relaxed Artificial Constraint]: Right now action bus allocation requires any destination written by meter colors to be allocated to a 8-bit PHV if the result of the operation can't be rotated. This set keeps a track of all such destinations.
|
inline |
|
inline |
|
inline |
|
inline |
bool ActionPhvConstraints::move_only_operations | ( | const PHV::Field * | f | ) | const |
f
is only ever written by move operations. bool ActionPhvConstraints::pack_conflicts_present | ( | const PHV::Allocation::MutuallyLiveSlices & | container_state, |
const std::vector< PHV::AllocSlice > & | slices ) const |
container_state
. bool ActionPhvConstraints::parser_constant_extract_satisfied | ( | const PHV::Container & | c, |
const PHV::Allocation::MutuallyLiveSlices & | container_state ) const |
ordered_set< const PHV::Field * > ActionPhvConstraints::slices_destinations | ( | const PHV::Field * | src, |
const std::vector< PHV::FieldSlice > & | slices ) const |
slices
of f
across all actions. NOTE: destination are returned iff it completely read from some slice in slices
. e.g., assume we have f<32>[0:28] = a<32>[0:28]; slices_destinations(a, {a[0:31]}) will return {} instead of {f}, because the operation does not completely write any source slice. ordered_set< const PHV::Field * > ActionPhvConstraints::slices_sources | ( | const PHV::Field * | dest, |
const std::vector< PHV::FieldSlice > & | slices ) const |
slices
of f
across all actions. NOTE: sources are returned iff it completely writes some slice in slices
. e.g., assume we have f<32>[0:28] = a<28>; slices_sources(f, {f[0:31]}) will return {} instead of {a}, because the operation does not completely write any source slice. void ActionPhvConstraints::sort | ( | std::list< const PHV::SuperCluster::SliceList * > & | slice_list | ) | const |
Approximates a topographical sorting of field lists such that all source-only slice lists are considered for allocation before destination-only slice lists. Sorts a given list of slice list such that the slice lists used the least times as sources are first allocated containers. If the number of times fields in a slice list is used as sources is the same as another slice list, the slice list which is written to in more actions ranks earlier in the sorting.
void ActionPhvConstraints::sort | ( | std::vector< PHV::FieldSlice > & | slice_list | ) | const |
Approximates a topographical sorting of FieldSlices such that all FieldSlices used only as sources are considered for allocation before destination-only FieldSlices
bool ActionPhvConstraints::written_by_ad_constant | ( | const PHV::Field * | f, |
const IR::MAU::Action * | act ) const |
f
is written in action act
by action data/constant source.
|
inline |
slice
is written in action act
. bool ActionPhvConstraints::written_in | ( | const PHV::Field * | f, |
const IR::MAU::Action * | act ) const |
f
is written in action act
.