12 #include "mlir/IR/Builders.h"
13 #include "mlir/IR/DialectImplementation.h"
14 #include "llvm/ADT/TypeSwitch.h"
15 #include "llvm/Support/Format.h"
17 using namespace circt;
39 return (value.getBitWidth() == key.getBitWidth() && value == key);
58 APInt BitVectorAttr::getValue()
const {
return getImpl()->value; }
61 function_ref<InFlightDiagnostic()> emitError,
63 if (value.getBitWidth() < 1)
64 return emitError() <<
"bit-width must be at least 1, but got "
65 << value.getBitWidth();
69 std::string BitVectorAttr::getValueAsString(
bool prefix)
const {
70 unsigned width = getValue().getBitWidth();
71 SmallVector<char> toPrint;
72 StringRef pref = prefix ?
"#" :
"";
74 getValue().toString(toPrint, 16,
false,
false,
false);
77 SmallVector<char> leadingZeros(
width / 4 - toPrint.size(),
'0');
78 return (pref +
"x" + Twine(leadingZeros) + toPrint).str();
81 getValue().toString(toPrint, 2,
false,
false,
false);
83 SmallVector<char> leadingZeros(
width - toPrint.size(),
'0');
84 return (pref +
"b" + Twine(leadingZeros) + toPrint).str();
88 static FailureOr<APInt>
92 return emitError() <<
"expected '#'";
95 return emitError() <<
"expected at least one digit";
98 return APInt(value.size() - 2, std::string(value.begin() + 2, value.end()),
102 return APInt((value.size() - 2) * 4,
103 std::string(value.begin() + 2, value.end()), 16);
105 return emitError() <<
"expected either 'b' or 'x'";
111 assert(succeeded(maybeValue) &&
"string must have SMT-LIB format");
116 BitVectorAttr::getChecked(function_ref<InFlightDiagnostic()> emitError,
117 MLIRContext *context, StringRef value) {
119 if (failed(maybeValue))
122 return Base::getChecked(emitError, context, *maybeValue);
131 BitVectorAttr::getChecked(function_ref<InFlightDiagnostic()> emitError,
132 MLIRContext *context, uint64_t value,
134 if (width < 64 && value >= (UINT64_C(1) <<
width)) {
135 emitError() <<
"value does not fit in a bit-vector of desired width";
138 return Base::getChecked(emitError, context, APInt(
width, value));
141 Attribute BitVectorAttr::parse(AsmParser &odsParser, Type odsType) {
142 llvm::SMLoc loc = odsParser.getCurrentLocation();
145 if (odsParser.parseLess() || odsParser.parseInteger(val) ||
146 odsParser.parseGreater())
150 if (!odsType || !llvm::isa<BitVectorType>(odsType)) {
151 odsParser.emitError(loc) <<
"explicit bit-vector type required";
155 unsigned width = llvm::cast<BitVectorType>(odsType).getWidth();
157 if (
width > val.getBitWidth()) {
161 val = val.sext(
width);
162 }
else if (
width < val.getBitWidth()) {
165 unsigned neededBits =
166 val.isNegative() ? val.getSignificantBits() : val.getActiveBits();
167 if (
width < neededBits) {
168 odsParser.emitError(loc)
169 <<
"integer value out of range for given bit-vector type " << odsType;
172 val = val.trunc(
width);
178 void BitVectorAttr::print(AsmPrinter &odsPrinter)
const {
182 odsPrinter <<
"<" << getValue() <<
">";
185 Type BitVectorAttr::getType()
const {
193 #define GET_ATTRDEF_CLASSES
194 #include "circt/Dialect/SMT/SMTAttributes.cpp.inc"
196 void SMTDialect::registerAttributes() {
198 #define GET_ATTRDEF_LIST
199 #include "circt/Dialect/SMT/SMTAttributes.cpp.inc"
assert(baseType &&"element must be base type")
static FailureOr< APInt > parseBitVectorString(function_ref< InFlightDiagnostic()> emitError, StringRef value)
Parse an SMT-LIB formatted bit-vector string.
static LogicalResult verify(Value clock, bool eventExists, mlir::Location loc)
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
llvm::hash_code hash_value(const BundledChannel channel)
std::optional< int64_t > getBitWidth(FIRRTLBaseType type, bool ignoreFlip=false)
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
static llvm::hash_code hashKey(const KeyTy &key)
bool operator==(const KeyTy &key) const
static BitVectorAttrStorage * construct(mlir::AttributeStorageAllocator &allocator, KeyTy &&key)
BitVectorAttrStorage(APInt value)