P4C
The P4 Compiler
Loading...
Searching...
No Matches
bf-p4c/specs/phv.h
1
18
19#ifndef BACKENDS_TOFINO_BF_P4C_SPECS_PHV_H_
20#define BACKENDS_TOFINO_BF_P4C_SPECS_PHV_H_
21
22#include <iosfwd>
23#include <limits>
24
25#include <boost/functional/hash.hpp>
26
27#include "lib/bitvec.h"
28#include "lib/cstring.h"
29#include "lib/exceptions.h"
30#include "lib/ordered_set.h"
31
32using namespace P4;
33using namespace P4::literals;
34
35namespace PHV {
36
39enum class Kind : unsigned short { tagalong = 0, dark = 1, mocha = 2, normal = 3 };
40
41const Kind KINDS[] = {Kind::tagalong, Kind::dark, Kind::mocha, Kind::normal};
42
43const std::map<Kind, cstring> STR_OF_KIND = {{Kind::tagalong, "tagalong"_cs},
44 {Kind::dark, "dark"_cs},
45 {Kind::mocha, "mocha"_cs},
46 {Kind::normal, "normal"_cs}};
47
48// all possible contexts a PHV container can participate in
49enum class Context : unsigned short {
50 parde = 0,
51 ixbar = 1,
52 vliw = 2,
53 vliw_set = 3 // Whole container move only
54};
55
56inline std::vector<Context> all_contexts(Kind kind) {
57 switch (kind) {
58 case PHV::Kind::normal:
59 return {Context::parde, Context::ixbar, Context::vliw, Context::vliw_set};
60
61 case PHV::Kind::tagalong:
62 return {Context::parde};
63
64 case PHV::Kind::mocha:
65 return {Context::parde, Context::ixbar, Context::vliw_set}; // move only
66
67 case PHV::Kind::dark:
68 return {Context::vliw_set}; // move only
69
70 default:
71 BUG("Unknown PHV container kind");
72 }
73}
74
80// TODO: This was previously a partial order. Turned into a total order so that things behave
81// properly when Kind is used as a key in std::map or an element in std::set. It's hard to search
82// for all the places where this operator is used, so I'm not confident that this won't break
83// anything.
84//
85// Previous ordering: normal > mocha > dark, mocha > tagalong. Deep had a comment that dark and
86// tagalong don't occur together, so an ordering between them didn't need to be established, but
87// the same could be said for tagalong and mocha.
88//
89// Current ordering: normal > mocha > dark > tagalong.
90inline bool operator<(Kind left, Kind right) {
91 // Unfortunately, using the all_contexts map to define this inequality causes a massive slowdown
92 // (>2x) in compilation times.
93 // TODO: Figure out a way to use the all_contexts map to define this inequality.
94
95 return (size_t)left < (size_t)right;
96}
97
98inline bool operator<=(Kind left, Kind right) { return left == right || left < right; }
99
100inline bool operator>(Kind left, Kind right) { return right < left; }
101
102inline bool operator>=(Kind left, Kind right) { return left == right || left > right; }
103
105enum class Size : unsigned short { null = 0, b8 = 8, b16 = 16, b32 = 32 };
106
107const Size SIZES[] = {Size::null, Size::b8, Size::b16, Size::b32};
108
109class Type {
110 Kind kind_;
111 Size size_;
112
113 public:
114 enum TypeEnum { // all possible PHV container types in BFN devices
115 B, // 8-b normal
116 H, // 16-b |
117 W, // 32-b _|
118 TB, // 8-b tagalong
119 TH, // 16-b |
120 TW, // 32-b _|
121 MB, // 8-b mocha
122 MH, // 16-b |
123 MW, // 32-b _|
124 DB, // 8-b dark
125 DH, // 16-b |
126 DW // 32-b _|
127 };
128
129 Type() : kind_(Kind::normal), size_(Size::null) {}
130 Type(Kind k, Size s) : kind_(k), size_(s) {}
131 Type(const Type &t) : kind_(t.kind_), size_(t.size_) {}
132
133 Type(TypeEnum te); // NOLINT(runtime/explicit)
134 Type(const char *name, bool abort_if_invalid = true); // NOLINT(runtime/explicit)
135
136 unsigned log2sz() const;
137 Kind kind() const { return kind_; }
138 Size size() const { return size_; }
139
140 Type &operator=(const Type &t) {
141 kind_ = t.kind_;
142 size_ = t.size_;
143 return *this;
144 }
145
146 bool operator==(Type c) const { return (kind_ == c.kind_) && (size_ == c.size_); }
147
148 bool operator!=(Type c) const { return !(*this == c); }
149
150 bool operator<(Type c) const {
151 if (kind_ < c.kind_) return true;
152 if (c.kind_ < kind_) return false;
153 if (size_ < c.size_) return true;
154 if (size_ > c.size_) return false;
155 return false;
156 }
157
158 friend size_t hash_value(const Type &c) {
159 size_t h = 0;
160 boost::hash_combine(h, c.kind_);
161 boost::hash_combine(h, c.size_);
162 return h;
163 }
164
165 bool valid() const { return size_ != Size::null; }
166
168 cstring toString() const;
169};
170
171class Container {
172 protected:
173 static constexpr unsigned MAX_INDEX = std::numeric_limits<unsigned>::max();
174
175 Type type_;
176 unsigned index_;
177
178 Container(Kind k, Size s, unsigned i) : type_(k, s), index_(i) {}
179
180 public:
183 Container() : type_(), index_(0) {}
184
186 Container(const char *name, bool abort_if_invalid = true); // NOLINT(runtime/explicit)
187
190 Container(PHV::Type t, unsigned index) : type_(t), index_(index) {}
191
192 size_t size() const { return size_t(type_.size()); }
193 unsigned log2sz() const { return type_.log2sz(); }
194 size_t msb() const { return size() - 1; }
195 size_t lsb() const { return 0; }
196
197 PHV::Type type() const { return type_; }
198 unsigned index() const { return index_; }
199
200 bool is(PHV::Kind k) const { return k == type_.kind(); }
201 bool is(PHV::Size sz) const { return sz == type_.size(); }
202
205 explicit operator bool() const { return type_.valid(); }
206
207 Container operator++() {
208 if (index_ != MAX_INDEX) ++index_;
209 return *this;
210 }
211 Container operator++(int) {
212 Container rv = *this;
213 ++*this;
214 return rv;
215 }
216 bool operator==(Container c) const { return type_ == c.type_ && index_ == c.index_; }
217 bool operator!=(Container c) const { return !(*this == c); }
218 bool operator<(Container c) const {
219 if (type_ < c.type_) return true;
220 if (c.type_ < type_) return false;
221 if (index_ < c.index_) return true;
222 if (c.index_ < index_) return false;
223 return false;
224 }
225
226 friend size_t hash_value(const Container &c) {
227 size_t h = 0;
228 boost::hash_combine(h, c.type_);
229 boost::hash_combine(h, c.index_);
230 return h;
231 }
232
234 cstring toString() const;
235};
236
240class FieldUse {
241 unsigned use_;
242
243 public:
244 enum use_t { READ = 1, WRITE = 2, READWRITE = READ | WRITE, LIVE = 4 };
245
246 // Construct an empty use, which is neither read, write, or live.
247 FieldUse() : use_(0) {}
248
249 // Construct a FieldUse object, given a specific kind of use.
250 explicit FieldUse(unsigned u) {
251 BUG_CHECK(u == READ || u == WRITE || u == READWRITE || u == LIVE,
252 "Invalid value %1% used to create a FieldUse object. Valid values are "
253 "1: READ, 2: WRITE, 3: READWRITE, 4: LIVE",
254 u);
255 use_ = u;
256 }
257
258 bool isRead() const { return use_ & READ; }
259 bool isOnlyReadAndNotLive() const { return use_ == READ; }
260 bool isOnlyWriteAndNotLive() const { return use_ == WRITE; }
261 bool isWrite() const { return use_ & WRITE; }
262 bool isLive() const { return use_ & LIVE; }
263 bool isReadWrite() const { return use_ & READWRITE; }
264 bool isReadAndWrite() const { return use_ == READWRITE; }
265
266 bool operator==(FieldUse u) const { return use_ == u.use_; }
267 bool operator!=(FieldUse u) const { return !(*this == u); }
268 bool operator<(FieldUse u) const { return use_ < u.use_; }
269 bool operator>(FieldUse u) const { return use_ > u.use_; }
270 bool operator<=(FieldUse u) const { return use_ <= u.use_; }
271 bool operator>=(FieldUse u) const { return use_ >= u.use_; }
272 explicit operator bool() const { return use_ == 0; }
273
274 FieldUse operator|(const FieldUse &u) const {
275 FieldUse ru;
276 ru.use_ = use_ | u.use_;
277 BUG_CHECK(ru.use_ <= (READWRITE | LIVE), "invalid use of FieldUse %1%", ru.use_);
278 return ru;
279 }
280
281 FieldUse &operator|=(const FieldUse &u) {
282 use_ |= u.use_;
283 BUG_CHECK(use_ <= (READWRITE | LIVE), "invalid use of FieldUse%1%", use_);
284 return *this;
285 }
286
287 FieldUse operator&(const FieldUse &u) const {
288 FieldUse ru;
289 ru.use_ = use_ & u.use_;
290 BUG_CHECK(ru.use_ <= (READWRITE | LIVE), "invalid use of FieldUse%1%", ru.use_);
291 return ru;
292 }
293
294 cstring toString(unsigned dark = 0) const;
295};
296
297// Pair of stage number and type of access for the field.
298using StageAndAccess = std::pair<int, FieldUse>;
299
300// Pair of two accesses.
301struct LiveRange {
302 StageAndAccess start;
303 StageAndAccess end;
304 LiveRange(const StageAndAccess &start, const StageAndAccess &end) : start(start), end(end) {}
305 bool is_disjoint(const LiveRange &other) const;
306 // extend live range to include @p access.
307 void extend(const StageAndAccess &access);
308 bool operator<(const LiveRange &other) const {
309 if (start.first != other.start.first)
310 return start.first < other.start.first;
311 else
312 return end.first < other.end.first;
313 }
314 bool operator==(const LiveRange &other) const {
315 return start == other.start && end == other.end;
316 }
317};
318
319std::ostream &operator<<(std::ostream &out, const PHV::Kind k);
320std::ostream &operator<<(std::ostream &out, const PHV::Size sz);
321std::ostream &operator<<(std::ostream &out, const PHV::Type t);
322std::ostream &operator<<(std::ostream &out, const PHV::Container c);
323std::ostream &operator<<(std::ostream &out, ordered_set<const PHV::Container *> &c_set);
324std::ostream &operator<<(std::ostream &out, const PHV::FieldUse u);
325std::ostream &operator<<(std::ostream &out, const StageAndAccess &s);
326std::ostream &operator<<(std::ostream &out, const LiveRange &s);
327
328} // namespace PHV
329
330#endif /* BACKENDS_TOFINO_BF_P4C_SPECS_PHV_H_ */
Definition cstring.h:85
Definition ordered_set.h:32
Definition bf-p4c/specs/phv.h:171
Container()
Definition bf-p4c/specs/phv.h:183
Container(PHV::Type t, unsigned index)
Definition bf-p4c/specs/phv.h:190
cstring toString() const
Definition bf-p4c/specs/phv.cpp:154
Definition bf-p4c/specs/phv.h:240
Definition bf-p4c/specs/phv.h:109
cstring toString() const
Definition bf-p4c/specs/phv.cpp:135
Definition cstring.h:80
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:24
The namespace encapsulating PHV-related stuff.
Definition bf-p4c/mau/gateway.h:32
Size
all possible PHV container sizes in BFN devices
Definition bf-p4c/specs/phv.h:105
Kind
Definition bf-p4c/specs/phv.h:39
Definition bf-p4c/specs/phv.h:301