C2000 CLA C Compiler

From Texas Instruments Wiki
Jump to: navigation, search


The CLA Compiler

The goal of the CLA compiler is to implement enough of the C programming environment to make it easier to access the capabilities of the CLA architecture and to make it easier to integrate CLA task code and data into a C28x application.

The compiler is available as part of the regular CCS updates for Codegen Tools v6.1.0 and above.


Overview

The README.txt file included with the codegen contains details on how the CLA compiler's C language implementation and it is highly recommended that you go over this document before you begin coding.

How to Invoke the CLA Compiler

The CLA compiler is invoked using the same command used for compiling C28x code (cl2000[.exe]).
Files that have a .cla extension will be recognized by the compiler as CLA C files. The shell will invoke separate CLA versions of the compiler passes to generate CLA-specific code. The object files generated by the compile can then be linked with C28x objects files to create a C28x/CLA program.
Usage:
    cl2000 -v28 --cla_support=cla0 [other options] file.cla
    cl2000 -v28 --cla_support=cla1 [other options] file.cla
NoteNote: The compiler does not support compiling both CLA AND C28x C files in one invocation. If you are building using a Code Composer Studio project, then this is not a concern. If you are building via a make file or other means then this should be taken into consideration.

CLA C Language Implementation

Characteristics

Language
Supports C only. No C++ or GCC extension support.
Data Types
(NOTE THE DIFFERENCES FROM C28X DATA TYPES!!)
  • char,short - 16 bits.
  • int,long - 32 bits (int is 16 bits on the C28x)
  • float, double, long double - 32 bits
  • pointers - 16 bits (pointers are 22 bits wide on the C28x)
Data Type Restrictions
These types are defined in the CLA for compatibility with C28x constructs. The only supported operations on these types are load/store - other operations, including arithmetic and logic, are not supported
  • long long
  • 64 bit data types

IMPORTANT NOTES:
The CLA and C28x CPU have different type sizes.
  • When declaring data that will be shared by both C28x and CLA use type declarations that will result in objects of the same size.
  • To avoid ambiguity use typedefs for basic types that include size information (eg. int32, uint16, etc)
  • Use type definitions in stdint.h, stdbool.h
The CLA architecture is oriented for 32-bit data types.
  • 16-bit data types incur sign extension overhead and should primarily be used for load/store operations such as reading/writing 16-bit peripherals.
NOTE!! THE CLA COMPILER DOES NOT HAVE 64-BIT TYPE SUPPORT.


Pragmas
The compiler accepts C28x pragmas except for the FAST_FUNC_CALL
C Standard Library
In general, the C standard library is not supported.
abs() and fabs() are supported as intrinsics.
An inline fast floating-point divide is supported.
Keywords
The 'cregister','far', and 'ioport' keywords are not recognized
Intrinsics
The following intrinsics are supported:
  • float __meisqrtf32(float)
  • float __meinvf32(float)
  • float __mminf32(float, float)
  • float __mmaxf32(float, float)
  • void __mswapf(float, float)
  • short __mf32toi16r(float)
  • unsigned short __mf32toui16r(float)
  • float __mfracf32(float)
  • __mdebugstop()
  • __meallow()
  • __medis()
  • __msetflg(unsigned short, unsigned short)
  • __mnop()

Compiler Conventions and Restrictions

C Language

Global Initialization
Defining and initializing global data is not supported.
Since the CLA code is executed in an interrupt driven environment there is no C system boot sequence. As a result, definitions of the form 'int global_var = 5;' are not allowed for variables that are defined globally (outside the scope of a function). Initialization of global data must either be done by the C28x driver code or within a function.
Variables defined as 'const' can be initialized globally. The compiler will create initialized data sections named .const_cla to hold these variables.
The same restriction applies to variables declared as 'static'. Even if the variable is defined within a function.


