Simulation#
Introduction#
The Legacy API implemented an offline mode. This mode populated the global data structures with some predefined module types. The API calls checked whether or not the global “offline” variable was set. Offline mode caused most of the API calls return a successful execution without executing any additional code. The mode didn’t allow for tests of the underlying API functionality. You couldn’t answer the question:
Did the API function call and underlying code behave as expected?
While this was useful for integration, it didn’t allow more comprehensive testing.
The Pixie SDK takes the concept of interacting with an “offline” crate or module and
implements a simulation framework. The crate simulation behaves like a physical
crate with modules. You can boot it, set/get parameters, start data runs, load
firmware, etc. The simulation exercises as much of the SDK framework as possible.
If you call Pixie16StartHistogramRun()
before booting, then you’ll get an error.
This is a drastic difference from the legacy API.
The Legacy implementation would return a success in this situation.
The simulation exercises the software using the same code used to communicate with the hardware. Utilizing the same code makes simulated crate almost indistinguishable from the hardware. Consistent API behavior eases integration and error handling.
The simulation framework forms the basis for a number of XIA’s internal test suites. Some use-cases include, but are not limited to,
Validating a settings file before importing it to a physical crate.
Developing integrations with the SDK in the absence of a physical system.
Writing integration and unit tests to test the SDK functionality.
Simulated Components#
The simulation starts with the crate. We emulate the 14 slot crate because this is the most common crate in use. The crate emulation uses the same backplane emulation as the hardware. This ensures that the simulated crate has the same restrictions. For example, only one crate leader.
Next, we emulate the modules. This is where the simulation gets into the nitty-gritty. Each module gets a memory block that’s identical to the one provided by the PLX driver. The SDK then interacts with this memory block with the same code that talks to the PLX driver. Just without actually talking to the driver.
Starting a data run sets values in the register addresses. Requesting the run status reads from the same address. This differs from the Legacy API. It never returned a run status that reflected the function calls made.
The emulation continues through to boots, parameter read/write, etc. Booting is an interesting case. You don’t need any firmware at all. Firmware only gets loaded from disk when it gets written to the hardware. Providing dummy names to the firmware registration or boot calls is sufficient.
It’s probably quicker to list what the simulation framework doesn’t do.
Limitations#
First, the simulation doesn’t generate any data. You can get traces, histograms, baselines, statistics, etc., but they’ll always be 0. This goes for list-mode data as well. You’ll never have data in the fifo. The list-mode data present a special challenge since the data format can vary depending on both the module and the firmware. We’ve thought about it, but it just hasn’t been scheduled.
Second, we don’t emulate the firmware behavior. This includes all firmware in the
system: signal processing FPGA, DSP behaviors, and system FPGA. Any calls that tell
the DSP to do something (ex. Pixie16SetDACs()
or
Pixie16AdjustOffsets()
), will return a success with the underlying data
unchanged. Any custom functionality implemented by the firmware may, or may not, work
as expected.
Third, synchronous data runs may not behave as expected. They can be configured. The SDK will do all the necessary error checking. The modules’ run status just might not always align with expectation for a synchronous run.
Finally, we do not completely vet the simulation module definitions. Our team uses the framework for testing and development. They need flexibility around what kinds of modules they can define. For this reason, we’ve limited the available configurations in the C API.
C API Implementation#
We provide user access to the simulation via Pixie16InitSystem()
. You set the
OfflineMode
argument to 1
. The C API and Legacy API diverge at this point.
The Legacy API didn’t require any additional steps to use the functions. This is because
most of those functions returned success no matter what. In contrast, the C API
requires that you call PixieBootCrate()
or Pixie16BootModule()
before trying to access API functions requiring modules to be online.
For example, after calling Pixie16InitSystem()
, you may call
PixieGetModuleInfo()
to get the module information. You could not call
Pixie16StartHistogramRun()
without first booting a module. Booting represents
the only major difference as far as use goes.
Configurations#
We wanted to keep the configuration as simple as possible. We’ve limited the number and type of modules available via the C API.
Note
We do not define the module number (ex. 0) here as that’s configurable in the
Pixie16InitSystem()
call. If you provide NULL
, then the modules will
index in increasing slot number.
Slot |
Rev |
ADC Bits |
ADC Freq |
Num Chans |
---|---|---|---|---|
2 |
15 |
16 |
250 |
16 |
3 |
15 |
14 |
500 |
16 |
4 |
15 |
14 |
250 |
16 |
5 |
17 |
14 |
250 |
32 |