14 #include "../PassDetail.h"
21 #include "mlir/IR/BuiltinTypes.h"
22 #include "mlir/Pass/Pass.h"
23 #include "mlir/Transforms/DialectConversion.h"
25 using namespace circt;
39 using OpConversionPattern::OpConversionPattern;
42 matchAndRewrite(HWModuleOp module, OpAdaptor adaptor,
43 ConversionPatternRewriter &rewriter)
const override {
45 unsigned numInputs = module.getNumInputPorts();
46 auto moduleInputs = module.getInputTypes();
47 auto moduleOutputs = module.getOutputTypes();
51 SmallVector<Type, 4> entityTypes;
52 entityTypes.append(moduleInputs.begin(), moduleInputs.end());
53 entityTypes.append(moduleOutputs.begin(), moduleOutputs.end());
57 if (!llvm::all_of(entityTypes,
58 [](Type type) {
return type.isa<SigType>(); }))
59 return rewriter.notifyMatchFailure(module,
"Not all ports had SigType");
63 auto entityType = rewriter.getFunctionType(entityTypes, {});
64 auto entity = rewriter.create<EntityOp>(module.getLoc(), entityType,
65 numInputs, ArrayAttr(),
69 Region &entityBodyRegion = entity.getBodyRegion();
70 rewriter.inlineRegionBefore(module.getBodyRegion(), entityBodyRegion,
71 entityBodyRegion.end());
75 rewriter.updateRootInPlace(entity, [&] {
76 entity.setName(module.getName());
77 entityBodyRegion.addArguments(
78 moduleOutputs, SmallVector<Location, 4>(moduleOutputs.size(),
79 rewriter.getUnknownLoc()));
83 rewriter.eraseOp(module);
91 using OpConversionPattern::OpConversionPattern;
94 matchAndRewrite(hw::OutputOp output, OpAdaptor adaptor,
95 ConversionPatternRewriter &rewriter)
const override {
97 auto entity = output->getParentOfType<EntityOp>();
99 return rewriter.notifyMatchFailure(output,
"parent was not an EntityOp");
100 size_t numInputs = entity.getIns();
104 for (
size_t i = 0, e = adaptor.getOperands().size(); i != e; ++i) {
106 auto src = adaptor.getOperands()[i];
107 auto dest = entity.getArgument(numInputs + i);
109 return rewriter.notifyMatchFailure(
110 output,
"output operand must map to result block arg");
113 if (
auto prb = src.getDefiningOp<PrbOp>())
114 src = prb.getSignal();
121 if (
auto sigTy = src.getType().dyn_cast<SigType>()) {
122 rewriter.create<llhd::ConnectOp>(output.getLoc(), dest, src);
128 delta = rewriter.create<ConstantTimeOp>(output.getLoc(), 0,
"ns", 1, 0);
130 rewriter.create<DrvOp>(output.getLoc(), dest, src, delta, Value());
134 rewriter.eraseOp(output);
144 using OpConversionPattern::OpConversionPattern;
147 matchAndRewrite(InstanceOp instance, OpAdaptor adaptor,
148 ConversionPatternRewriter &rewriter)
const override {
152 SmallVector<Value, 4> arguments;
154 for (
auto arg : adaptor.getOperands()) {
156 auto argType = arg.getType();
157 if (argType.isa<SigType>()) {
158 arguments.push_back(arg);
163 if (
auto prb = arg.getDefiningOp<PrbOp>()) {
164 arguments.push_back(prb.getSignal());
176 if (!argType.isa<IntegerType>())
177 return rewriter.notifyMatchFailure(instance, [&](Diagnostic &diag) {
178 diag <<
"argument type " << argType <<
" is not supported";
181 auto init = rewriter.create<ConstantOp>(arg.getLoc(), argType, 0);
182 SmallString<8> sigName(instance.getInstanceName());
184 sigName += std::to_string(argIdx++);
185 auto sig = rewriter.createOrFold<SigOp>(
188 delta = rewriter.create<ConstantTimeOp>(arg.getLoc(), 0,
"ns", 1, 0);
190 rewriter.create<DrvOp>(arg.getLoc(), sig, arg, delta, Value());
191 arguments.push_back(sig);
198 SmallVector<Value, 4> resultSigs;
199 SmallVector<Value, 4> resultValues;
200 for (
auto result : instance.getResults()) {
201 auto resultType = result.getType();
202 if (!resultType.isa<IntegerType>())
203 return rewriter.notifyMatchFailure(instance, [&](Diagnostic &diag) {
204 diag <<
"result type " << resultType <<
" is not supported";
207 Location loc = result.getLoc();
213 for (
auto &use : result.getUses()) {
214 if (isa<hw::OutputOp>(use.getOwner())) {
215 auto entity = instance->getParentOfType<EntityOp>();
218 sig = entity.getArgument(entity.getIns() + use.getOperandNumber());
232 auto init = rewriter.create<ConstantOp>(loc, resultType, 0);
233 SmallString<8> sigName(instance.getInstanceName());
234 sigName +=
"_result_";
235 sigName += std::to_string(result.getResultNumber());
236 sig = rewriter.createOrFold<SigOp>(loc,
SigType::get(resultType),
242 for (
auto &use : llvm::make_early_inc_range(result.getUses())) {
243 if (isa<hw::OutputOp>(use.getOwner())) {
244 rewriter.updateRootInPlace(use.getOwner(), [&]() { use.set(sig); });
250 auto prb = rewriter.create<PrbOp>(loc, resultType, sig);
251 resultSigs.push_back(sig);
252 resultValues.push_back(prb);
258 rewriter.create<InstOp>(instance.getLoc(), instance.getInstanceName(),
259 instance.getModuleName(), arguments, resultSigs);
260 rewriter.replaceOp(instance, resultValues);
273 struct HWToLLHDPass :
public ConvertHWToLLHDBase<HWToLLHDPass> {
274 void runOnOperation()
override;
279 struct HWToLLHDTypeConverter :
public TypeConverter {
280 HWToLLHDTypeConverter();
286 return std::make_unique<HWToLLHDPass>();
290 void HWToLLHDPass::runOnOperation() {
291 MLIRContext &context = getContext();
292 ModuleOp module = getOperation();
295 ConversionTarget target(context);
296 target.addLegalDialect<LLHDDialect>();
297 target.addLegalDialect<CombDialect>();
298 target.addLegalOp<ConstantOp>();
299 target.addIllegalOp<HWModuleOp>();
300 target.addIllegalOp<hw::OutputOp>();
301 target.addIllegalOp<InstanceOp>();
304 HWToLLHDTypeConverter typeConverter;
305 RewritePatternSet
patterns(&context);
308 patterns.add<ConvertHWModule>(&context);
309 patterns.add<ConvertInstance>(&context);
310 patterns.add<ConvertOutput>(&context);
311 if (failed(applyPartialConversion(module, target, std::move(
patterns))))
319 HWToLLHDTypeConverter::HWToLLHDTypeConverter() {
321 addConversion([](Type type) {
return SigType::get(type); });
324 addConversion([](SigType type) {
return type; });
327 addSourceMaterialization(
328 [](OpBuilder &
builder, Type type, ValueRange values, Location loc) {
329 assert(values.size() == 1);
330 auto op =
builder.create<PrbOp>(loc, type, values[0]);
331 return op.getResult();
assert(baseType &&"element must be base type")
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
void populateHWModuleLikeTypeConversionPattern(StringRef moduleLikeOpName, RewritePatternSet &patterns, TypeConverter &converter)
This file defines an intermediate representation for circuits acting as an abstraction for constraint...
std::unique_ptr< mlir::OperationPass< mlir::ModuleOp > > createConvertHWToLLHDPass()
Create a HW to LLHD conversion pass.