Glossary

API (component)

The emulator component which defines the outward-facing REST API for an IP block emulator. The IP block emulator API always implements a (non-strict) superset of the respective firmware driver API, such that the two interfaces may be loaded arbitrarily and interchangeably by a higher-level device for interaction. See: API (api.py)

bitstream emulator
top-level emulator

An emulator for a full FPGA bitstream. It is the container for the emulator engine, which constructs and creates the connections between IP block emulators, as well as the emulator controller, which exposes the APIs for each IP block emulator, plus some top-level endpoints.

components
emulator components

The simplified building blocks of an IP block emulator which are stored within the FPGA bitstream. These include the API, the event handler, the state machine, and the simulated IP block (see: IP Block Emulators).

controller
emulator controller

The top-level interface and service which controls and drives the emulator engine and its IP block emulators for a single bitstream emulator.

emulator

A software system which mocks hardware functionality. There are two levels of emulator for SKA: a bitstream emulator, which represents a full FPGA bitstream, and IP block emulators, which represent individual IP blocks on an FPGA card. The bitstream emulator drives the connection between all of the IP block emulators.

engine
emulator engine

The set of services which construct, connect and drive IP block emulators, based on the IP block emulator definitions in the FPGA bitstream.

event

A message sent from one IP block emulator to another, containing some data for the recipient to handle as well as some metadata. Event types include pulses, signal updates, and manual events.

event handler (component)

The emulator component which takes in events, processes them, potentially updates them, and returns new or updated events to send to the next downstream blocks. See: Event Handler (event_handler.py)

exchange
pulse exchange
manual exchange
signal update exchange

In the context of an emulator, an exchange is a RabbitMQ mechanism which distributes published messages to one or more queues. The emulator subcontrollers use exchanges to send messages to downstream IP block emulators.

injector
event injector

A global service (relative to any set of bitstream emulators) with the ability to inject arbitrary manual events into the manual event queue of any IP block emulator of any bitstream emulator at an arbitrary specified time. It lives as a separate process from all emulators and exposes a single API endpoint, which takes in a JSON file specifying a list of event groups, each containing events to send to a particular IP block emulator. See: Injector

IP block (component)
simulated IP block (component)

The emulator component which contains IP block-specific data, such as variables representing register values on an IP block, or simple methods to mutate such values. It is intended to be used primarily within other components, such as the API, e.g. for operations where registers or other data should be changed. See: Simulated IP Block (ip_block.py)

IP block emulator

An emulator for a single IP block on an FPGA card. Its functionality is written via a generic and very simplified interface (see: IP Block Emulators), which is stored along with the full FPGA bitstream, and is then pulled in at runtime by the emulator engine to construct the full IP block emulator. It mocks only at a high level some of the state changes, signal updates, and driver API methods of the original IP block.

manual event

An event which can only be triggered via manual request, either within a component or through the event injector. Manual events, as opposed to pulse events and signal updates, contain a timestamp separate from the pulse clock time. Manual events are processed upon receipt of a pulse event with a pulse clock timestamp greater than or equal to their own timestamps (e.g. a manual event with timestamp 1234 will not be processed on a pulse event with timestamp 1000, but will be processed on the next pulse event with timestamp 2000). Manuel events have unlimited multiplicity, but are always processed individually, as opposed to signal updates which are processed as an entire array at once. Formerly known as a “processing event” (this term is now deprecated).

module

The full set of data for an IP block emulator, including emulator components, the subcontroller, and all associated RabbitMQ queues and exchanges.

pulse
pulse event

An event used as the primary synchronization and timing mechanism for a bitstream emulator and its IP block emulators. It contains a timestamp (generated by the pulse clock) which remains static throughout the signal chain, and when received by an IP block emulator, informs its subcontroller to pull the latest signal updates and manual events from their respective queues for processing. Pulse events should generally contain no data of their own except for the pulse clock timestamp. They also have a strict multiplicity of 1, i.e. any given IP block emulator may only ever output 1 pulse event with a given timestamp, and any such IP block emulator which receives pulse events from multiple inputs with the same timestamp may only ever process 1 of those events (in the current model, the first received pulse event is kept, and all others with the same timestamp are discarded).

pulse clock

TODO

queue
pulse queue
manual queue
signal update queue

In the context of an emulator, a queue is a RabbitMQ mechanism which receives and stores messages from an exchange, until they are consumed. The emulator subcontrollers use queues to receive pulses, signal updates, manual events, and API requests.

RabbitMQ

The message broker used by the emulator. It uses queues and exchanges to receive and distribute messages within and across many services at scale, with the theoretical capability to handle millions of messages with minimal to no loss of performance. (This capability is yet to be seen from an emulator perspective.) See: RabbitMQ Documentation.

signal generator

TODO

signal router

TODO

signal update
signal update event

An event which provides data updates about the emulated signal from the Signal Generator. It follows the same path as pulse events, however it is only generated from the Signal Generator on the first pulse and then only by request in any block when data changes (for example if some values in an IP block emulator are configured that will change the downstream state of the signal). Signal updates from the previous IP block emulator(s) with a certain pulse clock timestamp are processed upon receipt of a pulse event with the same pulse clock timestamp. Additionally, signal update events, unlike pulse events, have unrestricted multiplicity, i.e. for any given pulse, an IP block emulator may process an unlimited number of input signal update events with the same timestamp, and may output an unlimited number of new or updated events to downstream blocks.

state machine (component)

The emulator component which maintains the state of an IP block emulator and handles any transitions between those states. The component defines a set of possible states, a set of possible triggers which may cause state transitions, and a set of all possible state transitions. See: State Machine (state_machine.py)

subcontroller

The interface and service which wraps and exposes the components of an IP block emulator as well as provides some common functionality which can be leveraged within the components. It is responsible for sending and receiving messages via RabbitMQ under the hood, and distributing the content of those messages to the components as required.