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.