Presentation is loading. Please wait.

Presentation is loading. Please wait.

* 07/16/96 This presentation will probably involve audience discussion, which will create action items. Use PowerPoint to keep track of these action items.

Similar presentations


Presentation on theme: "* 07/16/96 This presentation will probably involve audience discussion, which will create action items. Use PowerPoint to keep track of these action items."— Presentation transcript:

1 * 07/16/96 This presentation will probably involve audience discussion, which will create action items. Use PowerPoint to keep track of these action items during your presentation In Slide Show, click on the right mouse button Select “Meeting Minder” Select the “Action Items” tab Type in action items as they come up Click OK to dismiss this box This will automatically create an Action Item slide at the end of your presentation with your points entered. Process for systematic conversion of a design in “C-pseudo code” to SHARC assembly code M. Smith, Electrical and Computer Engineering, University of Calgary, Canada ucalgary.ca *

2 To be tackled today Example conversion of “C” program into ADSP21061 using a standard procedure Take into account register architecture Take into account LOAD/STORE architecture Take into account standard assembly code problems Handle Program Flow Constructs Then do conversion of code on line by line basis Learning why to avoid calling “C” from assembly 12/8/2018 ENCM Process for “pseudo-C” design to 21k assembly Copyright

3 SHARC process -- Respect the registers that the “C” compiler uses
Volatile Registers (not used by “C” compiler -- destroyed by “C”) R0, R1, R (also F0, F1, F2) R4, I4, M (also F4) (S.O.T.T.) R (also F8) (S.O.T.T.) R12, I12, M12 (also F12) (S.O.T.T.) S.O.T.T. means Some Of The Time -- special issues Non-volatile Registers (used by “C” compiler) EVERYTHING ELSE SHARC PROCESS -- Save and recover NON-VOLATILE registers 12/8/2018 ENCM Process for “pseudo-C” design to 21k assembly Copyright

4 3 parts of SHARC process to obtain “C” compatible assembly language code
PROLOGUE <- Always the “same” CODY BODY EPILOGUE <- Always the “same” Always the “same” means that you learn to write the code once and then use with only minor modification each time you write code in the future Just the same as with 68K “C”/assembly compatibly taught in ENMCM415. 12/8/2018 ENCM Process for “pseudo-C” design to 21k assembly Copyright

5 STANDARD SHARC PROCESS
We want to have a PROCESS to convert the basic parts of a design in “C” pseudo-code to SHARC 21k assembly code Minimize ERRORS -- jumping backwards and forwards between editor, assembler and linker while developing a prototype ERRORs become the big time waster when jumping to and from the simulator while testing this prototype. Minimize DEFECTS -- Defects are the carry over of the mistakes from one apparently working prototype into another protype -- HUGE TIME WASTER 12/8/2018 ENCM Process for “pseudo-C” design to 21k assembly Copyright

6 Remember the 5-OR-60 rule Spend enough time in design and code review.
An EXTREME PROGRAMMING APPROACH with 5 minutes for design and code review will save you 60 minutes during testing. What’s enough time? -- SEI INDUSTRY VALIDATION 12/8/2018 ENCM Process for “pseudo-C” design to 21k assembly Copyright

7 SHARC code -- FM-STEREO Example
AM - amplitude modulation -- typically MONO Carrier with varying amplitude Mix to bring to base frequency then rectify FM - frequency modulation Carrier with varying frequency/phase Use FM demodulator to convert frequency changes into amplitude changes Get DC components ( kHz) plus an AM modulated carrier ( khz) Channel 1 -- Left sound + Right Sound from DC Channel 2 -- Left Sound - Right Sound from carrier 12/8/2018 ENCM Process for “pseudo-C” design to 21k assembly Copyright

