ChimeraTK-DeviceAccess  03.18.00
Logical Name Mapping Backend

Backend to map logical register names onto real hardware registers. It reads the logical name map from an xml file and will open internally additional Devices as they are reference in that file.

This page is still incomplete and will be extended in future.

CDD syntax

The map file should be specified by the "map" parameter in the CDD, i.e.: (logicalNameMap?map=path/to/mapfile.xlmap)

Additional parameters can be passed through the CDD, which are available inside the xlmap file via <par></par> tags, e.g. when using the CDD (logicalNameMap?map=path/to/mapfile.xlmap&myParam=HelloWorld) the tag <par>myParam</par> inside the xlmap file would be replaced with HelloWorld.

Map file syntax

This section is incomplete.

Example with most features:

<logicalNameMap>
<redirectedRegister name="SingleWord">
<targetDevice>PCIE2</targetDevice>
<targetRegister>BOARD.WORD_USER</targetRegister>
</redirectedRegister>
<redirectedRegister name="FullArea">
<targetDevice>PCIE2</targetDevice>
<targetRegister>ADC.AREA_DMAABLE</targetRegister>
</redirectedRegister>
<redirectedRegister name="PartOfArea">
<targetDevice>PCIE2</targetDevice>
<targetRegister>ADC.AREA_DMAABLE</targetRegister>
<targetStartIndex>10</targetStartIndex>
<numberOfElements>20</numberOfElements>
</redirectedRegister>
<redirectedChannel name="Channel3">
<targetDevice>PCIE3</targetDevice>
<targetRegister>TEST.NODMA</targetRegister>
<targetChannel>3</targetChannel>
</redirectedChannel>
<constant name="Constant">
<type>integer</type>
<value>42</value>
</constant>
<redirectedRegister name="SingleWord_Scaled">
<targetDevice>PCIE2</targetDevice>
<targetRegister>BOARD.WORD_USER</targetRegister>
<plugin name="multiply">
<parameter name="factor">4.2</parameter>
</plugin>
</redirectedRegister>
<module name="MyModule">
<module name="SomeSubmodule">
<variable name="Variable">
<type>integer</type>
<value>2</value>
</variable>
</module>
<redirectedChannel name="ConfigurableChannel">
<targetDevice>PCIE3</targetDevice>
<targetRegister>TEST.NODMA</targetRegister>
<targetChannel><ref>/Constant</ref></targetChannel>
</redirectedChannel>
</module>
<redirectedBit name="Bit0ofVar">
<targetDevice>this</targetDevice>
<targetRegister>/MyModule/SomeSubmodule/Variable</targetRegister>
<targetBit>0</targetBit>
</redirectedBit>
<redirectedRegister name="MapFileRevision">
<targetDevice>PCIE2</targetDevice>
<targetRegister>BOARD.WORD_FIRMWARE</targetRegister>
<plugin name="bitRange">
<parameter name="shift">16</parameter>
<parameter name="numberOfBits">16</parameter>
</plugin>
</redirectedRegister>
</logicalNameMap>

Variables and constants

It is possible to define variables and constants that do not exist in the target device. They can be used to parameterize other registers or plugins.

<variable name="Variable">
<type>integer</type>
<value>2</value>
</variable>
<constant name="Constant">
<type>integer</type>
<value>42</value>
</constant>

The types available are defined by the ChimeraTK::DataType class: int8, uint8, int16, uint16, int32, uint32, int64, uint64, float32, float64, string. In addition, integer can be used as an alias for int32.

Self-referencing redirects

It is possible to redirect registers to other registers in the same xlmap file using the special device this:

<redirectedBit name="Bit0ofVar">
<targetDevice>this</targetDevice>
<targetRegister>/MyModule/SomeSubmodule/Variable</targetRegister>
<targetBit>0</targetBit>
</redirectedBit>

Accessor plugins

Special features like mathematical conversions can be enabled on a per-register basis by using accessor plugins. Any number of plugins can be enabled for each register. Each plugin takes a list of parameters, which depend on the type of the plugin.

