In a hardware simulation, it can often be useful to let something happen only after a certain amount of (simulated) time. This can be done in Simics by "posting an event", which means that a callback function is placed in a queue, to be executed later on in the simulation. The amount of simulated time before the event is triggered is usually specified in a number of seconds (as a floating-point number), but other units are possible; see the DML Reference Manual for more information.
We can modify our example to post an event when the register is written to, as follows:
dml 1.0; device simple_device; import "io-memory.dml"; data int32 delay; bank b { parameter function = 0; register r0 size 4 @0x0000 { method write(val) { $this = 0; $delay = val; inline $ev.post($delay, NULL); log "info": "Posted tick event"; } event ev { method event(void *data) { ++$r0; log "info": "Tick: %d.", $r0; inline $this.post($delay, NULL); } } } }We use the register itself as a counter, which is reset to zero upon a write access; the written value is used as the delay in seconds. Once the event happens, it re-posts itself after the same interval. Note the use of a data field to store the delay internally; we could also have chosen to put the counter in the data field instead, or in a more realistic example we could have modeled the counter as an additional register. Also, the post method must be called with the inline keyword, because its argument can be of varying types.
After recompiling and restarting Simics, just enter the command continue (or c for short). This simply runs the simulation of the hardware. You should see no messages, since there is nothing exciting going on in the machine, except that the clock is ticking away. Press Ctrl-C to pause the simulation and get back to the prompt.
Now write a large value to the register:
simics> phys_mem.set 0x1000 10000(ignore any error messages about "no associated queue") and enter c again. You should see "Tick"-messages being written at fairly short intervals. Press Ctrl-C and write a lower value to the register:
simics> phys_mem.set 0x1000 1then start the simulation again. The messages are now printed at high speed (although not ten thousand times as fast). The lesson from this is that simulated time is not strictly proportional to real time, and if a machine has very little to do, even 10,000 seconds can be simulated in a very short time.
For simple cases of posting a callback after a specific time, you don't even need to go through the trouble of declaring an event object and its event method, and then call post. The following DML statement creates and posts an anonymous event which calls a method after a given time t in seconds:
after (t) call $my_callback;Note that just like calling post, the effect is that the callback is placed on a queue, and the DML program continues immediately with the next statement following after, i.e., events are executed asynchronously.