CIRCT  19.0.0git
VerifToSV.cpp
Go to the documentation of this file.
1 //===- VerifToSV.cpp - HW To SV Conversion Pass ---------------------------===//
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 //
9 // This is the main Verif to SV Conversion Pass Implementation.
10 //
11 //===----------------------------------------------------------------------===//
12 
14 #include "../PassDetail.h"
16 #include "circt/Dialect/HW/HWOps.h"
17 #include "circt/Dialect/SV/SVOps.h"
19 #include "mlir/Transforms/DialectConversion.h"
20 #include "llvm/ADT/TypeSwitch.h"
21 
22 using namespace mlir;
23 using namespace circt;
24 using namespace sv;
25 using namespace verif;
26 
27 //===----------------------------------------------------------------------===//
28 // Conversion Patterns
29 //===----------------------------------------------------------------------===//
30 
31 namespace {
32 
33 struct PrintOpConversionPattern : public OpConversionPattern<PrintOp> {
35 
36  LogicalResult
37  matchAndRewrite(PrintOp op, OpAdaptor operands,
38  ConversionPatternRewriter &rewriter) const override {
39 
40  // Printf's will be emitted to stdout (32'h8000_0001 in IEEE Std 1800-2012).
41  Value fdStdout = rewriter.create<hw::ConstantOp>(
42  op.getLoc(), APInt(32, 0x80000001, false));
43 
44  auto fstrOp =
45  dyn_cast_or_null<FormatVerilogStringOp>(op.getString().getDefiningOp());
46  if (!fstrOp)
47  return op->emitOpError() << "expected FormatVerilogStringOp as the "
48  "source of the formatted string";
49 
50  rewriter.replaceOpWithNewOp<sv::FWriteOp>(
51  op, fdStdout, fstrOp.getFormatString(), fstrOp.getSubstitutions());
52  return success();
53  }
54 };
55 
56 struct HasBeenResetConversion : public OpConversionPattern<HasBeenResetOp> {
58 
59  LogicalResult
60  matchAndRewrite(HasBeenResetOp op, OpAdaptor operands,
61  ConversionPatternRewriter &rewriter) const override {
62  auto i1 = rewriter.getI1Type();
63  auto constOne = rewriter.create<hw::ConstantOp>(op.getLoc(), i1, 1);
64  auto constZero = rewriter.create<hw::ConstantOp>(op.getLoc(), i1, 0);
65  auto constX = rewriter.create<sv::ConstantXOp>(op.getLoc(), i1);
66 
67  // Declare the register that will track the reset state.
68  auto reg = rewriter.create<sv::RegOp>(
69  op.getLoc(), i1, rewriter.getStringAttr("hasBeenResetReg"));
70 
71  auto clock = operands.getClock();
72  auto reset = operands.getReset();
73 
74  // Explicitly initialize the register in an `initial` block. In general, the
75  // register will come up as X, but this may be overridden by simulator
76  // configuration options.
77  //
78  // In case the reset is async, check if the reset is already active during
79  // the `initial` block and immediately set the register to 1. Otherwise
80  // initialize to X.
81  rewriter.create<sv::InitialOp>(op.getLoc(), [&] {
82  auto assignOne = [&] {
83  rewriter.create<sv::BPAssignOp>(op.getLoc(), reg, constOne);
84  };
85  auto assignX = [&] {
86  rewriter.create<sv::BPAssignOp>(op.getLoc(), reg, constX);
87  };
88  if (op.getAsync())
89  rewriter.create<sv::IfOp>(op.getLoc(), reset, assignOne, assignX);
90  else
91  assignX();
92  });
93 
94  // Create the `always` block that sets the register to 1 as soon as the
95  // reset is initiated. For async resets this happens at the reset's posedge;
96  // for sync resets this happens on the clock's posedge if the reset is set.
97  Value triggerOn = op.getAsync() ? reset : clock;
98  rewriter.create<sv::AlwaysOp>(
99  op.getLoc(), sv::EventControl::AtPosEdge, triggerOn, [&] {
100  auto assignOne = [&] {
101  rewriter.create<sv::PAssignOp>(op.getLoc(), reg, constOne);
102  };
103  if (op.getAsync())
104  assignOne();
105  else
106  rewriter.create<sv::IfOp>(op.getLoc(), reset, assignOne);
107  });
108 
109  // Derive the actual result value:
110  // hasBeenReset = (hasBeenResetReg === 1) && (reset === 0);
111  auto regRead = rewriter.create<sv::ReadInOutOp>(op.getLoc(), reg);
112  auto regIsOne = rewriter.createOrFold<comb::ICmpOp>(
113  op.getLoc(), comb::ICmpPredicate::ceq, regRead, constOne);
114  auto resetIsZero = rewriter.createOrFold<comb::ICmpOp>(
115  op.getLoc(), comb::ICmpPredicate::ceq, reset, constZero);
116  auto resetStartedAndEnded = rewriter.createOrFold<comb::AndOp>(
117  op.getLoc(), regIsOne, resetIsZero, true);
118  rewriter.replaceOpWithNewOp<hw::WireOp>(
119  op, resetStartedAndEnded, rewriter.getStringAttr("hasBeenReset"));
120 
121  return success();
122  }
123 };
124 
125 } // namespace
126 
127 //===----------------------------------------------------------------------===//
128 // Pass Infrastructure
129 //===----------------------------------------------------------------------===//
130 
131 namespace {
132 struct VerifToSVPass : public LowerVerifToSVBase<VerifToSVPass> {
133  void runOnOperation() override;
134 };
135 } // namespace
136 
137 void VerifToSVPass::runOnOperation() {
138  MLIRContext &context = getContext();
139  hw::HWModuleOp module = getOperation();
140 
141  ConversionTarget target(context);
142  RewritePatternSet patterns(&context);
143 
144  target.addIllegalOp<PrintOp, HasBeenResetOp>();
145  target.addLegalDialect<sv::SVDialect, hw::HWDialect, comb::CombDialect>();
146  patterns.add<PrintOpConversionPattern, HasBeenResetConversion>(&context);
147 
148  if (failed(applyPartialConversion(module, target, std::move(patterns))))
149  signalPassFailure();
150 }
151 
152 std::unique_ptr<OperationPass<hw::HWModuleOp>>
154  return std::make_unique<VerifToSVPass>();
155 }
def create(data_type, value)
Definition: hw.py:393
Definition: sv.py:68
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Definition: DebugAnalysis.h:21
std::unique_ptr< OperationPass< hw::HWModuleOp > > createLowerVerifToSVPass()
Create the Verif to SV conversion pass.
Definition: VerifToSV.cpp:153
def reg(value, clock, reset=None, reset_value=None, name=None, sym_name=None)
Definition: seq.py:20
Definition: sv.py:1
Definition: verif.py:1