Function Nesting
On CGT 6.2.x and older, the function call depth was 1 i.e. a task could call a function but a function could not call another. On CGT 6.4.0+ this restriction is no longer present, the call depth is infinite (as long as you have the memory for it). See 'Calling Conventions' below for details.
Recursion
Recursive function calls are not supported.
Function Pointers
Function pointers are not supported.
Other Operations
The following operations are currently not supported due to lack of instruction set support making them expensive to implement. It is not clear that these operations are critical for typical CLA algorithms.
  • Integer divide, modulus
  • Integer unsigned compares


Linker Command File

Stack
Local variables and compiler temps are placed into a scratchpad memory area. On older CGT (before 6.4.0) these variables were accessed directly using the symbols '__cla_scratchpad_start' and '__cla_scratchpad_end' and it was expected that the user would manage this area and define these symbols using a linker command file. In CGT 6.4.0 (and above) these variables are placed in a ".scratchpad" memory section, which the compiler will then partition into local frames, one for the all eight tasks, and one for each leaf function. These local frames will have unique symbols that the compiler will use to access variables.

IMPORTANT NOTES:
Local variables and compiler temps are expected to be placed into a scratchpad memory area "CLAScratch" and accessed directly using the symbols '__cla_scratchpad_start' and '__cla_scratchpad_end' (for CGT 6.2.x and older), while they are placed in ".scratchpad" for CGT 6.4.0 (and above) and the compiler access them relative to the local frame symbol
  • For the legacy memory convention (CGT 6.2.x and older) the user is expected to manage the size of the area and define start/end symbols using a linker command file. For the newer convention (CGT 6.4.0+) this is handled by the compiler
  • This scratchpad serves as a CLA stack.
To allow debug of local variables, the linker .cmd file has been updated from that originally distributed with previous header file releases.
  • Please ensure the right linker file is included in your project: 28xxx_RAM_CLA_C_lnk.cmd
  • The linker file should look like the code shown below.
  • This also required a compiler released after July 21, 2011.


Linker Command File (CGT 6.2.x and older)

The following is an example of what was added to the original linker command file to define the CLA compiler scratchpad memory (legacy convention):
Define the scratchpad size. CLA_SCRATCHPAD_SIZE is a linker defined symbol that can added to the application's linker command file to designate the size of the scratchpad memory. Later, a SECTION's directive can reference this symbol to allocate the scratchpad area. This SECTION's directive reserves a 0x100 word memory hole to be used as the compiler scratchpad area. The value of CLA_SCRATCHPAD_SIZE can be changed based on the application.
Alternatively, the --define linker option can be used to define the CLA_SCRATCHPAD_SIZE symbol and assign it a value (eg. "cl2000 <options> <input files> -z --define CLA_SCRATCHPAD_SIZE=0x100 -lcla_lnk.cmd <other linker arguments>"). Note that the --define option must come before the linker command file.
// Define a size for the CLA scratchpad area that will be used
// by the CLA compiler for local symbols and temps
// Also force references to the special symbols that mark the
// scratchpad area.
 
CLA_SCRATCHPAD_SIZE = 0x100; // If using --define CLA_SCRATCHPAD_SIZE=0x100, remove this line
--undef_sym=__cla_scratchpad_end
--undef_sym=__cla_scratchpad_start
 
.....
MEMORY
{
.....
}
SECTIONS
{
   //
   // Must be allocated to memory the CLA has write access to
   //
   CLAscratch       :
                        { *.obj(CLAscratch)
                        . += CLA_SCRATCHPAD_SIZE;
                        *.obj(CLAscratch_end) } > CLARAM1,  PAGE = 1
}

The scratchpad size can alternatively be defined and altered in the linker options of a project as shown below

Adjusting the Scratchpad size through the linker options


Linker Command File (CGT 6.4.0 and newer)

