#include <assert.h>
#include "defines.h"
#include "reentrant.h"
#include "sys_tasks.h"
#include "util.h"
Functions | |
static int | reentrant_count_afu_bits (func_unit *funit) |
static void | reentrant_store_data_bits (func_unit *funit, reentrant *ren, unsigned int curr_bit) |
static void | reentrant_restore_data_bits (func_unit *funit, reentrant *ren, unsigned int curr_bit, expression *expr) |
reentrant * | reentrant_create (func_unit *funit) |
Allocates and initializes the reentrant structure for the given functional unit. | |
void | reentrant_dealloc (reentrant *ren, func_unit *funit, expression *expr) |
Deallocates all memory associated with the given reentrant structure. | |
Variables | |
const exp_info | exp_op_info [EXP_OP_NUM] |
static int reentrant_count_afu_bits | ( | func_unit * | funit | ) | [static] |
Recursively iterates up the functional unit tree keeping track of the total number of bits needed to store all information in the current reentrant task/function.
funit | Pointer to current function to count the bits of |
References vsuppl_u::data_type, ESUPPL_BITS_TO_STORE, exp_link_s::exp, func_unit_s::exp_head, EXPR_IS_STATIC, EXPR_OWNS_VEC, FUNIT_AFUNCTION, FUNIT_ANAMED_BLOCK, FUNIT_ATASK, exp_link_s::next, sig_link_s::next, expression_s::op, func_unit_s::parent, vsuppl_u::part, PROFILE, PROFILE_END, sig_link_s::sig, func_unit_s::sig_head, vector_s::suppl, func_unit_s::type, expression_s::value, vsignal_s::value, VDATA_R32, VDATA_R64, VDATA_UL, and vector_s::width.
Referenced by reentrant_create().
00042 { PROFILE(REENTRANT_COUNT_AFU_BITS); 00043 00044 sig_link* sigl; /* Pointer to current signal link */ 00045 exp_link* expl; /* Pointer to current expression link */ 00046 int bits = 0; /* Number of bits in this functional unit and all parent functional units in the reentrant task/function */ 00047 00048 if( (funit->type == FUNIT_ATASK) || (funit->type == FUNIT_AFUNCTION) || (funit->type == FUNIT_ANAMED_BLOCK) ) { 00049 00050 /* Count the number of signal bits in this functional unit */ 00051 sigl = funit->sig_head; 00052 while( sigl != NULL ) { 00053 switch( sigl->sig->value->suppl.part.data_type ) { 00054 case VDATA_UL : bits += (sigl->sig->value->width * 2) + 1; break; 00055 case VDATA_R64 : bits += 64; break; 00056 case VDATA_R32 : bits += 32; break; 00057 default : assert( 0 ); break; 00058 } 00059 sigl = sigl->next; 00060 } 00061 00062 /* Count the number of expression bits in this functional unit */ 00063 expl = funit->exp_head; 00064 while( expl != NULL ) { 00065 if( (EXPR_OWNS_VEC( expl->exp->op ) == 1) && (EXPR_IS_STATIC( expl->exp ) == 0) ) { 00066 bits += (expl->exp->value->width * 2); 00067 } 00068 bits += ((ESUPPL_BITS_TO_STORE % 2) == 0) ? ESUPPL_BITS_TO_STORE : (ESUPPL_BITS_TO_STORE + 1); 00069 expl = expl->next; 00070 } 00071 00072 /* If the current functional unit is a named block, gather the bits in the parent functional unit */ 00073 if( funit->type == FUNIT_ANAMED_BLOCK ) { 00074 bits += reentrant_count_afu_bits( funit->parent ); 00075 } 00076 00077 } 00078 00079 PROFILE_END; 00080 00081 return( bits ); 00082 00083 }
Allocates and initializes the reentrant structure for the given functional unit.
Allocates and initializes the reentrant structure for the given functional unit, compressing and packing the bits into the given data structure.
funit | Pointer to functional unit to create a new reentrant structure for |
References reentrant_s::data, reentrant_s::data_size, malloc_safe, PROFILE, PROFILE_END, reentrant_count_afu_bits(), and reentrant_store_data_bits().
Referenced by expression_op_func__passign().
00366 { PROFILE(REENTRANT_CREATE); 00367 00368 reentrant* ren = NULL; /* Pointer to newly created reentrant structure */ 00369 int data_size; /* Number of uint8s needed to store the given functional unit */ 00370 unsigned int bits = 0; /* Number of bits needed to store signal values */ 00371 int i; /* Loop iterator */ 00372 00373 /* Get size needed to store data */ 00374 bits = reentrant_count_afu_bits( funit ); 00375 00376 /* Calculate data size */ 00377 data_size = ((bits & 0x7) == 0) ? (bits >> 3) : ((bits >> 3) + 1); 00378 00379 /* If there is data to store, allocate the needed memory and populate it */ 00380 if( data_size > 0 ) { 00381 00382 /* Allocate the structure */ 00383 ren = (reentrant*)malloc_safe( sizeof( reentrant ) ); 00384 00385 /* Set the data size */ 00386 ren->data_size = data_size; 00387 00388 /* Allocate and initialize memory for data */ 00389 ren->data = (uint8*)malloc_safe( sizeof( uint8 ) * ren->data_size ); 00390 for( i=0; i<data_size; i++ ) { 00391 ren->data[i] = 0; 00392 } 00393 00394 /* Walk through the signal list in the reentrant functional unit, compressing and saving vector values */ 00395 reentrant_store_data_bits( funit, ren, 0 ); 00396 00397 } 00398 00399 PROFILE_END; 00400 00401 return( ren ); 00402 00403 }
void reentrant_dealloc | ( | reentrant * | ren, | |
func_unit * | funit, | |||
expression * | expr | |||
) |
Deallocates all memory associated with the given reentrant structure.
Pops data back into the given functional unit and deallocates all memory associated with the given reentrant structure.
ren | Pointer to the reentrant structure to deallocate from memory | |
funit | Pointer to functional unit associated with this reentrant structure | |
expr | Pointer of expression to exclude from updating (optional) |
References reentrant_s::data, reentrant_s::data_size, free_safe, PROFILE, PROFILE_END, and reentrant_restore_data_bits().
Referenced by expression_op_func__func_call(), and sim_thread().
00413 { PROFILE(REENTRANT_DEALLOC); 00414 00415 if( ren != NULL ) { 00416 00417 /* If we have data being stored, pop it */ 00418 if( ren->data_size > 0 ) { 00419 00420 /* Walk through each bit in the compressed data array and assign it back to its signal */ 00421 reentrant_restore_data_bits( funit, ren, 0, expr ); 00422 00423 /* Deallocate the data uint8 array */ 00424 free_safe( ren->data, (sizeof( uint8 ) * ren->data_size) ); 00425 00426 } 00427 00428 /* Deallocate memory allocated for this reentrant structure */ 00429 free_safe( ren, sizeof( reentrant ) ); 00430 00431 } 00432 00433 PROFILE_END; 00434 00435 }
static void reentrant_restore_data_bits | ( | func_unit * | funit, | |
reentrant * | ren, | |||
unsigned int | curr_bit, | |||
expression * | expr | |||
) | [static] |
Recursively restores the signal and expression values of the functional units in a reentrant task/function.
funit | Pointer to current functional unit to restore | |
ren | Pointer to reentrant structure containing bits to restore | |
curr_bit | Current bit in reentrant structure to restore | |
expr | Pointer to expression to exclude from updating |
References reentrant_s::data, vsuppl_u::data_type, ESUPPL_BITS_TO_STORE, esuppl_u::eval_f, esuppl_u::eval_t, exp_link_s::exp, func_unit_s::exp_head, EXPR_IS_STATIC, EXPR_OWNS_VEC, FUNIT_AFUNCTION, FUNIT_ANAMED_BLOCK, FUNIT_ATASK, esuppl_u::left_changed, exp_link_s::next, sig_link_s::next, expression_s::op, func_unit_s::parent, esuppl_u::part, vsuppl_u::part, esuppl_u::prev_called, PROFILE, PROFILE_END, vector_s::r32, vector_s::r64, esuppl_u::right_changed, vsuppl_u::set, sig_link_s::sig, func_unit_s::sig_head, expression_s::suppl, vector_s::suppl, sys_task_bitstoreal(), func_unit_s::type, vector_s::ul, UL_DIV, UL_MOD, rv32_s::val, rv64_s::val, expression_s::value, vector_s::value, vsignal_s::value, VDATA_R32, VDATA_R64, VDATA_UL, VTYPE_INDEX_VAL_VALH, VTYPE_INDEX_VAL_VALL, and vector_s::width.
Referenced by reentrant_dealloc().
00223 { PROFILE(REENTRANT_RESTORE_DATA_BITS); 00224 00225 int i; /* Loop iterator */ 00226 00227 if( (funit->type == FUNIT_ATASK) || (funit->type == FUNIT_AFUNCTION) || (funit->type == FUNIT_ANAMED_BLOCK) ) { 00228 00229 sig_link* sigl; 00230 exp_link* expl; 00231 00232 /* Walk through each bit in the compressed data array and assign it back to its signal */ 00233 sigl = funit->sig_head; 00234 while( sigl != NULL ) { 00235 switch( sigl->sig->value->suppl.part.data_type ) { 00236 case VDATA_UL : 00237 { 00238 unsigned int i; 00239 for( i=0; i<sigl->sig->value->width; i++ ) { 00240 ulong* entry = sigl->sig->value->value.ul[UL_DIV(i)]; 00241 if( UL_MOD(i) == 0 ) { 00242 entry[VTYPE_INDEX_VAL_VALL] = 0; 00243 entry[VTYPE_INDEX_VAL_VALH] = 0; 00244 } 00245 entry[VTYPE_INDEX_VAL_VALL] |= (ulong)((ren->data[curr_bit>>3] >> (curr_bit & 0x7)) & 0x1) << UL_MOD(i); 00246 curr_bit++; 00247 entry[VTYPE_INDEX_VAL_VALH] |= (ulong)((ren->data[curr_bit>>3] >> (curr_bit & 0x7)) & 0x1) << UL_MOD(i); 00248 curr_bit++; 00249 } 00250 sigl->sig->value->suppl.part.set = (ren->data[curr_bit>>3] >> (curr_bit & 0x7)) & 0x1; 00251 curr_bit++; 00252 } 00253 break; 00254 case VDATA_R64 : 00255 { 00256 uint64 real_bits = 0; 00257 unsigned int i; 00258 for( i=0; i<64; i++ ) { 00259 real_bits |= (uint64)ren->data[curr_bit>>3] << (i - curr_bit); 00260 curr_bit++; 00261 } 00262 sigl->sig->value->value.r64->val = sys_task_bitstoreal( real_bits ); 00263 } 00264 break; 00265 case VDATA_R32 : 00266 { 00267 uint64 real_bits = 0; 00268 unsigned int i; 00269 for( i=0; i<32; i++ ) { 00270 real_bits |= (uint64)ren->data[curr_bit>>3] << (i - curr_bit); 00271 curr_bit++; 00272 } 00273 sigl->sig->value->value.r32->val = (float)sys_task_bitstoreal( real_bits ); 00274 } 00275 break; 00276 default : assert( 0 ); break; 00277 } 00278 sigl = sigl->next; 00279 } 00280 00281 /* Walk through each bit in the compressed data array and assign it back to its expression */ 00282 expl = funit->exp_head; 00283 while( expl != NULL ) { 00284 if( expl->exp == expr ) { 00285 curr_bit += (expr->value->width * 2); 00286 } else { 00287 if( (EXPR_OWNS_VEC( expl->exp->op ) == 1) && (EXPR_IS_STATIC( expl->exp ) == 0) ) { 00288 switch( expl->exp->value->suppl.part.data_type ) { 00289 case VDATA_UL : 00290 { 00291 unsigned int i; 00292 for( i=0; i<expl->exp->value->width; i++ ) { 00293 ulong* entry = expl->exp->value->value.ul[UL_DIV(i)]; 00294 if( UL_MOD(i) == 0 ) { 00295 entry[VTYPE_INDEX_VAL_VALL] = 0; 00296 entry[VTYPE_INDEX_VAL_VALH] = 0; 00297 } 00298 entry[VTYPE_INDEX_VAL_VALL] |= (ulong)((ren->data[curr_bit>>3] >> (curr_bit & 0x7)) & 0x1) << UL_MOD(i); 00299 curr_bit++; 00300 entry[VTYPE_INDEX_VAL_VALH] |= (ulong)((ren->data[curr_bit>>3] >> (curr_bit & 0x7)) & 0x1) << UL_MOD(i); 00301 curr_bit++; 00302 } 00303 } 00304 break; 00305 case VDATA_R64 : 00306 { 00307 uint64 real_bits = 0; 00308 unsigned int i; 00309 for( i=0; i<64; i++ ) { 00310 real_bits |= (uint64)ren->data[curr_bit>>3] << (i - curr_bit); 00311 curr_bit++; 00312 } 00313 expl->exp->value->value.r64->val = sys_task_bitstoreal( real_bits ); 00314 } 00315 break; 00316 case VDATA_R32 : 00317 { 00318 uint64 real_bits = 0; 00319 unsigned int i; 00320 for( i=0; i<32; i++ ) { 00321 real_bits |= (uint64)ren->data[curr_bit>>3] << (i - curr_bit); 00322 curr_bit++; 00323 } 00324 expl->exp->value->value.r32->val = (float)sys_task_bitstoreal( real_bits ); 00325 } 00326 break; 00327 default : assert( 0 ); 00328 } 00329 } 00330 } 00331 for( i=0; i<(((ESUPPL_BITS_TO_STORE % 2) == 0) ? ESUPPL_BITS_TO_STORE : (ESUPPL_BITS_TO_STORE + 1)); i++ ) { 00332 switch( i ) { 00333 case 0 : expl->exp->suppl.part.left_changed = (ren->data[curr_bit>>3] >> (curr_bit & 0x7)); break; 00334 case 1 : expl->exp->suppl.part.right_changed = (ren->data[curr_bit>>3] >> (curr_bit & 0x7)); break; 00335 case 2 : expl->exp->suppl.part.eval_t = (ren->data[curr_bit>>3] >> (curr_bit & 0x7)); break; 00336 case 3 : expl->exp->suppl.part.eval_f = (ren->data[curr_bit>>3] >> (curr_bit & 0x7)); break; 00337 case 4 : expl->exp->suppl.part.prev_called = (ren->data[curr_bit>>3] >> (curr_bit & 0x7)); break; 00338 } 00339 curr_bit++; 00340 } 00341 expl = expl->next; 00342 } 00343 00344 /* 00345 If the current functional unit is a named block, restore the rest of the bits for the parent functional units 00346 in this reentrant task/function. 00347 */ 00348 if( funit->type == FUNIT_ANAMED_BLOCK ) { 00349 reentrant_restore_data_bits( funit->parent, ren, curr_bit, expr ); 00350 } 00351 00352 } 00353 00354 PROFILE_END; 00355 00356 }
static void reentrant_store_data_bits | ( | func_unit * | funit, | |
reentrant * | ren, | |||
unsigned int | curr_bit | |||
) | [static] |
Recursively gathers all signal data bits to store and stores them in the given reentrant structure.
funit | Pointer to current functional unit to traverse | |
ren | Pointer to reentrant structure to populate | |
curr_bit | Current bit to store (should be started at a value of 0) |
References reentrant_s::data, vsuppl_u::data_type, ESUPPL_BITS_TO_STORE, esuppl_u::eval_f, esuppl_u::eval_t, exp_link_s::exp, func_unit_s::exp_head, EXPR_IS_STATIC, EXPR_OWNS_VEC, FUNIT_AFUNCTION, FUNIT_ANAMED_BLOCK, FUNIT_ATASK, esuppl_u::left_changed, exp_link_s::next, sig_link_s::next, expression_s::op, func_unit_s::parent, esuppl_u::part, vsuppl_u::part, esuppl_u::prev_called, PROFILE, PROFILE_END, vector_s::r32, vector_s::r64, esuppl_u::right_changed, vsuppl_u::set, sig_link_s::sig, func_unit_s::sig_head, expression_s::suppl, vector_s::suppl, sys_task_realtobits(), func_unit_s::type, vector_s::ul, UL_DIV, UL_MOD, rv32_s::val, rv64_s::val, expression_s::value, vector_s::value, vsignal_s::value, VDATA_R32, VDATA_R64, VDATA_UL, VTYPE_INDEX_VAL_VALH, VTYPE_INDEX_VAL_VALL, and vector_s::width.
Referenced by reentrant_create().
00093 { PROFILE(REENTRANT_STORE_DATA_BITS); 00094 00095 if( (funit->type == FUNIT_ATASK) || (funit->type == FUNIT_AFUNCTION) || (funit->type == FUNIT_ANAMED_BLOCK) ) { 00096 00097 sig_link* sigl = funit->sig_head; 00098 exp_link* expl = funit->exp_head; 00099 00100 /* Walk through the signal list in the reentrant functional unit, compressing and saving vector values */ 00101 while( sigl != NULL ) { 00102 switch( sigl->sig->value->suppl.part.data_type ) { 00103 case VDATA_UL : 00104 { 00105 unsigned int i; 00106 for( i=0; i<sigl->sig->value->width; i++ ) { 00107 ulong* entry = sigl->sig->value->value.ul[UL_DIV(i)]; 00108 ren->data[curr_bit>>3] |= (((entry[VTYPE_INDEX_VAL_VALL] >> UL_MOD(i)) & 0x1) << (curr_bit & 0x7)); 00109 curr_bit++; 00110 ren->data[curr_bit>>3] |= (((entry[VTYPE_INDEX_VAL_VALH] >> UL_MOD(i)) & 0x1) << (curr_bit & 0x7)); 00111 curr_bit++; 00112 } 00113 ren->data[curr_bit>>3] |= sigl->sig->value->suppl.part.set << (curr_bit & 0x7); 00114 curr_bit++; 00115 /* Clear the set bit */ 00116 sigl->sig->value->suppl.part.set = 0; 00117 } 00118 break; 00119 case VDATA_R64 : 00120 { 00121 uint64 real_bits = sys_task_realtobits( sigl->sig->value->value.r64->val ); 00122 unsigned int i; 00123 for( i=0; i<64; i++ ) { 00124 ren->data[curr_bit>>3] |= (real_bits & 0x1) << (curr_bit & 0x7); 00125 real_bits >>= 1; 00126 curr_bit++; 00127 } 00128 } 00129 break; 00130 case VDATA_R32 : 00131 { 00132 uint64 real_bits = sys_task_realtobits( (double)sigl->sig->value->value.r32->val ); 00133 unsigned int i; 00134 for( i=0; i<32; i++ ) { 00135 ren->data[curr_bit>>3] |= (real_bits & 0x1) << (curr_bit & 0x7); 00136 real_bits >>= 1; 00137 curr_bit++; 00138 } 00139 } 00140 break; 00141 default : assert( 0 ); 00142 } 00143 sigl = sigl->next; 00144 } 00145 00146 /* Walk through expression list in the reentrant functional unit, compressing and saving vector and supplemental values */ 00147 while( expl != NULL ) { 00148 unsigned int i; 00149 if( (EXPR_OWNS_VEC( expl->exp->op ) == 1) && (EXPR_IS_STATIC( expl->exp ) == 0) ) { 00150 switch( expl->exp->value->suppl.part.data_type ) { 00151 case VDATA_UL : 00152 { 00153 for( i=0; i<expl->exp->value->width; i++ ) { 00154 ulong* entry = expl->exp->value->value.ul[UL_DIV(i)]; 00155 ren->data[curr_bit>>3] |= (((entry[VTYPE_INDEX_VAL_VALL] >> UL_MOD(i)) & 0x1) << (curr_bit & 0x7)); 00156 curr_bit++; 00157 ren->data[curr_bit>>3] |= (((entry[VTYPE_INDEX_VAL_VALH] >> UL_MOD(i)) & 0x1) << (curr_bit & 0x7)); 00158 curr_bit++; 00159 } 00160 } 00161 break; 00162 case VDATA_R64 : 00163 { 00164 uint64 real_bits = sys_task_realtobits( expl->exp->value->value.r64->val ); 00165 for( i=0; i<64; i++ ) { 00166 ren->data[curr_bit>>3] |= (real_bits & 0x1) << (curr_bit & 0x7); 00167 real_bits >>= 1; 00168 curr_bit++; 00169 } 00170 } 00171 break; 00172 case VDATA_R32 : 00173 { 00174 uint64 real_bits = sys_task_realtobits( (double)expl->exp->value->value.r32->val ); 00175 for( i=0; i<32; i++ ) { 00176 ren->data[curr_bit>>3] |= (real_bits & 0x1) << (curr_bit & 0x7); 00177 real_bits >>= 1; 00178 curr_bit++; 00179 } 00180 } 00181 break; 00182 default : assert( 0 ); break; 00183 } 00184 } 00185 for( i=0; i<(((ESUPPL_BITS_TO_STORE % 2) == 0) ? ESUPPL_BITS_TO_STORE : (ESUPPL_BITS_TO_STORE + 1)); i++ ) { 00186 switch( i ) { 00187 case 0 : ren->data[curr_bit>>3] |= (expl->exp->suppl.part.left_changed << (curr_bit & 0x7)); break; 00188 case 1 : ren->data[curr_bit>>3] |= (expl->exp->suppl.part.right_changed << (curr_bit & 0x7)); break; 00189 case 2 : ren->data[curr_bit>>3] |= (expl->exp->suppl.part.eval_t << (curr_bit & 0x7)); break; 00190 case 3 : ren->data[curr_bit>>3] |= (expl->exp->suppl.part.eval_f << (curr_bit & 0x7)); break; 00191 case 4 : ren->data[curr_bit>>3] |= (expl->exp->suppl.part.prev_called << (curr_bit & 0x7)); break; 00192 } 00193 curr_bit++; 00194 } 00195 /* Clear supplemental bits that have been saved off */ 00196 expl->exp->suppl.part.left_changed = 0; 00197 expl->exp->suppl.part.right_changed = 0; 00198 expl->exp->suppl.part.eval_t = 0; 00199 expl->exp->suppl.part.eval_f = 0; 00200 expl->exp->suppl.part.prev_called = 0; 00201 expl = expl->next; 00202 } 00203 00204 /* If the current functional unit is a named block, store the bits in the parent functional unit */ 00205 if( funit->type == FUNIT_ANAMED_BLOCK ) { 00206 reentrant_store_data_bits( funit->parent, ren, curr_bit ); 00207 } 00208 00209 } 00210 00211 PROFILE_END; 00212 00213 }
const exp_info exp_op_info[EXP_OP_NUM] |
Array containing static information about expression operation types. NOTE: This structure MUST be updated if a new expression is added! The third argument is an initialization to the exp_info_s structure.