Table of Contents

PP Assembly Style Guide


PP Assembly Style Guide

PP Assembly Style Guide

Image Computing Library Team Document # - ICSL-UWICL-2/96 rev. 2.0 Image Computing Systems Laboratory Department of Electrical Engineering University of Washington Seattle, WA 98195 Version 2.0

Version 2.0

1.0 Introduction

The Image Computing Systems Laboratory (ICSL) at the University of Washington is developing an image computing library (UWICL) for the Texas Instruments (TI) TMS320C80 Multimedia Video Processor (MVP). The purpose of the UWICL is to provide a portable and efficient library of core image computing algorithms to the MVP user community. This library will be made available as source code and or executables to companies who wish to purchase the library for product development with the MVP.

The purpose of this document is to establish common parallel processor (PP) assembly coding styles to be used for developing and maintaining the UWICL. There are many reasons for needing a standardized PP coding style. First, the style guide will ensure that all PP code has a consistent layout. Many different programmers will be viewing and maintaining the source code, both in-house and in industry. Second, code that is in a consistent layout will be easier to understand and maintain. Because many different programmers will be manipulating the UWICL source code, minimizing the learning curve to develop, maintain and understand the library will improve efficiency. Finally, enforcement of the PP coding style will help reduce the number of coding errors that otherwise might be introduced.

The PP style outlined in this document comes from the experience of UW MVP programmers and various published C style guides. The style issues that will be addressed in this guide include: · standardize file organization so that all PP assembly written by many different programmers has the same "look and feel" · use of comments to aid maintenance programmers in understanding the complex PP assembly code · use of whitespace (blank lines and spaces) to make the code more readable and to help describe the structure of the code · naming conventions so that function names, variable names and labels are consistent among all PP assembly

The style guidelines in this document are required to be used by all programmers developing and maintaining code for the UWICL. A style guide committee will review all code written for the UWICL on a regular basis to ensure that it conforms to the style rules. 2.0 File Organization 2.1 Module Files

A UWICL module consists of a set of files, documentation and source code, that implements one image computing library function. The files that make up the module include master processor (MP) and PP C source code, PP assembly source code, include files, macro libraries and a README file. Please note that all the source files are Big Endian dependent. 2.1.1 MP C

The MP source files will be written in C and will be used primarily to set up the packet request and initiate the PP assembly library functions. More details about the MP C source files can be found in the C Style Guide. 2.1.2 PP assembly

The PP assembly source files will include functions implementing the image computing functions. The image computing function for a given module should be logically grouped into different source files as opposed to putting all functions into one source file or one function into one source file. 2.1.3 Include files

Wherever possible, include files should be used to encapsulate data declarations, especially those to be used by multiple files. Acceptable declarations to be found in the PP include files include constant declarations, structure definitions, and external variable declarations. Note that PP macros are not to be declared in an include file (unlike C macros) but rather, grouped together into a PP macro library. Include files located in a module are to be used only by that module. Global include files that contain useful constants and structures to be used by all UWICL modules should be located in a public directory. 2.1.4 Macros

In the grand tradition of other assemblers, the TI assembler for PP assembly language supports the use of macros. In some instances the use of macros can be a powerful tool. Like all good tools however, disaster can befall upon the unwary user. The style used for macros then shall make them easy to use as well as flag their potential dangers. 2.1.5 README file

A README file should accompany each image computing (IC) module. The README file should be a global description of the IC module and include details about the source files and functions, such as the algorithms used, input/output specifications, timings and calling conventions. If relevant, information about compilation and installation should also be included. 2.2 File Naming

All function source file names will follow the 8.3 format. The first eight characters serve to describe the function. An optional bits per pixel field is included in the descriptive name if multiple data formats are supported. The three character extension designates the file type. 2.2.1 Assembly Source Files

[c_ or c]<Function description>[bits/pixel]<".pps">

where: · c_ or c (optional) identifies a color function. · Function description identifies the general purpose of the function. · bits/pixel (optional) identifies the pixel size such as 8 or 16. · ".pps" identifies the file as PP assembly code.

examples: c_affine.pps --> PP assembly source file for color affine geometric operation. add16.pps --> PP assembly source file for 16-bit add operation. sobel.pps --> PP assembly source file for Sobel edge detection operation. 2.2.2 Include Files

[c_ or c]<Function description>[bits/pixel]<".i">

