11#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
17#define GEN_PASS_DEF_LOWERTESTSPASS
18#include "circt/Dialect/Verif/Passes.h.inc"
26struct LowerTestsPass : verif::impl::LowerTestsPassBase<LowerTestsPass> {
27 void runOnOperation()
override;
28 LogicalResult lowerTest(FormalOp op);
29 LogicalResult lowerTest(SimulationOp op);
30 void addComment(
hw::HWModuleOp op, StringRef kind, StringAttr name,
31 DictionaryAttr params);
36LogicalResult LowerTestsPass::lowerTest(FormalOp op) {
37 IRRewriter rewriter(op);
40 SmallVector<SymbolicValueOp> symOps;
41 SmallVector<hw::PortInfo> ports;
42 for (
auto symOp : op.getOps<SymbolicValueOp>()) {
43 symOps.push_back(symOp);
45 port.
name = rewriter.getStringAttr(
"symbolic_value_" + Twine(ports.size()));
46 port.
type = symOp.getType();
48 ports.push_back(port);
53 hw::HWModuleOp::create(rewriter, op.getLoc(), op.getNameAttr(), ports);
54 moduleOp.getBodyBlock()->getOperations().splice(
55 moduleOp.getBodyBlock()->begin(), op.getBody().front().getOperations());
56 addComment(moduleOp,
"FORMAL", op.getNameAttr(), op.getParametersAttr());
59 for (
auto [symOp, arg] :
60 llvm::zip(symOps, moduleOp.getBody().getArguments())) {
61 rewriter.replaceAllUsesWith(symOp.getResult(), arg);
62 rewriter.eraseOp(symOp);
71LogicalResult LowerTestsPass::lowerTest(SimulationOp op) {
72 IRRewriter rewriter(op);
75 std::array<hw::PortInfo, 4> ports;
77 ports[0].name = rewriter.getStringAttr(
"clock");
78 ports[0].type = seq::ClockType::get(op.getContext());
81 ports[1].name = rewriter.getStringAttr(
"init");
82 ports[1].type = rewriter.getI1Type();
85 ports[2].name = rewriter.getStringAttr(
"done");
86 ports[2].type = rewriter.getI1Type();
89 ports[3].name = rewriter.getStringAttr(
"success");
90 ports[3].type = rewriter.getI1Type();
95 hw::HWModuleOp::create(rewriter, op.getLoc(), op.getNameAttr(), ports);
96 moduleOp.getBody().takeBody(op.getBodyRegion());
97 addComment(moduleOp,
"SIMULATION", op.getNameAttr(), op.getParametersAttr());
100 auto *yieldOp = moduleOp.getBodyBlock()->getTerminator();
101 rewriter.setInsertionPoint(yieldOp);
102 hw::OutputOp::create(rewriter, yieldOp->getLoc(), yieldOp->getOperands());
103 rewriter.eraseOp(yieldOp);
106 rewriter.eraseOp(op);
112 StringAttr name, DictionaryAttr params) {
113 SmallString<128> comment;
114 llvm::raw_svector_ostream(comment)
115 << kind <<
" TEST: " << name.getValue() <<
" " << params;
116 op.setComment(comment);
119void LowerTestsPass::runOnOperation() {
120 bool changed =
false;
121 for (
auto &op :
llvm::make_early_inc_range(getOperation().getOps())) {
122 auto result = TypeSwitch<Operation *, LogicalResult>(&op)
123 .Case<FormalOp, SimulationOp>([&](
auto op) {
125 return lowerTest(op);
127 .Default([](
auto) {
return success(); });
129 return signalPassFailure();
132 return markAllAnalysesPreserved();
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
This holds the name, type, direction of a module's ports.