Skip to content

Commit

Permalink
[HandshakeToDC] Implement ESIInstanceOp lowering (#7871)
Browse files Browse the repository at this point in the history
Lower the ESIInstanceOp to `hw.instance` with `dc.from_esi` and
`dc.to_esi` to convert the args/results.
  • Loading branch information
teqdruid authored Nov 21, 2024
1 parent 33fae2f commit 2b76cf8
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 1 deletion.
54 changes: 53 additions & 1 deletion lib/Conversion/HandshakeToDC/HandshakeToDC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "circt/Dialect/DC/DCOps.h"
#include "circt/Dialect/DC/DCTypes.h"
#include "circt/Dialect/HW/HWOps.h"
#include "circt/Dialect/HW/HWSymCache.h"
#include "circt/Dialect/HW/HWTypes.h"
#include "circt/Dialect/Handshake/HandshakeOps.h"
#include "circt/Dialect/Handshake/HandshakePasses.h"
Expand Down Expand Up @@ -692,6 +693,44 @@ class FuncOpConversion : public DCOpConversionPattern<handshake::FuncOp> {
}
};

/// Lower the ESIInstanceOp to `hw.instance` with `dc.from_esi` and `dc.to_esi`
/// to convert the args/results.
class ESIInstanceConversionPattern
: public OpConversionPattern<handshake::ESIInstanceOp> {
public:
ESIInstanceConversionPattern(MLIRContext *context,
const HWSymbolCache &symCache)
: OpConversionPattern(context), symCache(symCache) {}

LogicalResult
matchAndRewrite(ESIInstanceOp op, OpAdaptor adaptor,
ConversionPatternRewriter &rewriter) const override {
Location loc = op.getLoc();
SmallVector<Value> operands;
for (size_t i = ESIInstanceOp::NumFixedOperands, e = op.getNumOperands();
i < e; ++i)
operands.push_back(
rewriter.create<dc::FromESIOp>(loc, adaptor.getOperands()[i]));
operands.push_back(adaptor.getClk());
operands.push_back(adaptor.getRst());
// Locate the lowered module so the instance builder can get all the
// metadata.
Operation *targetModule = symCache.getDefinition(op.getModuleAttr());
// And replace the op with an instance of the target module.
auto inst = rewriter.create<hw::InstanceOp>(loc, targetModule,
op.getInstNameAttr(), operands);
SmallVector<Value> esiResults(
llvm::map_range(inst.getResults(), [&](Value v) {
return rewriter.create<dc::ToESIOp>(loc, v);
}));
rewriter.replaceOp(op, esiResults);
return success();
}

private:
const HWSymbolCache &symCache;
};

/// Add DC clock and reset ports to the module.
static void addClkRst(hw::HWModuleOp mod) {
auto *ctx = mod.getContext();
Expand Down Expand Up @@ -768,7 +807,7 @@ LogicalResult circt::handshaketodc::runHandshakeToDC(
ConversionTarget target(*ctx);
target.addIllegalDialect<handshake::HandshakeDialect>();
target.addLegalDialect<dc::DCDialect>();
target.addLegalOp<mlir::ModuleOp>();
target.addLegalOp<mlir::ModuleOp, handshake::ESIInstanceOp>();

// And any user-specified target adjustments
if (configureTarget)
Expand Down Expand Up @@ -811,5 +850,18 @@ LogicalResult circt::handshaketodc::runHandshakeToDC(
if (auto mod = dyn_cast<hw::HWModuleOp>(op); mod)
addClkRst(mod);

// Run conversions which need see everything.
HWSymbolCache symbolCache;
symbolCache.addDefinitions(op);
symbolCache.freeze();
ConversionTarget globalLoweringTarget(*ctx);
globalLoweringTarget.addIllegalDialect<handshake::HandshakeDialect>();
globalLoweringTarget.addLegalDialect<dc::DCDialect, hw::HWDialect>();
RewritePatternSet globalPatterns(ctx);
globalPatterns.add<ESIInstanceConversionPattern>(ctx, symbolCache);
if (failed(applyPartialConversion(op, globalLoweringTarget,
std::move(globalPatterns))))
return op->emitOpError() << "error during conversion";

return success();
}
13 changes: 13 additions & 0 deletions test/Conversion/HandshakeToDC/basic.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -248,3 +248,16 @@ handshake.func @pack_unpack(%arg0 : i32, %arg1 : i1) -> (i32, i1) {
%a, %b = handshake.unpack %packed : tuple<i32, i1>
return %a, %b : i32, i1
}

// CHECK-LABEL: hw.module @esi_outer(in %clk : !seq.clock, in %rst : i1, in %arg0 : !esi.channel<i32>, in %arg1 : !esi.channel<i1>, out out : !esi.channel<i32>) {
// CHECK-NEXT: [[R0:%.+]] = dc.from_esi %arg0 : <i32>
// CHECK-NEXT: [[R1:%.+]] = dc.from_esi %arg1 : <i1>
// CHECK-NEXT: %pack_unpack_inst.out0, %pack_unpack_inst.out1 = hw.instance "pack_unpack_inst" @pack_unpack(in0: [[R0]]: !dc.value<i32>, in1: [[R1]]: !dc.value<i1>, clk: %clk: !seq.clock, rst: %rst: i1) -> (out0: !dc.value<i32>, out1: !dc.value<i1>)
// CHECK-NEXT: [[R2:%.+]] = dc.to_esi %pack_unpack_inst.out0 : !dc.value<i32>
// CHECK-NEXT: [[R3:%.+]] = dc.to_esi %pack_unpack_inst.out1 : !dc.value<i1>
// CHECK-NEXT: hw.output [[R2]] : !esi.channel<i32>
// CHECK-NEXT: }
hw.module @esi_outer(in %clk: !seq.clock, in %rst: i1, in %arg0: !esi.channel<i32>, in %arg1: !esi.channel<i1>, out out: !esi.channel<i32>) {
%ret0, %ret1 = handshake.esi_instance @pack_unpack "pack_unpack_inst" clk %clk rst %rst (%arg0, %arg1) : (!esi.channel<i32>, !esi.channel<i1>) -> (!esi.channel<i32>, !esi.channel<i1>)
hw.output %ret0 : !esi.channel<i32>
}

0 comments on commit 2b76cf8

Please sign in to comment.