where: · c_ or c (optional) identifies a color function. · Function description identifies the general purpose of the function. · bits/pixel (optional) identifies the pixel size such as 8 or 16. · ".i" identifies the file as an assembly include file.

examples: c_affine.i --> include file for color affine assembly source file. and16.i --> include file for 16-bit add assembly source file. sobel.i --> include file for Sobel edge detection assembly source file. 2.2.3 PP macros

<"ppmac_"><description><".s">

where: · "ppmac_" identifies the file as containing a PP macro. · description summarizes the macro purpose: · the description should describe the function of the macro. · the suffix is: · ".s" identifies the file as containing one PP macro. · Example:

ppmac_min.s --> PP macro to determine the min of two numbers 2.3 File Structure

Each source file will contain a number of sections. These sections should be easily identifiable and separated by blank lines. The sections are ordered is as follows: Copyright statement. A copyright statement specifying copyright ownership to the Image Computing Systems Laboratory Comment prologue.

A global comment block must be listed first which includes the file name, global purpose of the file, contents of file (e.g. list of functions), author, and modification history. The format of this comment prologue is detailed later. Include files

If there are any include files for the source file, they will be listed next. It is suggested that a comment be appended to the include if the file is included for non-obvious reasons. External variable declarations

Any external variable declarations using the .global assembler directive are listed next. The external declaration allows the compiler to resolve references to it in other source files at link time. Global variable declarations

Any global variable declarations to be use only within the source file are declared next, again using the .global assembler directive. Global labels

Any global labels that identify PP functions or branch locations are listed next. Function source.

PP functions, identified by a global label, follow last. Each function should be preceded by a function comment prologue which includes all the details about the function. All functions in one source file should be declared in a breadth-first fashion, with functions of similar level of abstraction grouped together. Also, logically similar functions should be included in the same source file and distinctly different functions should be broken up into different source files (if possible). 2.4 File Comment Prologue

A block comment prologue must be included at beginning of EACH source file. This prologue should contain information such as the file name, global purpose of the file, contents of file (e.g. list of functions), author, and modification history. An example file comment prologue is as follows: ;****************************************************************** ;*$Id: add8.pps,v 1.4 1995/07/12 21:37:31 vikram Exp $ ;* NAME: add8.pps ;* ;* DESCRIPTION ;* This file contains image add tight loop. ;* ;* FUNCTIONS: ;* pp_add_tight_loop_8 ;* ;* AUTHOR: ;* Vikram Chalana ;* ;* MODIFICATION HISTORY: ;*$Log: add8.pps,v $ ;* Revision 1.4 1995/07/12 21:37:31 vikram ;* Modified according to Warren's comments. Also modified the constant names ;* to ease in building blocks. ;* ;* Revision 1.3 1995/03/29 15:12:57 vikram ;* New tools & Style Check ;* ;* Revision 1.2 1995/01/09 22:04:39 vikram ;* Added Copyright Statement ;* ;* Revision 1.1.1.1 1994/12/28 18:29:05 vikram ;* First Time ;* ;********************************************************************/ 3.0 Functions

Any code that implements a specific computation and that is repeatedly used by other functions should be encapsulated into a function, unless the code is in a tight loop. The PP assembler currently does not support the concept of functions. Instead, a logical grouping of assembly instructions that is be considered a function is preceded with a global label. The end of the function is identified with the comment string:

;* END: function_name

which may be followed by the .end assembler directive if it is the last function in the source file. 3.1 Naming Convention

The name of the global label identifying the function must follow the naming convention:

<"$pp_"><description>

where: · "$pp_" is the prefix identifying the label as a pp function · description is a meaningful string identifying the purpose of the function · Example

$pp_add_tight_loop_8

Note that although the function name is a global label, the label must be in ALL lower case. Global labels used for other purposes other that to identify a function must be ALL capitalized. This naming procedure will aid programmers in differentiating branching labels from function labels. 3.2 Function Comment Prologue

