12 #include "mlir/Analysis/TopologicalSortUtils.h"
13 #include "mlir/Dialect/Func/IR/FuncOps.h"
14 #include "mlir/Dialect/LLVMIR/FunctionCallUtils.h"
15 #include "mlir/Dialect/LLVMIR/LLVMDialect.h"
16 #include "mlir/Transforms/DialectConversion.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());
113 auto lecOp = builder.create<verif::LogicEquivalenceCheckingOp>(loc);
114 Value areEquivalent = lecOp.getAreEquivalent();
115 builder.cloneRegionBefore(moduleA.getBody(), lecOp.getFirstCircuit(),
116 lecOp.getFirstCircuit().end());
117 builder.cloneRegionBefore(moduleB.getBody(), lecOp.getSecondCircuit(),
118 lecOp.getSecondCircuit().end());
121 if (moduleA != moduleB)
125 auto *term = lecOp.getFirstCircuit().front().getTerminator();
126 OpBuilder::InsertionGuard guard(builder);
127 builder.setInsertionPoint(term);
128 builder.create<verif::YieldOp>(loc, term->getOperands());
130 term = lecOp.getSecondCircuit().front().getTerminator();
131 builder.setInsertionPoint(term);
132 builder.create<verif::YieldOp>(loc, term->getOperands());
136 sortTopologically(&lecOp.getFirstCircuit().front());
137 sortTopologically(&lecOp.getSecondCircuit().front());
141 Value eqFormatString =
143 Value neqFormatString =
145 Value formatString = builder.create<LLVM::SelectOp>(
146 loc, areEquivalent, eqFormatString, neqFormatString);
147 builder.create<LLVM::CallOp>(loc, printfFunc, ValueRange{formatString});
149 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.