8 void DecodeFMSTEREO(int, int *, int *)
void DecodeFMSTEREO(int channel_two_strength, int *channel_one, int *channel_two) { int temp_one = *channel_one; int temp_two = *channel_two; static int comment = 0; if (!comment) { Jump to “C” -- printf( ) -- why code the slow and obvious printf("Smith DecodeFMStereo() -- FM_STEREO demodulation example"); comment = 1; } // If Channel Strength is too weak then just use channel_one on both channels if (channel_two_strength < 25) *channel_two = *channel_one; // L + R else { *channel_one = (temp_one + temp_two) >> 1; // L+ R +(L - R) *channel_two = (temp_one - temp_two) >> 1; // L+ R - (L - R) 12/8/2018 ENCM Process for “pseudo-C” design to 21k assembly Copyright

9 SHARC PROCESS -- STEP 1A Convert C-design to account for RISC architecture
void DecodeFMSTEREO(int channel_two_strength, int *channel_one, int *channel_two) { ON SHARC -- First three subroutine parameters are PLACED in DATA registers even if the parameters are copies of values of pointer registers (index registers) void DecodeFMSTEREO(register int channel_two_strength, register int *channel_one, register int *channel_two) { 12/8/2018 ENCM Process for “pseudo-C” design to 21k assembly Copyright

10 register int temp_one = *channel_one;
SHARC PROCESS -- STEP 1B Convert C-design to account for RISC architecture int temp_one = *channel_one; int temp_two = *channel_two; static int comment = 0; if (!comment) { ……………. } BECOMES register int temp_one = *channel_one; register int temp_two = *channel_two; static int comment = 0; <- must be stored in memory and not register if (comment == 0) { <- Got to be specific when writing assembly ………... 12/8/2018 ENCM Process for “pseudo-C” design to 21k assembly Copyright

11 static int comment = 0; <- Must be stored in memory -- not register
SHARC PROCESS -- STEP 1C Convert C-design to account for RISC architecture static int comment = 0; <- Must be stored in memory and not register if (comment != 0) { <- Tests can’t be done on memory values printf( ); in a RISC processor architecture comment = 1; } BECOMES static int comment = 0; <- Must be stored in memory -- not register register int temp_comment; temp_comment = comment; <- Grab the value from memory if (temp_comment == 0) { <- Test using a register printf( ); comment = 1; <- Still okay in THIS RISC architecture ENDIF: <- Must add this to handle assembly code GOTO structure 12/8/2018 ENCM Process for “pseudo-C” design to 21k assembly Copyright

12 SHARC PROCESS -- STEP 1D Convert C-design to account for RISC architecture
if (channel_two_strength < 25) *channel_two = *channel_one; else { *channel_one = (temp_one + temp_two) >> 1; *channel_two = (temp_one - temp_two) >> 1; } BECOMES register int temp_constant; temp_constant = 25; ***************!!!!!*****!!!!!********* if (channel_two_strength < temp-constant) *channel_two = *channel_one; *channel_one = (temp_one + temp_two); *channel_one = *channel_one >> 1; *channel_two = (temp_one - temp_two); *channel_two = *channel_two >> 1; 12/8/2018 ENCM Process for “pseudo-C” design to 21k assembly Copyright

13 *channel_one = (temp_one + temp_two);
void DecodeFMSTEREO(register int channel_two_strength, register int *channel_one, register int *channel_two) { register int temp_one = *channel_one; register int temp_two = *channel_two; register temp_value; static int comment = 0; temp_value = comment; if (temp_value == 0) { WARNING -- SPECIAL CASE printf("Smith DecodeFMStereo() -- FM_STEREO demodulation example"); comment = 1; } else /* DO NOTHING */; WARNING -- MUST ADD THIS temp_value = 25; if (channel_two_strength < temp_value) *channel_two = *channel_one; else { *channel_one = (temp_one + temp_two); *channel_one = *channel_one >> 1; *channel_two = (temp_one - temp_two); *channel_two = *channel_two >> 1; } 12/8/2018 ENCM Process for “pseudo-C” design to 21k assembly Copyright

14 SHARC PROCESS -- STEP 2 Develop the subroutine PROLOGUE
void DecodeFMSTEREO(register int channel_two_strength, register int *channel_one, register int *channel_two) { register int temp_one = *channel_one; register int temp_two = *channel_two; register temp_value; Incoming register int channel_two_strength -- INPAR1 -- in R4 -- leave it there Incoming register int *channel_one -- INPAR2 -- in R8 -- CAN’T leave it there Must move into volatile DM pointer -- I4 Incoming register int *channel_two -- INPAR3 -- in R12 -- CAN’T leave it there Must move into volatile DM pointer -- BUT I4 already in use register int temp_one = *channel_one; Allowed in R1? register int temp_two = *channel_two; Allowed in R2? register temp_value; Allowed in R3? 12/8/2018 ENCM Process for “pseudo-C” design to 21k assembly Copyright

15 Make use of a standard format for register names -- “cdefines.i”
#define scratchR0 R0 (WARNING -- also retvalueR0) #define scratchR1 R1 #define scratchR2 R2 #define scratchF1 F1 (WARNING -- identical to R1 for storage) #define scratchF2 F2 (WARNING -- identical to R2 for storage) #define scratchDMpt I4 #define scratchDMmod M4 #define scratchPMpt I12 (WARNING -- Program Memory DAG) #define scratchPMmod M (WARNING -- Program Memory DAG) #define INPAR1_R4 R4 (WARNING -- DATA register NOT POINTER) #define INPAR2_R8 R even when used to pass copy of pointer #define INPAR3_R12 R12 #define scratchR4 R4 etc. 12/8/2018 ENCM Process for “pseudo-C” design to 21k assembly Copyright

16 SHARC PROCESS -- STEP 2A Develop the subroutine PROLOGUE
// Show the parameters being passed as part of documentation #define channel_two_strengthR4 scratchR4 // Same as INPAR1 void DecodeFMSTEREO(register int channel_two_strength, register int *channel_one, register int *channel_two) { #define temp_oneR1 scratchR1 // register int temp_one = GARBAGE register int temp_one = *channel_one; #define temp_twoR2 scratchR2 // register int temp_two = GARBAGE register int temp_two = *channel_two; #define temp_valueR0 scratchR0 // register temp_value = GARBAGE Incoming register int *channel_one -- INPAR2 -- in R8 -- CAN’T leave it there Must move into volatile DM pointer -- I4 Incoming register int *channel_two -- INPAR3 -- in R12 -- CAN’T leave it there Must move into volatile DM pointer -- BUT I4 already in use CHOICES -- Place I3 onto stack or Reuse I4 -- worry about speed later 12/8/2018 ENCM Process for “pseudo-C” design to 21k assembly Copyright

17 SHARC PROCESS -- STEP 2B Develop the subroutine PROLOGUE
// Show the parameters being passed as part of documentation #define channel_two_strengthR4 scratchR4 // Same as INPAR1 void DecodeFMSTEREO(register int channel_two_strength, register int *channel_one, register int *channel_two) { #define temp_oneR1 scratchR1 // register int temp_one = GARBAGE scratchDMpt = INPAR2; // register int temp_one = *channel_one; temp_oneR1 = dm(scratchDMpt); #define temp_twoR2 scratchR2 // register int temp_two = GARBAGE YOU ADD THE CODE // register int temp_two = *channel_two; #define temp_valueR0 scratchR0 // register temp_value = GARBAGE Placing I3 onto stack // Two extra lines -- if you get it right (Save/Recover) Reuse I // Four EXTRA lines of which only two shown here // Actually do-able in 3 (a little dicey) 12/8/2018 ENCM Process for “pseudo-C” design to 21k assembly Copyright

18 SHARC PROCESS -- STEP 2C Correct the subroutine PROLOGUE
.segment/pm seg_pmco; // void DecodeFMSTEREO(register int channel_two_strength, register int *channel_one, register int *channel_two) { .global _DecodeFMSTEREO, DecodeFM_STEREO _DecodeFMSTEREO: DecodeFMSTEREO: // Show the parameters being passed as part of documentation #define channel_two_strengthR4 scratchR4 // Same as INPAR1 #define temp_one scratchR1 // register int temp_one = GARBAGE scratchDMpt = INPAR2; // register int temp_one = *channel_one; temp_oneR1 = dm(scratchDMpt); #define temp_twoR2 scratchR2 // register int temp_two = GARBAGE YOU ADD THE CODE // register int temp_two = *channel_two; #define temp_valueR0 scratchR0 // register temp_value = GARBAGE 12/8/2018 ENCM Process for “pseudo-C” design to 21k assembly Copyright

19 SHARC PROCESS -- STEP 2D Correct the subroutine PROLOGUE CORRECTLY
void DecodeFMSTEREO(int channel_two_strength, int *channel_one, int *channel_two) { int temp_one = *channel_one; int temp_two = *channel_two; static int comment = 0; if (!comment) { printf("Smith DecodeFMStereo() -- FM_STEREO demodulation example"); comment = 1; } // If Channel Strength is too weak then just use channel_one on both channels if (channel_two_strength < 25) *channel_two = *channel_one; else { *channel_one = (temp_one + temp_two) >> 1; *channel_two = (temp_one - temp_two) >> 1; NOT A REGISTER NOR A STACK VALUE 12/8/2018 ENCM Process for “pseudo-C” design to 21k assembly Copyright

20 SHARC PROCESS -- STEP 2D Correct the subroutine PROLOGUE CORRECTLY
.segment/dm seg_dmda var int comment = 0; // NASTY HIDDEN ERROR .endseg; .segment/pm seg_pmco; // void DecodeFMSTEREO(register int channel_two_strength, register int *channel_one, register int *channel_two) { .global _DecodeFMSTEREO, DecodeFM_STEREO _DecodeFMSTEREO: DecodeFMSTEREO: // Show the parameters being passed as part of documentation #define channel_two_strength scratchR4 // Same as INPAR1 What’s missing? 12/8/2018 ENCM Process for “pseudo-C” design to 21k assembly Copyright

21 SHARC PROCESS -- STEP 3 Modify the standard EPILOGUE
// Place the return value in retvalueR N/A // Recover non-volatile registers from stack -- N/A scratchPMpt = dm(minus1DM, FP); nop; // might be carefully filled jump(plus1PM, scratchPMpt) (DB); nop; // might be carefully filled RFRAME; .endseg; Just a CUT-AND-PASTE job 12/8/2018 ENCM Process for “pseudo-C” design to 21k assembly Copyright

22 SHARC PROCESS -- STEP 4A Convert C-design body -- standard IF-ELSE
scratchR0 = 25; // temp_constant = 25; // if (channel_two_strength < temp-constant) COMP(channel_two_strength, scratchR0); // dead <- scratchR0 if LE jump(PC, DO_ELSE) (DB); nop; // Are these delayed branches fillable nop; scratchDMpt = INPAR2; // *channel_two = *channel_one; scratchR0 = dm(scratchDMpt); scratchDMpt = INPAR3; // Note the indenting as part of the documentation dm(scratchDMpt) = scratchR0; jump (PC, ENDIF) (DB); DO_ELSE: // else { // *channel_one = (temp_one + temp_two); // *channel_one = *channel_one >> 1; // *channel_two = (temp_one - temp_two); // *channel_two = *channel_two >> 1; // } 12/8/2018 ENCM Process for “pseudo-C” design to 21k assembly Copyright

23 SHARC PROCESS -- STEP 4A -- in this particular subroutine Convert C-design body -- standard IF-ELSE
scratchR0 = 25; // temp_constant = 25; // if (channel_two_strength < temp-constant) COMP(channel_two_strength, scratchR0); // dead <- scratchR0 if LE jump(PC, DO_ELSE) (DB); nop; // Are these delayed branches fillable nop; dm(scratchDMpt) = temp_oneR1 // *channel_two = *channel_one (temp_one); // INPAR3 just HAPPENS to be in scratchDMpt already jump (PC, ENDIF) (DB); // because of the code you added earlier DO_ELSE: // else { // *channel_one = (temp_one + temp_two); // *channel_one = *channel_one >> 1; // *channel_two = (temp_one - temp_two); // *channel_two = *channel_two >> 1; // } 12/8/2018 ENCM Process for “pseudo-C” design to 21k assembly Copyright

24 ENORMOUS DEFECT INTRODUCED
You can’t do any of this -- ALL WRONG You have forgotten what you are coding in the whole while micromanaging the details Key issues -- volatile/non-volatile register use. 21k “C” subroutines -- like 68k “C” subroutines -- destroy volatile registers (R0) 12/8/2018 ENCM Process for “pseudo-C” design to 21k assembly Copyright

25 void DecodeFMSTEREO(int, int *, int *)
void DecodeFMSTEREO(int channel_two_strength, int *channel_one, int *channel_two) { int temp_one = *channel_one; int temp_two = *channel_two; static int comment = 0; if (!comment) { printf("Smith DecodeFMStereo() -- FM_STEREO demodulation example"); comment = 1; } // If Channel Strength is too weak then just use channel_one on both channels if (channel_two_strength < 25) *channel_two = *channel_one; else { *channel_one = (temp_one + temp_two) >> 1; *channel_two = (temp_one - temp_two) >> 1; Using R1, R0, R4, I4 etc Probably destroys R1, R0, R4, I4 etc 12/8/2018 ENCM Process for “pseudo-C” design to 21k assembly Copyright

26 Program smart -- and cut the DEFECTS
void DecodeFMSTEREO(int channel_two_strength, int *channel_one, int *channel_two) { int temp_one = *channel_one; int temp_two = *channel_two; static int comment = 0; // printf( ) CODE WAS HERE // If Channel Strength is too week then just use channel_one on both channels if (channel_two_strength < 25) *channel_two = *channel_one; else { *channel_one = (temp_one + temp_two) >> 1; *channel_two = (temp_one - temp_two) >> 1; } if (!comment) { printf("Smith DecodeFMStereo() -- FM_STEREO demodulation example"); comment = 1; “C” CAN DESTROY VOLATILES TO HEART’S CONTENT 12/8/2018 ENCM Process for “pseudo-C” design to 21k assembly Copyright

27 SHARC PROCESS -- STEP 4A -- in this particular subroutine Convert C-design body -- standard IF-ELSE
scratchR0 = 25; // temp_constant = 25; // if (channel_two_strength < temp-constant) COMP(channel_two_strength, scratchR0); // dead <- scratchR0 if LE jump(PC, DO_ELSE) (DB); nop; // Are these delayed branches fillable nop; dm(scratchDMpt) = temp_oneR1 // *channel_two = *channel_one (temp_one); jump (PC, ENDIF) (DB); DO_ELSE: // else { scratchR0 = temp_oneR1 + temp_twoR2; // *channel_one = (temp_one + temp_two); scratchR0 = ASHIFT scratchR0 BY -1; // *channel_one = *channel_one >> 1; scratchDMpt = INPAR2; dm(scratchDMpt) = scratchR0; // dead <- scratchR0 // *channel_two = (temp_one - temp_two); // *channel_two = *channel_two >> 1; ENDIF: // } YOU COMPLETE 12/8/2018 ENCM Process for “pseudo-C” design to 21k assembly Copyright

28 void DecodeFMSTEREO(int, int *, int *)
static int comment = 0; if (comment == 0) { printf("Smith DecodeFMStereo() -- FM_STEREO demodulation example"); comment = 1; } Got placed in seg_dmda in PROLOGUE and given label “comment” Label means “address-location” not value scratchR0 = dm(comment); // NOT scratchR0 = comment // This operation would set 68k N and Z flags // which could then be used to control conditional branch // Not true on the 21k scratchR0 = PASS scratchR0; // Test for Zero and Negative if NE jump (PC, NOCOMMENT) (DB); NOP; // NOT pass(scratchR0) NOP; // which is MFE 12/8/2018 ENCM Process for “pseudo-C” design to 21k assembly Copyright

29 void DecodeFMSTEREO(int, int *, int *)
static int comment = 0; if (comment == 0) { printf("Smith DecodeFMStereo() -- FM_STEREO demodulation example"); comment = 1; } #define commentR0 scratchR0 // Better code maintainability commentR0 = dm(comment); commentR0 = PASS commentR0; // Test for Zero and Negative if NE jump (PC, NOCOMMENT) (DB); // dead <- R0 NOP; Code to call printf ( ) here NOCOMMENT: 12/8/2018 ENCM Process for “pseudo-C” design to 21k assembly Copyright

30 Why we don’t “Call C” from assembly Coding the “printf( )” call
printf(“Print out the value of %d”, comment); .segment/dm seg_dmda var int comment = 0; FORMAT1_LABEL: .var FORMAT1_STRING[ ] =83,109,105,116,104,32,68,101, etc, 0; // Don’t forget me! -- “C” EOS .endseg; Ascii code for “Print out the value of %d” .segment/pm seg_pmco; OUTPAR2 = FORMAT1_LABEL; // Pointer to string OUTPAR1 = dm(comment); // Value NOT pointer CALL _printf (DB): nop; 12/8/2018 ENCM Process for “pseudo-C” design to 21k assembly Copyright

31 Why we don’t “Call C” from assembly Coding the “printf( )” call
GOT ONE LINE RIGHT // Get starting address of printf format scratchR0 = FORMAT1_LABEL; // Note that is not the stack controlled by SP dm(CTOPstack,minus1DM) = scratchR0; .extern _printf; cjump _printf (DB); dm(CTOPstack,minus1DM) = r2; dm(CTOPstack,minus1DM) = pc; modify(CTOPstack,plus1DM); USING CJUMP not CALL dm(CTOPstack,minus1DM) = scratchR0; dm(CTOPstack,minus1DM) = r2; dm(CTOPstack,minus1DM) = pc; modify(CTOPstack,plus1DM); CJUMP causes R2 <- FP (I6) R2 is destroyed “internally” Save FP (as R2) Save Return Address (one off) 3 Values placed on stack Only 1 taken off here 12/8/2018 ENCM Process for “pseudo-C” design to 21k assembly Copyright

32 SHARC PROCESS -- STEP 5 OPTIMIZE THE CODE
Remember -- not normally worth the effort Going to require Knowing the parallel instructions Knowing which ones are valid in combination Taking into account the limitations associated with the finite number of bits in the op-code to describe the parallel operations wanted Understanding Hardware loops Understanding memory and ALU pipelining Optimization is “NEXT WEEK COUNTRY” 12/8/2018 ENCM Process for “pseudo-C” design to 21k assembly Copyright

33 Other examples of code conversion
Many examples in previous year’s web pages Take a look at the “assembly output” generated by the “C”-compiler for Lab. 0 Use the -S option and look for the .s file Get to know the “required stuff” so you can quickly break through the “barrier” and get to the stuff you really want to do -- DSP customization KEY -- Develop a PSP code review process 12/8/2018 ENCM Process for “pseudo-C” design to 21k assembly Copyright

34 Tackled today Prologue, Body and Epilogue of “C” program translated to assembly code (NO DIFFERENCE by hand or by compiler) Example conversion of “C” program into ADSP21061 using a standard procedure Take into account register architecture Take into account LOAD/STORE architecture Take into account standard assembly code problems Handle Program Flow Constructs Then do conversion of code on line by line basis Learning why to avoid calling “C” from assembly 12/8/2018 ENCM Process for “pseudo-C” design to 21k assembly Copyright


Download ppt "* 07/16/96 This presentation will probably involve audience discussion, which will create action items. Use PowerPoint to keep track of these action items."

Similar presentations


Ads by Google