/* port only used by fully-associative array */ int SIM_array_tag_update( SIM_array_info_t *info, SIM_array_t *arr, SIM_array_port_state_t *port, SIM_array_set_state_t *set ) { u_int i; LIB_Type_max_uint curr_tag; SIM_array_mem_t *tag_attach_mem; /* get current tag */ if ( set->entry ) curr_tag = (*info->get_entry_tag)( set->entry ); if ( IS_FULLY_ASSOC( info )) tag_attach_mem = &arr->tag_attach_mem; else tag_attach_mem = &arr->tag_mem; /* record tag bitline stats */ if ( IS_FULLY_ASSOC( info )) { if ( set->entry && curr_tag != set->tag_bak ) { /* shared wordline should be driven only once */ if ( ! set->write_back_flag ) SIM_array_wordline_record( &arr->tag_wordline, SIM_ARRAY_WRITE, 1 ); /* WHS: value of tag_line doesn't matter if not write_through */ SIM_array_bitline_record( &arr->tag_bitline, SIM_ARRAY_WRITE, info->eff_tag_cols, port->tag_line, curr_tag ); /* update state */ if ( IS_WRITE_THROUGH( info )) port->tag_line = curr_tag; } } else { /* tag update cannot occur at the 1st cycle, so no other sub-arrays */ SIM_array_bitline_record( &arr->tag_bitline, SIM_ARRAY_WRITE, info->eff_tag_cols, 0, 0 ); } /* record tag memory cell stats */ if ( HAVE_USE_BIT( info )) for ( i = 0; i < info->assoc; i ++ ) SIM_array_mem_record( tag_attach_mem, set->use_bak[i], (*info->get_set_use_bit)( set->entry_set, i ), info->use_bit_width ); if ( set->entry ) { SIM_array_mem_record( tag_attach_mem, set->valid_bak, (*info->get_entry_valid_bit)( set->entry ), info->valid_bit_width ); SIM_array_mem_record( &arr->tag_mem, set->tag_bak, curr_tag, info->tag_addr_width ); if ( IS_WRITE_BACK( info )) SIM_array_mem_record( tag_attach_mem, set->dirty_bak, (*info->get_entry_dirty_bit)( set->entry ), 1 ); } return 0; }
/* for now we simply initialize all fields to 0, which should not * add too much error if the program runtime is long enough :) */ int SIM_array_port_state_init( SIM_array_info_t *info, SIM_array_port_state_t *port ) { if ( IS_FULLY_ASSOC( info ) || !(info->share_rw)) bzero( port->data_line, port->data_line_size ); port->tag_line = 0; port->row_addr = 0; port->col_addr = 0; port->tag_addr = 0; return 0; }
/* data_line only used by fully-associative or RF array */ int SIM_array_data_write( SIM_array_info_t *info, SIM_array_t *arr, SIM_array_set_state_t *set, u_int n_item, u_char *data_line, u_char *old_data, u_char *new_data ) { u_int i; /* record bitline stats */ if ( IS_FULLY_ASSOC( info )) { /* wordline should be driven only once */ if ( ! set->write_flag ) { SIM_array_wordline_record( &arr->data_wordline, SIM_ARRAY_WRITE, 1 ); set->write_flag = 1; } /* for fully-associative array, data bank has no read * bitlines, so bitlines not written have no activity */ for ( i = 0; i < n_item; i ++ ) { SIM_array_bitline_record( &arr->data_bitline, SIM_ARRAY_WRITE, 8, data_line[i], new_data[i] ); /* update state */ data_line[i] = new_data[i]; } } else if (info->share_rw) { /* there is some subtlety here: write width may not be as wide as block size, * bitlines not written are actually read, but column selector should be off, * so read energy per bitline is the same as write energy per bitline */ SIM_array_bitline_record( &arr->data_bitline, SIM_ARRAY_WRITE, info->eff_data_cols, 0, 0 ); /* write in all sub-arrays if direct-mapped, which implies 1 cycle write latency, * in those sub-arrays wordlines are not driven, so only n items columns switch */ if ( IS_DIRECT_MAP( info ) && info->data_ndbl > 1 ) SIM_array_bitline_record( &arr->data_bitline, SIM_ARRAY_WRITE, n_item * 8 * ( info->data_ndbl - 1 ), 0, 0 ); } else /* separate R/W bitlines */ { /* same arguments as in the previous case apply here, except that when we say * read_energy = write_energy, we omit the energy of write driver gate cap */ for ( i = 0; i < n_item; i ++ ) { SIM_array_bitline_record( &arr->data_bitline, SIM_ARRAY_WRITE, 8, data_line[i], new_data[i] ); /* update state */ data_line[i] = new_data[i]; } } /* record memory cell stats */ for ( i = 0; i < n_item; i ++ ) SIM_array_mem_record( &arr->data_mem, old_data[i], new_data[i], 8 ); return 0; }
/* WHS: don't support 128-bit or wider integer */ int SIM_array_output( SIM_array_info_t *info, SIM_array_t *arr, u_int data_size, u_int length, void *data_out, void *data_all ) { u_int i, j; /* record output driver stats */ for ( i = 0; i < length; i ++ ) { switch ( data_size ) { case 1: SIM_array_outdrv_global_record( &arr->outdrv, ((u_int8_t *)data_out)[i] ); break; case 2: SIM_array_outdrv_global_record( &arr->outdrv, ((u_int16_t *)data_out)[i] ); break; case 4: SIM_array_outdrv_global_record( &arr->outdrv, ((u_int32_t *)data_out)[i] ); break; case 8: SIM_array_outdrv_global_record( &arr->outdrv, ((u_int64_t *)data_out)[i] ); break; default: printf ("error\n"); /* some error handler */ } } if ( ! IS_FULLY_ASSOC( info )) { for ( i = 0; i < info->assoc; i ++ ) for ( j = 0; j < info->n_item; j ++ ) /* sense amplifiers output 0 when idle */ switch ( data_size ) { case 1: SIM_array_outdrv_local_record( &arr->outdrv, 0, ((u_int8_t **)data_all)[i][j], SIM_ARRAY_RECOVER ); break; case 2: SIM_array_outdrv_local_record( &arr->outdrv, 0, ((u_int16_t **)data_all)[i][j], SIM_ARRAY_RECOVER ); break; case 4: SIM_array_outdrv_local_record( &arr->outdrv, 0, ((u_int32_t **)data_all)[i][j], SIM_ARRAY_RECOVER ); break; case 8: SIM_array_outdrv_local_record( &arr->outdrv, 0, ((u_int64_t **)data_all)[i][j], SIM_ARRAY_RECOVER ); break; default: printf ("error\n"); /* some error handler */ } } return 0; }
int SIM_array_set_state_init( SIM_power_array_info_t *info, SIM_array_set_state_t *set ) { set->entry = NULL; set->entry_set = NULL; if ( IS_FULLY_ASSOC( info )) { set->write_flag = 0; set->write_back_flag = 0; } /* no default value for other fields */ return 0; }
/* set only used by fully-associative array */ inline int SIM_power_array_tag_read( SIM_power_array_info_t *info, SIM_power_array_t *arr, SIM_array_set_state_t *set ) { if ( IS_FULLY_ASSOC( info )) { /* the only reason to read a fully-associative array tag is writing back */ SIM_array_wordline_record( &arr->tag_wordline, SIM_ARRAY_READ, 1 ); set->write_back_flag = 1; } SIM_array_bitline_record( &arr->tag_bitline, SIM_ARRAY_READ, info->eff_tag_cols, 0, 0 ); SIM_array_amp_record( &arr->tag_amp, info->eff_tag_cols ); return 0; }
/* data only used by RF array */ inline int SIM_power_array_data_read( SIM_power_array_info_t *info, SIM_power_array_t *arr, LIB_Type_max_uint data ) { if (info->data_end == 1) { SIM_array_bitline_record( &arr->data_bitline, SIM_ARRAY_READ, info->eff_data_cols, 0, data ); return 0; } else if ( ! IS_FULLY_ASSOC( info )) { SIM_array_bitline_record( &arr->data_bitline, SIM_ARRAY_READ, info->eff_data_cols, 0, 0 ); SIM_array_amp_record( &arr->data_amp, info->eff_data_cols ); return 0; } else return -1; }
/* only used by non-fully-associative array, but we check it anyway */ inline int SIM_power_array_dec( SIM_power_array_info_t *info, SIM_power_array_t *arr, SIM_array_port_state_t *port, LIB_Type_max_uint row_addr, int rw ) { if ( ! IS_FULLY_ASSOC( info )) { /* record row decoder stats */ if (info->row_dec_model) { SIM_array_dec_record( &arr->row_dec, port->row_addr, row_addr ); /* update state */ port->row_addr = row_addr; } /* record wordline stats */ SIM_array_wordline_record( &arr->data_wordline, rw, info->data_ndwl ); if ( HAVE_TAG( info )) SIM_array_wordline_record( &arr->tag_wordline, rw, info->tag_ndwl ); return 0; } else return -1; }