10#include "slang/ast/TimingControl.h"
11#include "llvm/ADT/ScopeExit.h"
12#include "llvm/Support/SaveAndRestore.h"
15using namespace ImportVerilog;
18 using slang::ast::EdgeKind;
20 case EdgeKind::NegEdge:
21 return ltl::ClockEdge::Neg;
22 case EdgeKind::PosEdge:
23 return ltl::ClockEdge::Pos;
28 case EdgeKind::BothEdges:
29 return ltl::ClockEdge::Both;
31 llvm_unreachable(
"all edge kinds handled");
35 using slang::ast::EdgeKind;
38 return moore::Edge::AnyChange;
39 case EdgeKind::PosEdge:
40 return moore::Edge::PosEdge;
41 case EdgeKind::NegEdge:
42 return moore::Edge::NegEdge;
43 case EdgeKind::BothEdges:
44 return moore::Edge::BothEdges;
46 llvm_unreachable(
"all edge kinds handled");
53struct EventControlVisitor {
59 LogicalResult visit(
const slang::ast::SignalEventControl &ctrl) {
65 if (ctrl.iffCondition) {
67 condition = context.
convertToBool(condition, Domain::TwoValued);
71 moore::DetectEventOp::create(builder, loc, edge, expr, condition);
76 LogicalResult visit(
const slang::ast::EventListControl &ctrl) {
77 for (
const auto *event : ctrl.events) {
80 if (failed(event->visit(visitor)))
88 LogicalResult visit(T &&ctrl) {
89 return mlir::emitError(loc)
90 <<
"unsupported event control: " << slang::ast::toString(ctrl.kind);
95struct DelayControlVisitor {
101 LogicalResult visit(
const slang::ast::DelayControl &ctrl) {
103 ctrl.expr, moore::TimeType::get(builder.getContext()));
106 moore::WaitDelayOp::create(builder, loc, delay);
111 template <
typename T>
112 LogicalResult visit(T &&ctrl) {
113 return mlir::emitError(loc)
114 <<
"unsupported delay control: " << slang::ast::toString(ctrl.kind);
118struct LTLClockControlVisitor {
124 Value visit(
const slang::ast::SignalEventControl &ctrl) {
130 if (ctrl.iffCondition) {
132 condition = context.
convertToBool(condition, Domain::TwoValued);
139 return ltl::ClockOp::create(builder, loc, seqOrPro, edge, expr);
142 template <
typename T>
143 Value visit(T &&ctrl) {
144 mlir::emitError(loc,
"unsupported LTL clock control: ")
145 << slang::ast::toString(ctrl.kind);
158 const slang::ast::TimingControl &ctrl,
159 moore::WaitEventOp *implicitWaitOp) {
160 auto &builder =
context.builder;
161 auto loc =
context.convertLocation(ctrl.sourceRange);
163 using slang::ast::TimingControlKind;
173 case TimingControlKind::RepeatedEvent:
174 return mlir::emitError(loc) <<
"unsupported repeated event control";
181 case TimingControlKind::ImplicitEvent:
183 return mlir::emitError(loc) <<
"implicit events cannot be used here";
184 *implicitWaitOp = moore::WaitEventOp::create(builder, loc);
188 case TimingControlKind::SignalEvent:
189 case TimingControlKind::EventList: {
190 auto waitOp = moore::WaitEventOp::create(builder, loc);
191 OpBuilder::InsertionGuard guard(builder);
192 builder.setInsertionPointToStart(&waitOp.getBody().emplaceBlock());
193 EventControlVisitor visitor{
context, loc, builder};
194 return ctrl.visit(visitor);
198 case TimingControlKind::Delay:
199 case TimingControlKind::Delay3:
200 case TimingControlKind::OneStepDelay:
201 case TimingControlKind::CycleDelay: {
202 DelayControlVisitor visitor{
context, loc, builder};
203 return ctrl.visit(visitor);
207 return mlir::emitError(loc,
"unsupported timing control: ")
208 << slang::ast::toString(ctrl.kind);
213Context::convertTimingControl(
const slang::ast::TimingControl &ctrl) {
219 const slang::ast::Statement &stmt) {
224 moore::WaitEventOp implicitWaitOp;
227 if (failed(
handleRoot(*
this, ctrl, &implicitWaitOp)))
235 llvm::SmallSetVector<Value, 8> readValues;
239 if (implicitWaitOp) {
242 readValues.insert(readOp.getInput());
243 if (previousCallback)
244 previousCallback(readOp);
253 if (implicitWaitOp) {
254 OpBuilder::InsertionGuard guard(
builder);
255 builder.setInsertionPointToStart(&implicitWaitOp.getBody().emplaceBlock());
256 for (
auto readValue : readValues) {
258 moore::ReadOp::create(
builder, implicitWaitOp.getLoc(), readValue);
259 moore::DetectEventOp::create(
builder, implicitWaitOp.getLoc(),
260 moore::Edge::AnyChange, value, Value{});
268 const Value &seqOrPro) {
271 LTLClockControlVisitor visitor{*
this, loc,
builder, seqOrPro};
272 return ctrl.visit(visitor);
static std::unique_ptr< Context > context
static LogicalResult handleRoot(Context &context, const slang::ast::TimingControl &ctrl, moore::WaitEventOp *implicitWaitOp)
static moore::Edge convertEdgeKind(const slang::ast::EdgeKind edge)
static ltl::ClockEdge convertEdgeKindLTL(const slang::ast::EdgeKind edge)
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
A helper class to facilitate the conversion from a Slang AST to MLIR operations.
Value convertToI1(Value value)
Helper function to convert a value to a MLIR I1 value.
Value convertLTLTimingControl(const slang::ast::TimingControl &ctrl, const Value &seqOrPro)
LogicalResult convertTimingControl(const slang::ast::TimingControl &ctrl)
OpBuilder builder
The builder used to create IR operations.
std::function< void(moore::ReadOp)> rvalueReadCallback
A listener called for every variable or net being read.
Value convertToBool(Value value)
Helper function to convert a value to its "truthy" boolean value.
Value convertRvalueExpression(const slang::ast::Expression &expr, Type requiredType={})
bool isInsideTimingControl
Whether we are currently converting expressions inside a timing control, such as @(posedge clk).
LogicalResult convertStatement(const slang::ast::Statement &stmt)
Location convertLocation(slang::SourceLocation loc)
Convert a slang SourceLocation into an MLIR Location.