The following is an example of the linker command file with the new memory convention (CGT 6.4.0+):
The old convention for CLAScratch will still be supported by the new compiler, albeit, inefficiently from a memory allocation standpoint. The new compiler creates a common local frame for the 8 tasks, i.e. each task's local frame is overlayed on top of each other - they use the same memory locations; this is possible since there is no nesting of tasks, so one task cannot corrupt the scratch area of another. By having the CLAScratch memory section, the compiler cannot take advantage of the overlaying strategy and is, instead, forced to allocate each task's locals in separate locations within the scratchpad.
.....
MEMORY
{
.....
}
SECTIONS
{
   //
   // Must be allocated to memory the CLA has write access to
   //
   .scratchpad     : > CLARAM1,  PAGE = 1
}





Memory Model - Sections

CLA Program
The CLA compiler will place CLA code into section "Cla1Prog" as per the current convention used for CLA assembly.
Global Data
Uninitialized global data will be placed in the section ".bss_cla"
Constants
Initialized constant data will be placed in section ".const_cla"
Heap
There is no support for operations such as malloc(). Therefore there is no C system heap for CLA.


Function Structure and Calling Conventions

Function Structure and Calling Conventions (CGT 6.2.x and older)

Function Nesting
The compiler supports 2 level of function calls (the trigger to the task, from a compiler standpoint, is one level). Functions declared as interrupts may call leaf functions only. Leaf function may not call other functions. Functions not declared as interrupt will be considered leaf functions.
Register Calling Convention
The CLA compiler supports calling functions with up to 2 arguments. Pointer arguments are passed in MAR0/MAR1. Integer/float arguments are passed in MR0,MR1. Integer and float return values from functions are passed in MR0. Pointer or return by reference value from functions are passed in MAR0.
Register Save/Restore
All registers except for MR3 are saved on call. MR3 is saved on entry.
Local Variables
A static scratchpad area is used as a stack for locals and compiler temporary variables.
NoteNote: The user is responsible for ensuring the scratchpad area is allocated into the memory map and is large enough. This is done using the linker command file or through the project's linker options(see above).
Mixing CLA C and Assembly
When interfacing with CLA assembly language modules use the calling conventions defined above to interface with compiled CLA code.

Function Structure and Calling Conventions (CGT 6.4.0 and newer)

Function Nesting
The compiler supports an infinite call depth (memory constraints apply).
Register Calling Convention
The CLA compiler supports calling functions with multiple arguments. Pointer arguments are passed in MAR0/MAR1. Integer/float arguments are passed in MR0, MR1 and MR2. Any additional arguments are passed onto the local frame. Integer and float return values from functions are passed in MR0. Pointer or return by reference value from functions are passed in MAR0.
Register Save/Restore
All registers except for MR3 are saved on call. MR3 is saved on entry.
Local Variables
A scratchpad area is used as a stack for locals, compiler temporary variables and passed arguments. A call graph is computed in the linker to determine which function frames can be overlayed in placement to save memory - these are usually the tasks since they can't be nested. All generated function frames are part of the .scratchpad section and are named in the form “.scratchpad:[function section name]”. For example:
  • .scratchpad:Cla1Prog:_Cla1Task2
  • .scratchpad:Cla1Prog:_Cla1Func1
Therefore, the only section that needs to be placed in the linker command file is the .scratchpad section. All function frames that are part of that section will be placed automatically within the .scratchpad placement. It is not necessary to specify a size for the .scratchpad section. Additionally, CLA object files compiled with previous tool versions will be fully compatible with newly generated object files as long as the user supports both scratchpad naming conventions in the linker command file. However, the scratchpad section used for old object files cannot be overlayed with the new .scratchpad section and the user must ensure enough memory is available for both.
Mixing CLA C and Assembly
When interfacing with CLA assembly language modules use the calling conventions defined above to interface with compiled CLA code.




Getting Started

Download the 6.1.0 (and newer) Compiler

For the best experience with the CLA compiler, CCS 5.2 beta 3 or later is strongly recommended. If you have an earlier verison of CCS then there are additional steps that have to be taken.

CCS 5.2 Beta 3 and Later

This beta is expected to be released the week of April 23rd.
The compiler is completely integrated and included in the install. There is no need to download anything additional or perform any manual configuration in Code Composer Studio.

