P4C
The P4 Compiler
|
#include <action_analysis.h>
Public Member Functions | |
void | add_alignment (le_bitrange wb, le_bitrange rb) |
bool | aligned () const |
bool | bitrange_contiguous () const |
int | bitrange_contiguous_size () const |
int | bitrange_cover_size () const |
bitvec | brm_src_mask (PHV::Container container) const |
bitvec | byte_rotate_merge_byte_mask (PHV::Container container) const |
bool | contiguous () const |
bool | deposit_field_src1 () const |
bool | deposit_field_src2 (PHV::Container container) const |
void | determine_brm_implicit_bits (PHV::Container container, bitvec src1_mask) |
void | determine_df_implicit_bits (PHV::Container container) |
bitvec | df_src1_mask () const |
bitvec | df_src2_mask (PHV::Container container) const |
bool | equiv_bit_totals () const |
void | implicit_bits_full (PHV::Container container) |
bool | is_byte_rotate_merge_src (PHV::Container container) const |
bool | is_wrapped_shift (PHV::Container container, int *lo=nullptr, int *hi=nullptr) const |
TotalAlignment | operator| (const TotalAlignment &ta) |
bitvec | read_bits () const |
void | set_implicit_bits_from_mask (bitvec mask, PHV::Container container) |
bool | verify_individual_alignments (PHV::Container &container) |
bitvec | write_bits () const |
Public Attributes | |
bitvec | direct_read_bits |
bitvec | direct_write_bits |
bitvec | implicit_read_bits |
bitvec | implicit_write_bits |
safe_vector< Alignment > | indiv_alignments |
bool | is_src1 = false |
int | right_shift = 0 |
bitvec | unused_container_bits |
bool | verbose = false |
Friends | |
std::ostream & | operator<< (std::ostream &out, const TotalAlignment &ta) |
Information on all PHV reads affecting a single container. Again used for verification and combining fields into MultiOperand. Understood to be the bits written and read by the entire container, rather than in individual instruction in the container. From these total alignment structures, we can determine if deposit-fields or bitmasked-sets are possible/necessary
|
inline |
A size that fits all the write bits provided they are continuous, or -1 if they are not. Value -1 therefore indicates that deposit-field instruction cannot be used.
|
inline |
Returns a size that fits all the non-zero bits of writes. The writes need not be contiguous.
bitvec ActionAnalysis::TotalAlignment::brm_src_mask | ( | PHV::Container | container | ) | const |
Based on what bits that are written and unused, this is the possible source mask bit by bit. Because of unused bits, the actual source mask can be a subset of this
bitvec ActionAnalysis::TotalAlignment::byte_rotate_merge_byte_mask | ( | PHV::Container | container | ) | const |
The byte mask appearing in the instruction
bool ActionAnalysis::TotalAlignment::deposit_field_src1 | ( | ) | const |
Src1 of a deposit-field does not have to be aligned, but must be contiguous after it has been rotated
bool ActionAnalysis::TotalAlignment::deposit_field_src2 | ( | PHV::Container | container | ) | const |
Src2 of a deposit-field has to be be aligned, but not contiguous, as long as there is only one hole within the deposit-field
bitvec ActionAnalysis::TotalAlignment::df_src1_mask | ( | ) | const |
The following functions are used during verify_alignment in order to determine which source each parameter is as well as determine which bits are written by src1/src2
The unused_container_bits are bits that are not live at the same time of any bits of fields in the same container, and thus can be written to.
For the deposit-field src1, the written bits must be a lo to hi that is contiguous on the write bits. For deposit-field src2, the opposite is true, as the write must contain a single contiguous hole.
For src1, this contiguous range can either container directly written bits, or unused container bits that can be read
bitvec ActionAnalysis::TotalAlignment::df_src2_mask | ( | PHV::Container | container | ) | const |
See comments above df_src1_mask for context.
The goal of this function is to find what bits are to be written by the src2 of the deposit field. This looks for a single contiguous hole in the bits written, and returns the reverse of this hole
The algorithm looks for holes in the direct_write_bits. These may actually not be the hole for the deposit-field if those bits are entirely unused_container_bits. Thus if the hole is not all unused_container_bits, this is assumed to be the hole.
If there are multiple holes, then the deposit-field mask is returned empty
bool ActionAnalysis::TotalAlignment::is_wrapped_shift | ( | PHV::Container | container, |
int * | lo = nullptr, | ||
int * | hi = nullptr ) const |
Determines if the source is to be wrapped around the container. If the thing is wrapped, the low position of the source is required to determine the location
A deposit-field operation has source that can be rotated bit by bit. This rotation can rotate the data around the container. The destination of a deposit-field src1 has to be contiguous, but this doesn't mean that the source is contiguous.
Say for example you were writing a 4 bit field, i.e. f1 = f2. The allocation could be
B0 [5..2] = f1[3..0] B1 [7..6] = f2[1..0] B1 [1..0] = f2[3..2]
By right rotating B1 by 4 bits, this will shift the B1 into the correct place. But notice that the field f2 is non contiguous in it's own container.
The instructions in the assembly file, when writing one slice to another slice are:
However, this is impossible to write with a source that is wrapped, as src_bit_hi is less than src_bit_lo. This is instead synthesized as a direct deposit-field instruction:
- deposit_field B0[5..2], B1(1), B0
This funciton returns true if the instruction has to be synthesized directly as a deposit-field because the source slice is not a lo to hi range. It also can return a lo and hi value for the IR::MAU::WrappedSlice
2 corner cases:
> lo is the bit of the read bits that needs to be aligned with bit 0
hi is the bit that needs to be aligned with container.size() - 1.
bool ActionAnalysis::TotalAlignment::verify_individual_alignments | ( | PHV::Container & | container | ) |
Guarantees that a single alignment is aligned correctly. The checks are:
int ActionAnalysis::TotalAlignment::right_shift = 0 |
The amount to bits to rotate right the write_bits in order to get the read_bits. The deposit-field write shift is the opposite, i.e. the amount to rotate right the read bits in order to get the write bits