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"
23#define GEN_PASS_DEF_CONSTRUCTLEC
24#include "circt/Tools/circt-lec/Passes.h.inc"
32struct 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());
46 auto arrayTy = LLVM::LLVMArrayType::get(b.getI8Type(), str.size() + 1);
47 global = b.create<LLVM::GlobalOp>(
48 loc, arrayTy,
true, LLVM::linkage::Linkage::Private, str,
49 StringAttr::get(b.getContext(), Twine(str).
concat(Twine(
'\00'))));
55 return builder.create<LLVM::AddressOfOp>(loc, global);
59 Operation *expectedModule = SymbolTable::lookupNearestSymbolFrom(
60 getOperation(), StringAttr::get(&getContext(), name));
61 if (!expectedModule || !isa<hw::HWModuleOp>(expectedModule)) {
62 getOperation().emitError(
"module named '") << name <<
"' not found";
65 return cast<hw::HWModuleOp>(expectedModule);
68void ConstructLECPass::runOnOperation() {
70 OpBuilder builder = OpBuilder::atBlockEnd(getOperation().getBody());
71 Location loc = getOperation()->getLoc();
72 auto ptrTy = LLVM::LLVMPointerType::get(builder.getContext());
73 auto voidTy = LLVM::LLVMVoidType::get(&getContext());
77 LLVM::lookupOrCreateFn(getOperation(),
"printf", ptrTy, voidTy,
true);
78 if (failed(printfFunc)) {
79 getOperation()->emitError(
"failed to lookup or create printf");
80 return signalPassFailure();
84 auto moduleA = lookupModule(firstModule);
86 return signalPassFailure();
87 auto moduleB = lookupModule(secondModule);
89 return signalPassFailure();
91 if (moduleA.getModuleType() != moduleB.getModuleType()) {
92 moduleA.emitError(
"module's IO types don't match second modules: ")
93 << moduleA.getModuleType() <<
" vs " << moduleB.getModuleType();
94 return signalPassFailure();
99 FunctionType functionType = FunctionType::get(&getContext(), {}, {});
100 func::FuncOp entryFunc =
101 builder.create<func::FuncOp>(loc, firstModule, functionType);
103 if (insertMainFunc) {
104 OpBuilder::InsertionGuard guard(builder);
105 auto i32Ty = builder.getI32Type();
106 auto mainFunc = builder.create<func::FuncOp>(
107 loc,
"main", builder.getFunctionType({i32Ty, ptrTy}, {i32Ty}));
108 builder.createBlock(&mainFunc.getBody(), {}, {i32Ty, ptrTy}, {loc, loc});
109 builder.create<func::CallOp>(loc, entryFunc, ValueRange{});
111 Value constZero = builder.create<LLVM::ConstantOp>(loc, i32Ty, 0);
112 builder.create<func::ReturnOp>(loc, constZero);
115 builder.createBlock(&entryFunc.getBody());
117 auto lecOp = builder.create<verif::LogicEquivalenceCheckingOp>(loc);
118 Value areEquivalent = lecOp.getAreEquivalent();
119 builder.cloneRegionBefore(moduleA.getBody(), lecOp.getFirstCircuit(),
120 lecOp.getFirstCircuit().end());
121 builder.cloneRegionBefore(moduleB.getBody(), lecOp.getSecondCircuit(),
122 lecOp.getSecondCircuit().end());
125 if (moduleA != moduleB)
129 auto *term = lecOp.getFirstCircuit().front().getTerminator();
130 OpBuilder::InsertionGuard guard(builder);
131 builder.setInsertionPoint(term);
132 builder.create<verif::YieldOp>(loc, term->getOperands());
134 term = lecOp.getSecondCircuit().front().getTerminator();
135 builder.setInsertionPoint(term);
136 builder.create<verif::YieldOp>(loc, term->getOperands());
140 sortTopologically(&lecOp.getFirstCircuit().front());
141 sortTopologically(&lecOp.getSecondCircuit().front());
145 Value eqFormatString =
147 Value neqFormatString =
149 Value formatString = builder.create<LLVM::SelectOp>(
150 loc, areEquivalent, eqFormatString, neqFormatString);
151 builder.create<LLVM::CallOp>(loc, printfFunc.value(),
152 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)
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.