Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
16 changes: 16 additions & 0 deletions include/circt/Dialect/Sim/EventQueue.h
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,14 @@ class TimeWheel {
/// Returns the number of events processed.
size_t processCurrentDelta();

/// Process all events in the current delta up to (inclusive) limitRegion.
/// Returns the number of events processed.
size_t processDeltaUpTo(SchedulingRegion limitRegion);

/// Peek at the next non-empty region in the current delta without advancing.
/// Returns NumRegions if no events remain in the current delta.
SchedulingRegion peekCurrentRegion() const;

/// Process all events at the current real time (all deltas and regions).
/// Returns the number of events processed.
size_t processCurrentTime();
Expand Down Expand Up @@ -566,6 +574,14 @@ class EventScheduler {
/// Returns false if simulation is complete.
bool stepDelta();

/// Step through the current delta up to (inclusive) the given region limit.
/// Returns true if any events were processed.
bool stepDeltaUpTo(SchedulingRegion limitRegion);

/// Peek at the next non-empty region in the current delta without advancing.
/// Returns NumRegions if no events remain in the current delta.
SchedulingRegion peekCurrentRegion() const;

/// Advance time to the next scheduled event without processing it.
/// This allows the caller to control when events are executed.
/// Returns true if time was advanced, false if no events or already at next event.
Expand Down
90 changes: 90 additions & 0 deletions lib/Dialect/Sim/EventQueue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,81 @@ size_t TimeWheel::processCurrentDelta() {
return total;
}

SchedulingRegion TimeWheel::peekCurrentRegion() const {
size_t slotIdx = getSlotIndex(currentTime.realTime, 0);
const auto &slot = levels[0].slots[slotIdx];
const DeltaCycleQueue *deltaQueuePtr = nullptr;
if (currentTime.deltaStep < Slot::kInlineDeltaSlots) {
if (slot.deltaQueues[currentTime.deltaStep].hasAnyEvents())
deltaQueuePtr = &slot.deltaQueues[currentTime.deltaStep];
} else {
auto it = slot.extraDeltaQueues.find(currentTime.deltaStep);
if (it != slot.extraDeltaQueues.end())
deltaQueuePtr = &it->second;
}
if (!deltaQueuePtr)
return SchedulingRegion::NumRegions;
return deltaQueuePtr->getNextNonEmptyRegion(
static_cast<SchedulingRegion>(currentTime.region));
}

size_t TimeWheel::processDeltaUpTo(SchedulingRegion limitRegion) {
size_t total = 0;
size_t slotIdx = getSlotIndex(currentTime.realTime, 0);
auto &slot = levels[0].slots[slotIdx];

DeltaCycleQueue *deltaQueue = nullptr;
bool isInline = (currentTime.deltaStep < Slot::kInlineDeltaSlots);
if (isInline) {
if (slot.deltaQueues[currentTime.deltaStep].hasAnyEvents())
deltaQueue = &slot.deltaQueues[currentTime.deltaStep];
} else {
auto it = slot.extraDeltaQueues.find(currentTime.deltaStep);
if (it != slot.extraDeltaQueues.end())
deltaQueue = &it->second;
}

if (deltaQueue) {
bool madeProgress = true;
while (madeProgress) {
madeProgress = false;
auto region = deltaQueue->getNextNonEmptyRegion(
static_cast<SchedulingRegion>(currentTime.region));
while (region != SchedulingRegion::NumRegions &&
static_cast<size_t>(region) <=
static_cast<size_t>(limitRegion)) {
size_t count = deltaQueue->executeAndClearRegion(region);
totalEvents -= count;
total += count;
madeProgress = true;

unsigned nextIdx = static_cast<unsigned>(region) + 1;
if (nextIdx > static_cast<unsigned>(limitRegion))
break;
region = deltaQueue->getNextNonEmptyRegion(
static_cast<SchedulingRegion>(nextIdx));
}
}

// Advance region cursor to just past the limit so subsequent stepRegion()
// calls start from the correct position.
unsigned nextIdx = static_cast<unsigned>(limitRegion) + 1;
if (nextIdx < static_cast<unsigned>(SchedulingRegion::NumRegions)) {
auto nextRegion = deltaQueue->getNextNonEmptyRegion(
static_cast<SchedulingRegion>(nextIdx));
if (nextRegion != SchedulingRegion::NumRegions)
currentTime.region = static_cast<uint8_t>(nextRegion);
}

if (!isInline && !deltaQueue->hasAnyEvents())
slot.extraDeltaQueues.erase(currentTime.deltaStep);
}

slot.hasEvents = slot.hasAnyEvents();
updateSlotBit(0, slotIdx, slot.hasEvents);
return total;
}

size_t TimeWheel::processCurrentTime() {
size_t total = 0;

Expand Down Expand Up @@ -656,6 +731,21 @@ bool EventScheduler::stepDelta() {
return processed > 0;
}

bool EventScheduler::stepDeltaUpTo(SchedulingRegion limitRegion) {
if (!wheel->hasEvents())
return false;

size_t processed = wheel->processDeltaUpTo(limitRegion);
stats.eventsProcessed += processed;
if (processed > 0)
++stats.deltaCycles;
return processed > 0;
}

SchedulingRegion EventScheduler::peekCurrentRegion() const {
return wheel->peekCurrentRegion();
}

bool EventScheduler::advanceToNextTime() {
if (!wheel->hasEvents())
return false;
Expand Down
Loading