12 #include "mlir/Dialect/Func/IR/FuncOps.h"
13 #include "mlir/Dialect/LLVMIR/FunctionCallUtils.h"
14 #include "mlir/Dialect/LLVMIR/LLVMDialect.h"
15 #include "mlir/Transforms/DialectConversion.h"
16 #include "mlir/Transforms/TopologicalSortUtils.h"
19 using namespace circt;
23 #define GEN_PASS_DEF_CONSTRUCTLEC
24 #include "circt/Tools/circt-lec/Passes.h.inc"
32 struct ConstructLECPass
33 :
public circt::impl::ConstructLECBase<ConstructLECPass> {
34 using circt::impl::ConstructLECBase<ConstructLECPass>::ConstructLECBase;
35 void runOnOperation()
override;
42 Location loc = moduleOp.getLoc();
43 auto global = moduleOp.lookupSymbol<LLVM::GlobalOp>(str);
45 OpBuilder b = OpBuilder::atBlockEnd(moduleOp.getBody());
47 global = b.create<LLVM::GlobalOp>(
48 loc, arrayTy,
true, LLVM::linkage::Linkage::Private, str,
55 return builder.create<LLVM::AddressOfOp>(loc, global);
59 Operation *expectedModule = SymbolTable::lookupNearestSymbolFrom(
61 if (!expectedModule || !isa<hw::HWModuleOp>(expectedModule)) {
62 getOperation().emitError(
"module named '") << name <<
"' not found";
65 return cast<hw::HWModuleOp>(expectedModule);
68 void ConstructLECPass::runOnOperation() {
70 OpBuilder
builder = OpBuilder::atBlockEnd(getOperation().getBody());
71 Location loc = getOperation()->getLoc();
77 LLVM::lookupOrCreateFn(getOperation(),
"printf", ptrTy, voidTy,
true);
80 auto moduleA = lookupModule(firstModule);
82 return signalPassFailure();
83 auto moduleB = lookupModule(secondModule);
85 return signalPassFailure();
87 if (moduleA.getModuleType() != moduleB.getModuleType()) {
88 moduleA.emitError(
"module's IO types don't match second modules: ")
89 << moduleA.getModuleType() <<
" vs " << moduleB.getModuleType();
90 return signalPassFailure();
96 func::FuncOp entryFunc =
97 builder.create<func::FuncOp>(loc, firstModule, functionType);
100 OpBuilder::InsertionGuard guard(
builder);
101 auto i32Ty =
builder.getI32Type();
102 auto mainFunc =
builder.create<func::FuncOp>(
103 loc,
"main",
builder.getFunctionType({i32Ty, ptrTy}, {i32Ty}));
104 builder.createBlock(&mainFunc.getBody(), {}, {i32Ty, ptrTy}, {loc, loc});
105 builder.create<func::CallOp>(loc, entryFunc, ValueRange{});
107 Value constZero =
builder.create<LLVM::ConstantOp>(loc, i32Ty, 0);
108 builder.create<func::ReturnOp>(loc, constZero);
111 builder.createBlock(&entryFunc.getBody());
114 if (moduleA == moduleB) {
120 auto lecOp =
builder.create<verif::LogicEquivalenceCheckingOp>(loc);
121 areEquivalent = lecOp.getAreEquivalent();
122 auto *outputOpA = moduleA.getBodyBlock()->getTerminator();
123 auto *outputOpB = moduleB.getBodyBlock()->getTerminator();
124 lecOp.getFirstCircuit().takeBody(moduleA.getBody());
125 lecOp.getSecondCircuit().takeBody(moduleB.getBody());
131 OpBuilder::InsertionGuard guard(
builder);
132 builder.setInsertionPoint(outputOpA);
133 builder.create<verif::YieldOp>(loc, outputOpA->getOperands());
135 builder.setInsertionPoint(outputOpB);
136 builder.create<verif::YieldOp>(loc, outputOpB->getOperands());
140 sortTopologically(&lecOp.getFirstCircuit().front());
141 sortTopologically(&lecOp.getSecondCircuit().front());
146 Value eqFormatString =
148 Value neqFormatString =
150 Value formatString =
builder.create<LLVM::SelectOp>(
151 loc, areEquivalent, eqFormatString, neqFormatString);
152 builder.create<LLVM::CallOp>(loc, printfFunc, ValueRange{formatString});
154 builder.create<func::ReturnOp>(loc, ValueRange{});
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 Value lookupOrCreateStringGlobal(OpBuilder &builder, ModuleOp moduleOp, StringRef str)
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.