Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simulator upgrades for rohme compatibility (registering now and cancelling) #468

Merged
merged 4 commits into from
Feb 29, 2024
Merged

Simulator upgrades for rohme compatibility (registering now and cancelling) #468

merged 4 commits into from
Feb 29, 2024

Conversation

AdamRose66
Copy link
Contributor

Description & Motivation

The intention of these changes is to enable Rohme / Rohd interoperability by Layering Rohme on top of the Rohd simulator.

Rohd needs three kinds of callback:

  1. Post to a future time ( Timer( SimDuration(...) , callback )
  2. Post to the next delta ( Timer( SimDuration.zero , callback )
  3. Post to "end of this delta" ( scheduleMicrotask )

Statistically speaking, (1) and (2) are common while (3) is rare.

As a result of (2), one time slot may have many delta cycles. Each time slot looks like this:

delta 0:

  • { callbacks originally scheduled for this time slot}
  • { microtasks scheduled by callbacks in delta 0}
    delta 1:
  • { zero time callbacks scheduled in delta 0}
  • { micro tasks scheduled by callbacks in delta 1 }
    ...
    delta n:
  • { time zero callbacks scheduled by delta n-1 }
  • { microtasks scheduled in this delta n }

The timeslot finishes when there have been no zero delay ( type (2) ) callbacks posted.

The following Rohme code uses type (2) zero time delays:

await Future.delayed( SimDuration.zero );
print('a');
await Future.delayed( SimDuration.zero );
print('b');
await Future.delayed( SimDuration.zero );
print('c');

Each call to Future.delayed( t ) above actually creates a Timer( current_time + t ).

Conceptually, it is very similar to the following SV code:

#0;
$display("a");
#0;
$display("b");
#0;
$display("c");

These zero delays are used for example to create mutexs which are fair and deterministic.

Mapping from Rohme to Rohd

  1. Posting to the future is mapped to registerAction( timestamp ) , where timestamps > Simulator.time
  • added a cancelAction( timestamp , action ) to support cancel ( and therefore suspend / resume )
  1. Posting to the next delta is done using registerAction( Simulator.time )
  • this creates another complete tickExecute at the current time
  1. End of delta ( ie, microtask ) callbacks are mapped to injectAction

Testing

All existing Rohd tests pass as previously. A few new tests have been added in test/simulator_test.dart.

Backwards-compatibility

Given that all current tests pass, there should be no backward compatibility issues.

Documentation

The small number of changes to the Simulator class have been documented inline.

Further Work

Package Organisation

For Rohme to use the Rohd simulator, it has to pull in the entire Rohd package. It would be easier for Rohme if the Rohd simulator was split out into its own package. We could also consider putting the Rohme simulator in this shared package. An external simulator might be useful for other packages which want to share the underlying timing with Rohme and Rohd.

Incremental execution

A feature of the Rohme simulator is that it can run for some time and then run again for a little more time. This might be useful in the future tool integrations where the simulator needs to be started and stopped. It isn't obvious if this feature is supported, or whether it is viable in Rohd ( since there are end-of-simulation events etc ).

Time zero reset

I ran a few experiments with doing Simulator.reset() before running a simulation. It seems that Simulator.reset() only works after a simulation has been run ( eg in a teardown method ). The reason I would like to run it before the simulation runs is that the Rohme simulator is an actual class with a constuctor, so it would be nice to put the reset in the constructor rather than a teardown method. That way a single test.dart can instantiate many Rohme simulators as it moves though the different tests. This might be as simple as doing nothing if a simulation has never been run. Alternatively, we could introduce a 'hasBeenRun' getter into the Rohd simulator so that Rohme could check for it before attempting to call Simulator.reset().

    Rohd needs three kinds of callback:
    1. Post to a future time ( Timer( SimDuration(...) , callback )
    2. Post to the next delta ( Timer( SimDuration.zero , callback )
    3. Post to "end of this delta" ( scheduleMicrotask )

    Statistically speaking, (1) and (2) are common while (3) is rare.

    As a result of (2), one time slot may have many delta cycles. Each time slot looks like this:

    delta 0:
    - { callbacks originally scheduled for this time slot}
    - { microtasks scheduled by callbacks in delta 0}
    delta 1:
    - { zero time callbacks scheduled in delta 0}
    - { micro tasks scheduled by callbacks in delta 1 }
    ...
    delta n:
    - { time zero callbacks scheduled by delta n-1 }
    - { microtasks  scheduled in this delta n }

    The timeslot finishes when there have been no zero delay ( type (2) ) callbacks posted.

    The following Rohme code uses type (2) zero time delays:

    await Future.delayed( SimDuration.zero );
    print('a');
    await Future.delayed( SimDuration.zero );
    print('b');
    await Future.delayed( SimDuration.zero );
    print('c');

    Each call to Future.delayed( t ) above actually creates a Timer( current_time + t ).

    Conceptually, it is very similar to the following SV code:

    #0;
    $display("a");
    #0;
    $display("b");
    #0;
    $display("c");

    These zero delays are used for example to create mutexs which are fair and deterministic.

    Mapping from Rohme to Rohd
    1. posting to the future is mapped to registerAction( timestamp ) , where timestamps > Simulator.time
    - added a cancelAction( timestamp , action ) to support cancel ( and therefore suspend / resume )
    2. posting to the next delta is done using registerAction( Simulator.time )
    - this creates another complete tickExecute at the current time
    3. end of delta ( ie, microtask ) callbacks are mapped to injectAction
lib/src/simulator.dart Outdated Show resolved Hide resolved
Copy link
Contributor

@mkorbel1 mkorbel1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good, thank you for your contribution!

@mkorbel1 mkorbel1 changed the title Candidate commit for Rohd Compatibility Simulator upgrades for rohme compatibility (registering now and cancelling) Feb 29, 2024
@mkorbel1 mkorbel1 merged commit a084c03 into intel:main Feb 29, 2024
3 checks passed
@mkorbel1
Copy link
Contributor

@AdamRose66

Incremental execution

These two issues might be related:
#451
#450

Time zero reset

I tried a test like this and it passed:

  test('simulator reset immediately works ok', () async {
    await Simulator.reset();

    var actionTaken = false;
    Simulator.registerAction(100, () => actionTaken = true);

    await Simulator.run();
    expect(actionTaken, equals(true));

    await Simulator.reset();
  });

What symptoms were you seeing? Would you have expected this test to fail?

@AdamRose66
Copy link
Contributor Author

Ah ! It's quite likely I was just doing
Simulator.reset();
rather than
await Simulator.reset();

@mkorbel1
Copy link
Contributor

Ah ! It's quite likely I was just doing Simulator.reset(); rather than await Simulator.reset();

Ah I see, yes that might not work right. Fortunately, Dart lint rules can catch this.

I would like to run it before the simulation runs is that the Rohme simulator is an actual class with a constuctor, so it would be nice to put the reset in the constructor rather than a teardown method.

I don't believe you can make a constructor async in Dart, so it sounds like you still may run into an issue there with your goals. Perhaps there's another place to reset it at the start of execution in your package rather than relying on a tearDown, which is really testing specific.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants