P4C
The P4 Compiler
Loading...
Searching...
No Matches
clot_info.h
1
19#ifndef BACKENDS_TOFINO_BF_P4C_PARDE_CLOT_CLOT_INFO_H_
20#define BACKENDS_TOFINO_BF_P4C_PARDE_CLOT_CLOT_INFO_H_
21
22#include <algorithm>
23
24#include "backends/tofino/bf-p4c/lib/assoc.h"
25#include "backends/tofino/bf-p4c/lib/cmp.h"
26#include "backends/tofino/bf-p4c/logging/filelog.h"
27#include "backends/tofino/bf-p4c/parde/clot/pragma/do_not_use_clot.h"
28#include "backends/tofino/bf-p4c/parde/dump_parser.h"
29#include "backends/tofino/bf-p4c/parde/parde_visitor.h"
30#include "backends/tofino/bf-p4c/phv/phv_parde_mau_use.h"
31#include "clot.h"
32#include "deparse_graph.h"
33#include "field_slice_set.h"
34#include "lib/ordered_map.h"
35#include "pseudoheader.h"
36
37class PhvInfo;
38
40
41class ClotInfo {
42 friend class AllocateClot;
43 friend class CollectClotInfo;
44 friend class ClotCandidate;
45 friend class GreedyClotAllocator;
46
47 PhvUse &uses;
48
50 ordered_set<const PHV::Field *> do_not_use_clot_fields;
51
54 parser_state_to_fields_;
55
59 parser_state_to_header_stacks_;
60
63 std::set<unsigned>>
64 header_stack_elements_;
65
68 ordered_map<const PHV::Field *,
69 std::unordered_map<const IR::BFN::ParserState *, const IR::BFN::ParserRVal *>>
70 field_to_parser_states_;
71
75 field_to_byte_idx;
76
80 byte_idx_to_field;
81
82 std::set<const PHV::Field *> checksum_dests_;
83 std::map<const PHV::Field *, std::vector<const IR::BFN::EmitChecksum *>>
84 field_to_checksum_updates_;
85
86 std::vector<Clot *> clots_;
87 std::map<const Clot *, std::pair<gress_t, std::set<cstring>>, Clot::Less>
88 clot_to_parser_states_;
91 std::map<gress_t, std::map<cstring, std::set<const Clot *>>> parser_state_to_clots_;
92
93 std::map<const IR::BFN::ParserState *, ordered_map<const PHV::Field *, nw_bitrange>>
94 field_range_;
95
96 std::map<const Clot *, std::vector<const IR::BFN::EmitChecksum *>> clot_to_emit_checksum_;
97
99 std::map<const PHV::Field *, std::set<const PHV::Field *> *> field_aliases_;
100
102 std::set<cstring> headers_added_by_mau_;
103
105 std::map<const PHV::Field *, std::set<const Pseudoheader *>> field_to_pseudoheaders_;
106
107 std::map<gress_t, DeparseGraph> deparse_graph_;
108
110 std::map<const PHV::Field *, PovBitSet> fields_to_pov_bits_;
111
112 public:
113 explicit ClotInfo(PhvUse &uses) : uses(uses) {}
114
115 private:
116 unsigned num_clots_allocated(gress_t gress) const { return Clot::tag_count.at(gress); }
117
119 std::optional<nw_bitrange> field_range(const IR::BFN::ParserState *state,
120 const PHV::Field *field) const;
121
123 std::optional<unsigned> offset(const IR::BFN::ParserState *state,
124 const PHV::Field *field) const;
125
126 public:
133 cstring sanitize_state_name(cstring state_name, gress_t gress) const;
134
135 CollectParserInfo parserInfo;
136
138 parser_state_to_fields() const {
139 return parser_state_to_fields_;
140 };
141
143 parser_state_to_header_stacks() const {
144 return parser_state_to_header_stacks_;
145 };
146
148 std::set<unsigned>> &
149 header_stack_elements() {
150 return header_stack_elements_;
151 }
152
155 std::set<const PHV::Field *> pov_extracted_without_fields;
156
157 const std::map<const Clot *, std::pair<gress_t, std::set<cstring>>, Clot::Less> &
158 clot_to_parser_states() const {
159 return clot_to_parser_states_;
160 }
161
162 std::map<cstring, std::set<const Clot *>> &parser_state_to_clots(gress_t gress) {
163 return parser_state_to_clots_.at(gress);
164 }
165
166 const std::map<cstring, std::set<const Clot *>> &parser_state_to_clots(gress_t gress) const {
167 return parser_state_to_clots_.at(gress);
168 }
169
170 const std::set<const Clot *> parser_state_to_clots(
171 const IR::BFN::LoweredParserState *state) const;
172
173 const Clot *parser_state_to_clot(const IR::BFN::LoweredParserState *state, unsigned tag) const;
174
175 const std::vector<Clot *> &clots() { return clots_; }
176
177 const std::map<const PHV::Field *, std::vector<const IR::BFN::EmitChecksum *>> &
178 field_to_checksum_updates() {
179 return field_to_checksum_updates_;
180 }
181
183 std::map<int, PHV::Container> get_overwrite_containers(const Clot *clot,
184 const PhvInfo &phv) const;
185
187 std::map<int, const PHV::Field *> get_csum_fields(const Clot *clot) const;
188
189 std::map<const Clot *, std::vector<const IR::BFN::EmitChecksum *>> &clot_to_emit_checksum() {
190 return clot_to_emit_checksum_;
191 }
192
193 const std::map<const Clot *, std::vector<const IR::BFN::EmitChecksum *>> &
194 clot_to_emit_checksum() const {
195 return clot_to_emit_checksum_;
196 }
197
204 void merge_parser_states(gress_t gress, cstring dst_state_name, cstring src_state_name);
205
206 private:
207 void add_field(const PHV::Field *f, const IR::BFN::ParserRVal *source,
208 const IR::BFN::ParserState *state);
209
210 void add_stack(const IR::HeaderStack *hs, const IR::BFN::ParserState *state, int index = -1);
211
213 void compute_byte_maps();
214
215 void add_clot(Clot *clot, ordered_set<const IR::BFN::ParserState *> states);
216
219 const ordered_set<const IR::BFN::ParserState *> *find_full_states(
220 const IR::BFN::ParserGraph *graph) const;
221
222 // A field may participate in multiple checksum updates, e.g. IPv4 fields
223 // may be included in both IPv4 and TCP checksum updates. In such cases,
224 // we require the IPv4 fields in both updates to be identical sets in order
225 // to be allocated to a CLOT (each CLOT can only compute one checksum)
226 bool is_used_in_multiple_checksum_update_sets(const PHV::Field *field) const;
227
229 bool is_extracted_in_multiple_non_mutex_states(const PHV::Field *f) const;
230
232 bool extracted_with_pov(const PHV::Field *field) const;
233
236 bool has_consistent_bit_in_byte_offset(const PHV::Field *field) const;
237
240 bool can_be_in_clot(const PHV::Field *field) const;
241
243 bool can_start_clot(const FieldSliceExtractInfo *extract_info) const;
244
246 bool can_end_clot(const FieldSliceExtractInfo *extract_info) const;
247
251 bool extracts_full_width(const PHV::Field *field) const;
252
254 mutable std::map<const PHV::Field *, bool> is_modified_;
255
256 public:
258 bool is_checksum(const PHV::Field *field) const;
259 bool is_checksum(const PHV::FieldSlice *slice) const;
260
263 bool is_modified(const PHV::Field *field) const;
264 bool is_modified(const PHV::FieldSlice *slice) const;
265
268 bool is_readonly(const PHV::Field *field) const;
269 bool is_readonly(const PHV::FieldSlice *slice) const;
270
273 bool is_unused(const PHV::Field *field) const;
274 bool is_unused(const PHV::FieldSlice *slice) const;
275
277 const std::set<const PHV::Field *> *clot_eligible_fields() const;
278
286
289 bool is_slice_below_min_offset(const PHV::FieldSlice *slice, int max_packet_bit_offset) const;
290
294 //
295 // If we had more precise slice-level usage information, we could instead return a non-null
296 // result if the given slice were unused.
301
304 const Clot *fully_allocated(const PHV::Field *field) const {
305 return is_unused(field) ? whole_field_clot(field) : nullptr;
306 }
307
310 //
311 // If we had more precise slice-level usage information, we could instead return a non-null
312 // result if the given slice were unused.
313 std::set<const Clot *, Clot::Less> *fully_allocated(const PHV::FieldSlice &slice) const {
314 return fully_allocated(&slice);
315 }
316
319 //
320 // If we had more precise slice-level usage information, we could instead return a non-null
321 // result if the given slice were unused.
322 std::set<const Clot *, Clot::Less> *fully_allocated(const PHV::FieldSlice *slice) const;
323
328 return whole_field_clot(field) && (is_readonly(field) || is_unused(field)) &&
329 !field->is_digest();
330 }
331
334 void adjust_clots(const PhvInfo &phv);
335
336 private:
341 bool adjust(const PhvInfo &phv, Clot *clot);
342
344 void crop(Clot *clot, cstring parser_state, unsigned start_bits, unsigned end_bits);
345
346 void crop(Clot *clot, cstring parser_state, unsigned num_bits, bool from_start);
347
348 public:
355 bool slice_overwritten(const PhvInfo &phvInfo, const Clot *clot,
356 const PHV::FieldSlice *f) const;
357
364 bool slice_overwritten_by_phv(const PhvInfo &phvInfo, const Clot *clot,
365 const PHV::FieldSlice *f) const;
366
367 private:
374 template <Endian Order = Endian::Network>
375 bitvec bits_overwritten(const PhvInfo &phvInfo, const Clot *clot,
376 const PHV::FieldSlice *f) const;
377
384 template <Endian Order = Endian::Network>
385 bitvec bits_overwritten_by_phv(const PhvInfo &phvInfo, const Clot *clot,
386 const PHV::FieldSlice *f) const;
387
388 public:
390 bool is_added_by_mau(cstring h) const;
391
395 const PHV::FieldSlice *slice) const;
396
403
406 Clot *whole_field_clot(const PHV::Field *field) const;
407
409 bool clot_covers_slice(const Clot *clot, const PHV::FieldSlice *slice) const;
410
411 std::string print(const PhvInfo *phvInfo = nullptr) const;
412
413 private:
414 void add_alias(const PHV::Field *f1, const PHV::Field *f2);
415
416 void clear();
417
425 //
426 // DANGER: This function assumes the parser graph is a DAG.
427 std::pair<unsigned, ordered_set<const IR::BFN::ParserState *> *> *find_largest_paths(
428 const std::map<cstring, std::set<const Clot *>> &parser_state_to_clots,
429 const IR::BFN::ParserGraph *graph, const IR::BFN::ParserState *state,
430 std::map<const IR::BFN::ParserState *,
431 std::pair<unsigned, ordered_set<const IR::BFN::ParserState *> *> *> *memo =
432 nullptr) const;
433};
434
439 const PhvInfo &phv;
440 ClotInfo &clotInfo;
441 const PragmaDoNotUseClot &pragmaDoNotUseClot;
442 Logging::FileLog *log = nullptr;
443
444 public:
445 explicit CollectClotInfo(const PhvInfo &phv, ClotInfo &clotInfo,
446 const PragmaDoNotUseClot &pragmaDoNotUseClot)
447 : phv(phv), clotInfo(clotInfo), pragmaDoNotUseClot(pragmaDoNotUseClot) {}
448
449 private:
450 Visitor::profile_t init_apply(const IR::Node *root) override;
451
453 bool preorder(const IR::BFN::Extract *extract) override;
454 bool preorder(const IR::BFN::ParserZeroInit *zero_init) override;
455
457 bool preorder(const IR::HeaderStackItemRef *hs) override;
458
460 bool preorder(const IR::BFN::EmitField *emit) override;
461
464 bool preorder(const IR::BFN::EmitChecksum *emit) override;
465
467 void postorder(const IR::BFN::Deparser *deparser) override;
468
473 void add_pseudoheader(
474 const PovBitSet pov_bits, const std::vector<const PHV::Field *> fields,
475 std::map<std::pair<const PovBitSet, const std::vector<const PHV::Field *>>,
476 const Pseudoheader *> &allocated);
477
479 bool preorder(const IR::BFN::AliasMember *alias) override {
480 add_alias_field(alias);
481 return true;
482 }
483
485 bool preorder(const IR::BFN::AliasSlice *alias) override {
486 add_alias_field(alias);
487 return true;
488 }
489
490 void add_alias_field(const IR::Expression *alias);
491
493 bool preorder(const IR::MAU::Instruction *instruction) override;
494
495 void end_apply(const IR::Node *root) override;
496};
497
498#endif /* BACKENDS_TOFINO_BF_P4C_PARDE_CLOT_CLOT_INFO_H_ */
Definition allocate_clot.h:26
Definition clot_candidate.h:31
Definition clot.h:57
static std::map< gress_t, int > tag_count
Definition clot.h:183
Definition clot_info.h:41
bool clot_covers_slice(const Clot *clot, const PHV::FieldSlice *slice) const
Definition clot_info.cpp:931
assoc::map< const PHV::FieldSlice *, Clot *, PHV::FieldSlice::Greater > * allocated_slices(const PHV::FieldSlice *slice) const
Definition clot_info.h:297
bool is_slice_below_min_offset(const PHV::FieldSlice *slice, int max_packet_bit_offset) const
Definition clot_info.cpp:420
bool is_added_by_mau(cstring h) const
Determines whether h is a header that might be added by MAU.
Definition clot_info.cpp:908
std::set< const Clot *, Clot::Less > * fully_allocated(const PHV::FieldSlice &slice) const
Definition clot_info.h:313
assoc::map< const PHV::FieldSlice *, Clot *, PHV::FieldSlice::Greater > * slice_clots(const PHV::FieldSlice *slice) const
Definition clot_info.cpp:910
const std::set< const PHV::Field * > * clot_eligible_fields() const
Produces the set of CLOT-eligible fields.
Definition clot_info.cpp:589
bool allocated_unmodified_undigested(const PHV::Field *field) const
Definition clot_info.h:327
cstring sanitize_state_name(cstring state_name, gress_t gress) const
Definition clot_info.cpp:59
const Clot * fully_allocated(const PHV::Field *field) const
Definition clot_info.h:304
bool is_modified(const PHV::Field *field) const
Definition clot_info.cpp:526
bool slice_overwritten(const PhvInfo &phvInfo, const Clot *clot, const PHV::FieldSlice *f) const
Definition clot_info.cpp:796
bool slice_overwritten_by_phv(const PhvInfo &phvInfo, const Clot *clot, const PHV::FieldSlice *f) const
Definition clot_info.cpp:801
bool is_checksum(const PHV::Field *field) const
Determines whether a field is a checksum field.
Definition clot_info.cpp:520
std::map< int, PHV::Container > get_overwrite_containers(const Clot *clot, const PhvInfo &phv) const
Definition clot_info.cpp:108
bool is_readonly(const PHV::Field *field) const
Definition clot_info.cpp:575
std::map< int, const PHV::Field * > get_csum_fields(const Clot *clot) const
Definition clot_info.cpp:159
std::set< const PHV::Field * > pov_extracted_without_fields
Definition clot_info.h:155
assoc::map< const PHV::FieldSlice *, Clot *, PHV::FieldSlice::Greater > * allocated_slices(const PHV::Field *field) const
Definition clot_info.h:282
void adjust_clots(const PhvInfo &phv)
Definition clot_info.cpp:626
Clot * whole_field_clot(const PHV::Field *field) const
Definition clot_info.cpp:925
bool is_unused(const PHV::Field *field) const
Definition clot_info.cpp:583
assoc::map< const PHV::FieldSlice *, Clot *, PHV::FieldSlice::Greater > * slice_clots(const PHV::Field *field) const
Definition clot_info.h:399
void merge_parser_states(gress_t gress, cstring dst_state_name, cstring src_state_name)
Definition clot_info.cpp:180
Holds information relating to a field slice's extract.
Definition field_slice_extract_info.h:31
Implements comparisons correctly.
Definition field_slice_set.h:25
A FileLog is used to redirect the logging output of a visitor pass to a file.
Definition filelog.h:48
Definition node.h:94
Definition visitor.h:400
Definition visitor.h:78
Definition bitvec.h:120
Definition cstring.h:85
Definition ordered_map.h:32
Definition ordered_set.h:32
Definition phv_fields.h:154
Definition phv_fields.h:898
const PHV::Field * field() const override
Definition phv_fields.h:977
Definition phv_fields.h:1095
Definition phv_parde_mau_use.h:154
do_not_use_clot pragma support.
Definition do_not_use_clot.h:37
Definition pseudoheader.h:27
Definition assoc.h:300
Definition clot_info.h:438
Definition allocate_clot.cpp:40
Definition parser_info.h:186