SSDsim simulation function:get_ppn()

此函数是在所给的channel,chip,die,plane里面找到一个active_block然后再在这个block里面找到一个页,再利用find_ppn()函数找到ppn。(可能产生擦除节点挂载plane上,可能产生GC节点挂载channel上)。

当要写入的页没有相应的映射关系时,直接为该写子请求利用find_ppn()函数找到一个空闲页获得ppn,并更新映射表。当要写入的页有相应的映射关系时,首先会将该映射关系所对应的ppn置为失效页,并设置好相关属性,然后会判断该ppn所在的block是否都是失效页,如果都是失效页的话则说明该block需要进行擦除之后才能再利用了,所以此时会产生一个可擦除节点(会开辟内存空间),该可擦除节点会挂载在此时所在的plane上,最后再利用find_ppn()函数找到一个新的ppn并更新映射表。然后修改该写子请求的ppn以及location相关变量属性以及修改ssd因一次写操作而产生的相关属性变化。最后如果没有主动策略,只采用gc_hard_threshold,并且无法中断GC过程,如果plane中的free_page的数目少于gc_hard_threshold所设定的阈值就产生gc操作,此时会产生一个gc_node(会开辟内存空间),设置该gc_node相关属性(next_node、chip、die、plane、block、page、state、priority),最后将该gc_node挂载到该gc_node所在的channel的gc_command上。gc_node属性只会精确到plane,然后从plane寻找可擦除节点,因为由失效页过多而产生的必须擦除才可用的现象发生在plane内部的block上,所以可擦除节点挂载到了plane上,故gc_node只需要精确到plane号就行,然后从plane寻找擦除节点,而该gc_noed挂载在响应的channel上。

struct ssd_info *get_ppn(struct ssd_info *ssd,unsigned int channel,unsigned int chip,unsigned int die,unsigned int plane,struct sub_request *sub)
{
	unsigned int ppn,lpn,full_page,active_block,block,page;
	struct local *location;
	struct direct_erase *direct_erase_node,*new_direct_erase;
	struct gc_operation *gc_node;
#ifdef DEBUG
	printf("enter get_ppn,channel:%d, chip:%d, die:%d, plane:%d\n",channel,chip,die,plane);
#endif
	full_page=~(0xffffffff<<(ssd->parameter->subpage_page));
	lpn=sub->lpn;
	/*************************************************************************************
	*利用函数find_active_block在channel,chip,die,plane找到活跃block
	*并且修改这个channel,chip,die,plane,active_block下的last_write_page和free_page_num
	**************************************************************************************/
	if(find_active_block(ssd,channel,chip,die,plane)==FAILURE){  //寻找活跃块
		printf("ERROR :there is no free page in channel:%d, chip:%d, die:%d, plane:%d\n",channel,chip,die,plane);
		return ssd;
	}
	active_block=ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].active_block;
	ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[active_block].last_write_page++;
	ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[active_block].free_page_num--;
	if(ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[active_block].last_write_page>63){
		printf("error! the last write page larger than 64!!\n");
		while(1){}
	}
	block=active_block;	
	page=ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[active_block].last_write_page;	
	if(ssd->dram->map->map_entry[lpn].state==0){    /*this is the first logical page*/
		if(ssd->dram->map->map_entry[lpn].pn!=0)
			printf("Error in get_ppn()\n");
		ssd->dram->map->map_entry[lpn].pn=find_ppn(ssd,channel,chip,die,plane,block,page);
		ssd->dram->map->map_entry[lpn].state=sub->state;
	}else{   /*这个逻辑页进行了更新,需要将原来的页置为失效*/
		ppn=ssd->dram->map->map_entry[lpn].pn;
		location=find_location(ssd,ppn);
		if(ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].blk_head[location->block].page_head[location->page].lpn!=lpn)
			printf("\nError in get_ppn()\n");
		ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].blk_head[location->block].page_head[location->page].valid_state=0; /*表示某一页失效,同时标记valid和free状态都为0*/
		ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].blk_head[location->block].page_head[location->page].free_state=0;  /*表示某一页失效,同时标记valid和free状态都为0*/
		ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].blk_head[location->block].page_head[location->page].lpn=0;
		ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].blk_head[location->block].invalid_page_num++;

		/*该block中全是invalid的页,可以直接删除,就在创建一个可擦除的节点,挂在location下的plane下面*/
		if(ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].blk_head[location->block].invalid_page_num==ssd->parameter->page_block){
			new_direct_erase=(struct direct_erase *)malloc(sizeof(struct direct_erase));
			alloc_assert(new_direct_erase,"new_direct_erase");
			memset(new_direct_erase,0, sizeof(struct direct_erase));

			new_direct_erase->block=location->block;
			new_direct_erase->next_node=NULL;
			direct_erase_node=ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].erase_node;
			if(direct_erase_node==NULL)
				ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].erase_node=new_direct_erase;
			else{
				new_direct_erase->next_node=ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].erase_node;
				ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].erase_node=new_direct_erase;
			}
		}
		free(location);
		location=NULL;
		ssd->dram->map->map_entry[lpn].pn=find_ppn(ssd,channel,chip,die,plane,block,page);
		ssd->dram->map->map_entry[lpn].state=(ssd->dram->map->map_entry[lpn].state|sub->state);
	}
	sub->ppn=ssd->dram->map->map_entry[lpn].pn;     /*修改sub子请求的ppn,location等变量*/
	sub->location->channel=channel;
	sub->location->chip=chip;
	sub->location->die=die;
	sub->location->plane=plane;
	sub->location->block=active_block;
	sub->location->page=page;

	ssd->program_count++;   /*修改ssd的program_count,free_page等变量*/
	ssd->channel_head[channel].program_count++;
	ssd->channel_head[channel].chip_head[chip].program_count++;
	ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].free_page--;
	ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[active_block].page_head[page].lpn=lpn;	
	ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[active_block].page_head[page].valid_state=sub->state;
	ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[active_block].page_head[page].free_state=((~(sub->state))&full_page);
	ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[active_block].page_head[page].written_count++;
	ssd->write_flash_count++;

	if(ssd->parameter->active_write==0)    /*如果没有主动策略,只采用gc_hard_threshold,并且无法中断GC过程*/
	{	/*如果plane中的free_page的数目少于gc_hard_threshold所设定的阈值就产生gc操作*/
		if (ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].free_page<(ssd->parameter->page_block*ssd->parameter->block_plane*ssd->parameter->gc_hard_threshold))
		{
			gc_node=(struct gc_operation *)malloc(sizeof(struct gc_operation));
			alloc_assert(gc_node,"gc_node");
			memset(gc_node,0, sizeof(struct gc_operation));

			gc_node->next_node=NULL;
			gc_node->chip=chip;
			gc_node->die=die;
			gc_node->plane=plane;
			gc_node->block=0xffffffff;
			gc_node->page=0;
			gc_node->state=GC_WAIT;
			gc_node->priority=GC_UNINTERRUPT;  //不可中断的GC节点
			gc_node->next_node=ssd->channel_head[channel].gc_command;
			ssd->channel_head[channel].gc_command=gc_node;
			ssd->gc_request++;
		}
	}
	return ssd;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
