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