Introduction to Worker Development
This section introduces the aspects of the worker development process that are common across all types of workers and authoring models. There are separate documents for each authoring model which describe their differing aspects in more detail, including languages and APIs. After this section introduces the general development process, following sections provide details for the contents of the various directories and files that are involved.
A worker is developed in its own directory, based on a component specification that typically exists in a file elsewhere. The component specification is the basis for multiple potential alternative implementations (workers). A component specification is an XML file called an OpenCPI Component Specification (OCS), abbreviated as a spec file, is described in detail in the Component Specifications (typically in OCS XML Files) topic. The spec file also typically references one or more OpenCPI Protocol Specification (OPS) files, defined in the Protocol Specification (OPS) Examples topic, to indicate the types of messages allowed to flow into and out of the component’s ports.
In addition to workers having their own directories, they are developed in a component library (a collection of workers). The worker directories are thus subdirectories of the component library’s directory, and the OCS (and OPS) for a worker is typically found in the specs subdirectory of the component library.
Some authoring models (e.g. RCC) support creating a single binary artifact that implements multiple workers, but usually a single worker implementation is in its own subdirectory and when compiled, results in a single binary artifact for each compilation target (e.g. type of CPU and compiler).
The names of the worker directories have a suffix indicating the authoring model used for that implementation (e.g. .rcc, .hdl). For a component whose component specification file is named xyz-spec.xml, the RCC authoring model implementation of that component will typically be in a worker directory called xyz.rcc. The worker’s directory must combine the name of the worker, before the ., and the authoring model used, after the .. A worker named abc written using the authoring model named rcc, would exist in a directory named abc.rcc.
The names of the spec file and the worker’s directory do not have to match, but it is recommended and allows the use of more defaults to simplify the process. An HDL implementation (for FPGAs) of the component spec xyz-spec.xml would be in the subdirectory xyz.hdl.
An xyz.test directory, at the same level as the worker directories, is created for unit tests common to all implementations of the xyz component’s spec file. This means that tests in this directory apply to all workers that implement the same spec.
It is possible to have multiple workers implementing the same component specification, written in the same authoring model. In this case, the worker names must be different and at least one of them must be different from the name implied by the component specification. E.g. one might have big_fast_xyz.rcc and small_slow_xyz.rcc, both implementing the OCS in xyz-spec.xml.
Once an OCS is available, a worker can be created in a library by using the ocpidev create worker command, which creates a worker’s directory and populates it with an initial version of several files that can be edited later. The ocpidev tool is described in the The ocpidev Tool for Managing Assets section. The initial files created that are then edited as necessary include:
OpenCPI Worker Description File (the OWD XML file,
xyz.xml)Worker initial source code file (named
xyz.<language-suffix>)
These file types have initial, automatically generated, skeletal contents that may be subsequently edited by the developer as required. Frequently only the source code file requires editing. These files are described in detail below. There are additional optional files in a worker’s directory that will also be discussed below.
The OWD file is an XML file that describes the worker itself, refers to an OCS, and includes any implementation-specific attributes needed by OpenCPI. The second file is the initial source code file for the worker’s actual logic.
The component specification (OCS) referred to by the worker’s OWD contains the description of the component’s external behavior. This OWD-to-OCS reference will exist in all workers that implement the component specification. The OWD adds information about a particular worker.
The OWD XML file has the name of the worker and the .xml suffix. The primary source code file has the name of the worker, with the typical suffix for the programming language used (.c, .cc, .vhd etc.). The primary source file for the xyz.rcc worker written in the C language would be xyz.rcc/xyz.c. A worker may also reference additional source files or libraries.
The worker building process (using ocpidev build) automatically creates and populates two types of subdirectories in the worker directory.
The first, called gen/, holds automatically generated source code and XML files that are target-independent (architecture independent). The second type, with the name target-<platform> holds architecture-specific object/binary files usually generated for or by a compiler for a specific target. In this case, <target> is the name of the compilation target being built, such as rocky9 for Rocky Linux 9.5 running on a 64-bit x86 processor. Both types of directories contain files resulting from the build process and are removed by the ocpidev clean command (analogous to the typical “make clean” command), as they are always regenerated and should never be manually edited. More details about these targets is in the Developing Workers section.
In the sections below, a simple example will be given, followed by a detailed description of the component specification files (OCS), followed by the types of worker files just introduced.
A Simple Example Worker
Here is a simple example of a worker written in C++. The component’s function adds a constant, biasValue, to each unsigned 32 bit integer at its input, and put the value at its output, one message containing many such values at a time. The component specification XML file, the OCS file, is named specs/bias-spec.xml, and contains
<ComponentSpec>
<property name='biasValue' writable='true' type='ulong'/>
<port name='in' protocol='u32-proto'/>
<port name='out' producer='true' protocol='u32-proto'/>
</ComponentSpec>
The protocol specification XML file, the OPS file, indicated by the protocol attributes in the OCS above, would be found in the file specs/u32-proto.xml (or elsewhere in other libraries or projects), and contains:
<Protocol>
<Operation name='info'>
<Argument name='values' type='ulong' sequenceLength='0'/>
</Operation>
</Protocol>
For the bias.rcc worker created by ocpidev, implementing the above spec using the C++ language, the OWD XML file is named bias.rcc/bias.xml, and contains:
<RccWorker language='c++' spec='bias-spec'/>
This OWD indicates that the authoring model is RCC, the spec is bias-spec, and the language is C++. The source file that implements this bias.rcc worker, simplified without header files or error checking, is in the file named bias.cc, and contains:
class BiasWorker : public BiasWorkerBase {
RCCResult run(bool /*timedout*/) {
size_t length = in.info().values().size();
const uint32_t *inData = in.info().values().data();
uint32_t *outData = out.info().values().data();
for (unsigned n = length; n; --n)
*outData++ = *inData++ + properties().biasValue;
out.info().values().resize(length);
out.setOpCode(in.opCode());
return RCC_ADVANCE;
}
};
If the worker was written to the HDL model, in the VHDL language, its OWD would be:
<HdlWorker language='vhdl' spec='bias-spec'/>
For a detailed explanation for creating HDL workers see the HDL Development Guide document for VHDL examples.