P4C
The P4 Compiler
Loading...
Searching...
No Matches
widereg.h
1
17
18#ifndef BACKENDS_TOFINO_BF_ASM_WIDEREG_H_
19#define BACKENDS_TOFINO_BF_ASM_WIDEREG_H_
20
21#include <limits.h>
22
23#include <functional>
24#include <iostream>
25#include <sstream>
26
27#include "lib/bitvec.h"
28#include "lib/log.h"
29
30using namespace P4;
31
32void print_regname(std::ostream &out, const void *addr, const void *end);
33
34struct widereg_base;
35
36struct widereg_base {
37 bitvec value, reset_value;
38 mutable bool read, write;
39 mutable bool disabled_;
40
41 widereg_base() : read(false), write(false), disabled_(false) {}
42 explicit widereg_base(bitvec v)
43 : value(v), reset_value(v), read(false), write(false), disabled_(false) {}
44 explicit widereg_base(uintptr_t v)
45 : value(v), reset_value(v), read(false), write(false), disabled_(false) {}
46#if __WORDSIZE == 64
47 // For 32-bit systems intptr_t is defined as int
48 explicit widereg_base(intptr_t v)
49 : value(v), reset_value(v), read(false), write(false), disabled_(false) {}
50#endif
51 explicit widereg_base(int v)
52 : value(v), reset_value(v), read(false), write(false), disabled_(false) {}
53 operator bitvec() const {
54 read = true;
55 return value;
56 }
57 bool modified() const { return write; }
58 void set_modified(bool v = true) { write = v; }
59 bool disabled() const { return disabled_; }
60 bool disable_if_unmodified() { return write ? false : (disabled_ = true); }
61 bool disable_if_zero() const { return value.empty() && !write; }
62 bool disable_if_reset_value() { return value == reset_value ? (disabled_ = true) : false; }
63 bool disable() const {
64 if (write) {
65 LOG1("ERROR: Disabling modified register in " << this);
66 return false;
67 }
68 disabled_ = true;
69 return disabled_;
70 }
71 void enable() const { disabled_ = false; }
72 void rewrite() { write = false; }
73 virtual bitvec operator=(bitvec v) = 0;
74 virtual unsigned size() = 0;
75 void log(const char *op, bitvec v) const;
76};
77
78inline static unsigned int to_unsigned(const bitvec &v) {
79 std::stringstream ss;
80 ss << v;
81 std::string str(ss.str());
82 unsigned int rv = std::strtoul(str.c_str(), 0, 16);
83 return rv;
84}
85
86inline std::ostream &operator<<(std::ostream &out, const widereg_base *u) {
87 print_regname(out, u, u + 1);
88 return out;
89}
90inline std::ostream &operator<<(std::ostream &out, const widereg_base &u) {
91 return out << to_unsigned(u.value);
92}
93
94template <int N>
95struct widereg : widereg_base {
96 widereg() : widereg_base() {}
97 const widereg &check() {
98 if (value.max().index() >= N) {
99 LOG1("ERROR: out of range for " << N << " bits in " << this);
100 value.clrrange(N, value.max().index() - N + 1);
101 }
102 return *this;
103 }
104 explicit widereg(bitvec v) : widereg_base(v) { check(); }
105 explicit widereg(uintptr_t v) : widereg_base(v) { check(); }
106#if __WORDSIZE == 64
107 // For 32-bit systems intptr_t is defined as int
108 explicit widereg(intptr_t v) : widereg_base(v) { check(); }
109#endif
110 explicit widereg(int v) : widereg_base(v) { check(); }
111 widereg(const widereg &) = delete;
112 widereg(widereg &&) = default;
113 bitvec operator=(bitvec v) {
114 if (disabled_) LOG1("ERROR: Writing disabled register value in " << this);
115 if (write) LOG1("WARNING: Overwriting " << value << " with " << v << " in " << this);
116 value = v;
117 write = true;
118 log("=", v);
119 check();
120 return v;
121 }
122 uintptr_t operator=(uintptr_t v) {
123 *this = bitvec(v);
124 return v;
125 }
126 intptr_t operator=(intptr_t v) {
127 *this = bitvec(v);
128 return v;
129 }
130 const widereg &operator=(const widereg &v) {
131 *this = v.value;
132 v.read = true;
133 return v;
134 }
135 const widereg_base &operator=(const widereg_base &v) {
136 *this = v.value;
137 v.read = true;
138 return v;
139 }
140 unsigned size() { return N; }
141 const widereg &operator|=(bitvec v) {
142 if (disabled_) LOG1("ERROR: Writing disabled register value in " << this);
143 if (write)
144 LOG1("WARNING: Overwriting " << value << " with " << (v | value) << " in " << this);
145 value |= v;
146 write = true;
147 log("|=", v);
148 return check();
149 }
150 const widereg &set_subfield(uintptr_t v, unsigned bit, unsigned size) {
151 if (disabled_) LOG1("ERROR: Writing disabled register value in " << this);
152 if (bit + size > N) {
153 LOG1("ERROR: subfield " << bit << ".." << (bit + size - 1) << " out of range in "
154 << this);
155 } else if (auto o = value.getrange(bit, size)) {
156 if (write)
157 LOG1((o != v ? "ERROR" : "WARNING")
158 << ": Overwriting subfield(" << bit << ".." << (bit + size - 1) << ") value "
159 << o << " with " << v << " in " << this);
160 }
161 if (v >= (1U << size))
162 LOG1("ERROR: Subfield value " << v << " too large for " << size << " bits in " << this);
163 value.putrange(bit, size, v);
164 write = true;
165 log("|=", bitvec(v) << bit);
166 return check();
167 }
168};
169
170#endif /* BACKENDS_TOFINO_BF_ASM_WIDEREG_H_ */
Definition bitvec.h:120
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:24
Definition widereg.h:36
void log(const char *op, bitvec v) const
Definition widereg.cpp:25