How to Miss Events in Specman
In ‘e’ language events are heavily used for all kinds of jobs, from coverage collection, to TCMs synchronization or even passing data between two entities (a reminiscence from the times when the concept of ports was not yet introduced).
The syntax for declaring an event in ‘e’ is pretty straight forward:
event event-type [is temporal-expression [using temporal-operators]]
One of the most simplest ways in which we can use this syntax is to declare an event as a “copy” of an other:
unit cfs_scoreboard { ... event copy_e is @monitor.original_e; ... };
Most of us, including myself, would say without a doubt that event copy_e is a perfect copy of event original_e – in the sense that, whenever original_e is emitted, also copy_e is emitted – but this is wrong.
Let’s see in what scenario the “equality” between the two events no longer holds water.
Let’s start from a very basic code in which we have a generator() TCM which generates original_e event, once on every rising edge of the clock, for two consecutive clock cycles.
unit cfs_monitor { event clk is rise('top/clock')@sim; event original_e; generator()@clk is { for i from 0 to 1 { wait[1]; emit original_e; }; }; run() is also { start generator(); }; on original_e { messagef(NONE, "%s.original_e", e_path()); }; };
The code of the copy_e event is very simple:
unit cfs_scoreboard { //Instance of the monitor monitor : cfs_monitor is instance; event copy_e is @monitor.original_e; on copy_e { messagef(NONE, "%s.copy_e", e_path()); }; }; extend sys { //Instance of the scoreboard scoreboard : cfs_scoreboard is instance; };
When we run this code the output is exactly what we expect: original_e is emitted two times and so it is copy_e:
You can give this code a try on EDA Playground in this small project: How to Miss Events in Specman 1
Now, here comes the weird part: let’s update generator() and emit original_e twice per each clock cycle.
unit cfs_monitor { ... generator()@clk is { for i from 0 to 1 { wait[1]; emit original_e; emit original_e; }; }; ... };
This means that original_e will be emitted four times. If you think that also copy_e will be emitted four times you would be wrong. Here is the output:
So what is happening? Is the all mighty Specman wrong? …. No! Apparently this is actually mentioned in Specman e Language Reference:
At the end of each tick, all temporal expressions that contain an event that was emitted during that tick are evaluated. Then, functions that depend on that event are called, including the function that handles on constructs and the function that handles cover constructs.
Specman e Language Reference
The key part is that “at the end of each tick“. In out generator() TCM code the two emit statements for original_e are happening on the same tick (a.k.a. some lines of code which are executed in zero time – not waiting for anything else). So once the two emit statements are executed and generator() code moves to that wait[1] only then the temporal expression of copy_e is evaluated. So this is why copy_e is emitted once per clock cycle even if original_e is emitted twice per clock cycle.
You can give this code a try on EDA Playground in this small project: How to Miss Events in Specman 2
Hope this article saved you some debug time 🙂
