10#include "slang/ast/TimingControl.h"
11#include "llvm/ADT/ScopeExit.h"
14using namespace ImportVerilog;
17 using slang::ast::EdgeKind;
19 case EdgeKind::NegEdge:
20 return ltl::ClockEdge::Neg;
21 case EdgeKind::PosEdge:
22 return ltl::ClockEdge::Pos;
27 case EdgeKind::BothEdges:
28 return ltl::ClockEdge::Both;
30 llvm_unreachable(
"all edge kinds handled");
34 using slang::ast::EdgeKind;
37 return moore::Edge::AnyChange;
38 case EdgeKind::PosEdge:
39 return moore::Edge::PosEdge;
40 case EdgeKind::NegEdge:
41 return moore::Edge::NegEdge;
42 case EdgeKind::BothEdges:
43 return moore::Edge::BothEdges;
45 llvm_unreachable(
"all edge kinds handled");
52struct EventControlVisitor {
58 LogicalResult visit(
const slang::ast::SignalEventControl &ctrl) {
64 if (ctrl.iffCondition) {
66 condition = context.
convertToBool(condition, Domain::TwoValued);
70 moore::DetectEventOp::create(builder, loc, edge, expr, condition);
75 LogicalResult visit(
const slang::ast::EventListControl &ctrl) {
76 for (
const auto *event : ctrl.events) {
79 if (failed(event->visit(visitor)))
87 LogicalResult visit(T &&ctrl) {
88 return mlir::emitError(loc)
89 <<
"unsupported event control: " << slang::ast::toString(ctrl.kind);
94struct DelayControlVisitor {
100 LogicalResult visit(
const slang::ast::DelayControl &ctrl) {
102 ctrl.expr, moore::TimeType::get(builder.getContext()));
105 moore::WaitDelayOp::create(builder, loc, delay);
110 template <
typename T>
111 LogicalResult visit(T &&ctrl) {
112 return mlir::emitError(loc)
113 <<
"unsupported delay control: " << slang::ast::toString(ctrl.kind);
117struct LTLClockControlVisitor {
123 Value visit(
const slang::ast::SignalEventControl &ctrl) {
129 if (ctrl.iffCondition) {
131 condition = context.
convertToBool(condition, Domain::TwoValued);
138 return ltl::ClockOp::create(builder, loc, seqOrPro, edge, expr);
141 template <
typename T>
142 Value visit(T &&ctrl) {
143 mlir::emitError(loc,
"unsupported LTL clock control: ")
144 << slang::ast::toString(ctrl.kind);
157 const slang::ast::TimingControl &ctrl,
158 moore::WaitEventOp &implicitWaitOp) {
159 auto &builder = context.
builder;
162 using slang::ast::TimingControlKind;
172 case TimingControlKind::RepeatedEvent:
173 return mlir::emitError(loc) <<
"unsupported repeated event control";
180 case TimingControlKind::ImplicitEvent:
181 implicitWaitOp = moore::WaitEventOp::create(builder, loc);
185 case TimingControlKind::SignalEvent:
186 case TimingControlKind::EventList: {
187 auto waitOp = moore::WaitEventOp::create(builder, loc);
188 OpBuilder::InsertionGuard guard(builder);
189 builder.setInsertionPointToStart(&waitOp.getBody().emplaceBlock());
190 EventControlVisitor visitor{context, loc, builder};
191 return ctrl.visit(visitor);
195 case TimingControlKind::Delay:
196 case TimingControlKind::Delay3:
197 case TimingControlKind::OneStepDelay:
198 case TimingControlKind::CycleDelay: {
199 DelayControlVisitor visitor{context, loc, builder};
200 return ctrl.visit(visitor);
204 return mlir::emitError(loc,
"unsupported timing control: ")
205 << slang::ast::toString(ctrl.kind);
210Context::convertTimingControl(
const slang::ast::TimingControl &ctrl,
211 const slang::ast::Statement &stmt) {
215 moore::WaitEventOp implicitWaitOp;
224 if (failed(
handleRoot(*
this, ctrl, implicitWaitOp)))
232 llvm::SmallSetVector<Value, 8> readValues;
237 if (implicitWaitOp) {
239 readValues.insert(readOp.getInput());
240 if (previousCallback)
241 previousCallback(readOp);
250 if (implicitWaitOp) {
251 OpBuilder::InsertionGuard guard(
builder);
252 builder.setInsertionPointToStart(&implicitWaitOp.getBody().emplaceBlock());
253 for (
auto readValue : readValues) {
255 moore::ReadOp::create(
builder, implicitWaitOp.getLoc(), readValue);
256 moore::DetectEventOp::create(
builder, implicitWaitOp.getLoc(),
257 moore::Edge::AnyChange, value, Value{});
265 const Value &seqOrPro) {
268 LTLClockControlVisitor visitor{*
this, loc,
builder, seqOrPro};
269 return ctrl.visit(visitor);
static moore::Edge convertEdgeKind(const slang::ast::EdgeKind edge)
static ltl::ClockEdge convertEdgeKindLTL(const slang::ast::EdgeKind edge)
static LogicalResult handleRoot(Context &context, const slang::ast::TimingControl &ctrl, moore::WaitEventOp &implicitWaitOp)
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)
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={})
LogicalResult convertStatement(const slang::ast::Statement &stmt)
Location convertLocation(slang::SourceLocation loc)
Convert a slang SourceLocation into an MLIR Location.