12#include "mlir/IR/AttrTypeSubElements.h"
13#include "mlir/IR/Iterators.h"
14#include "mlir/Pass/Pass.h"
16#define DEBUG_TYPE "hw-convert-bitcasts"
20#define GEN_PASS_DEF_HWCONVERTBITCASTS
21#include "circt/Dialect/HW/Passes.h.inc"
30struct HWConvertBitcastsPass
31 : circt::hw::impl::HWConvertBitcastsBase<HWConvertBitcastsPass> {
32 using circt::hw::impl::HWConvertBitcastsBase<
33 HWConvertBitcastsPass>::HWConvertBitcastsBase;
35 void runOnOperation()
override;
36 static bool isTypeSupported(Type ty);
37 LogicalResult convertBitcastOp(OpBuilder builder, BitcastOp bitcastOp);
45bool HWConvertBitcastsPass::isTypeSupported(Type ty) {
46 if (isa<IntegerType>(ty))
48 if (
auto arrayTy = hw::type_dyn_cast<hw::ArrayType>(ty))
49 return isTypeSupported(arrayTy.getElementType());
50 if (
auto structTy = hw::type_dyn_cast<hw::StructType>(ty))
51 return llvm::all_of(structTy.getElements(),
52 [](StructType::FieldInfo field) {
53 return isTypeSupported(field.type);
63 SmallVectorImpl<Value> &accumulator) {
65 if (
auto bitcast = inputVal.getDefiningOp<
BitcastOp>();
67 HWConvertBitcastsPass::isTypeSupported(bitcast.getInput().getType())) {
74 for (Value op :
concat.getInputs())
80 if (isa<IntegerType>(inputVal.getType())) {
81 accumulator.push_back(inputVal);
86 assert(numBits >= 0 &&
"Bitwidth of input must be known");
89 if (
auto arrayTy = dyn_cast<ArrayType>(inputVal.getType())) {
93 builder.getIntegerType(std::max(1u, llvm::Log2_64_Ceil(
numElements)));
97 builder, loc, builder.getIntegerAttr(indexType,
numElements - i - 1));
105 if (
auto structTy = dyn_cast<StructType>(inputVal.getType())) {
107 auto explodeOp = StructExplodeOp::create(builder, loc, inputVal);
108 for (
auto elt : explodeOp.getResults())
113 assert(
false &&
"Unsupported type");
119 ArrayRef<Value> integers,
120 size_t &idx,
size_t &bitOffset,
125 if (
auto intTy = dyn_cast<IntegerType>(targetType)) {
126 size_t remaining = intTy.getWidth();
130 SmallVector<Value> pieces;
131 while (remaining > 0) {
132 assert(idx < integers.size() &&
"Not enough bits in input");
133 Value cur = integers[idx];
134 size_t curWidth = cur.getType().getIntOrFloatBitWidth();
139 size_t take = std::min(remaining, curWidth - bitOffset);
140 if (bitOffset == 0 && take == curWidth) {
141 pieces.push_back(cur);
143 auto sliceTy = builder.getIntegerType(take);
145 curWidth - bitOffset - take));
148 if ((bitOffset += take) == curWidth) {
153 if (pieces.size() == 1)
154 return pieces.front();
155 return comb::ConcatOp::create(builder, loc, pieces);
158 SmallVector<Value> elements;
167 builder, loc, integers, idx, bitOffset, arrayTy.getElementType()));
176 auto fields = structTy.getElements();
177 elements.reserve(fields.size());
178 for (
const auto &field : fields) {
181 builder, loc, integers, idx, bitOffset, field.type));
188 assert(
false &&
"Unsupported type");
192LogicalResult HWConvertBitcastsPass::convertBitcastOp(OpBuilder builder,
193 BitcastOp bitcastOp) {
194 bool inputSupported = isTypeSupported(bitcastOp.getInput().getType());
195 bool outputSupported = isTypeSupported(bitcastOp.getType());
196 if (!allowPartialConversion) {
198 bitcastOp.emitOpError(
"has unsupported input type");
199 if (!outputSupported)
200 bitcastOp.emitOpError(
"has unsupported output type");
202 if (!(inputSupported && outputSupported))
205 builder.setInsertionPoint(bitcastOp);
208 SmallVector<Value> integers;
213 size_t idx = 0, bitOffset = 0;
216 bitOffset, bitcastOp.getType());
219 bitcastOp.getResult().replaceAllUsesWith(result);
224void HWConvertBitcastsPass::runOnOperation() {
225 OpBuilder builder(getOperation());
226 bool anyFailed =
false;
227 bool anyChanged =
false;
228 getOperation().getBody()->walk<WalkOrder::PostOrder, ReverseIterator>(
229 [&](BitcastOp bitcastOp) {
231 if (failed(convertBitcastOp(builder, bitcastOp)))
236 markAllAnalysesPreserved();
240 if (anyFailed && !allowPartialConversion)
assert(baseType &&"element must be base type")
MlirType uint64_t numElements
static SmallVector< T > concat(const SmallVectorImpl< T > &a, const SmallVectorImpl< T > &b)
Returns a new vector containing the concatenation of vectors a and b.
static void collectIntegersRecursively(OpBuilder builder, Location loc, Value inputVal, SmallVectorImpl< Value > &accumulator)
static Value constructAggregateRecursively(OpBuilder builder, Location loc, ArrayRef< Value > integers, size_t &idx, size_t &bitOffset, Type targetType)
false return failure()
Parse an optional keyword or string and set instance into 'result'.
create(elements, Type result_type=None)
create(elements, Type result_type=None)
BaseTy type_dyn_cast(Type type)
int64_t getBitWidth(mlir::Type type)
Return the hardware bit width of a type.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.