flux trace format is an open waveform/trace format targeting semiconductor and multi-core embedded system use-cases. The trace data is packed into a binary format and allows scalable compression.
A trace combines a set of signals and scopes (hierarchy of items). You may create multiple traces. Each trace is identified by an integer value. The output of multiple traces can be easily combined (e.g. the output from multiple cores).
On the emitter side (target, defice under test,..), a trace is represendet by a trace object. It is usually created at start-up (together with at least one buffer) and used as reference when calling methods of the trace API.
Buffers are used to store, organize and handle the trace data. The trace information is packed into snippets (entries).
You may create multiple buffers of different type. Each trace object needs to be connected to one buffer. You find linear and ring-buffers and may create your custom buffer.
Entries are binary representation (chunks of bytes) of item definitions or value changes, compiled by the flux methods and sent to the trace buffers and output.
Each entry is identified by a tag and followed by a tag specific structure.
Buffers may have handlers. In the first examples, we are using the flxWriteToFile handler (c language). This handler writes the content to a file as soon there is not enough buffer space available or when calling the flush method.
You may define your own handler (e.g. write the trace output to a custom interface). Handlers are also used for compression. The handler of one buffer may compress its entries and sends them into a second buffer.
Items are signals or scopes. Each item has an integer itemIdand a parentId. The parentId points to any scope item.The root scope itemhas the id=0.
Addionally you may add references to signals at a given scope. References dont have an itemId.
Adding items and writing legend data are optional steps. If you have this information already on receiver-side, there is no need to send. Get to the next chapter (Hello flux) to see a first example.
All trace items (mainly signals and scopes) have an item id. The root item has the value 0.
These item ids are used to:
If you pass the itemId 0 (root) to the flxOpen/open method, the whole hierarchy will be opended. If you pass an itemId>0, only the item and its children are opened.
This makes it possible to create trace with multiple domains, e.g.:
Byte: | 0 |
Byte: | ENTRY_HEAD |
4 Bytes: | HEAD |
Byte: | VERSION |
PInt: | traceId |
Value: | name |
Value: | description |
Byte: | mode |
PInt: | maxItemId |
Byte: | 0 |
Byte: | ENTRY_SWTH |
Value: | traceId |
Byte: | 0 |
Byte: | ENTRY_PBLK |
Byte: | mode |
PInt: | original size |
PInt: | compressed size |
N Bytes: | compressed |
Byte: | 0 |
Byte: | ENTRY_SECT |
Byte: | section index |
Byte: | section size (0-7) |
Byte: | section size (8-15) |
Byte: | section used (0-7) |
Byte: | section used (8-15) |
N Bytes: | section data |