CCS 5.1

  1. Help -> Check for new Software
  2. Click on "Available Software Sites"

    ::Ccs51 compiler update.jpg

  3. In the box enter "code..." and select "Code Generation Tools...."

    ::Ccs51 compiler update site.jpg

  4. Click "next"
  5. Select C2800 Compiler Tools 6.1.0 and click "next"
  6. Accept the license agreement and click "finish"
Later, when you have loaded a project, make sure to select the codegen tool version in the project properties:
  1. Right click on the project
  2. Select properties
  3. Select General
  4. Make sure the compiler specified is 6.1.0 or later.

CCS 4.2.x

Download and install the compiler:
  1. Select: Help->Software Updates
  2. Check: look for new features
  3. Download and install C2000 Code Generation Tools 6.1.0
Register the compiler:
In CCS 4.2.x you may need to register the 6.1.0 compiler before you can import a project. This step is not required in CCS 5.1 or CCS 5.2.If a project import fails, then register the compiler using the following steps:
  1. Open: window->preferences->CCS->Build->Code Generation Tools
  2. Select "Add"
  3. Browse to your install of the 6.1.x compiler and select it
  4. Click "Ok"
  5. Click "Ok"
Register Codegen Tool

Specify the compiler in the project properties
Later, when you have loaded a project, make sure to select the codegen tool version in the project properties:
  1. Right click on the project
  2. Select properties
  3. Select CCS Build
  4. Make sure the compiler specified is 6.1.0 or later.




Associate .cla with 'C'

CCS5.2 (and later)

This step is not needed.

CCS4 and CCS 5.1

CCS 4.2.x and older versions of CCS5 (prior to 5.2) do not recognize the .cla extension natively. If this is the first time using the CLA compiler with these versions of CCS, you will need to modify your workspace a bit.
  1. Go to Windows->Preferences->C/C++->File Types.
  2. Select "New"
  3. Type in *.cla in the top text box
  4. In the drop down menu select C source file(see figure).
  5. Select "ok"
The IDE will now recognize the .cla extension as code to be compiled.
NoteNote: If you create a new workspace you will need to repeat this process.
Workspace Setup




Create Your Own Project

The simplest way to start writing code is to copy over an existing project (from the header files CLA C examples) and to edit it. Lets take an example: I would like to create a new test, atan, from an existing test case exp2
  1. Copy a Project:
    • Make a copy of the exp2 folder in the test directory and rename it to atan
  2. Rename Files:
    • Rename all files exp2*.* to atan*.*. (Notice the naming convention.
    • All files have the test folder name as a prefix, see below)

      Naming Convention of Files

  3. Edit the Project Files:
    • Open the .cdtbuild and .project files in any text editor and replace all instances of the word exp2 with atan.
    • This will ensure all the object files come out with the correct name and any directory dependencies are taken care of.
    • Each project has a predefined symbol, TEST_NAME=<test_name>. For e.g. the exp2 project will have a predefined symbol, TEST_NAME=exp2. By altering the .cdtbuild files in the manner described you wont have to change the build settings for each new project .
  4. Import the Project:
    • Import the atan project into your workspace (see figure below).
    • The files highlighted in the red box are common to all projects and are linked in by the .project file. The rest of the source files are specific to each test case
      C2000 CLA C Compiler ImportedProjectNew.jpg

  5. Modify the Source:
    • Edit the test specific source files.

Suggested Build and Link Options

The following table lists build and link options that may be useful/instructive for CLA C code. You can setup build properties that apply only to *.cla file by right clicking the file and selecting Properties->C/C++ Build.

Option Notes
Basic Options->Debugging Model->Full Symoblic debug (-g) If you would like to access watch variables etc while debugging.
  • This is set by default.
