Main Page | Modules | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

/Users/trevorw/projects/release/covered-0.7.4/src/static.c File Reference


Detailed Description

Author:
Trevor Williams (phase1geo@gmail.com)
Date:
10/02/2002
To accommodate the need for parameters/genvars (variables) in static expressions, the static_expr structure and supporting code was created to maintain the efficiency of static expressions that consist of known values while being able to keep track of parameter/genvar uses in static expressions.
A static_expr structure consists of members: an int (stores known integer values) and an expression pointer. If the expression pointer is set to NULL for the given static_expr, it is assumed that the static_expr structure contains a valid, known value that can be used in immediate computations. If the expression pointer is not NULL, it is assumed that the static_expr structure contains an expression tree that needs to be evaluated at a later time (when parameters/genvars are being elaborated).
When a static expression is being parsed and a static value (integer value) is encountered, a new static_expr is allocated from heap memory and the number field is assigned to this integer value. The new static_expr structure is then passed up the tree to be used in further calculations, if necessary. If a static expression is being parsed and an identifier (parameter/genvar) is encountered, an expression is created with an operation type of EXP_OP_SIG to indicate that a parameter/genvar is required during elaboration. The name of the necessary parameter/genvar is bound to the newly created expression.
Using this strategy for handling static expressions, it becomes evident that we retain the efficiency of calculating static expression that consists entirely of known values (the only overhead is the allocation/deallocation of a static_expr structure from the heap). If a parameter/genvar is found during the parse stage, more effort is required to calculate the static_expr, but this is considered necessary in the larger scope of things so we will not concern ourselves with this overhead (which is fairly minimal anyways).

#include <stdio.h>
#include <assert.h>
#include "defines.h"
#include "static.h"
#include "expr.h"
#include "db.h"
#include "util.h"
#include "vector.h"
#include "binding.h"

Functions

static_exprstatic_expr_gen_unary (static_expr *stexp, exp_op_type op, int line, int first, int last)
 Calculates new values for unary static expressions and returns the new static expression.

static_exprstatic_expr_gen (static_expr *right, static_expr *left, int op, int line, int first, int last, char *func_name)
 Calculates new values for static expression and returns the new static expression.

void static_expr_calc_lsb_and_width_pre (static_expr *left, static_expr *right, unsigned int *width, int *lsb, int *big_endian)
 Calculates LSB, width and endianness for specified left/right pair for vector (used before parameter resolve).

void static_expr_calc_lsb_and_width_post (static_expr *left, static_expr *right, unsigned int *width, int *lsb, int *big_endian)
 Calculates LSB, width and endianness for specified left/right pair for vector (used after parameter resolve).

void static_expr_dealloc (static_expr *stexp, bool rm_exp)
 Deallocates static_expr memory from heap.


Variables

func_unitcurr_funit
int curr_expr_id


Function Documentation

void static_expr_calc_lsb_and_width_post static_expr left,
static_expr right,
unsigned int *  width,
int *  lsb,
int *  big_endian
 

Calculates LSB, width and endianness for specified left/right pair for vector (used after parameter resolve).

Parameters:
left Pointer to static expression on left of vector.
right Pointer to static expression on right of vector.
width Calculated width of combined right/left static expressions.
lsb Calculated lsb of combined right/left static expressions.
big_endian Set to 1 if the left expression is less than the right expression.
Calculates the LSB and width of a vector defined by the specified left and right static expressions. This function assumes that any expressions have been calculated for a legal value.

