Code Generation Tools Tips & Tricks For All TI Code Generation Tools July 2008 1 Actually Read the Readme • • • • • This talk only covers the highlights Many more features covered in the readme files Critical detail as well Well worth the 1 hour it takes to read it Find it at install\target\readme.1st – install: Directory where CCS is installed – target: C2000, C5400, C5500, C6000, or tms470 2 Agenda • • • • • • • • • • • • 3 Recommended Development Flow Types and Alignment 16 x 16 Î 32 Multiply Memory Models Diagnostics C Headers in Assembly Object Format vs. Debug Format More Useful Utilities Interrupt Intrinsics Predefined Symbols for Version Remaining Tips Top 10 Mistaken Ideas Characterize Common Problems • Common problems seen when learning C/C++ • Difference between == and = • Must use int when comparing to EOF getchar(); cc == getchar(); while (c (c != != EOF) EOF) // // cc must must be be type type int int while {{ …… getchar(); cc == getchar(); }} • 1.0 is a double • This talk covers a similar class of issues commonly seen by users new to TI compilers 4 Recommended Development Flow Start No Edit Compile -g Debug Works? Yes No Done Yes Goals Met? • Separate use of –g and -o 5 Profile Compile -o Optimization vs. Debug • As one improves the other degrades • If you combine them together … • Effects on debugging – Operations reordered – Variables eliminated • Effects on performance – Instruction scheduling is impaired • Compare performance -o vs. –o -g – C6x MP3 decoder – -o runs 16% faster than –o -g 6 Optimization Levels Option Scope Default None -o0 Statement -o1 Block -o2 or -o Function -o3 File low high • Optimization is critical! • Not on by default • Option is –olevel where level is 0-3 • Start with level 2 7 More Optimization Hints • Optimization may uncover user errors like: – Uninitialized variables – Loose adherence to ANSI standard – Failure to use volatile • Use volatile on variables modified by: – Interrupts – Peripherals – Other processors • volatile controls order of access, not timing 8 Agenda • • • • • • • • • • • • 9 Recommended Development Flow Types and Alignment 16 x 16 Î 32 Multiply Memory Models Diagnostics C Headers in Assembly Object Format vs. Debug Format More Useful Utilities Interrupt Intrinsics Predefined Symbols for Version Remaining Tips Top 10 Mistaken Ideas Type Sizes by CPU Hosted C6000TM 470 C55xTM C28xTM char 8 8 8 16 16 short 16 16 16 16 16 int 32 32 32 16 16 long 32 40 32 32 32 long long 64 64 64 40 32 float 32 32 32 32 32 double 64 64 64 32 32 long double 64 64 64 32 32 Type • Shaded sizes Æ different from hosted systems 10 Type Differences • Because char is 16-bits on C55xTM and C28xTM – sizeof(int) == sizeof(char) == 1 – Redefines the term byte – 8-bit wide external streams must be handled carefully – Application note SPRA757 on fread()/fwrite() • On 470 plain char is unsigned – Use plain char only for ASCII chars • Floating point is very slow on CPU’s without hardware support 11 Standard Integer Typedefs • stdint.h defines standard names for exact width integer types #if #if defined(__TMS320C2000__) || || defined(_TMS320C5XX) defined(_TMS320C5XX) \\ defined(__TMS320C2000__) || defined(__TMS320C55X__) defined(__TMS320C55X__) || typedef int int16_t; typedef int int16_t; typedef unsigned unsigned int int uint16_t; uint16_t; typedef typedef long int32_t; int32_t; typedef long typedef unsigned unsigned long long uint32_t; uint32_t; typedef #elif defined(_TMS320C6X) defined(_TMS320C6X) || || defined(__TMS470__) defined(__TMS470__) #elif typedef signed signed char char int8_t; int8_t; typedef typedef unsigned unsigned char char uint8_t; uint8_t; typedef typedef short int16_t; int16_t; typedef short typedef unsigned unsigned short short uint16_t; uint16_t; typedef typedef int int32_t; typedef int int32_t; typedef unsigned unsigned int int uint32_t; uint32_t; typedef #elif defined(__MSP430__) defined(__MSP430__) #elif …… • Other typedefs: minimum width, fastest, etc. • No need to define your own 12 inttypes.h • Another header file for standardizing types • Includes stdint.h • Also defines printf format strings #include <inttypes.h> <inttypes.h> #include …… printf(“%” PRId32 PRId32 “\n”, “\n”, (int32_t) (int32_t) 1); 1); // // portable portable printf(“%” Printf(“%d\n”, (int32_t) (int32_t) 1); 1); // not not portable portable Printf(“%d\n”, // – Note careful use of commas in first printf 13 Alignment & Structures • Alignment is different from hosted systems • Misaligned access – x86: Works but imposes cycle penalty – TI CPUs: Fails silently • TI CPUs alignment == size of type (few exceptions) • Structures are laid out differently between CPU’s – – – – 14 Order of members is guaranteed Any member, or the whole struct, may be aligned No method for packing data in structs Affects exchanging data with external sources Agenda • • • • • • • • • • • • 15 Recommended Development Flow Types and Alignment 16 x 16 Î 32 Multiply Memory Models Diagnostics C Headers in Assembly Object Format vs. Debug Format More Useful Utilities Interrupt Intrinsics Predefined Symbols for Version Remaining Tips Top 10 Mistaken Ideas 16 X 16 Î 32 Multiply • Do not write … long_var = short_var1 * short_var2; • Instead write … long_var = (long) short_var1 * (long) short_var2; • • • • Very important when sizeof(int) != sizeof(long) Accurately represents operation Implemented efficiently Details in application note SPRA683 – Search for SPRA683 at www.ti.com 16 Agenda • • • • • • • • • • • • 17 Recommended Development Flow Types and Alignment 16 x 16 Î 32 Multiply Memory Models Diagnostics C Headers in Assembly Object Format vs. Debug Format More Useful Utilities Interrupt Intrinsics Predefined Symbols for Version Remaining Tips Top 10 Mistaken Ideas Understanding Memory Models Large Small Full Partial Code Size Larger Smaller Speed Slower Faster See docs Default Memory Range To enable 18 Understanding Memory Models 19 CPU Extends Because C6000TM Code PC-relative branches C6000TM Data DP-offset global variables C55xTM Data 2 ways to access globals 2 sizes of address registers C28xTM Data 2 sizes of address registers Agenda • • • • • • • • • • • • 20 Recommended Development Flow Types and Alignment 16 x 16 Î 32 Multiply Memory Models Diagnostics C Headers in Assembly Object Format vs. Debug Format More Useful Utilities Interrupt Intrinsics Predefined Symbols for Version Remaining Tips Top 10 Mistaken Ideas Compiler Diagnostics Remark Warning Error Severity Low Medium High Build fails? No No Yes To enable -pdr Default Default • Is it okay to ignore remarks? 21 Automatic Error Detection • Remarks expose common bugs • This complete program compiles fine void main() main() {{ printf(“hello, printf(“hello, world\n”); world\n”); }} void • But doesn’t work • Compile with –pdr to see remarks “hello.c”, line line 1: 1: remark: remark: function function declared declared implicitly implicitly “hello.c”, • Always build with –pdr! • Take remarks seriously • Always include required RTS header files #include <stdio.h> <stdio.h> #include • Always prototype user functions 22 Elevate Remark to Error • Force remark to cause build to fail • Use 2 separate compilation steps • First, use –pden –pdr to see remark number "hello.c", line line 1: 1: remark remark #225-D: #225-D: function function declared declared implicitly implicitly "hello.c", • Second, use –pdsenum to elevate the remark • In this case –pdse225 gives "hello.c", line line 1: 1: error: error: function function declared declared implicitly implicitly "hello.c", error detected detected in in the the compilation compilation of of "hello.c". "hello.c". 11 error >> Compilation Compilation failure failure >> • Can use –pdse225, without –pdr, on all builds 23 Control Diagnostic Levels • First identify diagnostic id with -pden Set level to: Remark Option -pdsrid #pragma #pragma diag_remark id Warning -pdswid #pragma diag_warning id Error -pdseid #pragma diag_error id Default none -pdsid #pragma diag_default id Suppress #pragma diag_suppress id • Diagnostics with “-D” appended to id can be suppressed or changed – All warnings and remarks – A few errors • #pragma is alternative to -pdsXXX • #pragma provides line by line control 24 Diagnostic Control Example int ex(int i) { switch (i) { case 10 : return val(); break; /* line 7 */ /* line 9 */ … } } C:\dir> cl55 –pden –pdr ex.c "ex.c", line 7: remark #225-D: function declared implicitly "ex.c", line 9: warning #112-D: statement is unreachable 25 Diagnostic Control Example #pragma diag_error 225 /* Require explicit function decls int ex(int i) { switch (i) { case 10 : return val(); /* line 7 #pragma diag_suppress 112 /* suppress msg on break break; /* line 9 #pragma diag_default 112 /* restore msg level … } } C:\dir> cl55 –pden –pdr ex.c "ex.c", line 7: error #225-D: function declared implicitly 1 error detected in the compilation of "ex.c". >> Compilation failure • #pragma is alternative to -pdsXXX • #pragma provides precise control 26 */ */ */ */ */ Verbose Diagnostics -pdv • For this source line extern struct struct example; example; extern • The diagnostic is “ex.c", line line 1: 1: warning: warning: aa storage storage class class may may not not be be specified specified here here “ex.c", • To avoid confusion add -pdv “ex.c", line line 1: 1: warning: warning: aa storage storage class class may may not not be be specified specified here here “ex.c", extern struct struct example; example; extern ^^ 27 Agenda • • • • • • • • • • • • 28 Recommended Development Flow Types and Alignment 16 x 16 Î 32 Multiply Memory Models Diagnostics C Headers in Assembly Object Format vs. Debug Format More Useful Utilities Interrupt Intrinsics Predefined Symbols for Version Remaining Tips Top 10 Mistaken Ideas C Headers in Assembly .cdecls optional optional parameters parameters .cdecls %{ %{ /* C/C++ C/C++ code code here, here, usually usually #include’s #include’s */ */ /* %} %} • Converted constructs (usually found in .h files) – function/variable declarations (prototypes) – structs, unions, enumerations – Non-function-like macros • NOT converted – function/variable definitions – function-like macros • • • • 29 Each .cdecls region is separate context Conversion after pre-processing Option to warn on each construct NOT converted Includes generated assembly code in listing file How C/C++ is Transformed hd.h #define WANT_ID 1 #define NAME ”Jari\n” extern int var; extern float cvt(int src); struct duo { int ifld; float ffld; }; enum status { OK = 1, FAIL = 256 }; 30 .cdecls C, LIST, “hd.h” ----------------------------.define ”1”, WANT_ID .define ”””Jari\n”””, NAME .global _var .global _cvt duo .struct 0, ifld .field 16 .field 16 ffld .field 32 .endstruct status .enum OK .emember FAIL .emember .endenum 2 ; pretty and ; informative ; comments 1 256 Typical Usage hd.h #define WANT_ID 1 #define NAME ”Jari\n” extern int var; extern float cvt(int src); struct duo { int ifld; float ffld; }; enum status { OK = 1, FAIL = 256 }; 31 .cdecls C, LIST, ”hd.h” .data .if $defined(WANT_ID) id: .cstring NAME .endif .bss data, $sizeof(duo) data: .tag duo ... hope: AR1 = #data AC0 = *AR1(#(duo.ifld)) << 16 dbl(*AR1(#(duo.ffld))) = AC0 AR0 = #id T0 = #(status.OK) return Agenda • • • • • • • • • • • • 32 Recommended Development Flow Types and Alignment 16 x 16 Î 32 Multiply Memory Models Diagnostics C Headers in Assembly Object Format vs. Debug Format More Useful Utilities Interrupt Intrinsics Predefined Symbols for Version Remaining Tips Top 10 Mistaken Ideas Object Format vs. Debug Format • COFF and ELF are object file formats • Stabs and Dwarf are debug information formats • Unfortunately, sometimes the term COFF is used to refer to Stabs debug format • Object file formats – All current tools support COFF – Future tools will support ELF • Debug file formats – Tools before CCS 2.2 supported only Stabs – CCS 2.2 tools support Stabs (default) and Dwarf – CCS 3.1 tools support Dwarf (default) and Stabs (deprecated) – Future tools will support Dwarf only 33 Agenda • • • • • • • • • • • • 34 Recommended Development Flow Types and Alignment 16 x 16 Î 32 Multiply Memory Models Diagnostics C Headers in Assembly Object Format vs. Debug Format More Useful Utilities Interrupt Intrinsics Predefined Symbols for Version Remaining Tips Top 10 Mistaken Ideas More Useful Utilities • nmXX: Lists symbol table in .out or .obj file • stripXX: Strips symbol and debug information from .out file • demXX: Demangles symbols into their C++ form • disXX: Disassembler – Not on some ISA’s • Replace XX with the abbreviation for your ISA, e.g. nm6x, strip55, etc. • Documented in online help 35 Agenda • • • • • • • • • • • • 36 Recommended Development Flow Types and Alignment 16 x 16 Î 32 Multiply Memory Models Diagnostics C Headers in Assembly Object Format vs. Debug Format More Useful Utilities Interrupt Intrinsics Predefined Symbols for Version Remaining Tips Top 10 Mistaken Ideas Interrupt Intrinsics • For enabling/disabling interrupts unsigned int int _disable_interrupts(); _disable_interrupts(); // 33 cycles cycles on on C6000 C6000 unsigned // unsigned int int _enable_interrupts(); _enable_interrupts(); // 33 cycles cycles on on C6000 C6000 unsigned // void _restore_interrupts(unsigned int); int); // // 11 cycle cycle on on C6000 C6000 void _restore_interrupts(unsigned • Disable and enable return interrupt state before change; use that value when restoring state • Barriers to optimization • Usage example … unsigned int int local; local; unsigned local == _disable_interrupts(); _disable_interrupts(); local if (sem) (sem) sem--; sem--; /* atomic atomic test/update test/update of of semaphore semaphore */ */ if /* _restore_interrupts(local); _restore_interrupts(local); • Replacement for HWI_disable(), HWI_restore() – Faster. HWI_disable on C64x takes 16 cycles. • Cycle counts given are “best case” numbers 37 – Ignores cache effects, memory latency, etc. Agenda • • • • • • • • • • • • 38 Recommended Development Flow Types and Alignment 16 x 16 Î 32 Multiply Memory Models Diagnostics C Headers in Assembly Object Format vs. Debug Format More Useful Utilities Interrupt Intrinsics Predefined Symbols for Version Remaining Tips Top 10 Mistaken Ideas Predefined Symbols for Version • __TI_COMPILER_VERSION__ and __TI_ASSEMBLER_VERSION__ • Returns int corresponding to compiler version • Version number breaks down: – – – – Major number (1-2 digits) Minor version (3 digits) Patch version (3 digits) Example: v5.1.0 Î 5 001 000 Î 5001000 • Workaround compiler bugs #if defined(_TMS320C6X) defined(_TMS320C6X) && && __TI_COMPILER_VERSION__ __TI_COMPILER_VERSION__ == == 5001000 5001000 #if workaround C6x C6x compiler compiler bug bug workaround #endif #endif • Target independent test for TI compiler #if defined(__TI_COMPILER_VERSION__) defined(__TI_COMPILER_VERSION__) #if does not not work work with with older older compilers! compilers! does #endif #endif 39 Agenda • • • • • • • • • • • • 40 Recommended Development Flow Types and Alignment 16 x 16 Î 32 Multiply Memory Models Diagnostics C Headers in Assembly Object Format vs. Debug Format More Useful Utilities Interrupt Intrinsics Predefined Symbols for Version Remaining Tips Top 10 Mistaken Ideas Remaining Tips • C++ code is usually very efficient • Avoid asm() statements. Instead: – Use intrinsics int_prod = – Call assembly routines _smpy(int_op1, int_op2); // C6000 • #pragma is compiler specific and does not port • C++ is not a proper superset of C – http://david.tribble.com/text/cdiffs.htm (link) • Manuals online – http://www.ti.com/sc/docs/psheets/man_dsp.htm (link) • C FAQ – http://www.eskimo.com/~scs/C-faq/faq.html (link) • C++ FAQ – http://www.parashift.com/c++-faq-lite (link) 41 Agenda • • • • • • • • • • • • 42 Recommended Development Flow Types and Alignment 16 x 16 Î 32 Multiply Memory Models Diagnostics C Headers in Assembly Object Format vs. Debug Format More Useful Utilities Interrupt Intrinsics Predefined Symbols for Version Remaining Tips Top 10 Mistaken Ideas Top 10 Mistaken Ideas 1. Development: Embedded == Hosted 2. Don’t worry about memory placement 3. Ignore remarks (-pdr) 4. Optimization does not matter 5. It’s easy to debug optimized code 6. 8-bit char is ANSI standard 7. Structures work the same across all processors 8. Default memory model is always big enough 9. Ignore linker warnings (–w) 10. Global variables are initialized to 0 43