Basic Options->Debugging Model->Suppress all symbolic debug information View compiler generated assembly code without all the debug information.This is useful when estimating the cycle count for a small routine.
Basic Options->Optimization Level = none - O2 NoteNote: Due to the small number of registers available less aggressive optimization may yield better results (eg. -O1 vs -O2).
Assembly Options -> Keep generated assembly files (-k) Useful if you want to compare compiler generated code with hand coded assembly.
Linker Options-> Diagnostics -> --diag_suppress=16002
NoteNote: Object files(created with CGT 5.1 and prior) without build attributes will cause the linker to emit a warning if they are linked with object files that do have build attributes. The purpose of the warning is to let users know that they are responsible for enforcing compatibility between these files. You can suppress this warning using the diag_suppress option


C Language Tips and Tricks

Dealing with Pointers

Pointers are interpreted differently on the C28x and the CLA. The C28x treats them as 32-bit data types (address bus size being 22-bits wide can only fit into a 32-bit data type) while the CLA only has an address bus size of 16 bits. Assume the following structure is declared in a shared header file(i.e. common to the C28 and CLA) and defined and allocated to a memory section in a .c file
/********************************************************************
Shared Header File
********************************************************************/
typedef struct{                                                      
  float a;                                                           
  float *b;                                                          
  float *c;                                                          
}foo;                                                                
/********************************************************************
main.c
********************************************************************/
#pragma(X,"CpuToCla1MsgRam") //Assign X to section CpuToCla1MsgRam   
foo X;                                                               
/********************************************************************
test.cla
********************************************************************/
__interrupt void Cla1Task1 ( void )                                  
{                                                                    
  float f1,f2;                                                       
  f1 = *(X.b);                                                       
  f2 = *(X.c); //Pointer incorrectly dereferenced                    
               //Tries to access location 0x1503 instead             
               //of 0x1504                                           
}
Assume that the C28 compiler will allocate space for X at the top of the section CpuToCla1MsgRam as follows:
Element Address
X.a 0x1500
X.b 0x1502
X.c 0x1504
The CLA compiler will interpret this structure differently
Element Address
X.a 0x1500
X.b 0x1502
X.c 0x1503
The CLA compiler treats pointers b and c as 16-bits wide and, therefore, incorrectly de-references pointer c. The solution to this is to declare a new pointer as follows:
/********************************************************************
Shared Header File
********************************************************************/
typedef union{
  float *ptr; //Aligned to lower 16-bits
  Uint32 pad; //32-bits
}CLA_FPTR;
 
typedef struct{
  float a;
  CLA_FPTR b;
  CLA_FPTR c;
}foo;
 
/********************************************************************
main.c
********************************************************************/
#pragma(X,"CpuToCla1MsgRam") //Assign X to section CpuToCla1MsgRam
foo X;
/********************************************************************
test.cla
********************************************************************/
__interrupt void Cla1Task1 ( void )
{
  float f1,f2;
  f1 = *(X.b.ptr);
  f2 = *(X.c.ptr); //Correct Access
}
The new pointer CLA_FPTR is a union of a 32-bit integer and a pointer to a float. The CLA compiler recognizes the size of the larger of the two elements(the 32 bit integer) and therefore aligns the pointer to the lower 16-bits. Now both the pointers b and c will occupy 32-bit memory spaces and any instruction that tries to de-reference pointer c will access the correct address 0x1504.





Profiling

The CLA does not support the clock function and therefore it is not possible to get a direct cycle count of a particular task. The user can configure the time base module on an ePWM to keep track of the execution time of a task
Setup the time base of ePWM1(or any ePWM) to run at SYSCLKOUT in the up-count mode as shown below:
void InitEPwm(void)
{
  // Setup TBCLK
  EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Count up
  EPwm1Regs.TBPRD = 0xFFFF; // Set timer period
  EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Disable phase loading
  EPwm1Regs.TBPHS.half.TBPHS = 0x0000; // Phase is 0
  EPwm1Regs.TBCTR = 0x0000; // Clear counter
  EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // Clock ratio to SYSCLKOUT
  EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1;
}
Proceed to define two macros READ_CLOCK and RESTART_CLOCK, the former to freeze the ePWM timer and copy the elapsed time to a variable, and the latter to restart the ePWM timer.
#define READ_CLOCK(X) __meallow();\
                      EPwm1Regs.TBCTL.bit.CTRMODE = TB_FREEZE;\
                      X = EPwm1Regs.TBCTR;\
                      __medis();
