double _ssd_clean_block_fully(int blk, int plane_num, int elem_num, ssd_element_metadata *metadata, ssd_t *s) { double cost = 0; plane_metadata *pm = &metadata->plane_meta[plane_num]; ssd_power_element_stat *power_stat = &(s->elements[elem_num].power_stat); ASSERT((pm->clean_in_progress == 0) && (pm->clean_in_block = -1)); pm->clean_in_block = blk; pm->clean_in_progress = 1; // stat pm->num_cleans ++; s->elements[elem_num].stat.num_clean ++; cost = s->params.block_erase_latency; //Micky:add the power consumption of the erase ssd_power_flash_calculate(SSD_POWER_FLASH_ERASE, s->params.block_erase_latency, power_stat, s); ssd_update_free_block_status(blk, plane_num, metadata, s); ssd_update_block_lifetime(simtime+cost, blk, metadata); pm->clean_in_progress = 0; pm->clean_in_block = -1; return cost; }
double ssd_switch(ssd_t *s, ssd_element_metadata *metadata, ssd_power_element_stat *power_stat, int lbn, int elem_num) { int d_block = metadata->lba_table[lbn]; int log_index = metadata->block_usage[d_block].log_index; int log_block = metadata->log_data[log_index].bsn; int num_valid = 0; int num_valid_d = metadata->block_usage[d_block].num_valid; int num_valid_u = metadata->block_usage[log_block].num_valid; int d_plane_num = metadata->block_usage[d_block].plane_num; int log_plane_num = metadata->block_usage[log_block].plane_num; int i; double cost = 0.0; metadata->plane_meta[d_plane_num].clean_in_block = d_block; metadata->plane_meta[d_plane_num].clean_in_progress = 1; //switch for( i = 0 ; i < s->params.pages_per_block ; i++) { metadata->block_usage[d_block].page[i] = -1; metadata->log_data[log_index].page[i] = -1; } metadata->lba_table[lbn] = log_block; //update stat metadata->block_usage[d_block].log_index = -1; metadata->log_data[log_index].bsn = -1; metadata->log_data[log_index].data_block = -1; metadata->num_log--; metadata->log_pos = log_index; //update block usage metadata->block_usage[d_block].num_valid = 0; //update plane data metadata->plane_meta[d_plane_num].valid_pages -= num_valid_d; //erase two block(D) cost += s->params.block_erase_latency; ssd_power_flash_calculate(SSD_POWER_FLASH_ERASE, s->params.block_erase_latency, power_stat, s); ssd_update_free_block_status(d_block, d_plane_num, metadata, s); ssd_update_block_lifetime(simtime+cost, d_block, metadata); metadata->plane_meta[d_plane_num].clean_in_block = 0; metadata->plane_meta[d_plane_num].clean_in_progress = -1; metadata->plane_meta[d_plane_num].num_cleans++; s->elements[elem_num].stat.num_clean++; s->elements[elem_num].stat.num_switch++; return cost; }
//block_erase_opeeration double _ssd_erase_block_osr(ssd_t *s, ssd_element_metadata *metadata, int block, int plane_num, ssd_power_element_stat *power_stat) { double cost =0.0; if ((metadata->block_usage[block].num_valid == 0)&&(metadata->block_usage[block].state == SSD_BLOCK_SEALED)) { // add the cost of erasing the block //add the power consumption of the erase plane_metadata *pm = &metadata->plane_meta[plane_num]; cost = s->params.block_erase_latency; ssd_power_flash_calculate(SSD_POWER_FLASH_ERASE, cost, power_stat, s); ssd_update_free_block_status(block, plane_num, metadata, s); ssd_update_block_lifetime(simtime+s->params.block_erase_latency, block, metadata); pm->clean_in_progress = 0; pm->clean_in_block = -1; } return cost; }
/* * this routine cleans one page at a time in a block. if all the * valid pages are moved, then the block is erased. */ static double _ssd_clean_block_partially(int plane_num, int elem_num, ssd_t *s) { ssd_element_metadata *metadata = &(s->elements[elem_num].metadata); plane_metadata *pm = &metadata->plane_meta[plane_num]; double cost = 0; int block; int i; ASSERT(pm->clean_in_progress); block = pm->clean_in_block; if (metadata->block_usage[block].num_valid > 0) { // pick a page that is not yet cleaned and move it for (i = 0; i < s->params.pages_per_block; i ++) { int lp_num = metadata->block_usage[block].page[i]; if (lp_num != -1) { cost += ssd_clean_one_page(lp_num, i, block, plane_num, elem_num, metadata, s); break; } } } // if we've moved all the valid pages out of this block, // then we're done with it. so, erase it and update the // system state. if (metadata->block_usage[block].num_valid == 0) { // add the cost of erasing the block cost += s->params.block_erase_latency; ssd_update_free_block_status(block, plane_num, metadata, s); ssd_update_block_lifetime(simtime+cost, block, metadata); pm->clean_in_progress = 0; pm->clean_in_block = -1; } return cost; }
double ssd_fullmerge(ssd_t *s, ssd_element_metadata *metadata, ssd_power_element_stat *power_stat, int lbn, int elem_num) { int prev_block = metadata->lba_table[lbn]; int log_index = metadata->block_usage[prev_block].log_index; int log_block = metadata->log_data[log_index].bsn; int num_valid = 0; int num_valid_d = metadata->block_usage[prev_block].num_valid; int num_valid_u = metadata->block_usage[log_block].num_valid; int prev_plane_num = metadata->block_usage[prev_block].plane_num; int log_plane_num = metadata->block_usage[log_block].plane_num; int plane_num; int active_block; int i; double cost = 0.0; double r_cost, w_cost, xfer_cost; //set active_block metadata->active_block = metadata->plane_meta[prev_plane_num].active_block; active_block = metadata->active_block; _ssd_alloc_active_block(prev_plane_num, elem_num, s); plane_num = metadata->block_usage[active_block].plane_num; metadata->plane_meta[prev_plane_num].clean_in_block = prev_block; metadata->plane_meta[prev_plane_num].clean_in_progress = 1; metadata->plane_meta[log_plane_num].clean_in_block = prev_block; metadata->plane_meta[log_plane_num].clean_in_progress = 1; //page state copy & init page state for( i = 0 ; i < s->params.pages_per_block ; i++) { if((metadata->block_usage[prev_block].page[i] == 1) || (metadata->log_data[log_index].page[i] != -1)){ metadata->block_usage[active_block].page[i] = 1; } metadata->block_usage[prev_block].page[i] = -1; metadata->log_data[log_index].page[i] = -1; metadata->block_usage[log_block].page[i] = -1; } metadata->lba_table[lbn] = active_block; //update stat //update log_table metadata->block_usage[prev_block].log_index = -1; metadata->log_data[log_index].bsn = -1; metadata->log_data[log_index].data_block = -1; metadata->log_pos = log_index; metadata->num_log--; //update block usage metadata->block_usage[prev_block].num_valid = 0; metadata->block_usage[log_block].num_valid = 0; //update plane data metadata->plane_meta[prev_plane_num].valid_pages -= num_valid_d; metadata->plane_meta[log_plane_num].valid_pages -= num_valid_u; num_valid += num_valid_d; num_valid += num_valid_u; if(num_valid > s->params.pages_per_block) { fprintf(outputfile3, "Error number of pages : valid_page %d, Real_page %d\n", num_valid, s->params.pages_per_block); fprintf(outputfile3, "Error elem_num %d, lbn %d, original block %d, log block %d\n", elem_num, lbn, prev_block, log_block); exit(-1); } metadata->block_usage[active_block].num_valid = num_valid; metadata->plane_meta[plane_num].valid_pages += num_valid; //data tranfer cost //read r_cost = s->params.page_read_latency * num_valid; cost += r_cost; ssd_power_flash_calculate(SSD_POWER_FLASH_READ, r_cost, power_stat, s); //write w_cost = s->params.page_write_latency * num_valid; cost += w_cost; ssd_power_flash_calculate(SSD_POWER_FLASH_WRITE, w_cost, power_stat, s); //transfer cost for( i = 0 ; i < num_valid ; i++) { double xfer_cost; xfer_cost = ssd_crossover_cost(s, metadata, power_stat, prev_block, active_block); cost += xfer_cost; s->elements[elem_num].stat.tot_xfer_cost += xfer_cost; } //erase two block(D) cost += s->params.block_erase_latency; ssd_power_flash_calculate(SSD_POWER_FLASH_ERASE, s->params.block_erase_latency, power_stat, s); ssd_update_free_block_status(prev_block, prev_plane_num, metadata, s); ssd_update_block_lifetime(simtime+cost, prev_block, metadata); metadata->plane_meta[prev_plane_num].num_cleans++; metadata->plane_meta[prev_plane_num].clean_in_block = 0; metadata->plane_meta[prev_plane_num].clean_in_progress = -1; //erase two block(U) cost += s->params.block_erase_latency; ssd_power_flash_calculate(SSD_POWER_FLASH_ERASE, s->params.block_erase_latency, power_stat, s); ssd_update_free_block_status(log_block, log_plane_num, metadata, s); ssd_update_block_lifetime(simtime+cost, log_block, metadata); metadata->plane_meta[log_plane_num].num_cleans++; metadata->plane_meta[log_plane_num].clean_in_block = 0; metadata->plane_meta[log_plane_num].clean_in_progress = -1; //erase stat update s->elements[elem_num].stat.pages_moved += num_valid; s->elements[elem_num].stat.num_clean += 2; s->elements[elem_num].stat.num_fullmerge++; return cost; }
double ssd_replacement(ssd_t *s, int elem_num, int lbn) { ssd_element_metadata *metadata; ssd_power_element_stat *power_stat; int block; int log_index; int prev_log_block; int prev_plane_num; int log_block; int plane_num; int num_valid; double cost = 0.0; double r_cost, w_cost, xfer_cost; int i,j; metadata = &(s->elements[elem_num].metadata); power_stat = &(s->elements[elem_num].power_stat); block = metadata->lba_table[lbn]; log_index = metadata->block_usage[block].log_index; prev_log_block = metadata->log_data[log_index].bsn; prev_plane_num = metadata->block_usage[prev_log_block].plane_num; num_valid = metadata->block_usage[prev_log_block].num_valid; //alloc new logblock and erase old logblock log_block = metadata->plane_meta[prev_plane_num].active_block; _ssd_alloc_active_block(prev_plane_num, elem_num, s); plane_num = metadata->block_usage[log_block].plane_num; metadata->log_data[log_index].bsn = log_block; //move page old to new j = 0; for( i = 0 ; i < s->params.pages_per_block ; i++) { if( metadata->log_data[log_index].page[i] != -1) { metadata->log_data[log_index].page[i] = j; metadata->block_usage[log_block].page[j] = 1; metadata->block_usage[log_block].num_valid++; j++; } metadata->block_usage[prev_log_block].page[i] = -1; } metadata->block_usage[prev_log_block].num_valid = 0; //plane metadata update metadata->plane_meta[prev_plane_num].valid_pages -= metadata->block_usage[log_block].num_valid; metadata->plane_meta[plane_num].valid_pages += metadata->block_usage[log_block].num_valid; //cost //read r_cost = s->params.page_read_latency * num_valid; cost += r_cost; ssd_power_flash_calculate(SSD_POWER_FLASH_READ, r_cost, power_stat, s); //write w_cost = s->params.page_write_latency * num_valid; cost += w_cost; ssd_power_flash_calculate(SSD_POWER_FLASH_WRITE, w_cost, power_stat, s); //transfer cost for( i = 0 ; i < num_valid ; i++) { double xfer_cost; xfer_cost = ssd_crossover_cost(s, metadata, power_stat, prev_log_block, log_block); cost += xfer_cost; s->elements[elem_num].stat.tot_xfer_cost += xfer_cost; } //erase U block cost += s->params.block_erase_latency; ssd_power_flash_calculate(SSD_POWER_FLASH_ERASE, s->params.block_erase_latency, power_stat, s); ssd_update_free_block_status(prev_log_block, prev_plane_num, metadata, s); ssd_update_block_lifetime(simtime+cost, prev_log_block, metadata); s->elements[elem_num].stat.pages_moved += num_valid; s->elements[elem_num].stat.num_clean ++; s->elements[elem_num].stat.num_replacement++; metadata->plane_meta[prev_plane_num].num_cleans++; return cost; }