class vbase_test extends uvm_test; `uvm_component_utils(vbase_test) env m_env; vseqr m_vseqr; int unsigned simSeed; function new(string name, uvm_component parent); super.new(name, parent); endfunction : new extern function void build_phase (uvm_phase phase); extern function void connect_phase (uvm_phase phase); extern task reset_phase(uvm_phase phase); extern task reset_reg_model(); extern function void end_of_elaboration_phase(uvm_phase phase); extern function void start_of_simulation_phase(uvm_phase phase); extern task main_phase(uvm_phase phase); // report test result extern virtual function void report_phase(uvm_phase phase); endclass : vbase_test function void vbase_test::build_phase (uvm_phase phase); super.build_phase(phase); m_env = env::type_id::create(.name("m_env"), .parent(this)); // virtual sequencer m_vseqr = vseqr::type_id::create(.name("m_vseqr"), .parent(this)); uvm_config_db# (uvm_object_wrapper)::set(this,"m_vseqr.main_phase","default_sequence",vBaseSeq::type_id::get()); //uvm_config_db# (uvm_object_wrapper)::set(this,"m_vseqr.main_phase","default_sequence",vUniBaseSeq#()::type_id::get()); endfunction : build_phase function void vbase_test::connect_phase (uvm_phase phase); m_vseqr.p_rm = m_env.m_reg_model; m_vseqr.i2c_seqr = m_env.m_i2c_agent.m_seqr; endfunction : connect_phase task vbase_test::reset_phase(uvm_phase phase); //`uvm_info(get_type_name(), {"REGISTER MODEL:\n", m_reg_model.sprint()}, UVM_MEDIUM) reset_reg_model(); super.reset_phase(phase); endtask task vbase_test::reset_reg_model(); forever begin wait (tb_top.reset_n == 0); m_env.m_reg_model.reset(); `uvm_info(get_type_name(), "Reseting Complete", UVM_MEDIUM) wait (tb_top.reset_n == 1); end endtask function void vbase_test::end_of_elaboration_phase(uvm_phase phase); int handle; $system("rm -rf TEST_RUNNING"); simSeed = $get_initial_random_seed(); handle = $fopen($psprintf("TEST_RUNNING_%0d",simSeed),"w"); $fclose(handle); handle = $fopen("caseSeed","w"); $fwrite(handle,"%0d",simSeed); $fclose(handle); if($test$plusargs("uvm_tree")) uvm_top.print_topology(); endfunction : end_of_elaboration_phase function void vbase_test::start_of_simulation_phase(uvm_phase phase); `uvm_info(get_type_name(), {"start of simulation for ", get_full_name()}, UVM_HIGH); endfunction : start_of_simulation_phase task vbase_test::main_phase(uvm_phase phase); phase.phase_done.set_drain_time(this, 200ns); endtask : main_phase // report test result function void vbase_test::report_phase(uvm_phase phase); uvm_report_server server; int handle; int unsigned err_num; super.report_phase(phase); server = get_report_server(); err_num = (server.get_severity_count(UVM_ERROR) + server.get_severity_count(UVM_FATAL)); simSeed = $get_initial_random_seed(); $display("\n********************************************************************************************\n"); if (err_num != 0) begin $display("TEST CASE FAILED!!!"); handle = $fopen($psprintf("TEST_FAILED_%0d",simSeed),"w"); end else begin $display("TEST CASE PASSED!!!"); handle = $fopen($psprintf("TEST_PASSED_%0d",simSeed),"w"); end $fclose(handle); $display("\n********************************************************************************************\n"); $system("rm -rf TEST_RUNNING*"); endfunction `endif
07-25

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值