00396   { PROFILE(STATIC_EXPR_CALC_LSB_AND_WIDTH_POST);
00397   
00398   assert( left  != NULL );
00399   assert( right != NULL );
00400 
00401   *width      = 1;
00402   *lsb        = -1;
00403   *big_endian = 0;
00404 
00405   /* If the right static expression contains an expression, get its integer value and place it in the num field */
00406   if( right->exp != NULL ) {
00407     right->num = vector_to_int( right->exp->value );
00408   }
00409 
00410   /* If the left static expression contains an expression, get its integer value and place it in the num field */
00411   if( left->exp != NULL ) {
00412     left->num = vector_to_int( left->exp->value );
00413   }
00414   
00415   /* Get initial value for LSB */
00416   *lsb = right->num;
00417   assert( *lsb >= 0 );
00418 
00419   /* Calculate width and make sure that LSB is the lower of the two values */
00420   if( *lsb <= left->num ) {
00421     *width = (left->num - *lsb) + 1;
00422     assert( *width > 0 );
00423   } else {
00424     *width      = (*lsb - left->num) + 1;
00425     *lsb        = left->num;
00426     *big_endian = 1;
00427     assert( *width > 0 );
00428     assert( *lsb >= 0 );
00429   }
00430 
00431   PROFILE_END;
00432 
00433 }

void static_expr_calc_lsb_and_width_pre static_expr left,
static_expr right,
unsigned int *  width,
int *  lsb,
int *  big_endian
 

Calculates LSB, width and endianness for specified left/right pair for vector (used before parameter resolve).

Parameters:
left Pointer to static expression on left of vector.
right Pointer to static expression on right of vector.
width Calculated width of combined right/left static expressions.
lsb Calculated lsb of combined right/left static expressions.
big_endian Set to 1 if the MSB/LSB is specified in big endian order.
Calculates the LSB, width and endianness of a vector defined by the specified left and right static expressions. If the width cannot be obtained immediately (parameter in static expression), set width to 0. If the LSB cannot be obtained immediately (parameter in static expression), set LSB to -1. The endianness can only be used if the width is known. The returned width and lsb parameters can be used to size a vector instantiation.

00346   { PROFILE(STATIC_EXPR_CALC_LSB_AND_WIDTH_PRE);
00347 
00348   *width      = 0;
00349   *lsb        = -1;
00350   *big_endian = 0;
00351 
00352   if( (right != NULL) && (right->exp == NULL) ) {
00353     *lsb = right->num;
00354     assert( *lsb >= 0 );
00355   }
00356 
00357   if( (left != NULL) && (left->exp == NULL) ) {
00358     if( *lsb != -1 ) {
00359       if( *lsb <= left->num ) {
00360         *width = (left->num - *lsb) + 1;
00361         assert( *width > 0 );
00362       } else {
00363         *width      = (*lsb - left->num) + 1;
00364         *lsb        = left->num;
00365         *big_endian = 1;
00366         assert( *width > 0 );
00367         assert( *lsb >= 0 );
00368       }
00369     } else {
00370       *lsb = left->num;
00371       assert( *lsb >= 0 );
00372     }
00373   }
00374 
00375   PROFILE_END;
00376 
00377 }

void static_expr_dealloc static_expr stexp,
bool  rm_exp
 

Deallocates static_expr memory from heap.

Parameters:
stexp Pointer to static expression to deallocate.
rm_exp Specifies that expression tree should be deallocated.
Deallocates all allocated memory from the heap for the specified static_expr structure.

00445   { PROFILE(STATIC_EXPR_DEALLOC);
00446 
00447   if( stexp != NULL ) {
00448 
00449     if( rm_exp && (stexp->exp != NULL) ) {
00450       expression_dealloc( stexp->exp, FALSE );
00451     }
00452 
00453     free_safe( stexp, sizeof( static_expr ) );
00454 
00455   }
00456 
00457 }

static_expr* static_expr_gen static_expr right,
static_expr left,
int  op,
int  line,
int  first,
int  last,
char *  func_name
 

Calculates new values for static expression and returns the new static expression.

