P4C
The P4 Compiler
Loading...
Searching...
No Matches
PackWithConstraintSolver Class Reference

#include <bridged_packing.h>

Inheritance diagram for PackWithConstraintSolver:
[legend]

Public Member Functions

 PackWithConstraintSolver (const PhvInfo &p, ConstraintSolver &solver, const ordered_set< cstring > &c, ordered_map< cstring, const IR::Type_StructLike * > &r, PackingCandidateFields &pcf, PackingConstraints &pc)
 
void end_apply () override
 
Visitor::profile_t init_apply (const IR::Node *root) override
 
void optimize ()
 
bool preorder (const IR::BFN::DigestFieldList *dfl) override
 
bool preorder (const IR::HeaderOrMetadata *hdr) override
 
void set_pipeline_name (cstring name)
 
void solve ()
 
- Public Member Functions inherited from P4::Inspector
const IR::Nodeapply_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 Visitorclone () const
 
virtual ControlFlowVisitorcontrolFlowVisitor ()
 
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 Visitorflow_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 ContextgetChildContext () const
 
int getChildrenVisited () const
 
const ContextgetContext () const
 
int getContextDepth () const
 
const IR::NodegetCurrentNode () const
 
template<class T >
const T * getCurrentNode () const
 
const IR::NodegetOriginal () 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 VisitorsetCalledBy (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
 

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 Visitorcalled_by = nullptr
 
cstring internalName
 
SplitFlowVisit_base *& split_link
 
SplitFlowVisit_basesplit_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
 

Detailed Description

The class adjusts the packing of headers/metadata/digest field lists that contain the fields with the @flexible annotation whose width is not a multiply of eight bits.

The candidates for packing adjustment can be delivered through the constructor. This approach is used for bridged headers. If the list of candidates (PackWithConstraintSolver::candidates) is empty, the inspector looks for the candidates among all headers/metadata (IR::HeaderOrMetadata) and digest field lists (IR::BFN::DigestFieldList).

The class then computes the optimal field packing using the constraint solver (PackWithConstraintSolver::solver). We modeled as a single (larger) optimization problem as opposed to multiple (smaller) optimization because a field may exists in multiple flexible field lists. The computed alignment for the field must be consistent across all instances of the flexible field list. However, the optimizer is still optimizing each field list with individual optimization goals and constraints. The number of constraints scales linearly with respect to the number of fields list instances. Within each field lists, the number of constraints scales at O(n^2) with respect to the number of fields.

Logging options
-Tbridged_packing:1
  • A list of @flexible fields whose width is not a multiple of eight bits
  • Original (non-@flexible) and adjusted (@flexible whose width in not a multiply of eight bits) fields being used in the adjusted headers/metadata/digest field lists
  • Adjusted headers/metadata/digest field lists
-Tbridged_packing:3
  • Which digest field list is being processed
-Tbridged_packing:5
  • Print candidates to pack and when a header/metadata/digest field list is skipped
Precondition
Up-to-date PhvInfo.

Member Function Documentation

◆ end_apply()

void PackWithConstraintSolver::end_apply ( )
overridevirtual

Runs optimizer to trigger adding constraints to the constraint solver.

Reimplemented from P4::Visitor.

◆ optimize()

void PackWithConstraintSolver::optimize ( )

Triggers adding constraints for all @flexible fields whose width is not a multiply of eight bits to the constraint solver.

There are two steps. The first one adds constraints for individual headers/metadata/digest field lists using ConstraintSolver::add_constraints. The other step adds mutually aligned constraints for fields of all headers/metadata/digest field lists using ConstraintSolver::add_mutually_aligned_constraints.

If corresponding logging is enabled, the Z3 solver assertions are printed out to the log.

See also
ConstraintSolver for logging options to log the Z3 solver assertions.

◆ preorder() [1/2]

bool PackWithConstraintSolver::preorder ( const IR::BFN::DigestFieldList * d)
override

Looks for @flexible fields of digest field lists whose with is, and is not a multiple of eight bits and updates the PackWithConstraintSolver::byteAlignedFieldsMap, and PackWithConstraintSolver::nonByteAlignedFieldsMap maps, respectively.

Also stores the mapping from a PHV::Field to the corresponding IR::StructField into the PackWithConstraintSolver::phvFieldToStructFieldMap map and the mapping from a header/metadata name to the corresponding IR::Type_StructLike into the PackWithConstraintSolver::headerMap map.

◆ preorder() [2/2]

bool PackWithConstraintSolver::preorder ( const IR::HeaderOrMetadata * hdr)
override

Looks for @flexible header/metadata fields. For those whose witdh is a multiple of eight bits, it updates the PackWithConstraintSolver::byteAlignedFieldsMap map. For those whose width is not a multiple of eight bits, it updates the PackWithConstraintSolver::nonByteAlignedFieldsMap map.

Also stores the mapping from a PHV::Field to the corresponding IR::StructField into the PackWithConstraintSolver::phvFieldToStructFieldMap map and the mapping from a header/metadata name to the corresponding IR::Type_StructLike into the PackWithConstraintSolver::headerMap map.

◆ solve()

void PackWithConstraintSolver::solve ( )

Runs the constraint solver to get adjusted packing of @flexible fields whose width is not a multiply of eight bits and creates adjusted headers/metadata/digest field lists containing these fields.

Adjusted header/metadata/digest field list is composed as follows:

  1. Original non-@flexbile and non-@padding fields
  2. Original @flexible fields whose width is a multiply of eight bits
  3. Adjusted @flexible fields whose width is not a multiply of eigth bits including possible padding fields obtained from the constraint solver. The padding fields are annotated with @padding and @overlayable.

Adjusted headers/metadata/digest field lists are stored in PackWithConstraintSolver::repackedTypes.