In the xlmap file, plugins can be specified by adding one ore more <plugin> tags, e.g.:

<redirectedRegister name="SingleWord_Scaled_Twice">
<targetDevice>PCIE2</targetDevice>
<targetRegister>BOARD.WORD_USER</targetRegister>
<plugin name="multiply">
<parameter name="factor">2</parameter>
</plugin>
<plugin name="multiply">
<parameter name="factor">3</parameter>
</plugin>
</redirectedRegister>

This will enable two instances of the multiply plugin.

List of plugins

The following plugins can be enabled. It is not possible to extend the Logical Name Mapping Backend with plugins through runtime loading or linking, all plugins have to be shipped with the DeviceAccess library.

multiply

The multiply plugin multiplies the value of the register with the given factor. Note that the multiplication is done for both reading and writing. Hence if this plugin is used e.g. to convert a raw value into a physical value, the register should be used in one direction only. The plugin will internally always read the value as a 64 bit floating point, so the result may not be bit exact. The target register must be numeric.

Parameters:

  • factor: Factor to multiply the value with. Will be interpreted as a (floating-point) number.

math

The math plugin allows to apply an arbitrary mathematical formula to the data. The exprtk library is used to parse the library. For an exact documentation of the possible syntax, please refer to its documentation: http://www.partow.net/programming/exprtk/index.html

The math plugin enforces the register to be used in a single direction (read or write). If the target register is writable, the logical register will be write-only, otherwise read-only. In case a writeable register shall be read through the math plugin, the forceReadOnly plugin shall be specified before the math plugin.

The shape of the register cannot be changed, i.e. the number of elements returned by the formula must be equal to the number of elements of the target register. All calculations will be done internally as double-precision floating point.

Parameters:

  • formula: The formula to apply to the data. Within the formula, the parameter x can be used to reference the current register value.
  • enable_push_parameters: This parameter takes no value. It is allowed only for writing direction of math plugin. It enables push-like logic for all parameters which support wait_for_new_data, in particular for variables defined in the logical name map. When writing to these parameters, the formula result is recalculated and immediately written to the target register. A side constraint is that the value x was written as well, since last (re-)opening of the device. Note that for most cases with ApplicationCore, enable_push_parameters should be specified, since the order of writes (for x and additional parameters) on recovery is unspecified.
  • Any additional parameter value will be interpreted as a register name of the logical name mapper device. The register value will be made available to the formula by the name of the parameter. Everytime the formula is evaluated, the registers will be read, so the current values are provided. For math plugin writing to target, we allow only LNM variables or constants as parameters. With enable_push_parameters, initial values for variable parameters are not used! The plugin waits until all push-parameters as well as the main value x was written after (re-)opening of the device, before evaluating the formula.

Examples for formulae:

  • x/7 + 13

    This will only work for scalar registers

  • return [ x/7 + 13 ];

    Can be used for both scalars and arrays. In case of an array, the formula will be applied to each element of the array, since exprtk supports processing of arrays (or vectors as they call it in their documentation).

  • Full example with parameters:

    <plugin name="math">
    <parameter name="formula">x*factor + offset</parameter>
    <parameter name="factor">/Calibration/factor</parameter>
    <parameter name="offset">/Calibration/offset</parameter>
    </plugin>

    The registers /Calibration/factor and /Calibration/offset need to be specified in the same xlmap file. They wil be read each time the formula is evaluated (because the plugin register is read or written). Parameter registers can be scalar or 1D arrays.

    Hint: If the parameter register is a variable, it can be written by the application. This allows e.g. the use of calibration value otherwise not known to the device. Variables support AccessMode::wait_for_new_data, hence in combination with the enable_push_parameters parameter, writing to variables can trigger a write to the target register.

forceReadOnly

The forceReadOnly plugin changes the access mode of a register to read-only. The target register has to be writeable. This plugin accepts no parameters.

forcePollingRead

The forcePollingRead plugin changes the access mode of a register from push-type to poll-type. The plugin accepts no parameters. Will do nothing if the register is poll-type allready.

