Time framework

Time and performance units

Time inside the emulation is referred to as virtual time (as opposed to host time or real time) and is expressed in virtual seconds. Currently the resolution of virtual time, i.e., the minimum expressable time quant, is 10^-6 virtual second or 1 virtual microsecond. Performance of the CPU is expressed in MIPS units (millions instrunctions per second) and is an integer value. This means that the minimum time quant allows to execute exactly a single instruction on a CPU with performance of 1 MIPS.

Note

For CPU with performance higher than 1 MIPS, it is possible to execute instruction-by-instruction using a special stepping mode.

Time sources and sinks

Objects controlling flow of virtual time are called time sources. By default there is one time source, called master time source, assosiated with the emulation. Currently there is no API to create other master time sources, but the framework itself is capable of handling multiple time domains (with each master time source being a root of the domain).

Objects that are aware of the time flow are called time sinks. Each sink is connected to exactly one source (at any time, although it can change sources) and awaits information about how much virtual time has passed so far.

There are objects that play both roles: sink and source - they are called slave time sources. The reason for having a slave time source is explained in the following section.

Synchronization

Virtual time flows in the form of quants generated by master time sources and granted to sinks. The value of a quant is expressed in virtual seconds (or a fraction of it) and is configurable by the user.

Once a quant is granted to the sinks, the source waits for them to finish execution. After all slaves report back, it is time for a synchronization phase. As it is guaranteed that no nodes work during this phase, it is safe to process all inter-node communication during it. Only when the synchronization phase is finised, a new quant can be granted to all sinks.

It is possible to introduce slave time sources in the domain that divides the quantum into smaller fragments and allows for tighter synchronization of selected nodes.

Time domain

A configuration of time sources and time slaves connected together is called a time domain. All members of a time domain observe flow of the same virtual time and are synchronized together. In case of having multiple time domains the time values are not comparable between them - in other words, there is no synchronization across different time domains.

There is one time domain by default in the emulation. The master time source is associated with the emulation itself, every machine provides its own slave time source that drives CPU(s) being a sink.

Configuration and monitoring

There are several properties provided by a time source that can be used to tune the virtual time flow:

Quantum

The amount of virtual time between two synchronization phases. It is guraranteed that the difference of virtual time perceived of two slaves is never higher than a quantum of its closest common source.

The value of quantum can be changed between synchronization phases, but the new value won’t be used until the nearest grant.

The slave time source can have a different quantum than its master time source. In case the slave’s quantum is smaller than master’s, the slave will split the quantum into smaller pieces and report back to master only when all the pieces are used up. In case the slave’s quantum is bigger than master’s, the slave will report immediately (doing nothing) and accumulate the granted interval until it reaches the required quantum.

It is illegal to set quantum to zero as it would not allow the virtual time to pass at all.

Performance

Floating-point value describing the ratio of virtual to real time flow. Value of 1.0 means that the virtual time should in average pass in the same pace as a real one - the user feels like using real hardware; software that sleeps for 1 second should sleep for 1 real-world second. Value higher than 1.0 means that the virtual time should pass faster than the real one - it can be used to speed up long emulations (e.g., test what happens in the emulated system after 24 hours of uptime). Value lower than 1.0 means that the virtual time should pass slower than the real one - it can be used to slow down emulation when a lot of events is happening in a short period.

The performance of the host machine puts a natural limit on an effective values of this parameter (see CurrentLoad). It is possible to temporarily overwrite this setting by using AdanveImmediately property.

AdvanceImmediately
Boolean value that can be used to overwrite the current value of Performance and force the emulation to execute as fast as possible.

There are also some read-only properties that can be used to monitor the current state of the source:

CurrentLoad

Floating-point value indicating the stress the emulation puts on a host CPU.

Value of 1.0 (the maximal possible) means that the host uses all its CPU resources to run current emulation and it is not possible to execute it faster. In other words, increasing Performance will not give any effect.

Value of 0.5 means that the host is loaded only in 50% so it is possible to speed the emulation up by a factor of 2.

This value is calculated as an avarage of 10 samples.

CummulativeLoad
The same as Load but calculated as an average over all samples since the beginning of the emulation.
ElapsedVirtualTime
The amount of virtual time that passed since the source has been started.
NearestSyncPoint
The time stamp of the nearest synchronization phase.
NumberOfSyncPoints
The number of synchronization phases executed so far.

CPU pausing vs. halting

When any of the members of time domain pauses its execution it will effectively block virtual time from passing. As a result all other members will execute to the nearest synchronization phase and wait for paused member to continue.

Sometimes it is convinient to have a member in the domain that is disabled, but does not block others - e.g., a CPU that is not clocked in multi-CPU architectures. The CPU class provides the IsHalted property that allows to achieve this goal.