Each PP function will be preceded by a block comment prologue. This prologue not only provides useful information about the function, but it helps delineate the functions within a source file (particularly useful for PP assembly). The function prologue will contain information such as the name of the function, a general description of the function, parameters expected, return values, details of the algorithm , side-effects of the function, global variable modifications, author, and modification history (detailing the changes). The information contained within the comment prologue must be completed thoroughly as much of the information is vital to the understanding of the function. For example, although a PP function accepts no formal parameter list, it does access parameters through the parameter RAM. These parameters and descriptions should be included in the function prologue as it will NOT be obvious to a maintenance programmer reviewing the code. An example function prologue is as follows: ;****************************************************************** ;* NAME: ;* pp_add_tight_loop_8 ;* ;* DESCRIPTION: ;* This function is the add tight loop which add a ;* row of image and write the output to onchip memory. ;* ;* PARAMETERS: ;* Address of tight loop argument buffer saved in d1 register. ;* Parameters passed to tight loop include: ;* on_chip_width: Number of pixels in a row ;* on_chip_in1_addr: Source address of a row of image1 ;* on_chip_in2_addr: Source address of a row of image2 ;* on_chip_out_addr: Destination address of added row ;* ;* RETURNS: ;* Added image starting at address specified. ;* ;* ALGORITHM: ;* This function adds the gray value of each pixel. ;* ;* RESTRICTION: ;* The number of pixels in a row shouldn't exceed 1024, which is ;* the size of output Ping or Pong RAM. ;* ;* SPECIAL NOTES: ;* None ;* ;********************************************************************/ 3.3 Whitespace

All first level assembly statements within the function should be indented 4 spaces (Note: spaces are used instead of tabs to ensure consistent indentation with different editors and editor setups). Statements within loops should be indented additional spaces to identify those regions easily (details about loop indenting is detailed in the loop section). There must be one blank line above the function prologue and one blank line after it. There should also be one blank after the end comment that identifies the end of the function. 4.0 Macros

In the grand tradition of other assemblers, the TI assembler for PP assembly language supports the use of macros. In some instances the use of macros can be a powerful tool. Like all good tools however, disaster can befall upon the unwary user. The style used for macros then shall make them easy to use as well as flag their potential dangers.

Macros must not be written directly into a piece of PP assembly code. Instead, all macros must be encapsulated into their own .s files and archived into a macro library file using the mvpar archiver. Each file shall contain only one macro and shall begin with the prefix mac_ (see the file name convention section). All related macros (files) should be archived into one .lib library file and the file name should be representative of the macros contained within it. If macros can be used by other UWICL routines, they should be archived into a public macro libraries so that they then be used by all ICL team members, thus promoting the creation of reusable code. The macro libraries are included into PP assembly code by using the .mlib assembler directive. 4.1 Naming Convention

The name of the global label identifying the macro must follow the naming convention:

<description><"_m">

where: · description is a meaningful string identifying the purpose of the macro · "_m" is the prefix identifying the label as a PP macro. All macros must be named and append with an _m. The _m convention shall not be used in the name of anything but a macro. · Example

inc4_m

The names of the parameters of a macro must follow the naming convention:

<description><"_p#">

where: · description is a meaningful string identifying the parameter · "_p#" is the prefix identifying the variable as a parameter. The # is a numeric value identifying the parameter number, starting from 1. · Example count_p1 index_p2 4.2 Macro Comment Prologue

Each PP macro must begin with a comment prologue. The comment prologue must include three mandatory sub-blocks denoting macro name, macro usage, and macro restrictions. The macro restrictions section must carefully describe the limits of type on each of the parameters as well as the dangers in using the macro. For example, the use of macros in tight loops may make the loop look compact but the compiler will insert the macro code inserting all the macro instructions which may lead to cache misses. For example: ;********************************************** ;* MACRO: inc4_m ;* ;* USAGE: inc4_m d1, d2, d3, d4 ;* ;* RESTRICTIONS: None ;* ;* AUTHOR: ;* Chris Basoglu ;* ;* MODIFICATION HISTORY: ;* 06/12/94 Chris Basoglu Creation ;* 06/13/94 Chris Basoglu Fixed bug. Program now works. ;* 06/14/94 Chris Basoglu Optimized Code ;* 06/15/94 Chris Basoglu Fixed bugs introduced on 06/14/94 ;******************************************************************** 4.3 Whitespace

The macro comment prologue should have at least one full line of white space above it. and one below it. One blank line must follow the .ENDM label of the macro. 4.4 Restrictions

