Loading [MathJax]/jax/output/HTML-CSS/config.js
CIRCT 21.0.0git
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
DeseqUtils.h
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10#include "circt/Support/LLVM.h"
11#include "mlir/IR/Value.h"
12#include "llvm/ADT/APInt.h"
13#include "llvm/ADT/SmallVector.h"
14#include "llvm/Support/raw_ostream.h"
15
16namespace circt {
17namespace llhd {
18namespace deseq {
19
20//===----------------------------------------------------------------------===//
21// Disjunctive Normal Form
22//===----------------------------------------------------------------------===//
23
24/// A single AND operation within a DNF.
25struct DNFTerm {
26 /// A mask with two bits for each possible term that may be present. Even bits
27 /// indicate a term is present, odd bits indicate a term's negation is
28 /// present.
29 uint32_t andTerms = 0;
30
31 bool isTrue() const { return andTerms == 0; }
32 bool isFalse() const {
33 // If any term has both the even and odd bits set, the term is false.
34 return (andTerms & 0x55555555UL) & (andTerms >> 1);
35 }
36
37 bool operator==(DNFTerm other) const { return andTerms == other.andTerms; }
38 bool operator!=(DNFTerm other) const { return !(*this == other); }
39};
40
41/// A boolean function expressed in canonical disjunctive normal form. Supports
42/// functions with up to 32 terms. Consists of AND operations nested inside an
43/// OR operation.
44struct DNF {
45 SmallVector<DNFTerm, 2> orTerms;
46 bool isPoison() const { return orTerms.size() == 1 && orTerms[0].isFalse(); }
47 bool isTrue() const { return orTerms.size() == 1 && orTerms[0].isTrue(); }
48 bool isFalse() const { return orTerms.empty(); }
49};
50
51llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const DNFTerm &term);
52llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const DNF &dnf);
53
54//===----------------------------------------------------------------------===//
55// Truth Table
56//===----------------------------------------------------------------------===//
57
58/// A boolean function expressed as a truth table. The first term is treated as
59/// a special "unknown" value marker with special semantics. Truth tables have
60/// exponential memory requirements. They are only useful to track a small
61/// number of terms, say up to 16, which already requires 64 kB of memory.
62struct TruthTable {
63 /// The value of the boolean function for each possible combination of input
64 /// term assignments. If the boolean function has N input terms, this `APInt`
65 /// lists all `2**N` possible combinations. The special "poison" value is
66 /// represented as a zero-width `bits`.
67 APInt bits;
68
69 /// Get the number of terms in the truth table. Since the width of `bits`
70 /// corresponds to `2**numInputs`, we count the number of trailing zeros in
71 /// the width of `bits` to determine `numInputs`.
72 unsigned getNumTerms() const {
73 if (isPoison())
74 return 0;
75 return llvm::countr_zero(bits.getBitWidth());
76 }
77
78 static TruthTable getPoison() { return TruthTable{APInt::getZero(0)}; }
79 bool isPoison() const { return bits.getBitWidth() == 0; }
80 bool isTrue() const { return bits.isAllOnes(); }
81 bool isFalse() const { return bits.isZero(); }
82
83 /// Create a boolean expression with a constant true or false value.
84 static TruthTable getConst(unsigned numTerms, bool value) {
85 assert(numTerms <= 16 && "excessive truth table");
86 return TruthTable{value ? APInt::getAllOnes(1 << numTerms)
87 : APInt::getZero(1 << numTerms)};
88 }
89
90 /// Create a boolean expression consisting of a single term.
91 static TruthTable getTerm(unsigned numTerms, unsigned term) {
92 assert(numTerms <= 16 && "excessive truth table");
93 assert(term < numTerms);
94 return TruthTable{getTermMask(1 << numTerms, term)};
95 }
96
97 // Boolean operations.
98 TruthTable operator~() const;
99 TruthTable operator&(const TruthTable &other) const;
100 TruthTable operator|(const TruthTable &other) const;
101 TruthTable operator^(const TruthTable &other) const;
102
104 TruthTable &operator&=(const TruthTable &other);
105 TruthTable &operator|=(const TruthTable &other);
106 TruthTable &operator^=(const TruthTable &other);
107
108 bool operator==(const TruthTable &other) const { return bits == other.bits; }
109 bool operator!=(const TruthTable &other) const { return !(*this == other); }
110
111 /// Convert the truth table into its canonical disjunctive normal form.
112 DNF canonicalize() const;
113
114private:
115 /// Return a mask that has a 1 in all truth table rows where `term` is 1,
116 /// and a 0 otherwise. This is equivalent to the truth table of a boolean
117 /// expression consisting of a single term.
118 static APInt getTermMask(unsigned bitWidth, unsigned term) {
119 return APInt::getSplat(bitWidth,
120 APInt::getHighBitsSet(2 << term, 1 << term));
121 }
122 APInt getTermMask(unsigned term) const {
123 return getTermMask(bits.getBitWidth(), term);
124 }
125
126 // Adjust any `!x` terms to be `x` terms.
127 void fixupUnknown();
128};
129
130llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const TruthTable &table);
131
132//===----------------------------------------------------------------------===//
133// Value Table
134//===----------------------------------------------------------------------===//
135
136/// A single entry in a value table. Tracks the condition under which a value
137/// appears. Can be set to a special "poison" and "unknown" marker.
139 Value value;
140
141 ValueEntry() = default;
143
144 bool isPoison() const { return *this == getPoison(); }
145 bool isUnknown() const { return *this == getUnknown(); }
147 return Value::getFromOpaquePointer((void *)(1));
148 }
149 static ValueEntry getUnknown() { return Value(); }
150
151 void merge(ValueEntry other);
152
153 bool operator==(ValueEntry other) const { return value == other.value; }
154 bool operator!=(ValueEntry other) const { return value != other.value; }
155};
156
157/// A table of SSA values and the conditions under which they appear. This
158/// struct can be used to track the various concrete values an SSA value may
159/// assume depending on how control flow reaches it.
161 SmallVector<std::pair<TruthTable, ValueEntry>, 1> entries;
162
163 ValueTable() = default;
165 : entries({{condition, entry}}) {}
166
167 void addCondition(TruthTable condition);
168 void merge(const ValueTable &other);
169 void minimize();
170};
171
172llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const ValueEntry &entry);
173llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
174 const std::pair<TruthTable, ValueEntry> &pair);
175llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const ValueTable &table);
176
177//===----------------------------------------------------------------------===//
178// Clock and Reset Analysis
179//===----------------------------------------------------------------------===//
180
181/// A single reset extracted from a process during trigger analysis.
182struct ResetInfo {
183 /// The value acting as the reset, causing the register to be set to `value`
184 /// when triggered.
185 Value reset;
186 /// The value the register is reset to.
187 Value value;
188 /// Whether the reset is active when high.
190
191 /// Check if this reset info is null.
192 operator bool() const { return bool(reset); }
193};
194
195/// A single clock extracted from a process during trigger analysis.
196struct ClockInfo {
197 /// The value acting as the clock, causing the register to be set to a value
198 /// in `valueTable` when triggered.
199 Value clock;
200 /// The value the register is set to when the clock is triggered.
201 Value value;
202 /// Whether the clock is sensitive to a rising or falling edge.
204 /// The optional value acting as an enable.
205 Value enable;
206
207 /// Check if this clock info is null.
208 operator bool() const { return bool(clock); }
209};
210
211/// A drive op and the clock and reset that resulted from trigger analysis. A
212/// process may describe multiple clock and reset triggers, but since the
213/// registers we lower to only allow a single clock and a single reset, this
214/// struct tracks a single clock and reset, respectively. Processes describing
215/// multiple clocks or resets are skipped.
216struct DriveInfo {
217 /// The drive operation.
218 DrvOp op;
219 /// The clock that triggers a change to the driven value. Guaranteed to be
220 /// non-null.
222 /// The optional reset that triggers a change of the driven value to a fixed
223 /// reset value. Null if no reset was detected.
225
227 explicit DriveInfo(DrvOp op) : op(op) {}
228};
229
230//===----------------------------------------------------------------------===//
231// Value Assignments for Process Specialization
232//===----------------------------------------------------------------------===//
233
234/// A single `i1` value that is fixed to a given value in the past and the
235/// present.
237 /// The IR value being fixed.
238 Value value;
239 /// The assigned value in the past, as transported into the presented via a
240 /// destination operand of a process' wait op.
241 bool past;
242 /// The assigned value in the present.
244
245 bool operator==(const FixedValue &other) const {
246 return value == other.value && past == other.past &&
247 present == other.present;
248 }
249
250 operator bool() const { return bool(value); }
251};
252
253/// A list of `i1` values that are fixed to a given value. These are used when
254/// specializing a process to compute the value and enable condition for a drive
255/// when a trigger occurs.
256using FixedValues = SmallVector<FixedValue, 2>;
257
258static inline llvm::hash_code hash_value(const FixedValue &arg) {
259 return llvm::hash_combine(arg.value, arg.past, arg.present);
260}
261
262static inline llvm::hash_code hash_value(const FixedValues &arg) {
263 return llvm::hash_combine_range(arg.begin(), arg.end());
264}
265
266} // namespace deseq
267} // namespace llhd
268} // namespace circt
269
270namespace llvm {
271
272// Allow `FixedValue` to be used as hash map key.
273template <>
274struct DenseMapInfo<circt::llhd::deseq::FixedValue> {
275 using Value = mlir::Value;
277 static inline FixedValue getEmptyKey() {
278 return FixedValue{DenseMapInfo<Value>::getEmptyKey(), false, false};
279 }
280 static inline FixedValue getTombstoneKey() {
281 return FixedValue{DenseMapInfo<Value>::getTombstoneKey(), false, false};
282 }
283 static unsigned getHashValue(const FixedValue &key) {
284 return hash_value(key);
285 }
286 static bool isEqual(const FixedValue &a, const FixedValue &b) {
287 return a == b;
288 }
289};
290
291// Allow `FixedValues` to be used as hash map key.
292template <>
293struct DenseMapInfo<circt::llhd::deseq::FixedValues> {
296 static inline FixedValues getEmptyKey() {
298 }
302 static unsigned getHashValue(const FixedValues &key) {
303 return hash_value(key);
304 }
305 static bool isEqual(const FixedValues &a, const FixedValues &b) {
306 return a == b;
307 }
308};
309
310} // namespace llvm
assert(baseType &&"element must be base type")
llvm::raw_ostream & operator<<(llvm::raw_ostream &os, const DNFTerm &term)
SmallVector< FixedValue, 2 > FixedValues
A list of i1 values that are fixed to a given value.
Definition DeseqUtils.h:256
static llvm::hash_code hash_value(const FixedValue &arg)
Definition DeseqUtils.h:258
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
A single clock extracted from a process during trigger analysis.
Definition DeseqUtils.h:196
Value clock
The value acting as the clock, causing the register to be set to a value in valueTable when triggered...
Definition DeseqUtils.h:199
bool risingEdge
Whether the clock is sensitive to a rising or falling edge.
Definition DeseqUtils.h:203
Value value
The value the register is set to when the clock is triggered.
Definition DeseqUtils.h:201
Value enable
The optional value acting as an enable.
Definition DeseqUtils.h:205
A single AND operation within a DNF.
Definition DeseqUtils.h:25
uint32_t andTerms
A mask with two bits for each possible term that may be present.
Definition DeseqUtils.h:29
bool operator==(DNFTerm other) const
Definition DeseqUtils.h:37
bool operator!=(DNFTerm other) const
Definition DeseqUtils.h:38
A boolean function expressed in canonical disjunctive normal form.
Definition DeseqUtils.h:44
bool isPoison() const
Definition DeseqUtils.h:46
SmallVector< DNFTerm, 2 > orTerms
Definition DeseqUtils.h:45
A drive op and the clock and reset that resulted from trigger analysis.
Definition DeseqUtils.h:216
ClockInfo clock
The clock that triggers a change to the driven value.
Definition DeseqUtils.h:221
DrvOp op
The drive operation.
Definition DeseqUtils.h:218
ResetInfo reset
The optional reset that triggers a change of the driven value to a fixed reset value.
Definition DeseqUtils.h:224
A single i1 value that is fixed to a given value in the past and the present.
Definition DeseqUtils.h:236
bool present
The assigned value in the present.
Definition DeseqUtils.h:243
bool past
The assigned value in the past, as transported into the presented via a destination operand of a proc...
Definition DeseqUtils.h:241
bool operator==(const FixedValue &other) const
Definition DeseqUtils.h:245
Value value
The IR value being fixed.
Definition DeseqUtils.h:238
A single reset extracted from a process during trigger analysis.
Definition DeseqUtils.h:182
Value value
The value the register is reset to.
Definition DeseqUtils.h:187
Value reset
The value acting as the reset, causing the register to be set to value when triggered.
Definition DeseqUtils.h:185
bool activeHigh
Whether the reset is active when high.
Definition DeseqUtils.h:189
A boolean function expressed as a truth table.
Definition DeseqUtils.h:62
static APInt getTermMask(unsigned bitWidth, unsigned term)
Return a mask that has a 1 in all truth table rows where term is 1, and a 0 otherwise.
Definition DeseqUtils.h:118
bool operator!=(const TruthTable &other) const
Definition DeseqUtils.h:109
DNF canonicalize() const
Convert the truth table into its canonical disjunctive normal form.
static TruthTable getTerm(unsigned numTerms, unsigned term)
Create a boolean expression consisting of a single term.
Definition DeseqUtils.h:91
static TruthTable getPoison()
Definition DeseqUtils.h:78
bool operator==(const TruthTable &other) const
Definition DeseqUtils.h:108
APInt bits
The value of the boolean function for each possible combination of input term assignments.
Definition DeseqUtils.h:67
TruthTable operator~() const
APInt getTermMask(unsigned term) const
Definition DeseqUtils.h:122
unsigned getNumTerms() const
Get the number of terms in the truth table.
Definition DeseqUtils.h:72
TruthTable operator&(const TruthTable &other) const
TruthTable operator^(const TruthTable &other) const
static TruthTable getConst(unsigned numTerms, bool value)
Create a boolean expression with a constant true or false value.
Definition DeseqUtils.h:84
TruthTable operator|(const TruthTable &other) const
TruthTable & operator|=(const TruthTable &other)
TruthTable & operator&=(const TruthTable &other)
TruthTable & operator^=(const TruthTable &other)
A single entry in a value table.
Definition DeseqUtils.h:138
static ValueEntry getUnknown()
Definition DeseqUtils.h:149
bool operator!=(ValueEntry other) const
Definition DeseqUtils.h:154
static ValueEntry getPoison()
Definition DeseqUtils.h:146
void merge(ValueEntry other)
bool operator==(ValueEntry other) const
Definition DeseqUtils.h:153
A table of SSA values and the conditions under which they appear.
Definition DeseqUtils.h:160
SmallVector< std::pair< TruthTable, ValueEntry >, 1 > entries
Definition DeseqUtils.h:161
void addCondition(TruthTable condition)
ValueTable(TruthTable condition, ValueEntry entry)
Definition DeseqUtils.h:164
void merge(const ValueTable &other)
static bool isEqual(const FixedValue &a, const FixedValue &b)
Definition DeseqUtils.h:286
static unsigned getHashValue(const FixedValue &key)
Definition DeseqUtils.h:283
static unsigned getHashValue(const FixedValues &key)
Definition DeseqUtils.h:302
static bool isEqual(const FixedValues &a, const FixedValues &b)
Definition DeseqUtils.h:305