Skip to content

Commit

Permalink
Simulator upgrades for rohme compatibility (registering now and cance…
Browse files Browse the repository at this point in the history
…lling) (#468)
  • Loading branch information
AdamRose66 authored Feb 29, 2024
1 parent 48d51cd commit a084c03
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 5 deletions.
34 changes: 30 additions & 4 deletions lib/src/simulator.dart
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
// Copyright (C) 2021-2024 Intel Corporation
// Copyright (C) 2024 Adam Rose
// SPDX-License-Identifier: BSD-3-Clause
//
// simulator.dart
// The ROHD event-based static simulator
//
// 2021 May 7
// Author: Max Korbel <max.korbel@intel.com>

//
// 2024 Feb 28th
// Amended by Adam Rose <adam.david.rose@gmail.com> for Rohme compatibility
//
import 'dart:async';
import 'dart:collection';

Expand Down Expand Up @@ -183,7 +187,7 @@ abstract class Simulator {
///
/// The [action], if it returns a [Future], will be `await`ed.
static void registerAction(int timestamp, dynamic Function() action) {
if (timestamp <= _currentTimestamp) {
if (timestamp < _currentTimestamp) {
throw Exception('Cannot add timestamp "$timestamp" in the past.'
' Current time is ${Simulator.time}');
}
Expand All @@ -193,6 +197,25 @@ abstract class Simulator {
_pendingTimestamps[timestamp]!.add(action);
}

/// Cancels an [action] previously scheduled for [timestamp].
///
/// Returns true iff a [action] was previously registered at [timestamp].
static bool cancelAction(int timestamp, dynamic Function() action) {
if (!_pendingTimestamps.containsKey(timestamp)) {
return false;
}

if (!_pendingTimestamps[timestamp]!.remove(action)) {
return false;
}

if (_pendingTimestamps[timestamp]!.isEmpty) {
_pendingTimestamps.remove(timestamp);
}

return true;
}

/// Registers an arbitrary [action] to be executed at the end of the
/// simulation.
///
Expand Down Expand Up @@ -231,18 +254,21 @@ abstract class Simulator {
}

final nextTimeStamp = _pendingTimestamps.firstKey();

if (nextTimeStamp == null) {
return;
}

_currentTimestamp = nextTimeStamp;

final pendingList = _pendingTimestamps[nextTimeStamp]!;
_pendingTimestamps.remove(_currentTimestamp);

await tickExecute(() async {
for (final func in _pendingTimestamps[nextTimeStamp]!) {
for (final func in pendingList) {
await func();
}
});
_pendingTimestamps.remove(_currentTimestamp);
}

/// Executes all pending injected actions.
Expand Down
93 changes: 92 additions & 1 deletion test/simulator_test.dart
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
// Copyright (C) 2021-2024 Intel Corporation
// Copyright (C) 2024 Adam Rose
// SPDX-License-Identifier: BSD-3-Clause
//
// simulator_test.dart
// Unit tests for the ROHD simulator
//
// 2021 May 7
// Author: Max Korbel <max.korbel@intel.com>

//
// 2024 Feb 28th
// Amended by Adam Rose <adam.david.rose@gmail.com> for Rohme compatibility
//
import 'dart:async';

import 'package:rohd/rohd.dart';
Expand All @@ -24,6 +28,23 @@ void main() {
expect(actionTaken, equals(true));
});

test('simulator supports cancelation of previously scheduled actions',
() async {
var actionCount = 0;

void incrementCount() {
actionCount++;
}

Simulator.registerAction(
50, () => Simulator.cancelAction(100, incrementCount));
Simulator.registerAction(100, incrementCount);
Simulator.registerAction(200, incrementCount);

await Simulator.run();
expect(actionCount, equals(1));
});

test('simulator stops at maximum time', () async {
const timeLimit = 1000;
Simulator.setMaxSimTime(timeLimit);
Expand Down Expand Up @@ -115,4 +136,74 @@ void main() {
await Simulator.run();
expect(injectedActionExecuted, isTrue);
});

group('Rohme compatibility tests', () {
test('simulator supports delta cycles', () async {
// ignore: omit_local_variable_types
final List<String> testLog = [];

void deltaFunc(int t, int i) {
testLog.add('wake up $i');
Simulator.registerAction(100, () => testLog.add('delta $i'));
}

Simulator.registerAction(100, () => deltaFunc(Simulator.time, 0));
Simulator.registerAction(100, () => deltaFunc(Simulator.time, 1));

await Simulator.run();

// ignore: omit_local_variable_types
final List<String> expectedLog = [
'wake up 0',
'wake up 1',
'delta 0',
'delta 1'
];
expect(testLog, expectedLog);
});

test('simulator supports end of delta one shot callbacks', () async {
var callbackCount = 0;

// add a self cancelling listener
Simulator.registerAction(
100, () => Simulator.injectAction(() => callbackCount++));
Simulator.registerAction(200, () {});

await Simulator.run();
expect(callbackCount, 1);
});

test('deltas occur after end of delta', () async {
// ignore: omit_local_variable_types
final List<String> testLog = [];

void deltaFunc(int t, int i) {
testLog.add('first delta $i');

Simulator.registerAction(t, () {
Simulator.registerAction(
Simulator.time, () => testLog.add('next delta $i'));
Simulator.injectAction(() => testLog.add('end delta $i'));
});
}

Simulator.registerAction(100, () => deltaFunc(Simulator.time, 0));
Simulator.registerAction(100, () => deltaFunc(Simulator.time, 1));

await Simulator.run();

// ignore: omit_local_variable_types
final List<String> expectedLog = [
'first delta 0',
'first delta 1',
'end delta 0',
'end delta 1',
'next delta 0',
'next delta 1'
];

expect(testLog, expectedLog);
});
});
}

0 comments on commit a084c03

Please sign in to comment.