Careful attention must be paid to the last instruction of a macro. For example, if the last instruction in a macro is an assignment to an address register from a data unit operation, then there will be a delay slot of instruction after the execution of the macro. Such ending considerations must be well documented in the RESTRICTIONS sub-block of the macro comment prologue. 4.5 Example ;********************************************** ;* MACRO: inc4_m ;* ;* USAGE: inc4_m d1, d2, d3, d4 ;* ;* RESTRICTIONS: None ;* ;* AUTHOR: ;* Chris Basoglu ;* ;* MODIFICATION HISTORY: ;* 06/12/94 Chris Basoglu Creation ;* 06/13/94 Chris Basoglu Fixed bug. Program now works. ;* 06/14/94 Chris Basoglu Optimized Code ;* 06/15/94 Chris Basoglu Fixed bugs introduced on 06/14/94 ;******************************************************************** inc4_m .MACRO desc_name_p1, desc_name_p2, desc_name_p3, desc_name_p4 desc_name_p1 = desc_name_p1 + 1 desc_name_p2 = desc_name_p2 + 1 desc_name_p3 = desc_name_p3 + 1 desc_name_p4 = desc_name_p4 + 1 .ENDM 5.0 Variables

As with function declarations, the PP assembler currently does not support the concept of variable declarations. Instead, variables are defined by assigning a name to a PP register using the .set assembler directive: count_d6_b: .set d6 ;* Counter to keep track of number of pixels read diff_d7_b: .set d7 ;* Difference between pixels

All PP variable declarations should precede the assembly code that makes up the PP functions and not be embedded within the function. Global variable declarations should be listed after the include statements and before the first function comment prologue. Local variable declarations should be listed after the function prologue but before the function code. 5.1 Naming Convention

Labels can be assigned to address registers, index registers and data registers. Strict naming conventions will make the code much more readable/understandable and make the formidable task of maintaining PP assembler much easier for future programmers of the UWICL. For that reason, we will adopt a specific variable naming convention:

<descriptive name>< register>[data type]

where: · descriptive name indicating the purpose of the variable. Important that this be first as it is what the programmer reads first and it should be representative of its purpose. · register is one of: · "_La#" - local address register, # = 0 to 4 · "_Ga#" - global address register, # = 8 to 12 · "_Lx#" - local index register, # = 0 to 2 · "_Gx#" - global index register, # = 8 to 10 · "_La6_sp"/"_Ga14_sp" - local/global stack pointer register · "_d#" - data register, # = 0 to 7 · data type (optional and only for the data registers) is one of: · "_w" (word) · "_h" (half word) · "_b" (byte) · Examples: buffptr_La1 ;* Local address pointer using address register a1 bigbuf_Ga9 ;* Global address pointer using address register a9 buf_index_Lx1 ;* Local index register using index register x1 count_d1_b ;* byte counter variable using data register 1 diffpix_d2_w ;* word difference variable using data register 2

.

Note that all variable names should be alphanumerically unique and should not rely on capitalization for delineation. For example, there should never be two variables named foo and Foo in the UWICL code. Also, all descriptor parts of a register name must be lower case. For example use reg_d1_w, not Reg_d1_w. Also, is a name is to consist of more than one word, it is important to delineate the words with an underscore instead of using capitals. For example, use top_of_the_world instead of TopOfTheWorld. 5.2 Comments

All declared variables must have a side-bar comment describing the purpose of the variable. This procedure will also help the programmer understand the variable naming if the name is too cryptic. 5.3 WhiteSpace

The section of variable declarations should have one blank line above it and one blank line below it. Logical groupings of variables can also be delineated from the other variables by a blank line above and below. 6.0 Loops

The PP assembly language allows for the use of up to three simultaneous hardware controlled loops (see the PP Users Guide for detailed instructions on how to properly set up hardware controlled loops). Each of the three hardware loops has a set of registers associated with them. Thus, instead of using a compound loop statement (as in the while and for statements of C), loops are set up by assigning appropriate values into the loop registers. Because finding and understanding a PP assembly programs loops are usually essential to understanding the code, the PP style shall be used to ensure that all UWICL loops are readable and easily understandable.

