Main Content

Storage Containers

Introduction

While coding with the API for user-written fixed-point S-functions, it is important to keep in mind the difference between storage container size, storage container word length, and signal word length. The sections that follow discuss the containers used by the API to store signals in simulation and code generation.

Storage Containers in Simulation

In simulation, signals are stored in one of several types of containers of a specific size.

Storage Container Categories

During simulation, fixed-point signals are held in one of the types of storage containers, as shown in the following table. In many cases, signals are represented in containers with more bits than their specified word length.

Fixed-Point Storage Containers

Container Category

Signal
Word Length

Container Word Length

Container Size

FXP_STORAGE_INT8 (signed)
FXP_STORAGE_UINT8 (unsigned)

1 to 8 bits

8 bits

1 byte

FXP_STORAGE_INT16 (signed)
FXP_STORAGE_UINT16 (unsigned)

9 to 16 bits

16 bits

2 bytes

FXP_STORAGE_INT32 (signed)
FXP_STORAGE_UINT32 (unsigned)

17 to 32 bits

32 bits

4 bytes

FXP_STORAGE_OTHER_SINGLE_WORD

33 to word length of long data type

Length of long data type

Length of long data type

FXP_STORAGE_MULTIWORD

Greater than the word length of long data type to 128 bits

Multiples of length of long data type to 128 bits

Multiples of length of long data type to 128 bits

When the number of bits in the signal word length is less than the size of the container, the word length bits are always stored in the least significant bits of the container. The remaining container bits must be sign extended:

  • If the data type is unsigned, the sign extension bits must be cleared to zero.

  • If the data type is signed, the sign extension bits must be set to one for strictly negative numbers, and cleared to zero otherwise.

For example, a signal of data type sfix6_En4 is held in a FXP_STORAGE_INT8 container. The signal is held in the six least significant bits. The remaining two bits are set to zero when the signal is positive or zero, and to one when it is negative.

A signal of data type ufix6_En4 is held in a FXP_STORAGE_UINT8 container. The signal is held in the six least significant bits. The remaining two bits are always cleared to zero.

The signal and storage container word lengths are returned by the ssGetDataTypeFxpWordLength and ssGetDataTypeFxpContainWordLen functions, respectively. The storage container size is returned by the ssGetDataTypeStorageContainerSize function. The container category is returned by the ssGetDataTypeStorageContainCat function, which in addition to those in the table above, can also return the following values.

Other Storage Containers

Container Category

Description

FXP_STORAGE_UNKNOWN

Returned if the storage container category is unknown

FXP_STORAGE_SINGLE

The container type for a Simulink® single

FXP_STORAGE_DOUBLE

The container type for a Simulink double

FXP_STORAGE_SCALEDDOUBLE

The container type for a data type that has been overridden with Scaled double

Storage Containers in Simulation Example

An sfix24_En10 data type has a word length of 24, but is actually stored in 32 bits during simulation. For this signal,

Storage Containers in Code Generation

The storage containers used by this API for code generation are not always the same as those used for simulation. During code generation, a native C data type is always used. Floating-point data types are held in C double or float. Fixed-point data types are held in C signed and unsigned char, short, int, or long.

Emulation

Because it is valuable for rapid prototyping and hardware-in-the-loop testing, the emulation of smaller signals inside larger containers is supported in code generation. For example, a 29-bit signal is supported in code generation if there is a C data type available that has at least 32 bits. The rules for placing a smaller signal into a larger container, and for dealing with the extra container bits, are the same in code generation as for simulation.

If a smaller signal is emulated inside a larger storage container in simulation, it is not necessarily emulated in code generation. For example, a 24-bit signal is emulated in a 32-bit storage container in simulation. However, some DSP chips have native support for 24-bit quantities. On such a target, the C compiler can define an int or a long to be exactly 24 bits. In this case, the 24-bit signal is held in a 32-bit container in simulation, and in a 24-bit container in code generation.

Conversely, a signal that was not emulated in simulation might need to be emulated in code generation. For example, some DSP chips have minimal support for integers. On such chips, char, short, int, and long might all be defined to 32 bits. In that case, it is necessary to emulate 8- and 16-bit fixed-point data types in code generation.

Storage Container TLC Functions

Since the mapping of storage containers in simulation to storage containers in code generation is not one-to-one, the Target Language Compiler (TLC) functions for storage containers are different from those in simulation:

  • FixPt_DataTypeNativeType

  • FixPt_DataTypeStorageDouble

  • FixPt_DataTypeStorageSingle

  • FixPt_DataTypeStorageScaledDouble

  • FixPt_DataTypeStorageSInt

  • FixPt_DataTypeStorageUInt

  • FixPt_DataTypeStorageSLong

  • FixPt_DataTypeStorageULong

  • FixPt_DataTypeStorageSShort

  • FixPt_DataTypeStorageUShort

  • FixPt_DataTypeStorageMultiword

The first of these TLC functions, FixPt_DataTypeNativeType, is the closest analogue to ssGetDataTypeStorageContainCat in simulation. FixPt_DataTypeNativeType returns a TLC string that specifies the type of the storage container, and the Simulink Coder™ product automatically inserts a typedef that maps the string to a native C data type in the generated code.

For example, consider a fixed-data type that is held in FXP_STORAGE_INT8 in simulation. FixPt_DataTypeNativeType will return int8_T. The int8_T will be typdef'd to a char, short, int, or long in the generated code, depending upon what is appropriate for the target compiler.

The remaining TLC functions listed above return TRUE or FALSE depending on whether a particular standard C data type is used to hold a given API-registered data type. Note that these functions do not necessarily give mutually exclusive answers for a given registered data type, due to the fact that C data types can potentially overlap in size. In C,

sizeof(char) ≤ sizeof(short) ≤ sizeof(int) ≤ sizeof(long).

One or more of these C data types can be, and very often are, the same size.