monostableTrigger

The monostableTrigger implements a monostable behaviour triggered by a write transaction. The target register has to be an integral scalar and has to be writeable. The resulting logical register will be write only with the type RegisterInfo::FundamentalType::nodata, i.e. the data written to the register will be discarded. Instead, the "active" value will be written, and after a delay the "inactive" value.

Parameters:

  • milliseconds: Delay in milliseconds.
  • active: The active value to be written before the delay, as unsigned 32 bit integer. Optional, defaults to 1
  • inactive: The inactive value to be written after the delay, as unsigned 32 bit integer. Optional, defaults to 0

Note that writing to the logical register will block for the full duration of the two target write transfers including the delay.

typeHintModifier

The typeHintModifier is a simple plugin to change the type of the mapped variable in logical name mapper's catalogue. It does, however, NOT perform any type conversion on its own.

Parameters:

Double Buffering plugin for the Logical Name Mapper

This plugin provides a way to read values form the double buffering scheme provided by the firmware. The double buffering mechanism is abstracted away behind a read only register. The plugin is enabled from the LogicalNameMapping xlmap file:

<redirectedRegister name="bufferedValue">
<targetDevice>(dummy?map=DoubleBuffer.map)</targetDevice>
<targetRegister>APP.0.DAQ0_BUF0</targetRegister>
<plugin name="doubleBuffer">
<parameter name="secondBuffer"> APP.0.DAQ0_BUF1 </parameter>
<parameter name="enableDoubleBuffering"> ADC.1.WORD_DUB_BUF_ENA </parameter>
<parameter name="currentBufferNumber"> ADC.1.WORD_DUB_BUF_CURR </parameter>
<parameter name="daqNumber">0</parameter>
</plugin>
</redirectedRegister>

This example creates the read only register, bufferedValue. Reading this register returns the value from the current active buffer, hiding away the buffer switching and handshaking tasks under the hood.

The enableDoubleBuffering and currentBufferNumber hook into the corresponding firmware double buffering interface. The optional parameter daqNumber defines the offset used in the enableDoubleBuffering and currentBufferNumber. If not present, the value 0 is assumed.

Notes and CAVEATS:

  • doubleBuffer plugin is not supported for redirectedChannel. The reason we decided against it is that is would be difficult to optimize access to more than one channel. Instead, apply the plugin to the whole 2D area with redirectedRegister, and refer to the logical register in redirectedChannel by targetDevice=this.
  • Current implementation is safe for concurrent readers from the same process, i.e. the double buffering handshake with the firmware begins when first reader starts reading and ends when last reader of the same double buffered region finishes. Regions are identified on the basis of the enableDoubleBuffering. However, current implementation is not safe for concurrent readers from different processes.

bitRange

bitRange enables to split a single variable into one or multiple variables which can be used to manipulate those parts individually without having to deal with bit masks yourself.

Parameters:

  • shift: Position of the first bit of the mask
  • numberOfBits: Length of the mask. Cannot be larger than 32.
  • fractionalBits: Optional, how many of the bits are representing the fractional part of a fixed point value. Defaults to 0. See ChimeraTK::FixedPointConverter() for details.
  • signed: Optional, whether the type represented by numberOfBits is signed. Defaults to false

When used like below on a 32bit register, the redirected register will give access to the upper word of that register.

<plugin name="bitRange">
<parameter name="shift">16</parameter>
<parameter name="numberOfBits">16</parameter>
</plugin>

The snippet below will map the upper word to a signed 16 bit integer

<plugin name="bitRange">
<parameter name="shift">16</parameter>
<parameter name="numberOfBits">16</parameter>
<parameter name="signed">true</parameter>
</plugin>

Notes and CAVEATS:

  • wait_for_new_data is currently not supported
  • When overlapping bit ranges are used in a TransferGroup, the TransferGroup will become read-only since write order of overlapping registers cannot be guaranteed
  • If the target register is writeable, the plugin does read-modify-write if the target register is also readable.