Some kernels are not meant to be started for each individual execution of the top-level function, as was described in the previous section, but are meant to execute continuously with streaming input and output data, in a purely data-driven fashion. These kernels can be modeled in one of two ways:
- Using the
ap_ctrl_none
interface mode at the top level, if the kernel does not interact with the host code at all, for example it does not need to be started or stopped, and does not have anys_axilite
registers for its top arguments. - Using auto-restart mode (and the regular
ap_ctrl_hs
interface mode), if the kernel has mostly streaming I/O, but occasionally needs to be managed by the software, rather than at every top level "call", as in the previous section.
In the second case, the kernel must be started by the host code after reset and platform initialization, giving the CPU a chance to configure the rest of the platform. It can also be stopped by the host code if needed. For example, to reconfigure the kernel operation.
Auto-restart can do the following:
- Infinite, if the kernel executes continuously, as long as it has input streaming data, until it is stopped by the host code.
- Counted, if the kernel is executed a specified number of times (similar to work items in a work group in OpenCL).
Auto-restart is enabled by setting config_interface -s_axilite_auto_restart_counter=1
in the TCL file (values
other than 0, which means no auto-restart counter, and 1, which means one auto-restart
counter are not supported). In the former case, the host code must:
- Write a pattern of all 1's (equivalent to -1 for signed integers or ~0 for unsigned integers in C) into the auto-restart counter register (address 0x10) to start the kernel.
- Write a pattern of all 0's (equivalent to 0 for signed and unsigned integers in C) into the auto-restart counter register to stop the kernel.
In the latter case, the host code must:
- Write the number N of times the kernel must be executed into the auto-restart counter register to start the kernel for N times.
- Write 0 to stop the kernel before the end of the counted repetition (For example, to manage an error condition).
ap_done
bit in the kernel control register goes
high when the last execution has been completed, and the kernel is idle.XExample_EnableAutoRestart
and
XExample_DisableAutoRestart
. In this legacy mode ap_done
goes high every time the kernel has completed one
execution. When a kernel is executed in auto-restart mode, the host code may need to write a new value of its input arguments, or read a new value of its output arguments without stopping the kernel. This may happen in two ways, depending on the application requirements:
- If the top level arguments can be read or written by the host code
independent of each other, then the host code may directly read or write the
corresponding
s_axilite
registers, as described at the end of the previous section. - If the top level arguments must be read or written together, in a
single "transaction", then the mailbox mechanism can be used. For example, a routing
table kept in the
s_axilite
interface as a set of several registers must be updated together, to avoid dropping packets, or a 128 bit value must be read by the host code in a single "snapshot", without the risk of reading some words before an update by the kernel, and other words after an update by the kernel.
This can be achieved by using the mailbox I/O mechanism, which provides a
means to take a "snapshot" of the top s_axilite
I/O
registers that are shared between the host code and the kernel, without ever blocking
the host code or the kernel.
The mailbox is enabled for the input s_axilite
registers, output, or both by setting config_interface
-s_axilite_mailbox=none|input|output|both in the TCL file (default is none, meaning no
mailbox).
When the input or the output mailbox is present, s_axilite
registers are duplicated. One copy is accessed by the host code,
and the other copy is accessed by the kernel code at any given point in time.
- When the host code updates in the input mailbox, it must be locked, by setting bit 0 of the input mailbox control register (address 0x14) to a value of 0. As long as this bit stays at 0, the host code can freely access its copy of the mailbox, and no updated input values are seen by the kernel code.
- When the host code is done updating the input mailbox, it unlocks
the mailbox, by setting bit 0 of the mailbox control register to 1. From this point
on, when the kernel activates
ap_ready
to signal the start of a new iteration, the SW copy of the mailbox is copied to the HW copy. - The host code can be notified of the completion of this operation by reading bit 1 of the input mailbox control register, which is automatically set to 1 whenever bit 0 is set to 0, and it is reset to 0 after the input mailbox write has been completed by the kernel.
- It is also possible for the host code to lock the mailbox again before the kernel has had a chance to read it. In this case the update is not performed, and the value previously written into the SW side of the mailbox can be overwritten by the host code.
This ensures that the host code is able to ensure atomic updates, and at the same time neither is blocked by the other, as long as the host code does not wait for the write to be completed, which may take a long time if the kernel never restarts, for example because it has no input streaming data.
The output mailbox works similarly, where the host code writes a 0 into bit 0 of the output mailbox control register (address 0x18) when it needs to read the outputs from the kernel, and writes 1 into that bit when it is done. At that point the kernel can update (potentially many times) the output mailbox, until it is locked again. The kernel signals that an update has occurred by resetting to 0 bit 1 of the output mailbox control register.