#define RESTART_CLOCK __meallow();\
                      EPwm1Regs.TBCTL.bit.CTRMODE = TB_FREEZE;\
                      EPwm1Regs.TBCTR = 0;\
                      EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;\
                      __medis();
Define a variable e.g. ulCycleCount to hold the cycle count
#pragma DATA_SECTION(ulCycleCount,"Cla1ToCpuMsgRAM");
unsigned long ulCycleCount;
Place the macro RESTART_CLOCK at the beginning of a task to restart the ePWM timer and place READ_CLOCK at the end of the task to read the value of the timer. The elapsed time will be give you the cycle count plus a minimal overhead from the two macros
__interrupt void Cla1Task1 ( void )
{
  //Local Variables
  float a;
  __mdebugstop();
  RESTART_CLOCK;
  a = 10;
  ...
  ...
  ...
  READ_CLOCK(ulCycleCount);
}

Debugging

The user can follow these steps to start debugging their code on the CLA
  1. Add _mdebugstop()
    • Place an __mdebugstop() at the beginning of the CLA task you wish to debug. For example task 1 of exp2.cla.
  2. Set build options:
    • You can setup individual build properties for the *.cla file seperately from the rest of the application.
    • Right click the .cla file and select Properties->C/C++ Build.
  3. Connect to the CLA:
    • Once you have built your project and launched the debug session CCS, by default, will connect to only the C28 core.
    • To be able to debug CLA code you will need to connect to the CLA core.
    • NoteNote: Build the code with -g (Full Symbolic Debug) to generate the symbols that will be loaded to the debugger.
    1. Click on the CLA debug session (highlighted in figure below)
    2. Select Target->Connect to Target or hit Alt-C.
    3. Once the CLA core is connected proceed to load the project symbols by clicking on Target->Load Symbols-><test>.out (e.g. exp2.out).

      Connecting to the CLA debug session

  4. Run the C28x:
    • In the exp2 example we have enabled task 1 of the CLA and we trigger it in software on the C28 side. When we run the code on the C28 debug session it seems to stall at the Cla1ForceTask1andWait() routine. It is waiting for the CLA task 1 to run to completion. When we switch over to the CLA session we see that execution has stopped at the __mdebustop() intrinsic
  5. Debug the Code:
    • At this point we can proceed to single step through the code.
    • There are some restrictions to debugging the CLA and they are discussed next.

Known Debugging Issues

  1. The CLA pipeline is not flushed on a single step and so results may not be visible until a few instructions later. Please refer to the CLA user guide for more details about the pipeline.
  2. If you plan to debug (single step) code on the CLA it is necessary that MNOPs are placed prior to any MSTOP to ensure the instructions prior to the MSTOP proceed through the pipeline before the MSTOP executes. The compiler will insert these MNOPs if compiling with debug (-g). The MNOPs are unnecessary if you are not debugging the CLA code.(This behavior was verified when running the exp2 project)
  3. Run-to-Line is not supported. Step over works the same as Step into

Compiler Software Collateral

All CLA supported devices will have several demos in the examples folder under their respective device_support directories

Tutorials

The following tutorials are available (zip file below) to help you get started with the CLA compiler. The videos can be accessed from the training site (focus.ti.com/docs/training/catalog/events/event.jhtml) or downloaded from the link below

  1. Tutorial 1: Compiler Basics
  2. Tutorial 2: Example Code Structure
  3. Tutorial 3: Demo
  4. Tutorial 4: Debugging

DOWNLOAD LINK:Tutorial Videos (.zip)

Important Links

CLA C Compiler Training Series
https://training.ti.com/c2000-cla-c-compiler-4-part-series