As noted above, the proper loop registers must be set for each loop. In all UWICL defined loops, the initialization of the loop registers must be as close to the corresponding loop as possible. In setting the loop start and loop end registers, labels corresponding the start and stop addresses of the loop must be used (never use absolute addressing (e.g. 0x12345678) as it doesn't allow for dynamic linking). In setting the loop option bits of the loop control register, predefined labels should be used instead of absolute numbers. The predefined labels must be defined in a header file called pp_icl_names.i. For example: .include "pp_icl_names.i" . . . lctr = LOOP0_ENABLE | LOOP1_ENABLE | LOOP2_DISABLE 6.1 Naming Convention

The naming convention for the labels denoting the starting and ending address of the loop must consist of some lower case descriptive name following the convention:

<prefix><"_ls#" | "_le#">

where: · prefix is a descriptive name describing the purpose of the loop · if the label is: · a starting address label, "_ls#" is appended to the prefix, where # identifies the hardware loop being used · a ending address label, "_le#" is appended to the prefix, where # identifies the hardware loop being used · Example: thresh_ls1: thresh_le1: 6.2 Loop Comments

All loops must be preceded with a loop comment prologue. The comment prologue must appear after the loop register initialization, but before the actual loop code begins. The comment prologue will be broken down into four mandatory sub-blocks (which must be separated by a blank line) denoting loop name, number of iterations, function, and exiting conditions. For example: ;****************************************************************** ;* Loop: Add8 tight loop ;* ;* Iterations: ;* Number of pixels in the row/4 - 3 ;* ;* Functions: ;* Add with saturate ;* ;* Exiting condition: ;* End when all the iterations are complete ;* ;********************************************************************/ 6.3 Whitespace

The executable statements within the outermost loop must be indented four spaces from the indentation of the statements outside the loop. Note that the starting and ending loop labels must be in column 1. The executable statements within the inner loop must be indented four spaces from the indentation of the code in the loop above it. There should be no blank line between the loop start label and the fist loop instruction. Likewise no blank line should be found between the last loop instruction and the loop end label. Also, each label should be on it's own line. Finally, to give the loop a more cohesive look, there should be no whitespace between executable statements within the loop unless the statement is preceded by a comment line.

The comment prologue will be must have at least one full line of white space above it. If the comment block corresponds to an inner loop, it must have the same indentation as the code in the loop above it. 6.4 Restrictions

To keep each loop readable and manageable, all innermost hardware loops must contain less than 64 instructions. This will also ensure that there are no cache misses during inner loop execution (see the Design Guide for more details).

Use if the .loop assembler directive can lead to inefficient and unreadable code. Because the .loop instruction can be replaced by real hardware loops, the .loop assembler directive shall not be used in any UWICL code (see the Design Guide for more details). 6.5 Example . ls0 = add_ls0; le0 = add_le0; lr0 = pixels_d2_w; lctl = LOOP0_ENABLE ; enable the loop nop; .... ;****************************************************************** ;* Loop: Add8 tight loop ;* ;* Iterations: ;* Number of pixels in the row/4 - 3 ;* ;* Functions: ;* Add with saturate ;* ;* Exiting condition: ;* End when all the iterations are complete ;* ;********************************************************************/ add_ls0: temp_d3_w =mc temp_d3_w + temp_d4_w; Add Word #2 || *(output_buf_La2++) = temp_d5_w; Store Word # 1 add_le0: temp_d5_w = temp_d3_w | @mf; Saturate Word #2 || temp_d4_w = *(input_buf2_Ga8++); global || temp_d3_w = *(input_buf1_La0++); Load word #3: local temp_d3_w =mc temp_d3_w + temp_d4_w; Add || *(output_buf_La2++) = temp_d5_w; Store 7.0 Miscellaneous Statements 7.1 Parallel Statements

The MVP allows a number of parallel operations to occur. In particular, a multiplication, an arithmetic operation, a global addressing operation and a local operation. To make parallel PP assembly statements more readable, one of two different formats must be used. Each format is acceptable but a given function should be consistent and use only one or the other. In the first format, each parallel statement will be on its own line, indented 4 space from the first parallel statement (Note: spaces are used instead of tabs to ensure consistent indentation with different editors and editor setups). Additionally, each parallel statement may contain aligned side-bar comments indicating whether it is a multiplication, arithmetic, global addressing, or local addressing operation. For example: reg_d1_w = reg_d2_w * reg_d3_w ;* MULT || reg_d7_w = ealu (ADD: reg_d4_w + reg_d5_w) ;* ARITH || *(addr_Ga8) = reg_d6_w ;* GLOBAL || reg_d0_w = *(addr_La1+[ind_Lx0]) ;* LOCAL

In the second format, each parallel statement will be on its own line, directly below the first parallel statement For example: reg_d1_w = reg_d2_w * reg_d3_w ;* MULT || reg_d7_w = ealu (ADD: reg_d4_w + reg_d5_w) ;* ARITH || *(addr_Ga8) = reg_d6_w ;* GLOBAL || reg_d0_w = *(addr_La1+[ind_Lx0]) ;* LOCAL 7.2 Operators

In most cases PP assembly code is used to do the serious number crunching and/or data movement. Because of this, one is likely to find many operators binding PP data and address registers. To ensure that UW ICL PP assembly code is highly readable and maintainable, all UWICL code will be subject to style rules regarding the use of operators.

All binary operators must be preceded and succeeded by one space. All equal signs must me preceded and succeeded by one space. Finally, all unary operators should have no spaces between the operator and the operand. For example:

reg_d1_w = reg_d0_w + reg_d1_w

reg_d0_w = ~reg_d1_w 7.3 Structures/Unions

Structures/unions can be defined in PP assembly, similar to the C structure/union format. However, unlike C, the .struct/.endstruct and .union/.endunion constructs does not allocated memory but instead creates a symbolic template that can be used to symbolically reference memory. This feature is useful in producing readable code and should be used for any memory which has a complex structure.

In using the .struct/.endstruct and .union/.endunion, each element of a structure/union must be declared on it's own line, indented 4 spaces and be complete with a side-bar comment (Note: spaces are used instead of tabs to ensure consistent indentation with different editors and editor setups). An example of a complex PP assembly structure is as follows: .struct .access tPR_Next .word /* 0 All PRs */ tPR_Options .word /* 1 All PRs */ .union tPR_SrcStartAddress .word /* 2 Dimensioned Src PRs */ tPR_SrcBaseAddress .word /* 2 Guided Src PRs */ .endunion .union tPR_DstStartAddress .word /* 3 Dimensioned Dst PRs */ tPR_DstBaseAddress .word /* 3 Guided Dst PRs */ .endunion .union tPR_SrcBACount .word /* 4 Dimensioned Src PRs */ .struct fPR_SrcBCount .half /* 8 Dimensioned/Fixed Patch Src PRs */ fPR_SrcACount .half /* 9 Dimensioned/Fixed Patch Src PRs */ .endstruct .endunion .union tPR_DstBACount .word /* 5 Dimensioned Dst PRs */ .struct fPR_DstBCount .half /* 10 Dimensioned/Fixed Patch Dst PRs */ fPR_DstACount .half /* 11 Dimensioned/Fixed Patch Dst PRs */ .endstruct .endunion .union tPR_SrcCCount .word /* 6 Dimensioned Src PRs */ tPR_SrcNumEntries .word /* 6 Guided Src PRs */ .endunion .union tPR_DstCCount .word /* 7 Dimensioned Dst PRs */ tPR_DstNumEntries .word /* 7 Guided Dst PRs */ .endunion .union fPR_SrcABPitch .word /* 8 Dimensioned/Fixed Patch Src PRs */ fPR_LSFillWord .word /* 8 Fill with Value PRs */ .endunion fPR_DstABPitch .word /* 9 Dimensioned/Fixed Patch Dst PRs */ .union fPR_SrcBCPitch .word /* 10 Dimensioned Src PRs */ fPR_MSFillWord .word /* 10 Fill with Value PRs */ fPR_SrcGuideTablePtr .word /* 10 Guided Src PRs */ .endunion .union fPR_DstBCPitch .word /* 11 Dimensioned Dst PRs */ fPR_DstGuideTablePtr .word /* 11 Guided Dst PRs */ .endunion .union fPR_TransWord0 .word /* 12 Transparency PRs */ fPR_ColorRegWord0 .word /* 12 Block Write PRs */ .endunion .union fPR_TransWord1 .word /* 13 Transparency PRs */ fPR_ColorRegWord1 .word /* 13 Block Write PRs */ .endunion fPR_Reserved1 .word /* 14 Unused */ fPR_Reserved2 .word /* 15 Unused */ .endstruct 8.0 Module Management 8.1 Makefiles

All modules developed for the UWICL MUST use makefiles. Makefiles can be used for more than the standard automatic conditional compilation. Makefiles can be used to execute standard UNIX commands along with the make process. These UNIX commands can be tied to a convenient and easy to understand label. For example, many makefiles include a section that will remove all of the object files in the current directory. The command then to clean out the directory of object files would be:

%> make clean

All makefiles used by the UWCL team shall have the make labels shown in Table 1.

Table 1: Makefile Targets

-----------------------------------------------------------------------------
Makefile targets            Functionality                                      
-----------------------------------------------------------------------------
clean                       Remove all object files in current directory.      
all or <function name>.out  Compile the function to work with the hard         
                            ware.                                              
test.out                    Compile the function to work with the simula       
                            tor.                                               
cpimg / delimg              Create / delete link to images to test with this   
                            function, for use with simulator.                  
cplut / dellut              Create / delete link to look-up table (LUT)        
                            used to test the function with the simulator.      
-----------------------------------------------------------------------------

As mentioned above, the compilation and linking process requires the use of certain parameters. Each UWICL makefile specifies the object file names and additional makefile paramaters, which are passed to a common UWICL makefile. This step insures a uniform compiling process. 8.2 Conditional Compilation

As in C, the PP assembler allows for conditional compilation. In this way code can be complied in or out of the executable by changing the predefined value of a symbol without having to comment statements out or un-commenting statements in. One ideal use for conditional compilation is for debug type code. During development, debug and error checking code can be compiled into the executable. After debugging is complete, the debug code can be made as harmless as comments by switching the value on the conditional compilation. The advantage of keeping the debug code in the source files is that later modifications can be debugged using the statements used previously and thus, cutting down on the maintenance programmers time and effort.

Conditional compilation is set by using the assembler directives .if, .elseif, and .endif. For readability, the conditional compilation statements should begin in the left most column of the row they are intended for. Below is an example: reg_d1_w = a15 .if TEST1 reg_d1_w = reg_d2_w + reg_d3_w || *(addr_Ga8) = reg_d2_w .else ;* NOT TEST1 reg_d3_w =r reg_d2_w * reg_d3_w || ealu (ROUND) .endif

The PP assembly programmer should be very careful when using these options as it can lead to unforeseen errors. For example, the programmer may think some lines of code may be in the executable but they may not be their due to conditional compilation. 9.0 Miscellaneous Restrictions

The PP assembler allows for the use of header or include files. Unfortunately, the PP assembler defines two different assembler directives to accomplish the same task: .copy and .include. To avoid confusion, all UWICL team members must use only the .include assembler directive when they want to include header/include files.

The PP assembler allows for different types of global labels. To support these types, different assembler directives are supported: .def, .ref, and .global. If .global is used, the assembler itself will determine whether the variable needs to be of type .def or of type .ref. To avoid confusion then all UWICL team members must use only the .global assembler directive when defining global variables.

The PP assembler allows for the PP assembly code programmer to set well defined assembly time expressions to a symbol (label). Unfortunately the PP assembler supports two different directives to accomplish this task: .equ and .set. To avoid confusion, all UWICL team members must only use the .set assembler directive when equating an expression to a label.

Note: these restrictions will be updated and revised as we get more experience with PP assembly. 10.0 Exception Protocols

As with life, there are times when the rules just must be broken. Before a UWICL team member shall be allowed to violate a rule set forth in this document, he/she should consult with at least one member of the style guide committee. The programmer must justify why the style guidelines are to be violated and to explain why it is necessary to violate the rules. 11.0 Conclusion

This PP style guide has presented a style that is intend to make PP assembly well structure, easy to read, less errors and easily maintainable. It is important to ensure there are sufficient comments, there is adequate use of whitespace, file organizations are adhered to and name conventions are followed. In order for this style to be useful, it must be followed. If anyone has conflict with the style imposed, do NOT ignore them. Instead, approach the style guide committee and the style will be explained or modified. This document is intended to be updated on a frequent basis as better and additional style guidelines are defined. Appendix A: Example PP Assembly ;* ;*-------------------------------------------------------------- ;* ;* Copyright 1995, Image Computing Systems Laboratory, ;* University of Washington. All rights reserved. ;* ;*-------------------------------------------------------------- ;* ;****************************************************************** ;*$Id: add8.pps,v 1.4 1995/07/12 21:37:31 vikram Exp $ ;* NAME: add8.pps ;* ;* DESCRIPTION ;* This file contains image add tight loop. ;* ;* FUNCTIONS: ;* pp_add_tight_loop_8 ;* ;* AUTHOR: ;* Vikram Chalana ;* ;* MODIFICATION HISTORY: ;*$Log: pp_binary_ADDcore8.s,v $ ;* Revision 1.4 1995/07/12 21:37:31 vikram ;* Modified according to Warren's comments. Also modified the constant names ;* to ease in building blocks. ;* ;* Revision 1.3 1995/03/29 15:12:57 vikram ;* New tools & Style Check ;* ;* Revision 1.2 1995/01/09 22:04:39 vikram ;* Added Copyright Statement ;* ;* Revision 1.1.1.1 1994/12/28 18:29:05 vikram ;* First Time ;* ;********************************************************************/ .include "pp_icl.i" ;* IC library header file .include "add8.i" ;* add application header file ;* Global lable for functions .global $pp_add_tight_loop_8 ;****************************************************************** ;* NAME: ;* pp_add_tight_loop_8 ;* ;* DESCRIPTION: ;* This function is the add tight loop which add a ;* row of image and write the output to onchip memory. ;* ;* PARAMETERS: ;* Address of tight loop argument buffer saved in d1 register. ;* Parameters passed to tight loop include: ;* on_chip_width: Number of pixels in a row ;* on_chip_in1_addr: Source address of a row of image1 ;* on_chip_in2_addr: Source address of a row of image2 ;* on_chip_out_addr: Destination address of added row ;* ;* RETURNS: ;* Added image starting at address specified. ;* ;* ALGORITHM: ;* This function adds the gray value of each pixel. ;* ;* RESTRICTION: ;* The number of pixels in a row shouldn't exceed 1024, which is ;* the size of output Ping or Pong RAM. ;* ;* SPECIAL NOTES: ;* None ;* ;********************************************************************/ $pp_add_tight_loop_8: pointer_d1_w .set d1 ;pointer to the buffer input_buf1_La0 .set a0 ;pointer to the buffer output_buf_La2 .set a2 ;pointer to the buffer input_buf2_Ga8 .set a8 ;pointer to the buffer pixels_d2_w .set d2 ;number of pixels temp_d3_w .set d3 ;temporary data temp_d4_w .set d4 ;temporary data temp_d5_w .set d5 ;temporary data temp_addr_La1 .set a1 ;temprory address ;* ;* read input data from the loop buffer in PRAM ;* temp_addr_La1 = pointer_d1_w ;read the pointer into a1 nop pixels_d2_w = *temp_addr_La1.on_chip_width ;width temp_d3_w = *temp_addr_La1.on_chip_in1_addr ;address temp_d4_w = *temp_addr_La1.on_chip_in2_addr ;address temp_d5_w = *temp_addr_La1.on_chip_out_addr ;address ;* ;* Setup for tight-loop ;* pixels_d2_w = pixels_d2_w >> 2 input_buf1_La0 = temp_d3_w; input_buf2_Ga8 = temp_d4_w; output_buf_La2 = temp_d5_w; pixels_d2_w = pixels_d2_w - 3 ; specify number of loops ls0 = add_ls0; le0 = add_le0; lr0 = pixels_d2_w; lctl = LOOP0_ENABLE ; enable the loop nop; sr = ASIZE_8BIT | MSIZE_8BIT ; Set the multiple arithmetic temp_d3_w = *(input_buf1_La0++); Load word #1: local || temp_d4_w = *(input_buf2_Ga8++); global temp_d3_w =mc temp_d3_w + temp_d4_w; Add temp_d5_w = temp_d3_w | @mf; Saturate || temp_d4_w = *(input_buf2_Ga8++); global || temp_d3_w = *(input_buf1_La0++); Load word #2: local ;****************************************************************** ;* Loop: Add8 tight loop ;* ;* Iterations: ;* Number of pixels in the row/4 - 3 ;* ;* Functions: ;* Add with saturate ;* ;* Exiting condition: ;* End when all the iterations are complete ;* ;********************************************************************/ add_ls0: temp_d3_w =mc temp_d3_w + temp_d4_w; Add Word #2 || *(output_buf_La2++) = temp_d5_w; Store Word # 1 add_le0: temp_d5_w = temp_d3_w | @mf; Saturate Word #2 || temp_d4_w = *(input_buf2_Ga8++); global || temp_d3_w = *(input_buf1_La0++); Load word #3: local temp_d3_w =mc temp_d3_w + temp_d4_w; Add || *(output_buf_La2++) = temp_d5_w; Store br = iprs temp_d5_w = temp_d3_w | @mf; Saturate Word: delay 1 *(output_buf_La2++) = temp_d5_w; Store Word: delay 2 ;*END: add_tight_loop_8