CIRCT 22.0.0git
Loading...
Searching...
No Matches
LowerTests.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
11#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
12
13using namespace circt;
14
15namespace circt {
16namespace verif {
17#define GEN_PASS_DEF_LOWERTESTSPASS
18#include "circt/Dialect/Verif/Passes.h.inc"
19} // namespace verif
20} // namespace circt
21
22using namespace mlir;
23using namespace verif;
24
25namespace {
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);
32};
33} // namespace
34
35/// Convert a `verif.formal` to an `hw.module`.
36LogicalResult LowerTestsPass::lowerTest(FormalOp op) {
37 IRRewriter rewriter(op);
38
39 // Collect all symbolic values in the test and create ports for each.
40 SmallVector<SymbolicValueOp> symOps;
41 SmallVector<hw::PortInfo> ports;
42 for (auto symOp : op.getOps<SymbolicValueOp>()) {
43 symOps.push_back(symOp);
44 hw::PortInfo port;
45 port.name = rewriter.getStringAttr("symbolic_value_" + Twine(ports.size()));
46 port.type = symOp.getType();
48 ports.push_back(port);
49 }
50
51 // Create a module with these ports and inline the body of the formal op.
52 auto moduleOp =
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());
57
58 // Replace symbolic values with module arguments.
59 for (auto [symOp, arg] :
60 llvm::zip(symOps, moduleOp.getBody().getArguments())) {
61 rewriter.replaceAllUsesWith(symOp.getResult(), arg);
62 rewriter.eraseOp(symOp);
63 }
64
65 // Remove the original test op.
66 rewriter.eraseOp(op);
67 return success();
68}
69
70/// Convert a `verif.simulation` to an `hw.module`.
71LogicalResult LowerTestsPass::lowerTest(SimulationOp op) {
72 IRRewriter rewriter(op);
73
74 // Gather the list of ports for the module.
75 std::array<hw::PortInfo, 4> ports;
76
77 ports[0].name = rewriter.getStringAttr("clock");
78 ports[0].type = seq::ClockType::get(op.getContext());
79 ports[0].dir = hw::ModulePort::Input;
80
81 ports[1].name = rewriter.getStringAttr("init");
82 ports[1].type = rewriter.getI1Type();
83 ports[1].dir = hw::ModulePort::Input;
84
85 ports[2].name = rewriter.getStringAttr("done");
86 ports[2].type = rewriter.getI1Type();
87 ports[2].dir = hw::ModulePort::Output;
88
89 ports[3].name = rewriter.getStringAttr("success");
90 ports[3].type = rewriter.getI1Type();
91 ports[3].dir = hw::ModulePort::Output;
92
93 // Create a module with these ports and inline the body of the simulation op.
94 auto moduleOp =
95 hw::HWModuleOp::create(rewriter, op.getLoc(), op.getNameAttr(), ports);
96 moduleOp.getBody().takeBody(op.getBodyRegion());
97 addComment(moduleOp, "SIMULATION", op.getNameAttr(), op.getParametersAttr());
98
99 // Replace the `verif.yield` with an `hw.output` op.
100 auto *yieldOp = moduleOp.getBodyBlock()->getTerminator();
101 rewriter.setInsertionPoint(yieldOp);
102 hw::OutputOp::create(rewriter, yieldOp->getLoc(), yieldOp->getOperands());
103 rewriter.eraseOp(yieldOp);
104
105 // Remove the original test op.
106 rewriter.eraseOp(op);
107 return success();
108}
109
110/// Add a comment to an `hw.module` describing test kind, name, and parameters.
111void LowerTestsPass::addComment(hw::HWModuleOp op, StringRef kind,
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);
117}
118
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) {
124 changed = true;
125 return lowerTest(op);
126 })
127 .Default([](auto) { return success(); });
128 if (failed(result))
129 return signalPassFailure();
130 }
131 if (!changed)
132 return markAllAnalysesPreserved();
133}
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition verif.py:1
mlir::Type type
Definition HWTypes.h:31
mlir::StringAttr name
Definition HWTypes.h:30
This holds the name, type, direction of a module's ports.