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