Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions lib/Conversion/SimToSV/SimToSV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ struct SimConversionState {
bool usedSynthesisMacro = false;
bool usedFileDescriptorRuntime = false;
SetVector<StringAttr> dpiCallees;
llvm::SmallDenseMap<Block *, sv::IfDefOp> synthesisGuards;
};

struct SimTypeConverter : public TypeConverter {
Expand Down Expand Up @@ -267,6 +268,45 @@ static LogicalResult convert(PauseOp op, PatternRewriter &rewriter) {
return success();
}

class TriggeredLowering : public SimConversionPattern<TriggeredOp> {
public:
using SimConversionPattern<TriggeredOp>::SimConversionPattern;

LogicalResult
matchAndRewrite(TriggeredOp op, OpAdaptor adaptor,
ConversionPatternRewriter &rewriter) const final {
auto loc = op.getLoc();
state.usedSynthesisMacro = true;

auto [it, inserted] = state.synthesisGuards.try_emplace(op->getBlock());
auto ifdefOp = it->second;
if (!inserted) {
ifdefOp->moveBefore(op);
Comment thread
nanjo712 marked this conversation as resolved.
Outdated
} else {
ifdefOp = sv::IfDefOp::create(
rewriter, loc, "SYNTHESIS", [] {}, [] {});
it->second = ifdefOp;
}
rewriter.setInsertionPointToEnd(ifdefOp.getElseBlock());

auto trigger = seq::FromClockOp::create(rewriter, loc, adaptor.getClock());
auto alwaysOp = sv::AlwaysOp::create(
rewriter, loc, ArrayRef<sv::EventControl>{sv::EventControl::AtPosEdge},
ArrayRef<Value>{trigger});

Block *destination = alwaysOp.getBodyBlock();
if (auto condition = adaptor.getCondition()) {
rewriter.setInsertionPointToStart(destination);
destination =
sv::IfOp::create(rewriter, loc, condition, [] {}).getThenBlock();
}

rewriter.mergeBlocks(op.getBodyBlock(), destination);
rewriter.eraseOp(op);
return success();
}
};

class DPICallLowering : public SimConversionPattern<DPICallOp> {
public:
using SimConversionPattern<DPICallOp>::SimConversionPattern;
Expand Down Expand Up @@ -843,6 +883,7 @@ struct SimToSVPass : public circt::impl::LowerSimToSVBase<SimToSVPass> {
patterns.add<ClockedPauseOp>(convert);
patterns.add<TerminateOp>(convert);
patterns.add<PauseOp>(convert);
patterns.add<TriggeredLowering>(context, state);
patterns.add<DPICallLowering>(context, state);
auto result = applyPartialConversion(module, target, std::move(patterns));

Expand Down
64 changes: 64 additions & 0 deletions test/Conversion/SimToSV/triggered.mlir
Comment thread
nanjo712 marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// RUN: circt-opt --lower-sim-to-sv --allow-unregistered-dialect %s | FileCheck %s

// CHECK-LABEL: hw.module @simple_triggered
hw.module @simple_triggered(in %clock : !seq.clock) {
sim.triggered %clock {
"some.user"() : () -> ()
}

// CHECK: sv.ifdef @SYNTHESIS {
// CHECK-NEXT: } else {
// CHECK-NEXT: %[[CLOCK:.*]] = seq.from_clock %clock
// CHECK-NEXT: sv.always posedge %[[CLOCK]] {
// CHECK-NEXT: "some.user"() : () -> ()
// CHECK-NEXT: }
// CHECK-NEXT: }
}

// CHECK-LABEL: hw.module @conditional_triggered
hw.module @conditional_triggered(
in %clock : !seq.clock, in %en : i1) {
sim.triggered %clock if %en {
"some.user"() : () -> ()
}

// CHECK: sv.ifdef @SYNTHESIS {
// CHECK-NEXT: } else {
// CHECK-NEXT: %[[CLOCK:.*]] = seq.from_clock %clock
// CHECK-NEXT: sv.always posedge %[[CLOCK]] {
// CHECK-NEXT: sv.if %en {
// CHECK-NEXT: "some.user"() : () -> ()
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: }
}

// CHECK-LABEL: hw.module @multiple_triggered
hw.module @multiple_triggered(
in %clock : !seq.clock) {

sim.triggered %clock {
"some.user"() : () -> ()
}

%late_cond = "some.value"() : () -> i1

sim.triggered %clock if %late_cond {
"some.user"() : () -> ()
}

// CHECK: %[[LATE:.*]] = "some.value"() : () -> i1
// CHECK-NEXT: sv.ifdef @SYNTHESIS {
// CHECK-NEXT: } else {
// CHECK-NEXT: %[[CLOCK0:.*]] = seq.from_clock %clock
// CHECK-NEXT: sv.always posedge %[[CLOCK0]] {
// CHECK-NEXT: "some.user"() : () -> ()
// CHECK-NEXT: }
// CHECK-NEXT: %[[CLOCK1:.*]] = seq.from_clock %clock
// CHECK-NEXT: sv.always posedge %[[CLOCK1]] {
// CHECK-NEXT: sv.if %[[LATE]] {
// CHECK-NEXT: "some.user"() : () -> ()
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: }
}
Loading