P4C
The P4 Compiler
|
#include <action_analysis.h>
Public Types | |
enum | error_code_t { NO_PROBLEM = 0 , MULTIPLE_CONTAINER_ACTIONS = (1 << 0) , READ_PHV_MISMATCH = (1 << 1) , ACTION_DATA_MISMATCH = (1 << 2) , CONSTANT_MISMATCH = (1 << 3) , TOO_MANY_PHV_SOURCES = (1 << 4) , IMPOSSIBLE_ALIGNMENT = (1 << 5) , CONSTANT_TO_ACTION_DATA = (1 << 6) , MULTIPLE_ACTION_DATA = (1 << 7) , ILLEGAL_OVERWRITE = (1 << 8) , BIT_COLLISION = (1 << 9) , OPERAND_MISMATCH = (1 << 10) , UNHANDLED_ACTION_DATA = (1 << 11) , DIFFERENT_READ_SIZE = (1 << 12) , MAU_GROUP_MISMATCH = (1 << 13) , PHV_AND_ACTION_DATA = (1 << 14) , PARTIAL_OVERWRITE = (1 << 15) , MULTIPLE_SHIFTS = (1 << 16) , ILLEGAL_ACTION_DATA = (1 << 17) , REFORMAT_CONSTANT = (1 << 18) , UNRESOLVED_REPEATED_ACTION_DATA = (1 << 19) , ATTACHED_OUTPUT_ILLEGAL_ALIGNMENT = (1 << 20) , CONSTANT_TO_HASH = (1 << 21) , ILLEGAL_MOCHA_OR_DARK_WRITE = (1 << 22) , BIT_COLLISION_SET = (1 << 23) , MULTIPLE_SPECIALITIES = (1 << 24) } |
Public Member Functions | |
ContainerAction (cstring n, const IR::MAU::Table *tbl) | |
bool | action_data_isolated () const |
bool | ad_renamed () const |
int | ad_sources () const |
int | alignment_counts () const |
bool | convert_constant_to_actiondata () const |
bool | convert_constant_to_hash () const |
void | determine_implicit_bits (PHV::Container container, TotalAlignment &ad_alignment) |
void | determine_src1 () |
bool | has_ad_or_constant () const |
bool | is_byte_rotate_merge (PHV::Container container, TotalAlignment &ad_alignment) |
bool | is_commutative () const |
bool | is_from_set () const |
bool | is_funnel_shift () const |
bool | is_shift () const |
bool | is_single_shift () const |
bool | is_total_overwrite_possible () |
void | move_source_to_bit (safe_vector< int > &bit_uses, TotalAlignment &ta) |
bool | no_sources () const |
int | operands () const |
bool | partial_overwrite () const |
int | read_sources () const |
bool | set_invalidate_write_bits (le_bitrange write) |
void | set_mismatch (ActionParam::type_t type) |
bitvec | specialities () const |
std::string | to_string () const |
int | total_types () |
bitvec | total_write () const |
bool | unresolved_ad () const |
bool | verify_alignment (PHV::Container &container) |
bool | verify_deposit_field_variant (PHV::Container container, TotalAlignment &ad_alignment) |
bool | verify_mocha_and_dark (cstring &error_message, PHV::Container container) |
bool | verify_multiple_action_data () const |
bool | verify_one_alignment (TotalAlignment &tot_alignment, int size, int &unaligned_count, int &non_contiguous_count) |
bool | verify_only_read (const PhvInfo &phv, int num_source) |
bool | verify_overwritten (PHV::Container container, const PhvInfo &phv) |
bool | verify_phv_mau_group (PHV::Container container) |
bool | verify_possible (cstring &error_message, PHV::Container container, cstring action_name, const PhvInfo &phv) |
bool | verify_set_alignment (PHV::Container, TotalAlignment &ad_alignment) |
bool | verify_shift (cstring &error_message, PHV::Container container, const PhvInfo &phv) |
bool | verify_source_to_bit (int operands, PHV::Container container) |
bool | verify_speciality (cstring &error_message, PHV::Container container, cstring action_name) |
Public Attributes | |
ActionDataInfo | adi |
ConstantInfo | ci |
bool | constant_to_ad = false |
bool | convert_instr_to_bitmasked_set = false |
bool | convert_instr_to_byte_rotate_merge = false |
bool | convert_instr_to_deposit_field = false |
int | counts [ActionParam::TOTAL_TYPES] = {0, 0, 0} |
unsigned | error_code = NO_PROBLEM |
TotalAlignment | extra_resize_reads |
safe_vector< FieldAction > | field_actions |
bool | implicit_src1 = false |
bool | implicit_src2 = false |
bool | impossible = false |
ordered_map< PHV::Container, safe_vector< Alignment > > | initialization_phv_alignment |
bitvec | invalidate_write_bits |
bool | is_background_source = false |
bool | is_deposit_field_variant = false |
cstring | name |
std::multimap< PHV::Container, TotalAlignment > | phv_alignment |
const IR::MAU::Table * | table_context = nullptr |
bool | total_overwrite_possible = false |
bool | unhandled_action = false |
bool | verbose = false |
Static Public Attributes | |
static std::set< unsigned > | codesForErrorCases |
static const std::vector< cstring > | error_code_string_t |
Friends | |
std::ostream & | operator<< (std::ostream &out, const ContainerAction &ca) |
Information on all of the individual reads and writes within a single PHV container in an action function. Essentially coordinate to all the action that can happen within a single VLIW ALU
Eventually we want to craft correct backtrack/error messages from all of these error messages. In the meantime, used for tracking action data issues
|
inline |
Each alignment comes from an individual manipulation of alloc_slice or single contiguous slice of action format
void ActionAnalysis::ContainerAction::determine_implicit_bits | ( | PHV::Container | container, |
TotalAlignment & | ad_alignment ) |
The implicit bits are calculated as bits that aren't directly written or read from fields in the PHV, but are written anyway by the operation. Either fields can possibly be dead, or padding, or just empty space within the allocation.
This function runs at the end of verify_alignment, when src1 and src2 are possibly known
bool ActionAnalysis::ContainerAction::is_byte_rotate_merge | ( | PHV::Container | container, |
TotalAlignment & | ad_alignment ) |
bool ActionAnalysis::ContainerAction::verify_deposit_field_variant | ( | PHV::Container | container, |
TotalAlignment & | ad_alignment ) |
Verifies that the instruction can be encoded as a deposit-field. As mentioned above verify_set_alignment, deposit field is the following:
deposit-field: dest = ((src1 << shift) & mask) | (src2 & ~mask)
The mask is a contiguous range, and has a single lo and hi. Thus if src1 is a contiguous range of data (which can go around the container boundary), then this is supportable. The range has to be contiguous after the shift.
In a deposit field, a source must at least either be aligned, or can be contiguous. A source can be both. A source that is not aligned must be src1, and a source that is not contiguous is src2.
If the single PHV field in a deposit-field cannot be src1 due to non-contiguity, but can be src2 because it is aligned
Generally in a single source set, this is translated to set C0(lo..hi), C1(lo..hi), but when the source is wrapped, the only way for the assembler to understand is an explicit deposit-field instruction.
The deposit field for a single sourced wrapped source will be the following:
deposit-field C0(lo..hi), C1(lo), C0
The assembler will not understand the C1 slice if lo > hi, but the deposit-field instruction technically only requires the lo bit to determine the right shift
bool ActionAnalysis::ContainerAction::verify_only_read | ( | const PhvInfo & | phv, |
int | num_source ) |
Ensure that a read field is the only field within that container
bool ActionAnalysis::ContainerAction::verify_overwritten | ( | PHV::Container | container, |
const PhvInfo & | phv ) |
For nearly all instructions, the ALU operation acts over all bits in the container. The only instruction where this doesn't apply is the deposit-field instruction. That instruction can have a portion masked. Any other operation currently acts on the entire container, and all fields could be potentially affected.
bool ActionAnalysis::ContainerAction::verify_phv_mau_group | ( | PHV::Container | container | ) |
Each PHV ALU can only pull from a local group of PHVs in an operation. This guarantees that this clustering constraint is met.
bool ActionAnalysis::ContainerAction::verify_possible | ( | cstring & | error_message, |
PHV::Container | container, | ||
cstring | action_name, | ||
const PhvInfo & | phv ) |
The goal of this function is to validate a container operation given the allocation the write fields and the sources of the particular operation. The following checks are:
The reason these constraints exists are due to the Action ALU Instruction Set Architecture. If any of these are not true, then this instruction is not possible on Tofino.
bool ActionAnalysis::ContainerAction::verify_set_alignment | ( | PHV::Container | container, |
TotalAlignment & | ad_alignment ) |
Verifies that the set ContainerActions (which are translated from assignment operations) are possible to be translated to an instruction.
The following instructions are possible encodings of assignment statements. Note that all shifts are rotational, meaning that the container is rotated by this number of bits.
deposit-field: dest = ((src1 << shift) & mask) | (src2 & ~mask)
The mask is a contiguous range, and has a single lo and hi. Thus if src1 is a contiguous range of data (which can go around the container boundary), then this is supportable. The range has to be contiguous after the shift.
bitmasked-set: dest = (src1 & mask) | (src2 & ~mask)
where the src1 must come from action data, and everything must be aligned. The mask is not required to be contiguous. Instead the mask is stored as action data in the RAM entry.
byte-rotate-merge: dest = ((src1 << src1_shift) & mask) | ((src2 << src2_shift) & ~mask)
The limitation is that src1_shift and src2_shift % 8 must == 0. The mask is also a byte mask, requiring the entire byte to come from the source.
The purpose of this function is to verify that a ContainerAction can be translated to one of these possible instructions, and will return false if the action is impossible in the ALU. This also determines if the action cannot be output as a set in the assembly language. With a set operation, src2 (background) = destination is implicit, but in the case when this isn't true, the full field must be translated in the compiler, i.e: deposit-field C0(lo..hi), C1(lo..hi), C2
Each of these operations have different constraints:
bool ActionAnalysis::ContainerAction::verify_shift | ( | cstring & | error_message, |
PHV::Container | container, | ||
const PhvInfo & | phv ) |
Due to shifts being fairly unique when it comes to action constraints, a separate function is required. The following constraints are verified:
bool ActionAnalysis::ContainerAction::verify_source_to_bit | ( | int | operands, |
PHV::Container | container ) |
This checks to make sure that all bits are operated correctly, i.e. if the operation is a set, every bit in the write is either set once or not at all or e.g. add, subtract, or, each write bit has either two read bits, or no read bits affecting it (overwrite constraints are checked in a different verification)
When combining a conditional-set with another set, the number of operands is not perfect here, as the operands can be either one or two bits, i.e.
conditional-set f1, f2, arg1, cond-arg set f3, arg2
How many sources, the condtional-set would have either two sources, but the normal set would have one operand. Potentially can be rewritten
bool ActionAnalysis::ContainerAction::verify_speciality | ( | cstring & | error_message, |
PHV::Container | container, | ||
cstring | action_name ) |
Verifies that the use of a speciality argument is valid
For all cases:
For NO_SPECIAL (anything still applies)
For any non-HASH
For METER_ALU
For HASH:
|
static |
bool ActionAnalysis::ContainerAction::convert_instr_to_bitmasked_set = false |
determined by tofino_compliance check
bool ActionAnalysis::ContainerAction::convert_instr_to_byte_rotate_merge = false |
determined by tofino_compliance_check
|
static |
bool ActionAnalysis::ContainerAction::implicit_src2 = false |
determined by tofino_compliance_check
bool ActionAnalysis::ContainerAction::impossible = false |
determined by tofino_compliance_check