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:
182 return mlir::emitError(loc) <<
"implicit events cannot be used here";
183 *implicitWaitOp = moore::WaitEventOp::create(builder, loc);
187 case TimingControlKind::SignalEvent:
188 case TimingControlKind::EventList: {
189 auto waitOp = moore::WaitEventOp::create(builder, loc);
190 OpBuilder::InsertionGuard guard(builder);
191 builder.setInsertionPointToStart(&waitOp.getBody().emplaceBlock());
192 EventControlVisitor visitor{context, loc, builder};
193 return ctrl.visit(visitor);
197 case TimingControlKind::Delay:
198 case TimingControlKind::Delay3:
199 case TimingControlKind::OneStepDelay:
200 case TimingControlKind::CycleDelay: {
201 DelayControlVisitor visitor{context, loc, builder};
202 return ctrl.visit(visitor);
206 return mlir::emitError(loc,
"unsupported timing control: ")
207 << slang::ast::toString(ctrl.kind);
212Context::convertTimingControl(
const slang::ast::TimingControl &ctrl) {
218 const slang::ast::Statement &stmt) {
222 moore::WaitEventOp implicitWaitOp;
231 if (failed(
handleRoot(*
this, ctrl, &implicitWaitOp)))
239 llvm::SmallSetVector<Value, 8> readValues;
244 if (implicitWaitOp) {
246 readValues.insert(readOp.getInput());
247 if (previousCallback)
248 previousCallback(readOp);
257 if (implicitWaitOp) {
258 OpBuilder::InsertionGuard guard(
builder);
259 builder.setInsertionPointToStart(&implicitWaitOp.getBody().emplaceBlock());
260 for (
auto readValue : readValues) {
262 moore::ReadOp::create(
builder, implicitWaitOp.getLoc(), readValue);
263 moore::DetectEventOp::create(
builder, implicitWaitOp.getLoc(),
264 moore::Edge::AnyChange, value, Value{});
272 const Value &seqOrPro) {
275 LTLClockControlVisitor visitor{*
this, loc,
builder, seqOrPro};
276 return ctrl.visit(visitor);
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={})
LogicalResult convertStatement(const slang::ast::Statement &stmt)
Location convertLocation(slang::SourceLocation loc)
Convert a slang SourceLocation into an MLIR Location.