Returns:
Returns pointer to new static_expr structure.
Exceptions:
anonymous expression_create expression_create expression_create expression_create expression_create expression_create
Used by the parser to calculate a new static_expr structure based on the operation encountered while parsing. Based on the operation type specified in the argument list, performs unary operation (if both operands are static numbers, storing result into original static_expr number field and returns If only one of the operands is an expression, create a EXP_OP_STATIC expression for the other operand and create an expression consisting of these two expressions and the specified operation. If both operands are expressions, simply create a new expression consisting of those two expressions and specified operator. Store the newly create expression in the original right static_expr and deallocate the left static_expr.
Parameters:
right  Pointer to right static expression
left  Pointer to left static expression
op  Static expression operation
line  Line number that static expression operation found on
first  Column index of first character in expression
last  Column index of last character in expression
func_name  Name of function to call (only valid when op == EXP_OP_FUNC_CALL)

00205   { PROFILE(STATIC_EXPR_GEN);
00206 
00207   expression* tmpexp;     /* Temporary expression for holding newly created parent expression */
00208   int         i;          /* Loop iterator */
00209   int         value = 1;  /* Temporary value */
00210   
00211   assert( (op == EXP_OP_XOR)    || (op == EXP_OP_MULTIPLY) || (op == EXP_OP_DIVIDE) || (op == EXP_OP_MOD)       ||
00212           (op == EXP_OP_ADD)    || (op == EXP_OP_SUBTRACT) || (op == EXP_OP_AND)    || (op == EXP_OP_OR)        ||
00213           (op == EXP_OP_NOR)    || (op == EXP_OP_NAND)     || (op == EXP_OP_NXOR)   || (op == EXP_OP_EXPONENT)  ||
00214           (op == EXP_OP_LSHIFT) || (op == EXP_OP_RSHIFT)   || (op == EXP_OP_LIST)   || (op == EXP_OP_FUNC_CALL) ||
00215           (op == EXP_OP_GE)     || (op == EXP_OP_LE)       || (op == EXP_OP_EQ)     || (op == EXP_OP_GT)        ||
00216           (op == EXP_OP_LT)     || (op == EXP_OP_SBIT_SEL) || (op == EXP_OP_LAND)   || (op == EXP_OP_LOR)       ||
00217           (op == EXP_OP_NE) );
00218 
00219   if( (right != NULL) && (left != NULL) ) {
00220 
00221     if( right->exp == NULL ) {
00222 
00223       if( left->exp == NULL ) {
00224 
00225         switch( op ) {
00226           case EXP_OP_XOR      :  right->num = left->num ^ right->num;     break;
00227           case EXP_OP_MULTIPLY :  right->num = left->num * right->num;     break;
00228           case EXP_OP_DIVIDE   :  right->num = left->num / right->num;     break;
00229           case EXP_OP_MOD      :  right->num = left->num % right->num;     break;
00230           case EXP_OP_ADD      :  right->num = left->num + right->num;     break;
00231           case EXP_OP_SUBTRACT :  right->num = left->num - right->num;     break;
00232           case EXP_OP_EXPONENT :
00233             for( i=0; i<right->num; i++ ) {
00234               value *= left->num;
00235             }
00236             right->num = value;
00237             break;
00238           case EXP_OP_AND      :  right->num = left->num & right->num;     break;
00239           case EXP_OP_OR       :  right->num = left->num | right->num;     break;
00240           case EXP_OP_NOR      :  right->num = ~(left->num | right->num);  break;
00241           case EXP_OP_NAND     :  right->num = ~(left->num & right->num);  break;
00242           case EXP_OP_NXOR     :  right->num = ~(left->num ^ right->num);  break;
00243           /*@-shiftnegative -shiftimplementation@*/
00244           case EXP_OP_LSHIFT   :  right->num = left->num << right->num;    break;
00245           case EXP_OP_RSHIFT   :  right->num = left->num >> right->num;    break;
00246           /*@=shiftnegative =shiftimplementation@*/
00247           case EXP_OP_GE       :  right->num = (left->num >= right->num) ? 1 : 0;  break;
00248           case EXP_OP_LE       :  right->num = (left->num <= right->num) ? 1 : 0;  break;
00249           case EXP_OP_EQ       :  right->num = (left->num == right->num) ? 1 : 0;  break;
00250           case EXP_OP_NE       :  right->num = (left->num != right->num) ? 1 : 0;  break;
00251           case EXP_OP_GT       :  right->num = (left->num > right->num)  ? 1 : 0;  break;
00252           case EXP_OP_LT       :  right->num = (left->num < right->num)  ? 1 : 0;  break;
00253           case EXP_OP_LAND     :  right->num = (left->num && right->num) ? 1 : 0;  break;
00254           case EXP_OP_LOR      :  right->num = (left->num || right->num) ? 1 : 0;  break;
00255           default              :  break;
00256         }
00257 
00258       } else {
00259 
00260         right->exp = expression_create( NULL, NULL, EXP_OP_STATIC, FALSE, curr_expr_id, line, first, last, FALSE );
00261         curr_expr_id++;
00262         {
00263           vector* vec = vector_create( 32, VTYPE_EXP, VDATA_UL, TRUE );
00264           vector_dealloc( right->exp->value );
00265           right->exp->value = vec;
00266         }
00267         (void)vector_from_int( right->exp->value, right->num );
00268 
00269         tmpexp = expression_create( right->exp, left->exp, op, FALSE, curr_expr_id, line, first, last, FALSE );
00270         curr_expr_id++;
00271         right->exp = tmpexp;
00272         
00273       }
00274 
00275     } else {
00276 
00277       if( left->exp == NULL ) {
00278 
00279         left->exp = expression_create( NULL, NULL, EXP_OP_STATIC, FALSE, curr_expr_id, line, first, last, FALSE );
00280         curr_expr_id++;
00281         {
00282           vector* vec = vector_create( 32, VTYPE_EXP, VDATA_UL, TRUE );
00283           vector_dealloc( left->exp->value );
00284           left->exp->value = vec;
00285         }
00286         (void)vector_from_int( left->exp->value, left->num );
00287 
00288         tmpexp = expression_create( right->exp, left->exp, op, FALSE, curr_expr_id, line, first, last, FALSE );
00289         curr_expr_id++;
00290         right->exp = tmpexp;
00291 
00292       } else {
00293 
00294         tmpexp = expression_create( right->exp, left->exp, op, FALSE, curr_expr_id, line, first, last, FALSE );
00295         curr_expr_id++;
00296         right->exp = tmpexp;
00297 
00298       }
00299 
00300     }
00301 
00302   } else if( (op == EXP_OP_FUNC_CALL) || (op == EXP_OP_SBIT_SEL) ) {
00303 
00304     /*
00305      If this is a function call or SBIT_SEL, only the left expression will be a valid expression (so we need to special
00306      handle this)
00307     */
00308 
00309     assert( right == NULL );
00310     assert( left  != NULL );
00311 
00312     right = (static_expr*)malloc_safe( sizeof( static_expr ) );
00313     right->exp = expression_create( NULL, left->exp, op, FALSE, curr_expr_id, line, first, last, FALSE );
00314     curr_expr_id++;
00315 
00316     /* Make sure that we bind this later */
00317     bind_add( FUNIT_FUNCTION, func_name, right->exp, curr_funit );
00318 
00319   }
00320 
00321   static_expr_dealloc( left, FALSE );
00322 
00323   return( right );
00324 
00325 }

static_expr* static_expr_gen_unary static_expr stexp,
exp_op_type  op,
int  line,
int  first,
int  last
 

Calculates new values for unary static expressions and returns the new static expression.

Parameters:
stexp Pointer to static expression.
op Unary static expression operation.
line Line number that this expression was found on in file.
first Column index of first character in this expression.
last Column index of last character in this expression.
Returns:
Returns pointer to new static_expr structure.
Exceptions:
anonymous expression_create expression_create
Used by the parser to calculate a new static_expr structure based on the unary operation encountered while parsing. Based on the operation type specified in the argument list, performs unary operation (if operand is a static number and not an expression -- parameter in operand expression tree), storing result into original static_expr number field and returns the original structure back to the calling function. If the operand is an expression, create an expression for the specified operation type and store this expression in the original expression pointer field.
Parameters:
stexp  Pointer to static expression
op  Unary static expression operation
line  Line number that this expression was found on in file
first  Column index of first character in this expression
last  Column index of last character in this expression

00095   { PROFILE(STATIC_EXPR_GEN_UNARY);
00096 
00097   expression*  tmpexp;  /* Container for newly created expression */
00098   int          uop;     /* Temporary bit holder */
00099   unsigned int i;       /* Loop iterator */
00100 
00101   if( stexp != NULL ) {
00102 
00103     assert( (op == EXP_OP_UINV)  || (op == EXP_OP_UAND) || (op == EXP_OP_UOR)   || (op == EXP_OP_UXOR)  ||
00104             (op == EXP_OP_UNAND) || (op == EXP_OP_UNOR) || (op == EXP_OP_UNXOR) || (op == EXP_OP_UNOT)  ||
00105             (op == EXP_OP_PASSIGN) );
00106 
00107     if( stexp->exp == NULL ) {
00108 
00109       switch( op ) {
00110 
00111         case EXP_OP_UINV :
00112           stexp->num = ~stexp->num;
00113           break;
00114 
00115         case EXP_OP_UAND  :
00116         case EXP_OP_UOR   :
00117         case EXP_OP_UXOR  :
00118         case EXP_OP_UNAND :
00119         case EXP_OP_UNOR  :
00120         case EXP_OP_UNXOR :
00121           uop = stexp->num & 0x1;
00122           for( i=1; i<(SIZEOF_INT * 8); i++ ) {
00123             switch( op ) {
00124               case EXP_OP_UNAND :
00125               /*@-shiftimplementation@*/
00126               case EXP_OP_UAND  :  uop = uop & ((stexp->num >> i) & 0x1);  break;
00127               case EXP_OP_UNOR  :
00128               case EXP_OP_UOR   :  uop = uop | ((stexp->num >> i) & 0x1);  break;
00129               case EXP_OP_UNXOR :
00130               case EXP_OP_UXOR  :  uop = uop ^ ((stexp->num >> i) & 0x1);  break;
00131               /*@=shiftimplementation@*/
00132               default           :  break;
00133             }
00134           }
00135           switch( op ) {
00136             case EXP_OP_UAND  :
00137             case EXP_OP_UOR   :
00138             case EXP_OP_UXOR  :  stexp->num = uop;                 break;
00139             case EXP_OP_UNAND :
00140             case EXP_OP_UNOR  :
00141             case EXP_OP_UNXOR :  stexp->num = (uop == 0) ? 1 : 0;  break;
00142             default           :  break;
00143           }
00144           break;
00145 
00146         case EXP_OP_UNOT :
00147           stexp->num = (stexp->num == 0) ? 1 : 0;
00148           break;
00149 
00150         case EXP_OP_PASSIGN :
00151           tmpexp = expression_create( NULL, NULL, EXP_OP_STATIC, FALSE, curr_expr_id, line, first, last, FALSE );
00152           curr_expr_id++;
00153           {
00154             vector* vec = vector_create( 32, VTYPE_EXP, VDATA_UL, TRUE );
00155             vector_dealloc( tmpexp->value );
00156             tmpexp->value = vec;
00157           }
00158           (void)vector_from_int( tmpexp->value, stexp->num );
00159 
00160           stexp->exp = expression_create( tmpexp, NULL, op, FALSE, curr_expr_id, line, first, last, FALSE );
00161           curr_expr_id++;
00162           break;
00163         default :  break;
00164       }
00165 
00166     } else {
00167 
00168       tmpexp = expression_create( stexp->exp, NULL, op, FALSE, curr_expr_id, line, first, last, FALSE );
00169       curr_expr_id++;
00170       stexp->exp = tmpexp;
00171 
00172     }
00173 
00174   }
00175 
00176   PROFILE_END;
00177 
00178   return( stexp );
00179 
00180 }


Variable Documentation

int curr_expr_id
 

This static value contains the current expression ID number to use for the next expression found, it is incremented by one when an expression is found. This allows us to have a unique expression ID for each expression (since expressions have no intrinsic names).

func_unit* curr_funit
 

Pointer to the functional unit structure for the functional unit that is currently being parsed.


Generated on Wed Jun 17 22:19:24 2009 for Covered by doxygen 1.3.4