32class Phv :
public Section {
33 void start(
int lineno, VECTOR(
value_t) args)
override;
36 Phv() : Section(
"phv") {}
37 Phv(
const Phv &) =
delete;
38 Phv &operator=(
const Phv &) =
delete;
41 Target::Phv *target =
nullptr;
42 FOR_ALL_TARGETS(FRIEND_TARGET_CLASS, ::Phv)
47 enum type_t { NORMAL, TAGALONG, CHECKSUM, MOCHA, DARK } type;
50 unsigned short index = 0, uid = 0, size = 0;
51 Register() { type = NORMAL; }
52 Register(
const Register &) =
delete;
53 Register &operator=(
const Register &) =
delete;
54 Register(
const char *n, type_t t,
unsigned i,
unsigned u,
unsigned s)
55 : type(t), index(i), uid(u), size(s) {
56 strncpy(name, n,
sizeof(name));
59 bool operator==(
const Register &a)
const {
return uid == a.uid; }
60 bool operator!=(
const Register &a)
const {
return uid != a.uid; }
61 bool operator<(
const Register &a)
const {
return uid < a.uid; }
62 virtual int parser_id()
const {
return -1; }
63 virtual int mau_id()
const {
return -1; }
64 virtual int ixbar_id()
const {
return -1; }
65 virtual int deparser_id()
const {
return -1; }
90 Slice() : reg(invalid), valid(
false) {}
91 Slice(
const Register &r,
int l,
int h) : reg(r), lo(l), hi(h) {
92 valid = lo >= 0 && hi >= lo && hi < reg.size;
94 Slice(
const Register &r,
int b) : reg(r), lo(b), hi(b) {
95 valid = lo >= 0 && hi >= lo && hi < reg.size;
97 Slice(
const Slice &s,
int l,
int h) : reg(s.reg), lo(s.lo + l), hi(s.lo + h) {
98 valid = lo >= 0 && hi >= lo && hi <= s.hi && hi < reg.size;
100 Slice(
const Slice &) =
default;
101 explicit operator bool()
const {
return valid; }
102 Slice &operator=(
const Slice &a) {
103 new (
this) Slice(a.reg, a.lo, a.hi);
106 const Slice *operator->()
const {
return this; }
107 bool operator==(
const Slice &s)
const {
108 return valid && s.valid && reg.uid == s.reg.uid && lo == s.lo && hi == s.hi;
110 bool operator<(
const Slice &a)
const {
111 if (reg.uid < a.reg.uid)
return true;
112 if (reg.uid > a.reg.uid)
return false;
113 if (lo < a.lo)
return true;
114 if (lo > a.lo)
return false;
117 bool overlaps(
const Slice &a)
const {
118 return valid && a.valid && reg.uid == a.reg.uid && lo <= a.hi && a.lo <= hi;
120 unsigned size()
const {
return valid ? hi - lo + 1 : 0; }
121 std::string toString()
const;
122 void dbprint(std::ostream &out)
const;
127 std::vector<Register *> regs;
128 std::map<int, std::map<int, std::string>> phv_pov_names;
130 int max_stage = INT_MAX;
133 std::map<std::string, std::map<int, PerStageInfo>> names[3];
136 typedef std::map<int, std::set<std::string>> user_stagenames_t;
137 std::map<const Register *, std::pair<gress_t, user_stagenames_t>,
ptrless<Register>>
140 std::map<std::string, int> phv_field_sizes[3];
141 std::map<std::string, int> phv_pov_field_sizes[3];
147 void init_phv(target_t);
148 bool is_pov(std::string name) {
151 return (name.find(
".$valid") != std::string::npos ||
152 name.find(
".$deparse") != std::string::npos);
154 void gen_phv_field_size_map();
155 int addreg(gress_t gress,
const char *name,
const value_t &what,
int stage = -1,
156 int max_stage = INT_MAX);
157 int get_position_offset(gress_t gress, std::string name);
158 void add_phv_field_sizes(gress_t gress, std::string name,
int size) {
159 auto &phv_field_map = is_pov(name) ? phv_pov_field_sizes : phv_field_sizes;
160 phv_field_map[gress][name] += size;
162 int get_phv_field_size(gress_t gress, std::string name) {
163 if (phv_field_sizes[gress].count(name) > 0)
return phv_field_sizes[gress][name];
164 if (phv_pov_field_sizes[gress].count(name) > 0)
return phv_pov_field_sizes[gress][name];
169 static const Slice *get(gress_t gress,
int stage,
const std::string &name) {
170 phv.init_phv(options.target);
171 auto phvIt = phv.names[gress].find(name);
172 if (phvIt == phv.names[gress].end())
return 0;
173 auto &per_stage = phvIt->second;
174 auto it = per_stage.upper_bound(stage);
175 if (it == per_stage.begin()) {
176 if (it == per_stage.end() || stage != -1)
return 0;
180 if (stage > it->second.max_stage)
return 0;
181 return &it->second.slice;
183 static const Slice *get(gress_t gress,
int stg,
const char *name) {
184 return get(gress, stg, std::string(name));
191 int lo = -1, hi = -1;
195 Ref() : gress_(INGRESS), lineno(-1) {}
196 Ref(gress_t g,
int stage,
const value_t &n);
197 Ref(gress_t g,
int stage,
int line,
const std::string &n,
int l,
int h)
198 : gress_(g), name_(n), stage(stage), lo(l), hi(h), lineno(line) {}
199 Ref(
const Ref &r,
int l,
int h)
203 lo(r.lo < 0 ? l : r.lo + l),
204 hi(r.lo < 0 ? h : r.lo + h),
206 BUG_CHECK(r.hi < 0 || hi <= r.hi,
"Out of bounds slice: %s", r.toString().c_str());
208 Ref(
const Register &r, gress_t gr,
int lo = -1,
int hi = -1);
209 explicit operator bool()
const {
return lineno >= 0; }
210 Slice operator*()
const {
211 if (
auto *s = phv.get(gress_, stage, name_)) {
212 if (hi >= 0)
return Slice(*s, lo, hi);
215 error(lineno,
"No phv record %s (%s, stage %d)", name_.c_str(),
216 gress_ == INGRESS ?
"INGRESS" :
"EGRESS", stage);
217 phv.get(gress_, stage, name_);
221 bool operator<(
const Ref &r)
const {
222 return (**this).reg.parser_id() < (*r).reg.parser_id();
224 Slice operator->()
const {
return **
this; }
225 bool operator==(
const Ref &a)
const {
226 if (name_ == a.name_ && lo == a.lo && hi == a.hi)
return true;
229 bool check(
bool err =
true)
const {
230 if (
auto *s = phv.get(gress_, stage, name_)) {
231 if (hi >= 0 && !
Slice(*s, lo, hi).valid) {
232 error(lineno,
"Invalid slice of %s", name_.c_str());
236 }
else if (lineno >= 0 && err) {
237 error(lineno,
"No phv record %s", name_.c_str());
241 gress_t gress()
const {
return gress_; }
242 const char *name()
const override {
return name_.c_str(); }
243 std::string desc()
const;
244 int lobit()
const {
return lo < 0 ? 0 : lo; }
245 int hibit()
const {
return hi < 0 ? (**this).size() - 1 : hi; }
246 unsigned size()
const override {
247 if (lo >= 0)
return hi - lo + 1;
248 if (
auto *s = phv.get(gress_, stage, name_))
return s->size();
251 bool merge(
const Ref &r);
252 std::string toString()
const override;
253 void dbprint(std::ostream &out)
const override;
255 int get_lineno()
const override {
return lineno; }
256 int fieldlobit()
const override {
return lobit(); }
257 int fieldhibit()
const override {
return hibit(); }
258 int slicelobit()
const override {
return (**this).lo; }
259 int slicehibit()
const override {
return (**this).hi; }
262 static const Register *reg(
int idx) {
263 BUG_CHECK(idx >= 0 &&
size_t(idx) < phv.regs.size(),
"Register index out of range");
264 return phv.regs[idx];
267 static const Register *reg(std::string name) {
268 for (
auto ® : phv.regs)
269 if (reg->name == name)
return reg;
274 static int num_regs() {
return phv.regs.size(); }
277 static const std::string get_pov_name(
int reg,
int index) {
278 if (phv.phv_pov_names.count(reg) && phv.phv_pov_names.at(reg).count(index))
279 return phv.phv_pov_names[reg][index];
283 static const bitvec &use(gress_t gress) {
return phv.phv_use[gress]; }
284 static void setuse(gress_t gress,
const bitvec &u) { phv.phv_use[gress] |= u; }
285 static void unsetuse(gress_t gress,
const bitvec &u) { phv.phv_use[gress] -= u; }
286 static std::string db_regset(
const bitvec &s);
287 static unsigned mau_groupsize();
290 static const std::set<std::string> &aliases(
const Register *reg,
int stage) {
291 static std::set<std::string> empty;
292 if (!phv.user_defined.count(reg))
return empty;
293 auto &m = phv.user_defined.at(reg).second;
294 auto it = m.upper_bound(stage);
295 if (it == m.begin())
return empty;
296 return (--it)->second;
300 static void test_clear() {
301 phv.target =
nullptr;
303 phv.phv_pov_names.clear();
304 phv.names[INGRESS].clear();
305 phv.names[EGRESS].clear();
306 phv.names[GHOST].clear();