Host Access of Bitfields and Bools

<< Click to Display Table of Contents >>

Navigation:  ETEC 'C' Compiler Information >

Host Access of Bitfields and Bools

Previous pageReturn to chapter overviewNext page

The ETEC auto-defines file outputs all the necessary information for the host to be able to access bit-fields and _Bool variables. First, say the channel frame includes three _Bool variables:

static _Bool        _b1, _b2, _b3;

The 'defines' auto-generated interface file would contain the following information for these variables:

// 8-bit Channel Variable address offsets 

// address = ((CXCR.CPBA)<<3) + _CPBA8_Test__b1_ 

#define _CPBA8_Test__b1_ 0x00 

#define _CPBA8_BOOLBITOFFSET__b1_ 0x07 

#define _CPBA8_Test__b2_ 0x00 

#define _CPBA8_BOOLBITOFFSET__b2_ 0x06 

#define _CPBA8_Test__b3_ 0x00 

#define _CPBA8_BOOLBITOFFSET__b3_ 0x05 

_Bool variables in the channel frame get packed as bits into 8-bit locations. For each _Bool variable, there is a byte offset from the base of the channel frame, and a bit offset from the start of that byte. Host code to set and clear _Bool bits would then look something like:

char* CPBA; 

// initialize CPBA... 

// set _b1 

*(CPBA + _CPBA8_Test__b1_) |= (0x80 >> _CPBA8_BOOLBITOFFSET__b1_); 

// clear _b2 

*(CPBA + _CPBA8_Test__b2_) &= ~(0x80 >> _CPBA8_BOOLBITOFFSET__b2_); 

// extract _b3 

int b3_val = ((*(CPBA + _CPBA8_Test__b3_) & (0x80 >> _CPBA8_BOOLBITOFFSET__b3_)) != 0) 

Bit-field access is slightly more complicated. Given that bit-fields can be up to 24-bits in width, it is best to access them from the host via 32-bit accesses. For example, say on the eTPU side there is a variable declaration such as:

struct S1 

   unsigned int x : 4; 

   unsigned int y : 20; 

}; 

struct S1 g_S1;

Then the 'defines' auto-generated file would contain the following information:

// defines for type struct S1 

// size of a tag type 

// value (sizeof) = _GLOB_TAG_TYPE_SIZE_S1_ 

#define _GLOB_TAG_TYPE_SIZE_S1_ 0x03 

// offset of struct/union members from variable base location 

// the offset of bitfields is specified in bits, otherwise it is bytes 

// address = SPRAM + [variable SPRAM offset] + _GLOB_MEMBER_BITOFFSET_S1_x_ 

#define _GLOB_MEMBER_BITOFFSET_S1_x_ 0x14 

#define _GLOB_MEMBER_BITSIZE_S1_x_ 0x04 

#define _GLOB_MEMBER_BITOFFSET_S1_y_ 0x00 

#define _GLOB_MEMBER_BITSIZE_S1_y_ 0x14 

 

// Global Struct/Union Variable address 

// address = SPRAM + _GLOB_STRUCT_g_S1_ 

#define _GLOB_STRUCT_g_S1_ 0x01 

Given the above, the host can write to, and read from bit fields using code like the following:

uint32* SPRAM; 

// initialize SPRAM... 

#define _S1_X_WORD_OFFSET ((((_GLOB_STRUCT_g_S1_ & 3) * 8) + _GLOB_MEMBER_BITOFFSET_S1_x_) / 32) // word offset within structure 

#define _S1_X_WORD_MSB_BITOFFSET ((((_GLOB_STRUCT_g_S1_ & 3) * 8) + _GLOB_MEMBER_BITOFFSET_S1_x_) - _S1_X_WORD_OFFSET*32) 

#define _S1_X_WORD_LSB_BITOFFSET (32 - _S1_X_WORD_MSB_BITOFFSET - _GLOB_MEMBER_BITSIZE_S1_x_) 

#define _S1_X_MASK (((1 << _GLOB_MEMBER_BITSIZE_S1_x_) ? 1) << S1_X_WORD_LSB_BITOFFSET) 

 

// read g_S1.x 

uint32 X = (*(SPRAM + (_GLOB_STRUCT_g_S1_ >> 2) + _S1_X_WORD_OFFSET) & _S1_X_MASK) >> _S1_X_WORD_LSB_BITOFFSET; 

// write g_S1.x 

// NOTE: this is not coherent!! Use CDC if coherency required!! 

// clear bit-field first 

*(SPRAM + (_GLOB_STRUCT_g_S1_ >> 2) + _S1_X_WORD_OFFSET) &= ~_S1_X_MASK; 

// write in new value 

*(SPRAM + (_GLOB_STRUCT_g_S1_ >> 2) + _S1_X_WORD_OFFSET) = (X << _S1_X_WORD_LSB_BITOFFSET) & _S1_X_MASK;