· 6 years ago · Apr 23, 2019, 04:48 PM
1/*****************************************************************************************************************************
2This project was supported by the National Basic Research 973 Program of China under Grant No.2011CB302301
3Huazhong University of Science and Technology (HUST) Wuhan National Laboratory for Optoelectronics
4
5FileName£º flash.c
6Author: Hu Yang Version: 2.1 Date:2011/12/02
7Description:
8
9History:
10<contributor> <time> <version> <desc> <e-mail>
11Yang Hu 2009/09/25 1.0 Creat SSDsim yanghu@foxmail.com
12 2010/05/01 2.x Change
13Zhiming Zhu 2011/07/01 2.0 Change 812839842@qq.com
14Shuangwu Zhang 2011/11/01 2.1 Change 820876427@qq.com
15Chao Ren 2011/07/01 2.0 Change 529517386@qq.com
16Hao Luo 2011/01/01 2.0 Change luohao135680@gmail.com
17*****************************************************************************************************************************/
18
19#include "flash.h"
20
21void pr(int value)
22{
23 printf("%d\n", value);
24}
25// #include "ssd.h"
26// #include "pagemap.h"
27// #include "initialize.h"
28/**********************
29*This function only works on write requests
30***********************/
31
32
33/**********************
34*This function only works on write requests
35***********************/
36Status allocate_location(struct ssd_info * ssd ,struct sub_request * sub_req)
37{
38 struct sub_request * update=NULL;
39 unsigned int channel_num=0,chip_num=0,die_num=0,plane_num=0;
40 struct local *location=NULL;
41
42 channel_num=ssd->parameter->channel_number;
43 chip_num=ssd->parameter->chip_channel[0];
44 die_num=ssd->parameter->die_chip;
45 plane_num=ssd->parameter->plane_die;
46
47
48 if (ssd->parameter->allocation_scheme==0) /*Dynamic allocation*/
49 {
50 /******************************************************************
51 *In dynamic allocation, because the page update operation does not use the copyback operation,
52* A read request needs to be generated, and the write operation of this page can be performed only after the read request is completed.
53 *******************************************************************/
54 if (ssd->dram->map->map_entry[sub_req->lpn].state!=0)
55 {
56 if (ssd->dram->map->map_entry[sub_req->lpn].multi_version_flag == 0)/* When the buffer sends a write request, you need to enable additional reads, but use multi-version data here. */
57 {
58 if ((sub_req->state&ssd->dram->map->map_entry[sub_req->lpn].state) != ssd->dram->map->map_entry[sub_req->lpn].state)
59 {
60 ssd->dram->map->map_entry[sub_req->lpn].multi_version_flag = 1;
61 ssd->dram->map->map_entry[sub_req->lpn].state2 = sub_req->state;//Read the data of the logical page, first find it on pn2. If it is not found, look it up on pn. If neither of them is found, the logical page cannot be found on the flash memory.
62 }
63 }
64 else
65 {
66 if (sub_req->state&(ssd->dram->map->map_entry[sub_req->lpn].state | ssd->dram->map->map_entry[sub_req->lpn].state2) == ssd->dram->map->map_entry[sub_req->lpn].state)//Subsequent subrequests contain all sectors of the two version pages
67 {
68 ssd->dram->map->map_entry[sub_req->lpn].multi_version_flag = 2;//Revert back to a version of page
69 }
70 else //If you do not include all sectors, you need to re-read the data of two physical pages and merge them together.
71 {
72 ssd->dram->map->map_entry[sub_req->lpn].multi_version_flag = 3;//Revert back to a version of page, but requires two additional reads
73 ssd->read_count=ssd->read_count+2;
74 ssd->update_read_count==ssd->update_read_count+2;
75
76 //Execute the first read subrequest
77 update = (struct sub_request *)malloc(sizeof(struct sub_request));
78 alloc_assert(update, "update");
79 memset(update, 0, sizeof(struct sub_request));
80
81 if (update == NULL)
82 {
83 return ERROR;
84 }
85 update->location = NULL;
86 update->next_node = NULL;
87 update->next_subs = NULL;
88 update->update = NULL;
89 location = find_location(ssd, ssd->dram->map->map_entry[sub_req->lpn].pn);
90 update->location = location;
91 update->begin_time = ssd->current_time;
92 update->current_state = SR_WAIT;
93 update->current_time = 0x7fffffffffffffff;
94 update->next_state = SR_R_C_A_TRANSFER;
95 update->next_state_predict_time = 0x7fffffffffffffff;
96 update->lpn = sub_req->lpn;
97 update->state = ((ssd->dram->map->map_entry[sub_req->lpn].state^sub_req->state) & 0x7fffffff);
98 update->size = size(update->state);
99 update->ppn = ssd->dram->map->map_entry[sub_req->lpn].pn;
100 update->operation = READ;
101
102 if (ssd->channel_head[location->channel].subs_r_tail != NULL) ///* Generate a new read request and hang to the end of the channel's subs_r_tail queue
103 {
104 ssd->channel_head[location->channel].subs_r_tail->next_node = update;
105 ssd->channel_head[location->channel].subs_r_tail = update;
106 }
107 else
108 {
109 ssd->channel_head[location->channel].subs_r_tail = update;
110 ssd->channel_head[location->channel].subs_r_head = update;
111 }
112
113 //Execute the second read subrequest
114 update = (struct sub_request *)malloc(sizeof(struct sub_request));
115 alloc_assert(update, "update");
116 memset(update, 0, sizeof(struct sub_request));
117
118 if (update == NULL)
119 {
120 return ERROR;
121 }
122 update->location = NULL;
123 update->next_node = NULL;
124 update->next_subs = NULL;
125 update->update = NULL;
126 location = find_location(ssd, ssd->dram->map->map_entry[sub_req->lpn].pn2);
127 update->location = location;
128 update->begin_time = ssd->current_time;
129 update->current_state = SR_WAIT;
130 update->current_time = 0x7fffffffffffffff;
131 update->next_state = SR_R_C_A_TRANSFER;
132 update->next_state_predict_time = 0x7fffffffffffffff;
133 update->lpn = sub_req->lpn;
134 update->state = ((ssd->dram->map->map_entry[sub_req->lpn].state2^sub_req->state) & 0x7fffffff);
135 update->size = size(update->state);
136 update->ppn = ssd->dram->map->map_entry[sub_req->lpn].pn2;
137 update->operation = READ;
138
139 if (ssd->channel_head[location->channel].subs_r_tail != NULL) ///*Generate a new read request and hang it at the end of the channel's subs_r_tail queue
140 {
141 ssd->channel_head[location->channel].subs_r_tail->next_node = update;
142 ssd->channel_head[location->channel].subs_r_tail = update;
143 }
144 else
145 {
146 ssd->channel_head[location->channel].subs_r_tail = update;
147 ssd->channel_head[location->channel].subs_r_head = update;
148 }
149
150 }
151 }
152
153 /*
154 ssd->read_count++;
155 ssd->update_read_count++;
156 ssd->m1 = 1;
157
158 update = (struct sub_request *)malloc(sizeof(struct sub_request));
159 alloc_assert(update, "update");
160 memset(update, 0, sizeof(struct sub_request));
161
162 if (update == NULL)
163 {
164 return ERROR;
165 }
166 update->location = NULL;
167 update->next_node = NULL;
168 update->next_subs = NULL;
169 update->update = NULL;
170 location = find_location(ssd, ssd->dram->map->map_entry[sub_req->lpn].pn);
171 update->location = location;
172 update->begin_time = ssd->current_time;
173 update->current_state = SR_WAIT;
174 update->current_time = 0x7fffffffffffffff;
175 update->next_state = SR_R_C_A_TRANSFER;
176 update->next_state_predict_time = 0x7fffffffffffffff;
177 update->lpn = sub_req->lpn;
178 update->state = ((ssd->dram->map->map_entry[sub_req->lpn].state^sub_req->state) & 0x7fffffff);
179 update->size = size(update->state);
180 update->ppn = ssd->dram->map->map_entry[sub_req->lpn].pn;
181 update->operation = READ;
182
183 if (ssd->channel_head[location->channel].subs_r_tail != NULL) ///*Generate a new read request and hang it at the end of the channel's subs_r_tail queue
184 {
185 ssd->channel_head[location->channel].subs_r_tail->next_node = update;
186 ssd->channel_head[location->channel].subs_r_tail = update;
187 }
188 else
189 {
190 ssd->channel_head[location->channel].subs_r_tail = update;
191 ssd->channel_head[location->channel].subs_r_head = update;
192 }*/
193
194 }
195 /***************************************
196 *Here are a few cases of dynamic allocation.
197*0: Full dynamic allocation
198*1: indicates that the channel is set to package, die, and plane.
199 ****************************************/
200 switch(ssd->parameter->dynamic_allocation)
201 {
202 case 0:
203 {
204 sub_req->location->channel=-1;
205 sub_req->location->chip=-1;
206 sub_req->location->die=-1;
207 sub_req->location->plane=-1;
208 sub_req->location->block=-1;
209 sub_req->location->page=-1;
210
211 if (ssd->subs_w_tail!=NULL)
212 {
213 ssd->subs_w_tail->next_node=sub_req;
214 ssd->subs_w_tail=sub_req;
215 }
216 else
217 {
218 ssd->subs_w_tail=sub_req;
219 ssd->subs_w_head=sub_req;
220 }
221
222 if (update!=NULL)
223 {
224 sub_req->update=update;
225 }
226
227 break;
228 }
229 case 1:
230 {
231
232 sub_req->location->channel=sub_req->lpn%ssd->parameter->channel_number;
233 sub_req->location->chip=-1;
234 sub_req->location->die=-1;
235 sub_req->location->plane=-1;
236 sub_req->location->block=-1;
237 sub_req->location->page=-1;
238
239 if (update!=NULL)
240 {
241 sub_req->update=update;
242 }
243
244 break;
245 }
246 case 2:
247 {
248 break;
249 }
250 case 3:
251 {
252 break;
253 }
254 }
255
256 }
257 else
258 { /***************************************************************************
259 * is a static allocation method, so you can get the final channel, chip, die, plane of this subrequest
260* There are a total of 0, 1, 2, 3, 4, 5, these six static allocation methods.
261 ****************************************************************************/
262 switch (ssd->parameter->static_allocation)
263 {
264 case 0: //no striping static allocation
265 {
266 sub_req->location->channel=(sub_req->lpn/(plane_num*die_num*chip_num))%channel_num;
267 sub_req->location->chip=sub_req->lpn%chip_num;
268 sub_req->location->die=(sub_req->lpn/chip_num)%die_num;
269 sub_req->location->plane=(sub_req->lpn/(die_num*chip_num))%plane_num;
270 break;
271 }
272 case 1:
273 {
274 sub_req->location->channel=sub_req->lpn%channel_num;
275 sub_req->location->chip=(sub_req->lpn/channel_num)%chip_num;
276 sub_req->location->die=(sub_req->lpn/(chip_num*channel_num))%die_num;
277 sub_req->location->plane=(sub_req->lpn/(die_num*chip_num*channel_num))%plane_num;
278
279 break;
280 }
281 case 2:
282 {
283 sub_req->location->channel=sub_req->lpn%channel_num;
284 sub_req->location->chip=(sub_req->lpn/(plane_num*channel_num))%chip_num;
285 sub_req->location->die=(sub_req->lpn/(plane_num*chip_num*channel_num))%die_num;
286 sub_req->location->plane=(sub_req->lpn/channel_num)%plane_num;
287 break;
288 }
289 case 3:
290 {
291 sub_req->location->channel=sub_req->lpn%channel_num;
292 sub_req->location->chip=(sub_req->lpn/(die_num*channel_num))%chip_num;
293 sub_req->location->die=(sub_req->lpn/channel_num)%die_num;
294 sub_req->location->plane=(sub_req->lpn/(die_num*chip_num*channel_num))%plane_num;
295 break;
296 }
297 case 4:
298 {
299 sub_req->location->channel=sub_req->lpn%channel_num;
300 sub_req->location->chip=(sub_req->lpn/(plane_num*die_num*channel_num))%chip_num;
301 sub_req->location->die=(sub_req->lpn/(plane_num*channel_num))%die_num;
302 sub_req->location->plane=(sub_req->lpn/channel_num)%plane_num;
303
304 break;
305 }
306 case 5:
307 {
308 sub_req->location->channel=sub_req->lpn%channel_num;
309 sub_req->location->chip=(sub_req->lpn/(plane_num*die_num*channel_num))%chip_num;
310 sub_req->location->die=(sub_req->lpn/channel_num)%die_num;
311 sub_req->location->plane=(sub_req->lpn/(die_num*channel_num))%plane_num;
312
313 break;
314 }
315 default : return ERROR;
316
317 }
318 if (ssd->dram->map->map_entry[sub_req->lpn].state!=0)
319 { /* The logical page of the subrequest that is written back cannot overwrite the data that was previously
320 written back. A read request needs to be generated*/
321 if ((sub_req->state&ssd->dram->map->map_entry[sub_req->lpn].state)!=ssd->dram->map->map_entry[sub_req->lpn].state)
322 {
323 ssd->read_count++;
324 ssd->update_read_count++;
325 ssd->m1 = 1;
326 update=(struct sub_request *)malloc(sizeof(struct sub_request));
327 alloc_assert(update,"update");
328 memset(update,0, sizeof(struct sub_request));
329
330 if(update==NULL)
331 {
332 return ERROR;
333 }
334 update->location=NULL;
335 update->next_node=NULL;
336 update->next_subs=NULL;
337 update->update=NULL;
338 location = find_location(ssd,ssd->dram->map->map_entry[sub_req->lpn].pn);
339 update->location=location;
340 update->begin_time = ssd->current_time;
341 update->current_state = SR_WAIT;
342 update->current_time=0x7fffffffffffffff;
343 update->next_state = SR_R_C_A_TRANSFER;
344 update->next_state_predict_time=0x7fffffffffffffff;
345 update->lpn = sub_req->lpn;
346 update->state=((ssd->dram->map->map_entry[sub_req->lpn].state^sub_req->state)&0x7fffffff);
347 update->size=size(update->state);
348 update->ppn = ssd->dram->map->map_entry[sub_req->lpn].pn;
349 update->operation = READ;
350
351 if (ssd->channel_head[location->channel].subs_r_tail!=NULL)
352 {
353 ssd->channel_head[location->channel].subs_r_tail->next_node=update;
354 ssd->channel_head[location->channel].subs_r_tail=update;
355 }
356 else
357 {
358 ssd->channel_head[location->channel].subs_r_tail=update;
359 ssd->channel_head[location->channel].subs_r_head=update;
360 }
361 }
362
363 if (update!=NULL)
364 {
365 sub_req->update=update;
366
367 sub_req->state=(sub_req->state|update->state);
368 sub_req->size=size(sub_req->state);
369 }
370
371 }
372 }
373 if ((ssd->parameter->allocation_scheme!=0)||(ssd->parameter->dynamic_allocation!=0))
374 {
375 if (ssd->channel_head[sub_req->location->channel].subs_w_tail!=NULL)
376 {
377 ssd->channel_head[sub_req->location->channel].subs_w_tail->next_node=sub_req;
378 ssd->channel_head[sub_req->location->channel].subs_w_tail=sub_req;
379 }
380 else
381 {
382 ssd->channel_head[sub_req->location->channel].subs_w_tail=sub_req;
383 ssd->channel_head[sub_req->location->channel].subs_w_head=sub_req;
384 }
385 }
386 return SUCCESS;
387}
388
389/*******************************************************************************
390*The insert2buffer function is called in the buffer_management to allocate sub-request services specifically for write requests.
391********************************************************************************/
392struct ssd_info * insert2buffer(struct ssd_info *ssd,unsigned int lpn,int state,struct sub_request *sub,struct request *req)
393{
394 int write_back_count,flag=0; /*Flag indicates whether the space for writing new data is completed, 0 indicates
395 that further traversal is required, and 1 indicates that it has vacated*/
396 unsigned int i,lsn,hit_flag,add_flag,sector_count,active_region_flag=0,free_sector=0;
397 struct buffer_group *buffer_node=NULL,*pt,*new_node=NULL,key, *temp_node, *pt1;
398 struct sub_request *sub_req=NULL,*update=NULL;
399 int round_flag; //@@@@ modified Continue to loop
400 int temp_sector=0;
401 int h;
402
403
404 unsigned int sub_req_state=0, sub_req_size=0,sub_req_lpn=0;
405
406 // #ifdef DEBUG
407 // printf("enter insert2buffer, current time:%lld, lpn:%d, state:%d,\n",ssd->current_time,lpn,state);
408 // #endif
409 ssd->m1 = 0;
410 sector_count=size(state); /*The number of sectors that need to be written to the buffer*/
411 key.group=lpn;
412 buffer_node= (struct buffer_group*)avlTreeFind(ssd->dram->buffer, (TREE_NODE *)&key); /*Looking for a buffer node in a balanced binary tree*/
413
414
415 /************************************************************************************************
416 *No hits.
417* The first step depends on how many subpages of this lpn need to be written to the buffer, remove the lsn that has been written back,
418 and make room for the lpn.
419* First, calculate the free sector (indicating how many buffer nodes can be written directly).
420*If free_sector>=sector_count, there is extra space for the lpn sub-request to write, no need to generate a writeback request
421* Otherwise, there is no extra space for the lpn sub-request to write, in which case some space needs to be freed to generate a
422 write-back request. Just creat_sub_request()
423 *************************************************************************************************/
424 if(buffer_node==NULL)
425 {
426 //printf("I am if buffer node null\n");
427 free_sector=ssd->dram->buffer->max_buffer_sector-ssd->dram->buffer->buffer_sector_count;
428 if(free_sector>=sector_count)
429 {
430 flag=1;
431 ssd->dram->buffer->write_hit += sector_count;
432 }
433 if(flag==0)
434 {
435 write_back_count=sector_count-free_sector;
436 //printf("write back count before while loop %d\n",write_back_count );
437 ssd->dram->buffer->write_miss_hit += write_back_count;
438 int count =1, mew;
439 while(write_back_count>0)
440 {
441
442 if (ssd->adaptive_mark == 1) //ÆôÓÃLoop-LRU
443 {
444 printf("adaptive mark ==1 \n");
445 temp_node = ssd->dram->buffer->buffer_tail;
446 //printf("temp_node completion flag %d and unaligned_access value %d\n",temp_node->complete_flag, temp_node->unaligned_access );
447 while (temp_node->complete_flag == 0 && temp_node->unaligned_access == 0) /*@@@@@ modify: Select full page
448 replacement If the full page is
449 directly replaced. If not, then the incomplete page is placed at the LRU head end until
450 the full page is selected for replacement. */
451 {
452 ssd->dram->buffer->buffer_tail = temp_node->LRU_link_pre;
453 ssd->dram->buffer->buffer_tail->LRU_link_next = NULL;
454 temp_node->LRU_link_pre = NULL;
455 temp_node->LRU_link_next = ssd->dram->buffer->buffer_head;
456 ssd->dram->buffer->buffer_head->LRU_link_pre = temp_node;
457 ssd->dram->buffer->buffer_head = temp_node;
458 temp_node->unaligned_access = 1;
459 temp_node = ssd->dram->buffer->buffer_tail;
460 //ssd->delay_incomlete_page_count++;
461 //ssd->delay_hit0++;
462 }
463 temp_node = NULL;
464 free(temp_node);
465 }
466
467 sub_req=NULL;
468 sub_req_state=ssd->dram->buffer->buffer_tail->stored;
469 sub_req_size=size(ssd->dram->buffer->buffer_tail->stored);
470 sub_req_lpn=ssd->dram->buffer->buffer_tail->group;
471
472
473 if (ssd->dram->map->map_entry[sub_req_lpn].state != 0 && ssd->dram->map->map_entry[sub_req_lpn].multi_version_flag == 0
474 && (sub_req_state & ssd->dram->map->map_entry[sub_req_lpn].state) != ssd->dram->map->map_entry[sub_req_lpn].state)
475 {
476 pt = ssd->dram->buffer->buffer_tail;
477 pt1 = NULL;
478 if (size(pt->stored) < ssd->parameter->subpage_page*0.5) //accessed less than 50% of the page
479 {
480
481 h = 0;
482 while (h < 20)
483 {
484 ssd->a[h] = 0;
485 h++;
486 }
487 h = 0;
488 for (int i = 0; i < (ssd->buffer_page_count / 1000); i++)
489 {
490
491 if (pt1 == NULL)
492 {
493 temp_sector = size(pt->stored);
494 pt = pt->LRU_link_pre;
495 pt1 = pt->LRU_link_pre;
496 }
497 else
498 {
499 pt = pt1;
500 pt1 = pt->LRU_link_pre;
501 //temp_sector = size(pt->stored);
502 }
503
504 if (ssd->dram->map->map_entry[pt->group].state == 0 && size(pt->stored) < ssd->parameter->subpage_page &&
505 (temp_sector + size(pt->stored)) < ssd->parameter->subpage_page && ssd->dram->map->map_entry[pt->group].multi_version_flag == 0)
506 {
507 printf(" I am here making m1 ==1 \n");
508 ssd->m1 = 1;
509 avlTreeDel(ssd->dram->buffer, (TREE_NODE *)pt);
510 pt -> LRU_link_pre->LRU_link_next = pt -> LRU_link_next;
511 pt -> LRU_link_next->LRU_link_pre = pt->LRU_link_pre;
512 pt->LRU_link_next = NULL;
513 pt->LRU_link_pre = NULL;
514 temp_sector += size(pt->stored);
515
516 ssd->write_incomplete_page_count++;
517 ssd->buffer_incomplete_page_count--;
518 ssd->buffer_page_count--;
519
520 if (ssd->dram->map->map_entry[pt->group].state == 0)
521 {
522 ssd->dram->map->map_entry[pt->group].state = pt->stored;
523 ssd->a[h] = pt->group;
524 h++;
525 }
526
527
528
529 AVL_TREENODE_FREE(ssd->dram->buffer, (TREE_NODE *)pt);
530 pt = NULL;
531
532
533 }
534 if (temp_sector > ssd->parameter->subpage_page*0.8)
535 {
536 break;
537 }
538 }
539 }
540 }
541
542 // pr(ssd->buffer_page_count);
543 // printf("sub request size after 0.8 multi %d\n",sub_req_size);
544 // printf("sub paze size after 0.8 multi %d\n",ssd->parameter->subpage_page);
545
546 if (sub_req_size < ssd->parameter->subpage_page)
547 {
548 ssd->write_incomplete_page_count++;
549 // pr("write_incomplete_page_count\n");
550 // pr( ssd->write_incomplete_page_count);
551 ssd->buffer_incomplete_page_count--;
552 }
553 // pr(ssd->buffer_page_count--);
554
555
556
557 if (ssd->m1 == 0)
558 {
559 sub_req = creat_sub_request(ssd, sub_req_lpn, sub_req_size, sub_req_state, req, WRITE);
560 ssd->dram->buffer->buffer_sector_count = ssd->dram->buffer->buffer_sector_count - sub_req->size;
561 write_back_count = write_back_count - sub_req->size;
562 // printf("I am if m1==0 count %d \n", count++);
563 // printf("write back count after m1==0 %d\n",write_back_count );
564 }
565
566 else if (ssd->m1 == 1)
567 {
568 sub_req_size = temp_sector;
569 sub_req = creat_sub_request(ssd, sub_req_lpn, sub_req_size, sub_req_state, req, WRITE);
570 ssd->dram->buffer->buffer_sector_count = ssd->dram->buffer->buffer_sector_count - temp_sector;
571 write_back_count = write_back_count - temp_sector;
572 printf("I am if m1==1\n");
573 }
574 //printf("write back count after m1 checking %d\n",write_back_count );
575 sub_req=creat_sub_request(ssd,sub_req_lpn,sub_req_size,sub_req_state,req,WRITE);
576 ssd->write_back_to_flash_count++;
577
578 //sub_req=creat_sub_request(ssd,sub_req_lpn,sub_req_size,sub_req_state,req,WRITE);
579 /**********************************************************************************
580 *Req is not empty, indicating that the insert2buffer function is called in buffer_management, passing the request in.
581*req is empty, indicating that this function is to read the one-to-many mapping relationship in the process function, you need to
582read this The data is added to the buffer, which may result in a real-time writeback operation, which needs to hang the subrequest of
583this real-time writeback operation The total request for this read request
584 ***********************************************************************************/
585 if(req!=NULL)
586 {
587 }
588 else
589 {
590 sub_req->next_subs=sub->next_subs;
591 sub->next_subs=sub_req;
592 }
593
594
595
596 /*The write request is inserted into the balanced binary tree, and the buffer_sector_count of the dram is modified.
597 Maintain balanced L2 tree calls avlTreeDel() and AVL_TREENODE_FREE() functions; maintain LRU algorithm; */
598
599 ssd->dram->buffer->buffer_sector_count = ssd->dram->buffer->buffer_sector_count - sub_req->size;
600 pt = ssd->dram->buffer->buffer_tail;
601 avlTreeDel(ssd->dram->buffer, (TREE_NODE *) pt);
602 if(ssd->dram->buffer->buffer_head->LRU_link_next == NULL){
603 ssd->dram->buffer->buffer_head = NULL;
604 ssd->dram->buffer->buffer_tail = NULL;
605 }
606 else
607 {
608 ssd->dram->buffer->buffer_tail=ssd->dram->buffer->buffer_tail->LRU_link_pre;
609 ssd->dram->buffer->buffer_tail->LRU_link_next=NULL;
610 }
611
612 pt->LRU_link_next=NULL;
613 pt->LRU_link_pre=NULL;
614 AVL_TREENODE_FREE(ssd->dram->buffer, (TREE_NODE *) pt);
615 pt = NULL;
616 write_back_count=write_back_count - sub_req->size;
617 /*Because of the real-time writeback operation, it is necessary to
618 increase the active writeback operation area*/
619
620
621
622 } //end of while write_back-count > 0
623 //printf("write back count after while ends %d\n",write_back_count );
624 } //if flag = 0 ends
625
626 /*****************************************************************************
627 *Generate a buffer node, assign each member according to the situation of this page, add to the leader and binary tree
628 ******************************************************************************/
629 new_node=NULL;
630 new_node=(struct buffer_group *)malloc(sizeof(struct buffer_group));
631 alloc_assert(new_node,"buffer_group_node");
632 memset(new_node,0, sizeof(struct buffer_group));
633
634 new_node->group=lpn;
635 new_node->stored=state;
636 new_node->dirty_clean=state;
637 new_node->LRU_link_pre = NULL;
638 new_node->LRU_link_next=ssd->dram->buffer->buffer_head;
639 if(ssd->dram->buffer->buffer_head != NULL){
640 ssd->dram->buffer->buffer_head->LRU_link_pre=new_node;
641 }else{
642 ssd->dram->buffer->buffer_tail = new_node;
643 }
644 ssd->dram->buffer->buffer_head=new_node;
645 new_node->LRU_link_pre=NULL;
646 avlTreeAdd(ssd->dram->buffer, (TREE_NODE *) new_node);
647 ssd->dram->buffer->buffer_sector_count += sector_count;
648 } // if buffer_node == NULL
649 /****************************************************************************************
650 *Hit in the buffer
651* It is a hit, but the hit is only lpn, there may be new write requests, just need to write some sub_page of lpn page
652* There is a need for further judgment at this time
653 *****************************************************************************************/
654 else
655 {
656 //printf("buffer node not null\n");
657 for(i=0;i<ssd->parameter->subpage_page;i++)
658 {
659 /*************************************************************
660 *Determine if the state i bit is 1
661* And judge whether the i-th sector exists in the buffer, 1 means existence, 0 means no.
662 **************************************************************/
663 if((state>>i)%2!=0)
664 {
665 lsn=lpn*ssd->parameter->subpage_page+i;
666 hit_flag=0;
667 hit_flag=(buffer_node->stored)&(0x00000001<<i);
668
669 if(hit_flag!=0) /*Hit, need to move the node to the head of the buffer, and mark the hit lsn */
670 {
671 active_region_flag=1; /*Whether lsn used to record in this buffer node is hit, used to determine the
672 threshold later */
673
674 if(req!=NULL)
675 {
676 if(ssd->dram->buffer->buffer_head!=buffer_node)
677 {
678 if(ssd->dram->buffer->buffer_tail==buffer_node)
679 {
680 ssd->dram->buffer->buffer_tail=buffer_node->LRU_link_pre;
681 buffer_node->LRU_link_pre->LRU_link_next=NULL;
682 }
683 else if(buffer_node != ssd->dram->buffer->buffer_head)
684 {
685 buffer_node->LRU_link_pre->LRU_link_next=buffer_node->LRU_link_next;
686 buffer_node->LRU_link_next->LRU_link_pre=buffer_node->LRU_link_pre;
687 }
688 buffer_node->LRU_link_next=ssd->dram->buffer->buffer_head;
689 ssd->dram->buffer->buffer_head->LRU_link_pre=buffer_node;
690 buffer_node->LRU_link_pre=NULL;
691 ssd->dram->buffer->buffer_head=buffer_node;
692 }
693 ssd->dram->buffer->write_hit++;
694 req->complete_lsn_count++;
695 /*The key is to use req->complete_lsn_count++ to write data to the buffer when hit in the buffer. */
696 }
697 else
698 {
699 }
700 }
701 else
702 {
703 /************The lsn does not hit, but the node is in the buffer, you need to add this lsn to the corresponding node of the buffer.
704* Find a node from the end of the buffer, delete an already written lsn from the node (if found), change the state of the node, and add
705 this new lsn is added to the corresponding buffer node, which may be in the buffer header, if not, move it to the head. If you have not
706 found the lsn that has been written back, in the buffer
707* The node finds a group as a whole and writes it back, and hangs this subrequest on this request. Can be hung on a channel in advance.
708* The first step: delete the node that has been written back at the end of the buffer, and make room for the new lsn. Here you need to
709modify the stored state of a node at the end of the queue.
710* Added, when there is no lsn that can be deleted between, you need to generate a new write sub-request and write back to the last node
711of the LRU.
712*Step 2: Add a new lsn to the buffer node.
713 ************************************************************************************************************/
714 ssd->dram->buffer->write_miss_hit++;
715
716 if(ssd->dram->buffer->buffer_sector_count>=ssd->dram->buffer->max_buffer_sector)
717 {
718 if (buffer_node==ssd->dram->buffer->buffer_tail) /*If the hit node is the last node in the buffer, swap the last two nodes*/
719 {
720 pt = ssd->dram->buffer->buffer_tail->LRU_link_pre;
721 ssd->dram->buffer->buffer_tail->LRU_link_pre=pt->LRU_link_pre;
722 ssd->dram->buffer->buffer_tail->LRU_link_pre->LRU_link_next=ssd->dram->buffer->buffer_tail;
723 ssd->dram->buffer->buffer_tail->LRU_link_next=pt;
724 pt->LRU_link_next=NULL;
725 pt->LRU_link_pre=ssd->dram->buffer->buffer_tail;
726 ssd->dram->buffer->buffer_tail=pt;
727
728 }
729 sub_req=NULL;
730 sub_req_state=ssd->dram->buffer->buffer_tail->stored;
731 sub_req_size=size(ssd->dram->buffer->buffer_tail->stored);
732 sub_req_lpn=ssd->dram->buffer->buffer_tail->group;
733 sub_req=creat_sub_request(ssd,sub_req_lpn,sub_req_size,sub_req_state,req,WRITE);
734
735 if(req!=NULL)
736 {
737
738 }
739 else if(req==NULL)
740 {
741 sub_req->next_subs=sub->next_subs;
742 sub->next_subs=sub_req;
743 }
744
745 ssd->dram->buffer->buffer_sector_count=ssd->dram->buffer->buffer_sector_count-sub_req->size;
746 pt = ssd->dram->buffer->buffer_tail;
747 avlTreeDel(ssd->dram->buffer, (TREE_NODE *) pt);
748
749
750 /************************************************************************/
751 /*Change: Hanging on the subrequest, the buffer node should not be deleted immediately, */
752 /* will not be deleted until after writing back */
753
754 if(ssd->dram->buffer->buffer_head->LRU_link_next == NULL)
755 {
756 ssd->dram->buffer->buffer_head = NULL;
757 ssd->dram->buffer->buffer_tail = NULL;
758 }else{
759 ssd->dram->buffer->buffer_tail=ssd->dram->buffer->buffer_tail->LRU_link_pre;
760 ssd->dram->buffer->buffer_tail->LRU_link_next=NULL;
761 }
762 pt->LRU_link_next=NULL;
763 pt->LRU_link_pre=NULL;
764 AVL_TREENODE_FREE(ssd->dram->buffer, (TREE_NODE *) pt);
765 pt = NULL;
766 }
767
768 /*Step 2: Add a new lsn to the buffer node */
769 add_flag=0x00000001<<(lsn%ssd->parameter->subpage_page);
770
771 if(ssd->dram->buffer->buffer_head!=buffer_node) /*If the buffer node is not at the head of the buffer,
772 you need to refer this node to the leader*/
773 {
774 if(ssd->dram->buffer->buffer_tail==buffer_node)
775 {
776 buffer_node->LRU_link_pre->LRU_link_next=NULL;
777 ssd->dram->buffer->buffer_tail=buffer_node->LRU_link_pre;
778 }
779 else
780 {
781 buffer_node->LRU_link_pre->LRU_link_next = buffer_node->LRU_link_next;
782 buffer_node->LRU_link_next->LRU_link_pre = buffer_node->LRU_link_pre;
783 }
784 buffer_node->LRU_link_next=ssd->dram->buffer->buffer_head;
785 ssd->dram->buffer->buffer_head->LRU_link_pre=buffer_node;
786 buffer_node->LRU_link_pre=NULL;
787 ssd->dram->buffer->buffer_head=buffer_node;
788 }
789 buffer_node->stored = buffer_node->stored | add_flag;
790 buffer_node->dirty_clean = buffer_node -> dirty_clean | add_flag;
791 ssd->dram->buffer->buffer_sector_count++;
792 }
793
794 }
795 }
796 }
797
798 return ssd;
799}
800
801
802
803/**************************************************************************************
804*º¯ÊýµÄ¹¦ÄÜÊÇѰÕÒ»îÔ¾¿ì£¬Ó¦ÎªÃ¿¸öplaneÖö¼Ö»ÓÃÒ»¸ö»îÔ¾¿é£¬Ö»ÓÃÕâ¸ö»îÔ¾¿éÖòÅÄܽøÃòÙ×÷
805***************************************************************************************/
806Status find_active_block(struct ssd_info *ssd,unsigned int channel,unsigned int chip,unsigned int die,unsigned int plane)
807{
808 unsigned int active_block;
809 unsigned int free_page_num=0;
810 unsigned int count=0;
811
812 active_block=ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].active_block;
813 free_page_num=ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[active_block].free_page_num;
814 //last_write_page=ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[active_block].free_page_num;
815 while((free_page_num==0)&&(count<ssd->parameter->block_plane))
816 {
817 active_block=(active_block+1)%ssd->parameter->block_plane;
818 free_page_num=ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[active_block].free_page_num;
819 count++;
820 }
821 ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].active_block=active_block;
822 if(count<ssd->parameter->block_plane)
823 {
824 return SUCCESS;
825 }
826 else
827 {
828 return FAILURE;
829 }
830}
831
832/*************************************************
833*The function of this function is to simulate a real write operation.
834* is to change the relevant parameters of this page, as well as the statistical parameters of the entire ssd
835**************************************************/
836Status write_page(struct ssd_info *ssd,unsigned int channel,unsigned int chip,unsigned int die,unsigned int plane,unsigned int active_block,unsigned int *ppn)
837{
838 int last_write_page=0;
839 last_write_page=++(ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[active_block].last_write_page);
840 if(last_write_page>=(int)(ssd->parameter->page_block))
841 {
842 ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[active_block].last_write_page=0;
843 printf("error! the last write page larger than 64!!\n");
844 return ERROR;
845 }
846
847 ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[active_block].free_page_num--;
848 ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].free_page--;
849 ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[active_block].page_head[last_write_page].written_count++;
850 ssd->write_flash_count++;
851 *ppn=find_ppn(ssd,channel,chip,die,plane,active_block,last_write_page);
852
853 return SUCCESS;
854}
855
856/**********************************************
857*The function of this function is to create sub-requests based on lpn, size, state
858**********************************************/
859struct sub_request * creat_sub_request(struct ssd_info * ssd,unsigned int lpn,int size,unsigned int state,struct request * req,unsigned int operation)
860{
861 struct sub_request* sub=NULL,* sub_r=NULL, *sub1=NULL;
862 struct channel_info * p_ch=NULL;
863 struct local * loc=NULL;
864 unsigned int flag=0;
865
866 sub = (struct sub_request*)malloc(sizeof(struct sub_request)); /*Structure for applying for a subrequest*/
867 alloc_assert(sub,"sub_request");
868 memset(sub,0, sizeof(struct sub_request));
869
870 if(sub==NULL)
871 {
872 return NULL;
873 }
874 sub->location=NULL;
875 sub->next_node=NULL;
876 sub->next_subs=NULL;
877 sub->update=NULL;
878
879 if(req!=NULL)
880 {
881 sub->next_subs = req->subs;
882 req->subs = sub;
883 }
884
885 /*
886 If the operation is a read operation and needs to request a new sub-request to read data from the flash, the find_location() function is first called
887 according to the known physical page number pn (the reason for obtaining the physical page number is because there is a dram structure) The structure
888 entry of a physical address mapping table, SSDsim uses an array of entry structure to represent the mapping relationship between the logical page number
889 lpn and the physical page number pn, and lpn as the subscript of the structure array. For each initialization program The page will have a map_entry
890 structure mapping, representing the mapping between lpn and ppn)
891
892Then, the specific physical address of the physical page is searched (the physical address of the flash memory in SSDsim is represented by a location
893structure, wherein the information includes a specific physical channel, chip, die, etc.), and the physical address loc of the SSD corresponding to the
894lpn is obtained. Then according to loc, set the relevant member information and status flag of the sub, and according to the physical channel information
895 provided by the loc, let the p_ch pointer point to the channel where the sub operation is located, and set the sub->state to be the subpage status flag
896 equal to the lpn mapping table structure in the current dram. The state in the subpage maps the valid flag bit (that is, the subpage that makes the
897 mapping successful can directly provide the read request operation. Here, the mapping relationship of the read request in the mapping table can be
898 directly used because the read request and the processing function are passed. After the processing, the mapping relationship corresponding to all
899 read requests has been initialized.
900
901Then the program makes the sub_r defined in this module point to the head of the read sub-request queue of the target channel, and starts to look
902
903for the sub-request node corresponding to ppn in the read request queue of the channel; this is because the need to consider when creating the read
904 sub-request Whether the read sub-request node with the target ppn already exists in the read sub-request queue under the channel
905 (ie, judge sub_r->ppn == sub->ppn); if present, setting the flag flag to 1 indicates that the flag can be directly Use the existing
906 read sub-request node (because the data of the same page is read, there is no need to do two repeated read operations), at this time,
907 the relevant state identifier of the sub can be directly set: the current state is the data transmission state. SR_R_DATA_TRANSFER,
908 the current time is the current time of the system represents the immediate execution of this read sub-request, the next state is
909 the completion state SR_COMPLETE, the next state is expected to be the current time offset of 1000, etc. The above settings can
910 immediately perform the operation of reading the sub-request. Then return directly to sub.
911
912*/
913 if (operation == READ)
914 {
915 if (ssd->dram->map->map_entry[lpn].multi_version_flag == 0)
916 {
917
918 loc = find_location(ssd, ssd->dram->map->map_entry[lpn].pn);
919 sub->location = loc;
920 sub->begin_time = ssd->current_time;
921 sub->current_state = SR_WAIT;
922 sub->current_time = 0x7fffffffffffffff;
923 sub->next_state = SR_R_C_A_TRANSFER;
924 sub->next_state_predict_time = 0x7fffffffffffffff;
925 sub->lpn = lpn;
926 sub->size = size; /*Need to calculate the request size of this subrequest*/
927 //printf("I am in the new READ multi_version_flag ==0\n");
928 p_ch = &ssd->channel_head[loc->channel];
929 sub->ppn = ssd->dram->map->map_entry[lpn].pn;
930 sub->operation = READ;
931 sub->state = (ssd->dram->map->map_entry[lpn].state & 0x7fffffff);
932 sub_r = p_ch->subs_r_head; /*The following lines include the flag to determine whether the
933 read sub-request queue is the same as the sub-request, and if so, the new sub-request is directly assigned to completion.*/
934 flag = 0;
935 while (sub_r != NULL)
936 {
937 if (sub_r->ppn == sub->ppn)
938 {
939 flag = 1;
940 break;
941 }
942 sub_r = sub_r->next_node;
943 }
944 if (flag == 0)
945 {
946 if (p_ch->subs_r_tail != NULL)
947 {
948 p_ch->subs_r_tail->next_node = sub;
949 p_ch->subs_r_tail = sub;
950 }
951 else
952 {
953 p_ch->subs_r_head = sub;
954 p_ch->subs_r_tail = sub;
955 }
956 }
957 else
958 {
959 sub->current_state = SR_R_DATA_TRANSFER;
960 sub->current_time = ssd->current_time;
961 sub->next_state = SR_COMPLETE;
962 sub->next_state_predict_time = ssd->current_time + 1000;
963 sub->complete_time = ssd->current_time + 1000;
964 }
965 }
966 else ///read multiple versions of the page
967 {
968 if (state&ssd->dram->map->map_entry[lpn].state2 == state)//Read only pn2
969 {
970
971 //printf("I am in the new READ multi_version_flag > 0 \n");
972 loc = find_location(ssd, ssd->dram->map->map_entry[lpn].pn2);
973 sub->location = loc;
974 sub->begin_time = ssd->current_time;
975 sub->current_state = SR_WAIT;
976 sub->current_time = 0x7fffffffffffffff;
977 sub->next_state = SR_R_C_A_TRANSFER;
978 sub->next_state_predict_time = 0x7fffffffffffffff;
979 sub->lpn = lpn;
980 sub->size = size; /*Need to calculate the request size of the subrequest*/
981
982 p_ch = &ssd->channel_head[loc->channel];
983 sub->ppn = ssd->dram->map->map_entry[lpn].pn2;
984 sub->operation = READ;
985 sub->state = (ssd->dram->map->map_entry[lpn].state2 & 0x7fffffff);
986 sub_r = p_ch->subs_r_head; /*The following lines include the flag to determine whether the read sub-request queue is the same as the sub-request, and if so, the new sub-request is directly assigned to completion.*/
987 flag = 0;
988 while (sub_r != NULL)
989 {
990 if (sub_r->ppn == sub->ppn)
991 {
992 flag = 1;
993 break;
994 }
995 sub_r = sub_r->next_node;
996 }
997 if (flag == 0)
998 {
999 if (p_ch->subs_r_tail != NULL)
1000 {
1001 p_ch->subs_r_tail->next_node = sub;
1002 p_ch->subs_r_tail = sub;
1003 }
1004 else
1005 {
1006 p_ch->subs_r_head = sub;
1007 p_ch->subs_r_tail = sub;
1008 }
1009 }
1010 else
1011 {
1012 sub->current_state = SR_R_DATA_TRANSFER;
1013 sub->current_time = ssd->current_time;
1014 sub->next_state = SR_COMPLETE;
1015 sub->next_state_predict_time = ssd->current_time + 1000;
1016 sub->complete_time = ssd->current_time + 1000;
1017 }
1018 }
1019 else if ((state&ssd->dram->map->map_entry[lpn].state2 != state)&&(state&ssd->dram->map->map_entry[lpn].state2==0)) //Read only pn1
1020 {
1021 loc = find_location(ssd, ssd->dram->map->map_entry[lpn].pn);
1022 sub->location = loc;
1023 sub->begin_time = ssd->current_time;
1024 sub->current_state = SR_WAIT;
1025 sub->current_time = 0x7fffffffffffffff;
1026 sub->next_state = SR_R_C_A_TRANSFER;
1027 sub->next_state_predict_time = 0x7fffffffffffffff;
1028 sub->lpn = lpn;
1029 sub->size = size; /*Need to calculate the request size of the subrequest*/
1030
1031 p_ch = &ssd->channel_head[loc->channel];
1032 sub->ppn = ssd->dram->map->map_entry[lpn].pn;
1033 sub->operation = READ;
1034 sub->state = (ssd->dram->map->map_entry[lpn].state & 0x7fffffff);
1035 sub_r = p_ch->subs_r_head; /*The following lines include the flag to determine whether the read sub-request queue is the same as the sub-request, and if so, the new sub-request is directly assigned to completion.*/
1036 flag = 0;
1037 while (sub_r != NULL)
1038 {
1039 if (sub_r->ppn == sub->ppn)
1040 {
1041 flag = 1;
1042 break;
1043 }
1044 sub_r = sub_r->next_node;
1045 }
1046 if (flag == 0)
1047 {
1048 if (p_ch->subs_r_tail != NULL)
1049 {
1050 p_ch->subs_r_tail->next_node = sub;
1051 p_ch->subs_r_tail = sub;
1052 }
1053 else
1054 {
1055 p_ch->subs_r_head = sub;
1056 p_ch->subs_r_tail = sub;
1057 }
1058 }
1059 else
1060 {
1061 sub->current_state = SR_R_DATA_TRANSFER;
1062 sub->current_time = ssd->current_time;
1063 sub->next_state = SR_COMPLETE;
1064 sub->next_state_predict_time = ssd->current_time + 1000;
1065 sub->complete_time = ssd->current_time + 1000;
1066 }
1067 }
1068 else //if ((state&ssd->dram->map->map_entry[lpn].state2 != state)&&(state&ssd->dram->map->map_entry[lpn].state2 != 0))//¶Ãpn1 ºÃpn2
1069 {
1070 ssd->read_sub_add++;
1071 sub1 = (struct sub_request*)malloc(sizeof(struct sub_request)); /*Structure for applying for a sub1 subrequest*/
1072 alloc_assert(sub1, "sub_request");
1073 memset(sub1, 0, sizeof(struct sub_request));
1074
1075 if (sub1 == NULL)
1076 {
1077 return NULL;
1078 }
1079 sub1->location = NULL;
1080 sub1->next_node = NULL;
1081 sub1->next_subs = NULL;
1082 sub1->update = NULL;
1083
1084 if (req != NULL)
1085 {
1086 sub1->next_subs = req->subs;
1087 req->subs = sub1;
1088 }
1089 //ÃȶÃpn2
1090 loc = find_location(ssd, ssd->dram->map->map_entry[lpn].pn2);
1091 sub1->location = loc;
1092 sub1->begin_time = ssd->current_time;
1093 sub1->current_state = SR_WAIT;
1094 sub1->current_time = 0x7fffffffffffffff;
1095 sub1->next_state = SR_R_C_A_TRANSFER;
1096 sub1->next_state_predict_time = 0x7fffffffffffffff;
1097 sub1->lpn = lpn;
1098 sub1->size = size-1; /*Need to calculate the request size of the subrequest*/
1099
1100 p_ch = &ssd->channel_head[loc->channel];
1101 sub1->ppn = ssd->dram->map->map_entry[lpn].pn2;
1102 sub1->operation = READ;
1103 sub1->state = (ssd->dram->map->map_entry[lpn].state2 & 0x7fffffff);
1104 sub_r = p_ch->subs_r_head; /*The following lines include the flag to
1105 determine whether the read sub-request queue is the same as the sub-request, and if so, the new sub-request is directly assigned to completion.*/
1106 flag = 0;
1107 while (sub_r != NULL)
1108 {
1109 if (sub_r->ppn == sub1->ppn)
1110 {
1111 flag = 1;
1112 break;
1113 }
1114 sub_r = sub_r->next_node;
1115 }
1116 /* // However, if the node corresponding to ppn is not found after the traversal in the sub_r read sub-request queue under the channel
1117// (that is, the flag is 0 at this time), the program first determines whether the subs_r read sub-request queue under the channel
1118// indicated by p_ch is Empty: If empty, insert the newly created sub into the empty read request queue. If it is not empty,
1119// insert the sub into the tail of the queue and then return to sub.
1120
1121// Therefore, we can see that all created read sub-requests will eventually be hooked up to the sub-request queue under the corresponding channel. */
1122 if (flag == 0)
1123 {
1124 if (p_ch->subs_r_tail != NULL)
1125 {
1126 p_ch->subs_r_tail->next_node = sub1;
1127 p_ch->subs_r_tail = sub1;
1128 }
1129 else
1130 {
1131 p_ch->subs_r_head = sub1;
1132 p_ch->subs_r_tail = sub1;
1133 }
1134 }
1135 else
1136 {
1137 sub1->current_state = SR_R_DATA_TRANSFER;
1138 sub1->current_time = ssd->current_time;
1139 sub1->next_state = SR_COMPLETE;
1140 sub1->next_state_predict_time = ssd->current_time + 1000;
1141 sub1->complete_time = ssd->current_time + 1000;
1142 }
1143
1144 //ÔÙ¶Ãpn1
1145 loc = find_location(ssd, ssd->dram->map->map_entry[lpn].pn);
1146 sub->location = loc;
1147 sub->begin_time = ssd->current_time;
1148 sub->current_state = SR_WAIT;
1149 sub->current_time = 0x7fffffffffffffff;
1150 sub->next_state = SR_R_C_A_TRANSFER;
1151 sub->next_state_predict_time = 0x7fffffffffffffff;
1152 sub->lpn = lpn;
1153 sub->size = 1; /*Need to calculate the request size of the subrequest*/
1154
1155 p_ch = &ssd->channel_head[loc->channel];
1156 sub->ppn = ssd->dram->map->map_entry[lpn].pn;
1157 sub->operation = READ;
1158 sub->state = (ssd->dram->map->map_entry[lpn].state & 0x7fffffff);
1159 sub_r = p_ch->subs_r_head; /*The following lines include the flag to determine whether the read sub-request queue is the same as the sub-request, and if so, the new sub-request is directly assigned to completion.*/
1160 flag = 0;
1161 while (sub_r != NULL)
1162 {
1163 if (sub_r->ppn == sub->ppn)
1164 {
1165 flag = 1;
1166 break;
1167 }
1168 sub_r = sub_r->next_node;
1169 }
1170 if (flag == 0)
1171 {
1172 if (p_ch->subs_r_tail != NULL)
1173 {
1174 p_ch->subs_r_tail->next_node = sub;
1175 p_ch->subs_r_tail = sub;
1176 }
1177 else
1178 {
1179 p_ch->subs_r_head = sub;
1180 p_ch->subs_r_tail = sub;
1181 }
1182 }
1183 else
1184 {
1185 sub->current_state = SR_R_DATA_TRANSFER;
1186 sub->current_time = ssd->current_time;
1187 sub->next_state = SR_COMPLETE;
1188 sub->next_state_predict_time = ssd->current_time + 1000;
1189 sub->complete_time = ssd->current_time + 1000;
1190 }
1191 }
1192
1193
1194 }
1195 }
1196
1197 /*
1198 If the operation is a read operation and needs to request a new sub-request to read data from the flash, the find_location() function is first called
1199 according to the known physical page number pn (the reason for obtaining the physical page number is because there is a dram structure) The structure
1200 entry of a physical address mapping table, SSDsim uses an array of entry structure to represent the mapping relationship between the logical page number
1201 lpn and the physical page number pn, and lpn as the subscript of the structure array. For each initialization program The page will have a map_entry
1202 structure mapping, representing the mapping between lpn and ppn)
1203
1204Then, the specific physical address of the physical page is searched (the physical address of the flash memory in SSDsim is represented by a location
1205structure, wherein the information includes a specific physical channel, chip, die, etc.), and the physical address loc of the SSD corresponding to the
1206lpn is obtained. Then according to loc, set the relevant member information and status flag of the sub, and according to the physical channel information
1207 provided by the loc, let the p_ch pointer point to the channel where the sub operation is located, and set the sub->state to be the subpage status flag
1208 equal to the lpn mapping table structure in the current dram. The state in the subpage maps the valid flag bit (that is, the subpage that makes the
1209 mapping successful can directly provide the read request operation. Here, the mapping relationship of the read request in the mapping table can be
1210 directly used because the read request and the processing function are passed. After the processing, the mapping relationship corresponding to all
1211 read requests has been initialized.
1212
1213Then the program makes the sub_r defined in this module point to the head of the read sub-request queue of the target channel, and starts to look
1214
1215for the sub-request node corresponding to ppn in the read request queue of the channel; this is because the need to consider when creating the read
1216 sub-request Whether the read sub-request node with the target ppn already exists in the read sub-request queue under the channel
1217 (ie, judge sub_r->ppn == sub->ppn); if present, setting the flag flag to 1 indicates that the flag can be directly Use the existing
1218 read sub-request node (because the data of the same page is read, there is no need to do two repeated read operations), at this time,
1219 the relevant state identifier of the sub can be directly set: the current state is the data transmission state. SR_R_DATA_TRANSFER,
1220 the current time is the current time of the system represents the immediate execution of this read sub-request, the next state is
1221 the completion state SR_COMPLETE, the next state is expected to be the current time offset of 1000, etc. The above settings can
1222 immediately perform the operation of reading the sub-request. Then return directly to sub.
1223
1224*/
1225
1226// if (operation == READ)
1227// {
1228// loc = find_location(ssd,ssd->dram->map->map_entry[lpn].pn);
1229// sub->location=loc;
1230// sub->begin_time = ssd->current_time;
1231// sub->current_state = SR_WAIT;
1232// sub->current_time=MAX_INT64;
1233// sub->next_state = SR_R_C_A_TRANSFER;
1234// sub->next_state_predict_time=MAX_INT64;
1235// sub->lpn = lpn;
1236// sub->size=size; /*Need to calculate the request size of this subrequest*/
1237
1238
1239// p_ch = &ssd->channel_head[loc->channel];
1240// sub->ppn = ssd->dram->map->map_entry[lpn].pn;
1241// sub->operation = READ;
1242// sub->state=(ssd->dram->map->map_entry[lpn].state&0x7fffffff);
1243// sub_r=p_ch->subs_r_head; /*The following lines include the flag to determine whether the
1244// read sub-request queue is the same as the sub-request, and if so, the new sub-request is directly assigned to completion.*/
1245// flag=0;
1246// while (sub_r!=NULL)
1247// {
1248// if (sub_r->ppn==sub->ppn)
1249// {
1250// flag=1;
1251// break;
1252// }
1253// sub_r=sub_r->next_node;
1254// }
1255
1256// However, if the node corresponding to ppn is not found after the traversal in the sub_r read sub-request queue under the channel
1257// (that is, the flag is 0 at this time), the program first determines whether the subs_r read sub-request queue under the channel
1258// indicated by p_ch is Empty: If empty, insert the newly created sub into the empty read request queue. If it is not empty,
1259// insert the sub into the tail of the queue and then return to sub.
1260
1261// Therefore, we can see that all created read sub-requests will eventually be hooked up to the sub-request queue under the corresponding channel.
1262// if (flag==0)
1263// {
1264// if (p_ch->subs_r_tail!=NULL)
1265// {
1266// p_ch->subs_r_tail->next_node=sub;
1267// p_ch->subs_r_tail=sub;
1268// }
1269// else
1270// {
1271// p_ch->subs_r_head=sub;
1272// p_ch->subs_r_tail=sub;
1273// }
1274// }
1275// else
1276// {
1277// sub->current_state = SR_R_DATA_TRANSFER;
1278// sub->current_time=ssd->current_time;
1279// sub->next_state = SR_COMPLETE;
1280// sub->next_state_predict_time=ssd->current_time+1000;
1281// sub->complete_time=ssd->current_time+1000;
1282// }
1283// }
1284
1285 /*************************************************************************************
1286 if the operation is a write operation that requires a request to allocate a new
1287subrequest, the program first sets sub->ppn to zero and begins to allocate space and initialization for sub->location, while setting the sub
1288The current state is the subrequest wait state SR_WAIT, the related member information is set according to the current system time, the
1289incoming lpn, size, state, and then the allocate_location() function is called to allocate the physical address for the sub.
1290The allocate_location() will perform the corresponding allocation policy of the physical address according to the current physical address
1291
1292allocation mode. In essence, it is the process of actually creating the corresponding write sub-request. Specifically, it will be described
1293in detail when introducing allocate_location(). Followed by the program will determine the value of allocate_location (), if not ERROR,
1294create a write request successfully returns directly sub, and if allocate_location () returns ERROR, the allocation fails, you need to
1295release the location space that malloc dynamically applied, and release sub and return NULL means that the creation of a write subrequest failed.
1296
1297At the same time, if it is judged that the operation is neither READ nor WRITE, then the incoming operation is incorrect. In this case,
1298 the location of the previously dynamically applied location needs to be released and the sub is released, and the error message is
1299 printed and NULL is returned.
1300At this point, the entire Creat_sub_request() completes all the processes.
1301 **************************************************************************************/
1302 else if(operation == WRITE)
1303 {
1304 sub->ppn=0;
1305 sub->operation = WRITE;
1306 sub->location=(struct local *)malloc(sizeof(struct local));
1307 alloc_assert(sub->location,"sub->location");
1308 memset(sub->location,0, sizeof(struct local));
1309
1310 sub->current_state=SR_WAIT;
1311 sub->current_time=ssd->current_time;
1312 sub->lpn=lpn;
1313 sub->size=size;
1314 sub->state=state;
1315 sub->begin_time=ssd->current_time;
1316
1317 if (allocate_location(ssd ,sub)==ERROR)
1318 {
1319 free(sub->location);
1320 sub->location=NULL;
1321 free(sub);
1322 sub=NULL;
1323 return NULL;
1324 }
1325
1326 }
1327 else
1328 {
1329 free(sub->location);
1330 sub->location=NULL;
1331 free(sub);
1332 sub=NULL;
1333 printf("\nERROR ! Unexpected command.\n");
1334 return NULL;
1335 }
1336
1337 return sub;
1338}
1339
1340/******************************************************
1341*º¯ÊýµÄ¹¦ÄÜÊÇÔÚ¸ø³öµÄchannel£¬chip£¬dieÉÃÃæÑ°ÕÒ¶Ã×ÓÇëÇó
1342*Õâ¸ö×ÓÇëÇóµÄppnÒªÓëÃà Ó¦µÄplaneµÄ¼Ä´æÆ÷ÀïÃæµÄppnÃà ·û
1343*******************************************************/
1344struct sub_request * find_read_sub_request(struct ssd_info * ssd, unsigned int channel, unsigned int chip, unsigned int die)
1345{
1346 unsigned int plane=0;
1347 unsigned int address_ppn=0;
1348 struct sub_request *sub=NULL,* p=NULL;
1349
1350 for(plane=0;plane<ssd->parameter->plane_die;plane++)
1351 {
1352 address_ppn=ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].add_reg_ppn;
1353 if(address_ppn!=-1)
1354 {
1355 sub=ssd->channel_head[channel].subs_r_head;
1356 if(sub->ppn==address_ppn)
1357 {
1358 if(sub->next_node==NULL)
1359 {
1360 ssd->channel_head[channel].subs_r_head=NULL;
1361 ssd->channel_head[channel].subs_r_tail=NULL;
1362 }
1363 ssd->channel_head[channel].subs_r_head=sub->next_node;
1364 }
1365 while((sub->ppn!=address_ppn)&&(sub->next_node!=NULL))
1366 {
1367 if(sub->next_node->ppn==address_ppn)
1368 {
1369 p=sub->next_node;
1370 if(p->next_node==NULL)
1371 {
1372 sub->next_node=NULL;
1373 ssd->channel_head[channel].subs_r_tail=sub;
1374 }
1375 else
1376 {
1377 sub->next_node=p->next_node;
1378 }
1379 sub=p;
1380 break;
1381 }
1382 sub=sub->next_node;
1383 }
1384 if(sub->ppn==address_ppn)
1385 {
1386 sub->next_node=NULL;
1387 return sub;
1388 }
1389 else
1390 {
1391 printf("Error! Can't find the sub request.");
1392 }
1393 }
1394 }
1395 return NULL;
1396}
1397
1398/*******************************************************************************
1399*º¯ÊýµÄ¹¦ÄÜÊÇѰÕÒô×ÓÇëÇó¡£
1400*·ÖýÖÖÇé¿ö1£¬ÒªÊÇÊÇÃêÈ«¶¯Ì¬·ÖÅä¾ÃÔÚssd->subs_w_head¶ÓÃÃÉÃÕÒ
1401*2£¬ÒªÊDz»ÊÇÃêÈ«¶¯Ì¬·ÖÅäÄÇô¾ÃÔÚssd->channel_head[channel].subs_w_head¶ÓÃÃÉòéÕÒ
1402********************************************************************************/
1403struct sub_request * find_write_sub_request(struct ssd_info * ssd, unsigned int channel)
1404{
1405 struct sub_request * sub=NULL,* p=NULL;
1406 if ((ssd->parameter->allocation_scheme==0)&&(ssd->parameter->dynamic_allocation==0)) /*ÊÇÃêÈ«µÄ¶¯Ì¬·ÖÅä*/
1407 {
1408 sub=ssd->subs_w_head;
1409 while(sub!=NULL)
1410 {
1411 if(sub->current_state==SR_WAIT)
1412 {
1413 if (sub->update!=NULL) /*Èç¹ûÓÃÃèÒªÌáǰ¶Ã³öµÄÒ³*/
1414 {
1415 if ((sub->update->current_state==SR_COMPLETE)||((sub->update->next_state==SR_COMPLETE)&&(sub->update->next_state_predict_time<=ssd->current_time))) //±»¸üõÄÒ³ÒѾ±»¶Ã³ö
1416 {
1417 break;
1418 }
1419 }
1420 else
1421 {
1422 break;
1423 }
1424 }
1425 p=sub;
1426 sub=sub->next_node;
1427 }
1428
1429 if (sub==NULL) /*Èç¹ûûÓÃÕÒµ½¿ÉÒÔ·þÎñµÄ×ÓÇëÇó£¬Ìø³öÕâ¸öforÑ»·*/
1430 {
1431 return NULL;
1432 }
1433
1434 if (sub!=ssd->subs_w_head)
1435 {
1436 if (sub!=ssd->subs_w_tail)
1437 {
1438 p->next_node=sub->next_node;
1439 }
1440 else
1441 {
1442 ssd->subs_w_tail=p;
1443 ssd->subs_w_tail->next_node=NULL;
1444 }
1445 }
1446 else
1447 {
1448 if (sub->next_node!=NULL)
1449 {
1450 ssd->subs_w_head=sub->next_node;
1451 }
1452 else
1453 {
1454 ssd->subs_w_head=NULL;
1455 ssd->subs_w_tail=NULL;
1456 }
1457 }
1458 sub->next_node=NULL;
1459 if (ssd->channel_head[channel].subs_w_tail!=NULL)
1460 {
1461 ssd->channel_head[channel].subs_w_tail->next_node=sub;
1462 ssd->channel_head[channel].subs_w_tail=sub;
1463 }
1464 else
1465 {
1466 ssd->channel_head[channel].subs_w_tail=sub;
1467 ssd->channel_head[channel].subs_w_head=sub;
1468 }
1469 }
1470 /**********************************************************
1471 *³ýÃËÈ«¶¯Ì¬·ÖÅ䷽ʽ£¬ÆäËû·½Ê½µÄÇëÇóÒѾ·ÖÅäµ½ÌØ¶¨µÄchannel£¬
1472 *¾ÃÖ»ÃèÒªÔÚchannelÉÃÕÒ³ö×¼±¸·þÎñµÄ×ÓÇëÇó
1473 ***********************************************************/
1474 else
1475 {
1476 sub=ssd->channel_head[channel].subs_w_head;
1477 while(sub!=NULL)
1478 {
1479 if(sub->current_state==SR_WAIT)
1480 {
1481 if (sub->update!=NULL)
1482 {
1483 if ((sub->update->current_state==SR_COMPLETE)||((sub->update->next_state==SR_COMPLETE)&&(sub->update->next_state_predict_time<=ssd->current_time))) //±»¸üõÄÒ³ÒѾ±»¶Ã³ö
1484 {
1485 break;
1486 }
1487 }
1488 else
1489 {
1490 break;
1491 }
1492 }
1493 p=sub;
1494 sub=sub->next_node;
1495 }
1496
1497 if (sub==NULL)
1498 {
1499 return NULL;
1500 }
1501 }
1502
1503 return sub;
1504}
1505
1506/*********************************************************************************************
1507*רÃÅΪ¶Ã×ÓÇëÇó·þÎñµÄº¯Êý
1508*1£¬Ö»Óõ±¶Ã×ÓÇëÇóµÄµ±Ç°×´Ì¬ÊÇSR_R_C_A_TRANSFER
1509*2£¬¶Ã×ÓÇëÇóµÄµ±Ç°×´Ì¬ÊÇSR_COMPLETE»òÕßÃÂһ״̬ÊÇSR_COMPLETE²¢ÇÒÃÂһ״̬µ½´ïµÄʱ¼ä±Èµ±Ç°Ê±¼äá
1510**********************************************************************************************/
1511Status services_2_r_cmd_trans_and_complete(struct ssd_info * ssd)
1512{
1513 unsigned int i=0;
1514 struct sub_request * sub=NULL, * p=NULL;
1515 for(i=0;i<ssd->parameter->channel_number;i++) /*Õâ¸öÑ»·´¦Àò»ÃèÒªchannelµÄʱ¼ä(¶ÃÃüÃîÒѾµ½´ïchip£¬chipÓÉready±äΪbusy)£¬µ±¶ÃÇëÇóÃê³Éʱ£¬½«Æä´ÓchannelµÄ¶ÓÃÃÖÃÈ¡³ö*/
1516 {
1517 sub=ssd->channel_head[i].subs_r_head;
1518
1519 while(sub!=NULL)
1520 {
1521 if(sub->current_state==SR_R_C_A_TRANSFER) /*¶ÃÃüÃî·¢ËÃÃê±Ã£¬½«¶ÔÓ¦µÄdieÖÃΪbusy£¬Ã¬Ê±ÃÞ¸ÄsubµÄ״̬; Õâ¸ö²¿·ÖרÃÅ´¦ÀöÃÇëÇóÓɵ±Ç°×´Ì¬Îª´«ÃüÃî±äΪdie¿ªÊ¼busy£¬die¿ªÊ¼busy²»ÃèÒªchannelΪ¿Õ£¬ËùÒÔµ¥¶ÀÃóö*/
1522 {
1523 if(sub->next_state_predict_time<=ssd->current_time)
1524 {
1525 go_one_step(ssd, sub,NULL, SR_R_READ,NORMAL); /*×´Ì¬Ìø±ä´¦Àú¯Êý*/
1526
1527 }
1528 }
1529 else if((sub->current_state==SR_COMPLETE)||((sub->next_state==SR_COMPLETE)&&(sub->next_state_predict_time<=ssd->current_time)))
1530 {
1531 if(sub!=ssd->channel_head[i].subs_r_head) /*if the request is completed, we delete it from read queue */
1532 {
1533 p->next_node=sub->next_node;
1534 }
1535 else
1536 {
1537 if (ssd->channel_head[i].subs_r_head!=ssd->channel_head[i].subs_r_tail)
1538 {
1539 ssd->channel_head[i].subs_r_head=sub->next_node;
1540 }
1541 else
1542 {
1543 ssd->channel_head[i].subs_r_head=NULL;
1544 ssd->channel_head[i].subs_r_tail=NULL;
1545 }
1546 }
1547 }
1548 p=sub;
1549 sub=sub->next_node;
1550 }
1551 }
1552
1553 return SUCCESS;
1554}
1555
1556/**************************************************************************
1557*Õâ¸öº¯ÊýÒ²ÊÇÖ»´¦ÀöÃ×ÓÇëÇ󣬴¦ÀÃchipµ±Ç°×´Ì¬ÊÇCHIP_WAIT£¬
1558*»òÕßÃÂÒ»¸ö״̬ÊÇCHIP_DATA_TRANSFER²¢ÇÒÃÂһ״̬µÄÔ¤¼ÆÊ±¼äáÓÚµ±Ç°Ê±¼äµÄchip
1559***************************************************************************/
1560Status services_2_r_data_trans(struct ssd_info * ssd,unsigned int channel,unsigned int * channel_busy_flag, unsigned int * change_current_time_flag)
1561{
1562 int chip=0;
1563 unsigned int die=0,plane=0,address_ppn=0,die1=0;
1564 struct sub_request * sub=NULL, * p=NULL,*sub1=NULL;
1565 struct sub_request * sub_twoplane_one=NULL, * sub_twoplane_two=NULL;
1566 struct sub_request * sub_interleave_one=NULL, * sub_interleave_two=NULL;
1567 for(chip=0;chip<ssd->channel_head[channel].chip;chip++)
1568 {
1569 if((ssd->channel_head[channel].chip_head[chip].current_state==CHIP_WAIT)||((ssd->channel_head[channel].chip_head[chip].next_state==CHIP_DATA_TRANSFER)&&
1570 (ssd->channel_head[channel].chip_head[chip].next_state_predict_time<=ssd->current_time)))
1571 {
1572 for(die=0;die<ssd->parameter->die_chip;die++)
1573 {
1574 sub=find_read_sub_request(ssd,channel,chip,die); /*ÔÚchannel,chip,dieÖÃÕÒµ½¶Ã×ÓÇëÇó*/
1575 if(sub!=NULL)
1576 {
1577 break;
1578 }
1579 }
1580
1581 if(sub==NULL)
1582 {
1583 continue;
1584 }
1585
1586 /**************************************************************************************
1587 *Èç¹ûssdÖ§³Ö¸ß¼¶ÃüÃÄÇûÎÒÃÇ¿ÉÒÔÒ»Æð´¦ÀÃÖ§³ÖAD_TWOPLANE_READ£¬AD_INTERLEAVEµÄ¶Ã×ÓÇëÇó
1588 *1£¬ÓÿÉÄܲúÉúÃËtwo plane²Ù×÷£¬ÔÚÕâÖÖÇé¿ö㬽«Ã¬Ò»¸ödieÉõÄý¸öplaneµÄÊý¾ÃÒÀ´Î´«³ö
1589 *2£¬ÓÿÉÄܲúÉúÃËinterleave²Ù×÷£¬ÔÚÕâÖÖÇé¿ö㬽«²»Ã¬dieÉõÄý¸öplaneµÄÊý¾ÃÒÀ´Î´«³ö
1590 ***************************************************************************************/
1591 if(((ssd->parameter->advanced_commands&AD_TWOPLANE_READ)==AD_TWOPLANE_READ)||((ssd->parameter->advanced_commands&AD_INTERLEAVE)==AD_INTERLEAVE))
1592 {
1593 if ((ssd->parameter->advanced_commands&AD_TWOPLANE_READ)==AD_TWOPLANE_READ) /*ÓÿÉÄܲúÉúÃËtwo plane²Ù×÷£¬ÔÚÕâÖÖÇé¿ö㬽«Ã¬Ò»¸ödieÉõÄý¸öplaneµÄÊý¾ÃÒÀ´Î´«³ö*/
1594 {
1595 sub_twoplane_one=sub;
1596 sub_twoplane_two=NULL;
1597 /*ΪÃ˱£Ö¤ÕÒµ½µÄsub_twoplane_twoÓësub_twoplane_one²»Ã¬£¬Ãîadd_reg_ppn=-1*/
1598 ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[sub->location->plane].add_reg_ppn=-1;
1599 sub_twoplane_two=find_read_sub_request(ssd,channel,chip,die); /*ÔÚÃà ìµÄchannel,chip,dieÖÃѰÕÒÃÃÃâÒ»¸ö¶Ã×ÓÇëÇó*/
1600
1601 /******************************************************
1602 *Èç¹ûÕÒµ½ÃËÄÇô¾ÃÖ´ÃÃTWO_PLANEµÄ״̬ת»»º¯Êýgo_one_step
1603 *Èç¹ûûÕÒµ½ÄÇô¾ÃÖ´ÃÃÆÕèÃüÃîµÄ״̬ת»»º¯Êýgo_one_step
1604 ******************************************************/
1605 if (sub_twoplane_two==NULL)
1606 {
1607 go_one_step(ssd, sub_twoplane_one,NULL, SR_R_DATA_TRANSFER,NORMAL);
1608 *change_current_time_flag=0;
1609 *channel_busy_flag=1;
1610
1611 }
1612 else
1613 {
1614 go_one_step(ssd, sub_twoplane_one,sub_twoplane_two, SR_R_DATA_TRANSFER,TWO_PLANE);
1615 *change_current_time_flag=0;
1616 *channel_busy_flag=1;
1617
1618 }
1619 }
1620 else if ((ssd->parameter->advanced_commands&AD_INTERLEAVE)==AD_INTERLEAVE) /*ÓÿÉÄܲúÉúÃËinterleave²Ù×÷£¬ÔÚÕâÖÖÇé¿ö㬽«²»Ã¬dieÉõÄý¸öplaneµÄÊý¾ÃÒÀ´Î´«³ö*/
1621 {
1622 sub_interleave_one=sub;
1623 sub_interleave_two=NULL;
1624 ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[sub->location->plane].add_reg_ppn=-1;
1625
1626 for(die1=0;die1<ssd->parameter->die_chip;die1++)
1627 {
1628 if(die1!=die)
1629 {
1630 sub_interleave_two=find_read_sub_request(ssd,channel,chip,die1); /*ÔÚÃà ìµÄchannel£¬chhip²»Ã¬µÄdieÉÃÃæÕÒÃÃÃâÒ»¸ö¶Ã×ÓÇëÇó*/
1631 if(sub_interleave_two!=NULL)
1632 {
1633 break;
1634 }
1635 }
1636 }
1637 if (sub_interleave_two==NULL)
1638 {
1639 go_one_step(ssd, sub_interleave_one,NULL, SR_R_DATA_TRANSFER,NORMAL);
1640
1641 *change_current_time_flag=0;
1642 *channel_busy_flag=1;
1643
1644 }
1645 else
1646 {
1647 go_one_step(ssd, sub_twoplane_one,sub_interleave_two, SR_R_DATA_TRANSFER,INTERLEAVE);
1648
1649 *change_current_time_flag=0;
1650 *channel_busy_flag=1;
1651
1652 }
1653 }
1654 }
1655 else /*Èç¹ûssd²»Ö§³Ö¸ß¼¶ÃüÃîÄÇô¾ÃÖ´ÃÃÒ»¸öÒ»¸öµÄÖ´ÃöÃ×ÓÇëÇó*/
1656 {
1657
1658 go_one_step(ssd, sub,NULL, SR_R_DATA_TRANSFER,NORMAL);
1659 *change_current_time_flag=0;
1660 *channel_busy_flag=1;
1661
1662 }
1663 break;
1664 }
1665
1666 if(*channel_busy_flag==1)
1667 {
1668 break;
1669 }
1670 }
1671 return SUCCESS;
1672}
1673
1674
1675/******************************************************
1676*Õâ¸öº¯ÊýÒ²ÊÇÖ»·þÎñ¶Ã×ÓÇëÇ󣬲¢ÇÒ´¦Óڵȴý״̬µÄ¶Ã×ÓÇëÇó
1677*******************************************************/
1678int services_2_r_wait(struct ssd_info * ssd,unsigned int channel,unsigned int * channel_busy_flag, unsigned int * change_current_time_flag)
1679{
1680 unsigned int plane=0,address_ppn=0;
1681 struct sub_request * sub=NULL, * p=NULL;
1682 struct sub_request * sub_twoplane_one=NULL, * sub_twoplane_two=NULL;
1683 struct sub_request * sub_interleave_one=NULL, * sub_interleave_two=NULL;
1684
1685
1686 sub=ssd->channel_head[channel].subs_r_head;
1687
1688
1689 if ((ssd->parameter->advanced_commands&AD_TWOPLANE_READ)==AD_TWOPLANE_READ) /*to find whether there are two sub request can be served by two plane operation*/
1690 {
1691 sub_twoplane_one=NULL;
1692 sub_twoplane_two=NULL;
1693 /*ѰÕÒÄÜÖ´ÃÃtwo_planeµÄý¸ö¶Ã×ÓÇëÇó*/
1694 find_interleave_twoplane_sub_request(ssd,channel,sub_twoplane_one,sub_twoplane_two,TWO_PLANE);
1695
1696 if (sub_twoplane_two!=NULL) /*¿ÉÒÔÖ´ÃÃtwo plane read ²Ù×÷*/
1697 {
1698 go_one_step(ssd, sub_twoplane_one,sub_twoplane_two, SR_R_C_A_TRANSFER,TWO_PLANE);
1699
1700 *change_current_time_flag=0;
1701 *channel_busy_flag=1; /*ÒѾÂÕ¼ÓÃÃËÕâ¸öÖÜÆÚµÄ×ÜÃߣ¬²»ÓÃÖ´ÃÃdieÖÃÊý¾ÃµÄ»Ø´«*/
1702 }
1703 else if((ssd->parameter->advanced_commands&AD_INTERLEAVE)!=AD_INTERLEAVE) /*ûÓÃÂú×ãÌõ¼þµÄý¸öpage£¬£¬²¢ÇÒûÓÃinterleave readÃüÃîʱ£¬Ö»ÄÜÖ´Ãõ¥¸öpageµÄ¶Ã*/
1704 {
1705 while(sub!=NULL) /*if there are read requests in queue, send one of them to target die*/
1706 {
1707 if(sub->current_state==SR_WAIT)
1708 { /*×¢ÒâøöÕâ¸öÅöÃÌõ¼þÓëservices_2_r_data_transÖÃÅöÃÌõ¼þµÄ²»Ã¬
1709 */
1710 if((ssd->channel_head[sub->location->channel].chip_head[sub->location->chip].current_state==CHIP_IDLE)||((ssd->channel_head[sub->location->channel].chip_head[sub->location->chip].next_state==CHIP_IDLE)&&
1711 (ssd->channel_head[sub->location->channel].chip_head[sub->location->chip].next_state_predict_time<=ssd->current_time)))
1712 {
1713 go_one_step(ssd, sub,NULL, SR_R_C_A_TRANSFER,NORMAL);
1714
1715 *change_current_time_flag=0;
1716 *channel_busy_flag=1; /*ÒѾÂÕ¼ÓÃÃËÕâ¸öÖÜÆÚµÄ×ÜÃߣ¬²»ÓÃÖ´ÃÃdieÖÃÊý¾ÃµÄ»Ø´«*/
1717 break;
1718 }
1719 else
1720 {
1721 /*ÒòΪdieµÄbusyµ¼ÖµÄ×èÈû*/
1722 }
1723 }
1724 sub=sub->next_node;
1725 }
1726 }
1727 }
1728 if ((ssd->parameter->advanced_commands&AD_INTERLEAVE)==AD_INTERLEAVE) /*to find whether there are two sub request can be served by INTERLEAVE operation*/
1729 {
1730 sub_interleave_one=NULL;
1731 sub_interleave_two=NULL;
1732 find_interleave_twoplane_sub_request(ssd,channel,sub_interleave_one,sub_interleave_two,INTERLEAVE);
1733
1734 if (sub_interleave_two!=NULL) /*¿ÉÒÔÖ´ÃÃinterleave read ²Ù×÷*/
1735 {
1736
1737 go_one_step(ssd, sub_interleave_one,sub_interleave_two, SR_R_C_A_TRANSFER,INTERLEAVE);
1738
1739 *change_current_time_flag=0;
1740 *channel_busy_flag=1; /*ÒѾÂÕ¼ÓÃÃËÕâ¸öÖÜÆÚµÄ×ÜÃߣ¬²»ÓÃÖ´ÃÃdieÖÃÊý¾ÃµÄ»Ø´«*/
1741 }
1742 else /*ûÓÃÂú×ãÌõ¼þµÄý¸öpage£¬Ö»ÄÜÖ´Ãõ¥¸öpageµÄ¶Ã*/
1743 {
1744 while(sub!=NULL) /*if there are read requests in queue, send one of them to target die*/
1745 {
1746 if(sub->current_state==SR_WAIT)
1747 {
1748 if((ssd->channel_head[sub->location->channel].chip_head[sub->location->chip].current_state==CHIP_IDLE)||((ssd->channel_head[sub->location->channel].chip_head[sub->location->chip].next_state==CHIP_IDLE)&&
1749 (ssd->channel_head[sub->location->channel].chip_head[sub->location->chip].next_state_predict_time<=ssd->current_time)))
1750 {
1751
1752 go_one_step(ssd, sub,NULL, SR_R_C_A_TRANSFER,NORMAL);
1753
1754 *change_current_time_flag=0;
1755 *channel_busy_flag=1; /*ÒѾÂÕ¼ÓÃÃËÕâ¸öÖÜÆÚµÄ×ÜÃߣ¬²»ÓÃÖ´ÃÃdieÖÃÊý¾ÃµÄ»Ø´«*/
1756 break;
1757 }
1758 else
1759 {
1760 /*ÒòΪdieµÄbusyµ¼ÖµÄ×èÈû*/
1761 }
1762 }
1763 sub=sub->next_node;
1764 }
1765 }
1766 }
1767
1768 /*******************************
1769 *ssd²»ÄÜÖ´ÃÃÖ´Ãø߼¶ÃüÃîµÄÇé¿öÃÂ
1770 *******************************/
1771 if (((ssd->parameter->advanced_commands&AD_INTERLEAVE)!=AD_INTERLEAVE)&&((ssd->parameter->advanced_commands&AD_TWOPLANE_READ)!=AD_TWOPLANE_READ))
1772 {
1773 while(sub!=NULL) /*if there are read requests in queue, send one of them to target chip*/
1774 {
1775 if(sub->current_state==SR_WAIT)
1776 {
1777 if((ssd->channel_head[sub->location->channel].chip_head[sub->location->chip].current_state==CHIP_IDLE)||((ssd->channel_head[sub->location->channel].chip_head[sub->location->chip].next_state==CHIP_IDLE)&&
1778 (ssd->channel_head[sub->location->channel].chip_head[sub->location->chip].next_state_predict_time<=ssd->current_time)))
1779 {
1780
1781 go_one_step(ssd, sub,NULL, SR_R_C_A_TRANSFER,NORMAL);
1782
1783 *change_current_time_flag=0;
1784 *channel_busy_flag=1; /*ÒѾÂÕ¼ÓÃÃËÕâ¸öÖÜÆÚµÄ×ÜÃߣ¬²»ÓÃÖ´ÃÃdieÖÃÊý¾ÃµÄ»Ø´«*/
1785 break;
1786 }
1787 else
1788 {
1789 /*ÒòΪdieµÄbusyµ¼ÖµÄ×èÈû*/
1790 }
1791 }
1792 sub=sub->next_node;
1793 }
1794 }
1795
1796 return SUCCESS;
1797}
1798
1799/*********************************************************************
1800*µ±Ò»¸öô×ÓÇëÇó´¦ÀÃÃêºó£¬Òª´ÓÇëÇó¶ÓÃÃÉÃɾ³ý£¬Õâ¸öº¯Êý¾ÃÊÇÖ´ÃÃÕâ¸ö¹¦ÄÜ¡£
1801**********************************************************************/
1802int delete_w_sub_request(struct ssd_info * ssd, unsigned int channel, struct sub_request * sub )
1803{
1804 struct sub_request * p=NULL;
1805 if (sub==ssd->channel_head[channel].subs_w_head) /*½«Õâ¸ö×ÓÇëÇó´Óchannel¶ÓÃÃÖÃɾ³ý*/
1806 {
1807 if (ssd->channel_head[channel].subs_w_head!=ssd->channel_head[channel].subs_w_tail)
1808 {
1809 ssd->channel_head[channel].subs_w_head=sub->next_node;
1810 }
1811 else
1812 {
1813 ssd->channel_head[channel].subs_w_head=NULL;
1814 ssd->channel_head[channel].subs_w_tail=NULL;
1815 }
1816 }
1817 else
1818 {
1819 p=ssd->channel_head[channel].subs_w_head;
1820 while(p->next_node !=sub)
1821 {
1822 p=p->next_node;
1823 }
1824
1825 if (sub->next_node!=NULL)
1826 {
1827 p->next_node=sub->next_node;
1828 }
1829 else
1830 {
1831 p->next_node=NULL;
1832 ssd->channel_head[channel].subs_w_tail=p;
1833 }
1834 }
1835
1836 return SUCCESS;
1837}
1838
1839/*
1840*º¯ÊýµÄ¹¦ÄܾÃÊÇÖ´ÃÃcopybackÃüÃîµÄ¹¦ÄÜ£¬
1841*/
1842Status copy_back(struct ssd_info * ssd, unsigned int channel, unsigned int chip, unsigned int die,struct sub_request * sub)
1843{
1844 int old_ppn=-1, new_ppn=-1;
1845 long long time=0;
1846 if (ssd->parameter->greed_CB_ad==1) /*ÔÊÃÃ̰À·Ê¹ÓÃcopyback¸ß¼¶ÃüÃî*/
1847 {
1848 old_ppn=-1;
1849 if (ssd->dram->map->map_entry[sub->lpn].state!=0) /*˵Ã÷Õâ¸öÂß¼Âҳ֮ǰÓÃô¹ý£¬ÃèҪʹÓÃcopyback+random inputÃüÃ·ñÔòÖ±½ÓôÃÂÈ¥¼´¿É*/
1850 {
1851 if ((sub->state&ssd->dram->map->map_entry[sub->lpn].state)==ssd->dram->map->map_entry[sub->lpn].state)
1852 {
1853 sub->next_state_predict_time=ssd->current_time+7*ssd->parameter->time_characteristics.tWC+(sub->size*ssd->parameter->subpage_capacity)*ssd->parameter->time_characteristics.tWC;
1854 }
1855 else
1856 {
1857 sub->next_state_predict_time=ssd->current_time+19*ssd->parameter->time_characteristics.tWC+ssd->parameter->time_characteristics.tR+(sub->size*ssd->parameter->subpage_capacity)*ssd->parameter->time_characteristics.tWC;
1858 ssd->copy_back_count++;
1859 ssd->read_count++;
1860 ssd->update_read_count++;
1861 old_ppn=ssd->dram->map->map_entry[sub->lpn].pn; /*¼Ç¼ÔÂÀ´µÄÎïÀÃÒ³£¬ÓÃÓÚÔÚcopyback汣Ã¶ÃÊÇ·ñÂú×ãÃ¬ÎªÆæµØÖ·»òÕßżµØÖ·*/
1862 }
1863 }
1864 else
1865 {
1866 sub->next_state_predict_time=ssd->current_time+7*ssd->parameter->time_characteristics.tWC+(sub->size*ssd->parameter->subpage_capacity)*ssd->parameter->time_characteristics.tWC;
1867 }
1868 sub->complete_time=sub->next_state_predict_time;
1869 time=sub->complete_time;
1870
1871 get_ppn(ssd,sub->location->channel,sub->location->chip,sub->location->die,sub->location->plane,sub);
1872
1873 if (old_ppn!=-1) /*²ÉÓÃÃËcopyback²Ù×÷£¬ÃèÒªÅöÃÊÇ·ñÂú×ãÃËÆæÅ¼µØÖ·µÄÃÞÖÆ*/
1874 {
1875 new_ppn=ssd->dram->map->map_entry[sub->lpn].pn;
1876 while (old_ppn%2!=new_ppn%2) /*ûÓÃÂú×ãÆæÅ¼µØÖ·ÃÞÖÆ£¬ÃèÒªÔÙÃùÃÂÕÒÒ»Ò³*/
1877 {
1878 get_ppn(ssd,sub->location->channel,sub->location->chip,sub->location->die,sub->location->plane,sub);
1879 ssd->program_count--;
1880 ssd->write_flash_count--;
1881 ssd->waste_page_count++;
1882 new_ppn=ssd->dram->map->map_entry[sub->lpn].pn;
1883 }
1884 }
1885 }
1886 else /*²»ÄṴ̈À·µÄʹÓÃcopyback¸ß¼¶ÃüÃî*/
1887 {
1888 if (ssd->dram->map->map_entry[sub->lpn].state!=0)
1889 {
1890 if ((sub->state&ssd->dram->map->map_entry[sub->lpn].state)==ssd->dram->map->map_entry[sub->lpn].state)
1891 {
1892 sub->next_state_predict_time=ssd->current_time+7*ssd->parameter->time_characteristics.tWC+(sub->size*ssd->parameter->subpage_capacity)*ssd->parameter->time_characteristics.tWC;
1893 get_ppn(ssd,sub->location->channel,sub->location->chip,sub->location->die,sub->location->plane,sub);
1894 }
1895 else
1896 {
1897 old_ppn=ssd->dram->map->map_entry[sub->lpn].pn; /*¼Ç¼ÔÂÀ´µÄÎïÀÃÒ³£¬ÓÃÓÚÔÚcopyback汣Ã¶ÃÊÇ·ñÂú×ãÃ¬ÎªÆæµØÖ·»òÕßżµØÖ·*/
1898 get_ppn(ssd,sub->location->channel,sub->location->chip,sub->location->die,sub->location->plane,sub);
1899 new_ppn=ssd->dram->map->map_entry[sub->lpn].pn;
1900 if (old_ppn%2==new_ppn%2)
1901 {
1902 ssd->copy_back_count++;
1903 sub->next_state_predict_time=ssd->current_time+19*ssd->parameter->time_characteristics.tWC+ssd->parameter->time_characteristics.tR+(sub->size*ssd->parameter->subpage_capacity)*ssd->parameter->time_characteristics.tWC;
1904 }
1905 else
1906 {
1907 sub->next_state_predict_time=ssd->current_time+7*ssd->parameter->time_characteristics.tWC+ssd->parameter->time_characteristics.tR+(size(ssd->dram->map->map_entry[sub->lpn].state))*ssd->parameter->time_characteristics.tRC+(sub->size*ssd->parameter->subpage_capacity)*ssd->parameter->time_characteristics.tWC;
1908 }
1909 ssd->read_count++;
1910 ssd->update_read_count++;
1911 }
1912 }
1913 else
1914 {
1915 sub->next_state_predict_time=ssd->current_time+7*ssd->parameter->time_characteristics.tWC+(sub->size*ssd->parameter->subpage_capacity)*ssd->parameter->time_characteristics.tWC;
1916 get_ppn(ssd,sub->location->channel,sub->location->chip,sub->location->die,sub->location->plane,sub);
1917 }
1918 sub->complete_time=sub->next_state_predict_time;
1919 time=sub->complete_time;
1920 }
1921
1922 /****************************************************************
1923 *Ö´ÃÃcopyback¸ß¼¶ÃüÃîʱ£¬ÃèÒªÃÞ¸Ächannel£¬chipµÄ״̬£¬ÒÔ¼°Ê±¼äµÈ
1924 *****************************************************************/
1925 ssd->channel_head[channel].current_state=CHANNEL_TRANSFER;
1926 ssd->channel_head[channel].current_time=ssd->current_time;
1927 ssd->channel_head[channel].next_state=CHANNEL_IDLE;
1928 ssd->channel_head[channel].next_state_predict_time=time;
1929
1930 ssd->channel_head[channel].chip_head[chip].current_state=CHIP_WRITE_BUSY;
1931 ssd->channel_head[channel].chip_head[chip].current_time=ssd->current_time;
1932 ssd->channel_head[channel].chip_head[chip].next_state=CHIP_IDLE;
1933 ssd->channel_head[channel].chip_head[chip].next_state_predict_time=time+ssd->parameter->time_characteristics.tPROG;
1934
1935 return SUCCESS;
1936}
1937
1938/*****************
1939*¾²Ì¬Ã´²Ù×÷µÄʵÃÖ
1940******************/
1941Status static_write(struct ssd_info * ssd, unsigned int channel,unsigned int chip, unsigned int die,struct sub_request * sub)
1942{
1943 long long time=0;
1944 if (ssd->dram->map->map_entry[sub->lpn].state!=0) /*˵Ã÷Õâ¸öÂß¼Âҳ֮ǰÓÃô¹ý£¬ÃèҪʹÓÃÃȶóöÀ´£¬ÔÙôÃÂÈ¥£¬·ñÔòÖ±½ÓôÃÂÈ¥¼´¿É*/
1945 {
1946 if ((sub->state&ssd->dram->map->map_entry[sub->lpn].state)==ssd->dram->map->map_entry[sub->lpn].state) /*¿ÉÒÔ¸²¸Ç*/
1947 {
1948 sub->next_state_predict_time=ssd->current_time+7*ssd->parameter->time_characteristics.tWC+(sub->size*ssd->parameter->subpage_capacity)*ssd->parameter->time_characteristics.tWC;
1949 }
1950 else
1951 {
1952 sub->next_state_predict_time=ssd->current_time+7*ssd->parameter->time_characteristics.tWC+ssd->parameter->time_characteristics.tR+(size((ssd->dram->map->map_entry[sub->lpn].state^sub->state)))*ssd->parameter->time_characteristics.tRC+(sub->size*ssd->parameter->subpage_capacity)*ssd->parameter->time_characteristics.tWC;
1953 ssd->read_count++;
1954 ssd->update_read_count++;
1955 }
1956 }
1957 else
1958 {
1959 sub->next_state_predict_time=ssd->current_time+7*ssd->parameter->time_characteristics.tWC+(sub->size*ssd->parameter->subpage_capacity)*ssd->parameter->time_characteristics.tWC;
1960 }
1961 sub->complete_time=sub->next_state_predict_time;
1962 time=sub->complete_time;
1963
1964 get_ppn(ssd,sub->location->channel,sub->location->chip,sub->location->die,sub->location->plane,sub);
1965
1966 /****************************************************************
1967 *Ö´ÃÃcopyback¸ß¼¶ÃüÃîʱ£¬ÃèÒªÃÞ¸Ächannel£¬chipµÄ״̬£¬ÒÔ¼°Ê±¼äµÈ
1968 *****************************************************************/
1969 ssd->channel_head[channel].current_state=CHANNEL_TRANSFER;
1970 ssd->channel_head[channel].current_time=ssd->current_time;
1971 ssd->channel_head[channel].next_state=CHANNEL_IDLE;
1972 ssd->channel_head[channel].next_state_predict_time=time;
1973
1974 ssd->channel_head[channel].chip_head[chip].current_state=CHIP_WRITE_BUSY;
1975 ssd->channel_head[channel].chip_head[chip].current_time=ssd->current_time;
1976 ssd->channel_head[channel].chip_head[chip].next_state=CHIP_IDLE;
1977 ssd->channel_head[channel].chip_head[chip].next_state_predict_time=time+ssd->parameter->time_characteristics.tPROG;
1978
1979 return SUCCESS;
1980}
1981
1982/********************
1983ô×ÓÇëÇóµÄ´¦Àú¯Êý
1984*********************/
1985Status services_2_write(struct ssd_info * ssd,unsigned int channel,unsigned int * channel_busy_flag, unsigned int * change_current_time_flag)
1986{
1987 int j=0,chip=0;
1988 unsigned int k=0;
1989 unsigned int old_ppn=0,new_ppn=0;
1990 unsigned int chip_token=0,die_token=0,plane_token=0,address_ppn=0;
1991 unsigned int die=0,plane=0;
1992 long long time=0;
1993 struct sub_request * sub=NULL, * p=NULL;
1994 struct sub_request * sub_twoplane_one=NULL, * sub_twoplane_two=NULL;
1995 struct sub_request * sub_interleave_one=NULL, * sub_interleave_two=NULL;
1996
1997 /************************************************************************************************************************
1998 *ô×ÓÇëÇó¹ÒÔÚý¸öµØ·½Ò»¸öÊÇchannel_head[channel].subs_w_head£¬ÃÃÃâÒ»¸öÊÇssd->subs_w_head£¬ËùÒÔÒª±£Ö¤ÖÃÉÙÓÃÒ»¸ö¶ÓÃò»Îª¿Õ
1999 *ìʱ×ÓÇëÇóµÄ´¦Àû¹·ÖΪ¶¯Ì¬·ÖÅäºÃ¾²Ì¬·ÖÅä¡£
2000 *************************************************************************************************************************/
2001 if((ssd->channel_head[channel].subs_w_head!=NULL)||(ssd->subs_w_head!=NULL))
2002 {
2003 if (ssd->parameter->allocation_scheme==0) /*¶¯Ì¬·ÖÅä*/
2004 {
2005 for(j=0;j<ssd->channel_head[channel].chip;j++)
2006 {
2007 if((ssd->channel_head[channel].subs_w_head==NULL)&&(ssd->subs_w_head==NULL))
2008 {
2009 break;
2010 }
2011
2012 chip_token=ssd->channel_head[channel].token; /*ÃîÅÆ*/
2013 if (*channel_busy_flag==0)
2014 {
2015 if((ssd->channel_head[channel].chip_head[chip_token].current_state==CHIP_IDLE)||((ssd->channel_head[channel].chip_head[chip_token].next_state==CHIP_IDLE)&&(ssd->channel_head[channel].chip_head[chip_token].next_state_predict_time<=ssd->current_time)))
2016 {
2017 if((ssd->channel_head[channel].subs_w_head==NULL)&&(ssd->subs_w_head==NULL))
2018 {
2019 break;
2020 }
2021 die_token=ssd->channel_head[channel].chip_head[chip_token].token;
2022 if (((ssd->parameter->advanced_commands&AD_INTERLEAVE)!=AD_INTERLEAVE)&&((ssd->parameter->advanced_commands&AD_TWOPLANE)!=AD_TWOPLANE)) //can't use advanced commands
2023 {
2024 sub=find_write_sub_request(ssd,channel);
2025 if(sub==NULL)
2026 {
2027 break;
2028 }
2029
2030 if(sub->current_state==SR_WAIT)
2031 {
2032 plane_token=ssd->channel_head[channel].chip_head[chip_token].die_head[die_token].token;
2033
2034 get_ppn(ssd,channel,chip_token,die_token,plane_token,sub);
2035
2036 ssd->channel_head[channel].chip_head[chip_token].die_head[die_token].token=(ssd->channel_head[channel].chip_head[chip_token].die_head[die_token].token+1)%ssd->parameter->plane_die;
2037
2038 *change_current_time_flag=0;
2039
2040 if(ssd->parameter->ad_priority2==0)
2041 {
2042 ssd->real_time_subreq--;
2043 }
2044 go_one_step(ssd,sub,NULL,SR_W_TRANSFER,NORMAL); /*Ö´ÃÃÆÕèµÄ״̬µÄת±ä¡£*/
2045 delete_w_sub_request(ssd,channel,sub); /*ɾµô´¦ÀÃÃêºóµÄô×ÓÇëÇó*/
2046
2047 *channel_busy_flag=1;
2048 /**************************************************************************
2049 *Ìø³öforÑ»·Ç°£¬ÃÞ¸ÄÃîÅÆ
2050 *ÕâÀïµÄtokenµÄ±ä»¯Ãêȫȡ¾öÓÚÔÚÕâ¸öchannel chip die planeÃÂôÊÇ·ñ³É¹¦
2051 *³É¹¦Ã˾Ãbreak û³É¹¦token¾ÃÒª±ä»¯Ö±µ½ÕÒµ½ÄÜô³É¹¦µÄchannel chip die plane
2052 ***************************************************************************/
2053 ssd->channel_head[channel].chip_head[chip_token].token=(ssd->channel_head[channel].chip_head[chip_token].token+1)%ssd->parameter->die_chip;
2054 ssd->channel_head[channel].token=(ssd->channel_head[channel].token+1)%ssd->parameter->chip_channel[channel];
2055 break;
2056 }
2057 }
2058 else /*use advanced commands*/
2059 {
2060 if (dynamic_advanced_process(ssd,channel,chip_token)==NULL)
2061 {
2062 *channel_busy_flag=0;
2063 }
2064 else
2065 {
2066 *channel_busy_flag=1; /*Ö´ÃÃÃËÒ»¸öÇëÇ󣬴«ÊäÃËÊý¾Ã£¬Õ¼ÓÃÃË×ÜÃᜪÃèÒªÌø³öµ½ÃÂÒ»¸öchannel*/
2067 ssd->channel_head[channel].chip_head[chip_token].token=(ssd->channel_head[channel].chip_head[chip_token].token+1)%ssd->parameter->die_chip;
2068 ssd->channel_head[channel].token=(ssd->channel_head[channel].token+1)%ssd->parameter->chip_channel[channel];
2069 break;
2070 }
2071 }
2072
2073 ssd->channel_head[channel].chip_head[chip_token].token=(ssd->channel_head[channel].chip_head[chip_token].token+1)%ssd->parameter->die_chip;
2074 }
2075 }
2076
2077 ssd->channel_head[channel].token=(ssd->channel_head[channel].token+1)%ssd->parameter->chip_channel[channel];
2078 }
2079 }
2080 else if(ssd->parameter->allocation_scheme==1) /*¾²Ì¬·ÖÅä*/
2081 {
2082 for(chip=0;chip<ssd->channel_head[channel].chip;chip++)
2083 {
2084 if((ssd->channel_head[channel].chip_head[chip].current_state==CHIP_IDLE)||((ssd->channel_head[channel].chip_head[chip].next_state==CHIP_IDLE)&&(ssd->channel_head[channel].chip_head[chip].next_state_predict_time<=ssd->current_time)))
2085 {
2086 if(ssd->channel_head[channel].subs_w_head==NULL)
2087 {
2088 break;
2089 }
2090 if (*channel_busy_flag==0)
2091 {
2092
2093 if (((ssd->parameter->advanced_commands&AD_INTERLEAVE)!=AD_INTERLEAVE)&&((ssd->parameter->advanced_commands&AD_TWOPLANE)!=AD_TWOPLANE)) /*²»Ö´Ãø߼¶ÃüÃî*/
2094 {
2095 for(die=0;die<ssd->channel_head[channel].chip_head[chip].die_num;die++)
2096 {
2097 if(ssd->channel_head[channel].subs_w_head==NULL)
2098 {
2099 break;
2100 }
2101 sub=ssd->channel_head[channel].subs_w_head;
2102 while (sub!=NULL)
2103 {
2104 if ((sub->current_state==SR_WAIT)&&(sub->location->channel==channel)&&(sub->location->chip==chip)&&(sub->location->die==die)) /*¸Ã×ÓÇëÇó¾ÃÊǵ±Ç°dieµÄÇëÇó*/
2105 {
2106 break;
2107 }
2108 sub=sub->next_node;
2109 }
2110 if (sub==NULL)
2111 {
2112 continue;
2113 }
2114
2115 if(sub->current_state==SR_WAIT)
2116 {
2117 sub->current_time=ssd->current_time;
2118 sub->current_state=SR_W_TRANSFER;
2119 sub->next_state=SR_COMPLETE;
2120
2121 if ((ssd->parameter->advanced_commands&AD_COPYBACK)==AD_COPYBACK)
2122 {
2123 copy_back(ssd, channel,chip, die,sub); /*Èç¹û¿ÉÒÔÖ´ÃÃcopyback¸ß¼¶ÃüÃÄÇô¾ÃÓú¯Êýcopy_back(ssd, channel,chip, die,sub)´¦ÀÃô×ÓÇëÇó*/
2124 *change_current_time_flag=0;
2125 }
2126 else
2127 {
2128 static_write(ssd, channel,chip, die,sub); /*²»ÄÜÖ´ÃÃcopyback¸ß¼¶ÃüÃÄÇô¾ÃÓÃstatic_write(ssd, channel,chip, die,sub)º¯ÊýÀ´´¦ÀÃô×ÓÇëÇó*/
2129 *change_current_time_flag=0;
2130 }
2131
2132 delete_w_sub_request(ssd,channel,sub);
2133 *channel_busy_flag=1;
2134 break;
2135 }
2136 }
2137 }
2138 else /*²»ÄÜ´¦Àø߼¶ÃüÃî*/
2139 {
2140 if (dynamic_advanced_process(ssd,channel,chip)==NULL)
2141 {
2142 *channel_busy_flag=0;
2143 }
2144 else
2145 {
2146 *channel_busy_flag=1; /*Ö´ÃÃÃËÒ»¸öÇëÇ󣬴«ÊäÃËÊý¾Ã£¬Õ¼ÓÃÃË×ÜÃᜪÃèÒªÌø³öµ½ÃÂÒ»¸öchannel*/
2147 break;
2148 }
2149 }
2150
2151 }
2152 }
2153 }
2154 }
2155 }
2156 return SUCCESS;
2157}
2158
2159
2160/********************************************************
2161*Õâ¸öº¯ÊýµÄÖ÷Òª¹¦ÄÜÊÇÖ÷¿Ø¶Ã×ÓÇëÇóºÃô×ÓÇëÇóµÄ״̬±ä»¯´¦ÀÃ
2162*********************************************************/
2163
2164struct ssd_info *process(struct ssd_info *ssd)
2165{
2166
2167 /*********************************************************************************************************
2168 *flag_die±ÃʾÊÇ·ñÒòΪdieµÄbusy£¬×èÈûÃËʱ¼äǰ½ø£¬-1±ÃʾûÓ㬷Ç-1±ÃʾÓÃ×èÈû£¬
2169 *flag_dieµÄÖµ±ÃʾdieºÅ,old ppn¼Ç¼ÔÚcopyback֮ǰµÄÎïÀÃÒ³ºÅ£¬ÓÃÓÚÅöÃcopybackÊÇ·ñ×ñÊØÃËÆæÅ¼µØÖ·µÄÃÞÖÆ£»
2170 *two_plane_bit[8],two_plane_place[8]Êý×é³ÉÔ±±Ãʾìһ¸öchannelÉÃÿ¸ödieµÄÇëÇó·ÖÅäÇé¿ö£»
2171 *chg_cur_time_flag×÷ΪÊÇ·ñÃèÒªµ÷Õûµ±Ç°Ê±¼äµÄ±ê־룬µ±ÒòΪchannel´¦ÓÚbusyµ¼ÖÂÇëÇó×èÈûʱ£¬ÃèÒªµ÷Õûµ±Ç°Ê±¼ä£»
2172 *³õʼÈÃΪÃèÒªµ÷Õû£¬ÖÃΪ1£¬µ±ÈκÎÒ»¸öchannel´¦ÀÃÃË´«ËÃÃüÃî»òÕßÊý¾Ãʱ£¬Õâ¸öÖµÖÃΪ0£¬±Ãʾ²»ÃèÒªµ÷Õû£»
2173 **********************************************************************************************************/
2174 int old_ppn=-1,flag_die=-1;
2175 unsigned int i,chan,random_num;
2176 unsigned int flag=0,new_write=0,chg_cur_time_flag=1,flag2=0,flag_gc=0;
2177 int64_t time, channel_time=MAX_INT64;
2178 struct sub_request *sub;
2179
2180#ifdef DEBUG
2181 printf("enter process, current time:%lld\n",ssd->current_time);
2182#endif
2183
2184 /*********************************************************
2185 *ÅöÃÊÇ·ñÓöÃô×ÓÇëÇó£¬Èç¹ûÓÃÄÇôflagÃîΪ0£¬Ã»ÓÃflag¾ÃΪ1
2186 *µ±flagΪ1ʱ£¬ÈôssdÖÃÓÃgc²Ù×÷Õâʱ¾Ã¿ÉÒÔÖ´ÃÃgc²Ù×÷
2187 **********************************************************/
2188 for(i=0;i<ssd->parameter->channel_number;i++)
2189 {
2190 if((ssd->channel_head[i].subs_r_head==NULL)&&(ssd->channel_head[i].subs_w_head==NULL)&&(ssd->subs_w_head==NULL))
2191 {
2192 flag=1;
2193 }
2194 else
2195 {
2196 flag=0;
2197 break;
2198 }
2199 }
2200 if(flag==1)
2201 {
2202 ssd->flag=1;
2203 if (ssd->gc_request>0) /*SSDÖÃÓÃgc²Ù×÷µÄÇëÇó*/
2204 {
2205 gc(ssd,0,1); /*Õâ¸ögcÒªÇóËùÓÃchannel¶¼±ØÃë±éÀúµ½*/
2206 }
2207 return ssd;
2208 }
2209 else
2210 {
2211 ssd->flag=0;
2212 }
2213
2214 time = ssd->current_time;
2215 services_2_r_cmd_trans_and_complete(ssd); /*´¦Àõ±Ç°×´Ì¬ÊÇSR_R_C_A_TRANSFER»òÕßµ±Ç°×´Ì¬ÊÇSR_COMPLETE£¬»òÕßÃÂһ״̬ÊÇSR_COMPLETE²¢ÇÒÃÂһ״̬Ԥ¼ÆÊ±¼äáÓÚµ±Ç°×´Ì¬Ê±¼ä*/
2216
2217 random_num=ssd->program_count%ssd->parameter->channel_number; /*²úÉúÒ»¸öËæ»úÊý£¬±£Ö¤Ã¿´Î´Ó²»Ã¬µÄchannel¿ªÊ¼²éѯ*/
2218
2219 /*****************************************
2220 *Ñ»·´¦ÀÃËùÓÃchannelÉõĶÃô×ÓÇëÇó
2221 *·¢¶ÃÇëÇóÃüÃ´«¶ÃôÊý¾Ã£¬¶¼ÃèÒªÕ¼ÓÃ×ÜÃᜪ
2222 ******************************************/
2223 for(chan=0;chan<ssd->parameter->channel_number;chan++)
2224 {
2225 i=(random_num+chan)%ssd->parameter->channel_number;
2226 flag=0;
2227 flag_gc=0; /*ÿ´Î½øÈëchannelʱ£¬½«gcµÄ±ê־λÖÃΪ0£¬Ä¬ÈÃÈÃΪûÓýøÃÃgc²Ù×÷*/
2228 if((ssd->channel_head[i].current_state==CHANNEL_IDLE)||(ssd->channel_head[i].next_state==CHANNEL_IDLE&&ssd->channel_head[i].next_state_predict_time<=ssd->current_time))
2229 {
2230 if (ssd->gc_request>0) /*ÓÃgc²Ù×÷£¬ÃèÒª½øÃÃÒ»¶¨µÄÅöÃ*/
2231 {
2232 if (ssd->channel_head[i].gc_command!=NULL)
2233 {
2234 flag_gc=gc(ssd,i,0); /*gcº¯Êý·µ»ØÒ»¸öÖµ£¬±ÃʾÊÇ·ñÖ´ÃÃÃËgc²Ù×÷£¬Èç¹ûÖ´ÃÃÃËgc²Ù×÷£¬Õâ¸öchannelÔÚÕâ¸öʱ¿Ì²»ÄÜ·þÎñÆäËûµÄÇëÇó*/
2235 }
2236 if (flag_gc==1) /*Ö´Ãùýgc²Ù×÷£¬ÃèÒªÌø³ö´Ë´ÎÑ»·*/
2237 {
2238 continue;
2239 }
2240 }
2241
2242 sub=ssd->channel_head[i].subs_r_head; /*ÃÈ´¦ÀöÃÇëÇó*/
2243 services_2_r_wait(ssd,i,&flag,&chg_cur_time_flag); /*´¦Àô¦Óڵȴý״̬µÄ¶Ã×ÓÇëÇó*/
2244
2245 if((flag==0)&&(ssd->channel_head[i].subs_r_head!=NULL)) /*if there are no new read request and data is ready in
2246 some dies, send these data to controller and response this request*/
2247 {
2248 services_2_r_data_trans(ssd,i,&flag,&chg_cur_time_flag);
2249
2250 }
2251 if(flag==0) /*if there are no read request to take channel, we can serve write requests*/
2252 {
2253 services_2_write(ssd,i,&flag,&chg_cur_time_flag);
2254
2255 }
2256 }
2257 }
2258
2259 return ssd;
2260}
2261
2262/****************************************************************************************************************************
2263*µ±ssdÖ§³Ö¸ß¼¶ÃüÃîʱ£¬Õâ¸öº¯ÊýµÄ×÷ÓþÃÊÇ´¦Àø߼¶ÃüÃîµÄô×ÓÇëÇó
2264*¸ù¾ÃÇëÇóµÄ¸öÊý£¬¾ö¶¨Ñ¡ÔñÄÄÖָ߼¶ÃüÃÕâ¸öº¯ÊýÖ»´¦ÀÃôÇëÇ󣬶ÃÇëÇóÒѾ·ÖÅ䵽ÿ¸öchannel£¬ËùÒÔÔÚÖ´ÃÃʱ֮¼ä½øÃÃѡȡÃà Ó¦µÄÃüÃ
2265*****************************************************************************************************************************/
2266struct ssd_info *dynamic_advanced_process(struct ssd_info *ssd,unsigned int channel,unsigned int chip)
2267{
2268 unsigned int die=0,plane=0;
2269 unsigned int subs_count=0;
2270 int flag;
2271 unsigned int gate; /*record the max subrequest that can be executed in the same channel. it will be used when channel-level priority order is highest and allocation scheme is full dynamic allocation*/
2272 unsigned int plane_place; /*record which plane has sub request in static allocation*/
2273 struct sub_request *sub=NULL,*p=NULL,*sub0=NULL,*sub1=NULL,*sub2=NULL,*sub3=NULL,*sub0_rw=NULL,*sub1_rw=NULL,*sub2_rw=NULL,*sub3_rw=NULL;
2274 struct sub_request ** subs=NULL;
2275 unsigned int max_sub_num=0;
2276 unsigned int die_token=0,plane_token=0;
2277 unsigned int * plane_bits=NULL;
2278 unsigned int interleaver_count=0;
2279
2280 unsigned int mask=0x00000001;
2281 unsigned int i=0,j=0;
2282
2283 max_sub_num=(ssd->parameter->die_chip)*(ssd->parameter->plane_die);
2284 gate=max_sub_num;
2285 subs=(struct sub_request **)malloc(max_sub_num*sizeof(struct sub_request *));
2286 alloc_assert(subs,"sub_request");
2287
2288 for(i=0;i<max_sub_num;i++)
2289 {
2290 subs[i]=NULL;
2291 }
2292
2293 if((ssd->parameter->allocation_scheme==0)&&(ssd->parameter->dynamic_allocation==0)&&(ssd->parameter->ad_priority2==0))
2294 {
2295 gate=ssd->real_time_subreq/ssd->parameter->channel_number;
2296
2297 if(gate==0)
2298 {
2299 gate=1;
2300 }
2301 else
2302 {
2303 if(ssd->real_time_subreq%ssd->parameter->channel_number!=0)
2304 {
2305 gate++;
2306 }
2307 }
2308 }
2309
2310 if ((ssd->parameter->allocation_scheme==0)) /*È«¶¯Ì¬·ÖÅ䣬ÃèÒª´Óssd->subs_w_headÉÃѡȡµÈ´ý·þÎñµÄ×ÓÇëÇó*/
2311 {
2312 if(ssd->parameter->dynamic_allocation==0)
2313 {
2314 sub=ssd->subs_w_head;
2315 }
2316 else
2317 {
2318 sub=ssd->channel_head[channel].subs_w_head;
2319 }
2320
2321 subs_count=0;
2322
2323 while ((sub!=NULL)&&(subs_count<max_sub_num)&&(subs_count<gate))
2324 {
2325 if(sub->current_state==SR_WAIT)
2326 {
2327 if ((sub->update==NULL)||((sub->update!=NULL)&&((sub->update->current_state==SR_COMPLETE)||((sub->update->next_state==SR_COMPLETE)&&(sub->update->next_state_predict_time<=ssd->current_time))))) //ûÓÃÃèÒªÌáǰ¶Ã³öµÄÒ³
2328 {
2329 subs[subs_count]=sub;
2330 subs_count++;
2331 }
2332 }
2333
2334 p=sub;
2335 sub=sub->next_node;
2336 }
2337
2338 if (subs_count==0) /*ûÓÃÇëÇó¿ÉÒÔ·þÎñ£¬·µ»ØNULL*/
2339 {
2340 for(i=0;i<max_sub_num;i++)
2341 {
2342 subs[i]=NULL;
2343 }
2344 free(subs);
2345
2346 subs=NULL;
2347 free(plane_bits);
2348 return NULL;
2349 }
2350 if(subs_count>=2)
2351 {
2352 /*********************************************
2353 *two plane,interleave¶¼¿ÉÒÔʹÓÃ
2354 *ÔÚÕâ¸öchannelÉã¬Ñ¡ÓÃinterleave_two_planeÖ´ÃÃ
2355 **********************************************/
2356 if (((ssd->parameter->advanced_commands&AD_TWOPLANE)==AD_TWOPLANE)&&((ssd->parameter->advanced_commands&AD_INTERLEAVE)==AD_INTERLEAVE))
2357 {
2358 get_ppn_for_advanced_commands(ssd,channel,chip,subs,subs_count,INTERLEAVE_TWO_PLANE);
2359 }
2360 else if (((ssd->parameter->advanced_commands&AD_TWOPLANE)==AD_TWOPLANE)&&((ssd->parameter->advanced_commands&AD_INTERLEAVE)!=AD_INTERLEAVE))
2361 {
2362 if(subs_count>ssd->parameter->plane_die)
2363 {
2364 for(i=ssd->parameter->plane_die;i<subs_count;i++)
2365 {
2366 subs[i]=NULL;
2367 }
2368 subs_count=ssd->parameter->plane_die;
2369 }
2370 get_ppn_for_advanced_commands(ssd,channel,chip,subs,subs_count,TWO_PLANE);
2371 }
2372 else if (((ssd->parameter->advanced_commands&AD_TWOPLANE)!=AD_TWOPLANE)&&((ssd->parameter->advanced_commands&AD_INTERLEAVE)==AD_INTERLEAVE))
2373 {
2374
2375 if(subs_count>ssd->parameter->die_chip)
2376 {
2377 for(i=ssd->parameter->die_chip;i<subs_count;i++)
2378 {
2379 subs[i]=NULL;
2380 }
2381 subs_count=ssd->parameter->die_chip;
2382 }
2383 get_ppn_for_advanced_commands(ssd,channel,chip,subs,subs_count,INTERLEAVE);
2384 }
2385 else
2386 {
2387 for(i=1;i<subs_count;i++)
2388 {
2389 subs[i]=NULL;
2390 }
2391 subs_count=1;
2392 get_ppn_for_normal_command(ssd,channel,chip,subs[0]);
2393 }
2394
2395 }//if(subs_count>=2)
2396 else if(subs_count==1) //only one request
2397 {
2398 get_ppn_for_normal_command(ssd,channel,chip,subs[0]);
2399 }
2400
2401 }//if ((ssd->parameter->allocation_scheme==0))
2402 else /*¾²Ì¬·ÖÅ䷽ʽ£¬Ö»Ãè´ÓÕâ¸öÌØ¶¨µÄchannelÉÃѡȡµÈ´ý·þÎñµÄ×ÓÇëÇó*/
2403 {
2404 /*ÔÚ¾²Ì¬·ÖÅ䷽ʽÖ㬸ù¾ÃchannelÉõÄÇëÇóÂäÔÚìһ¸ödieÉõÄÄÇéplaneÀ´È·¶¨Ê¹ÓÃʲôÃüÃî*/
2405
2406 sub=ssd->channel_head[channel].subs_w_head;
2407 plane_bits=(unsigned int * )malloc((ssd->parameter->die_chip)*sizeof(unsigned int));
2408 alloc_assert(plane_bits,"plane_bits");
2409 memset(plane_bits,0, (ssd->parameter->die_chip)*sizeof(unsigned int));
2410
2411 for(i=0;i<ssd->parameter->die_chip;i++)
2412 {
2413 plane_bits[i]=0x00000000;
2414 }
2415 subs_count=0;
2416
2417 while ((sub!=NULL)&&(subs_count<max_sub_num))
2418 {
2419 if(sub->current_state==SR_WAIT)
2420 {
2421 if ((sub->update==NULL)||((sub->update!=NULL)&&((sub->update->current_state==SR_COMPLETE)||((sub->update->next_state==SR_COMPLETE)&&(sub->update->next_state_predict_time<=ssd->current_time)))))
2422 {
2423 if (sub->location->chip==chip)
2424 {
2425 plane_place=0x00000001<<(sub->location->plane);
2426
2427 if ((plane_bits[sub->location->die]&plane_place)!=plane_place) //we have not add sub request to this plane
2428 {
2429 subs[sub->location->die*ssd->parameter->plane_die+sub->location->plane]=sub;
2430 subs_count++;
2431 plane_bits[sub->location->die]=(plane_bits[sub->location->die]|plane_place);
2432 }
2433 }
2434 }
2435 }
2436 sub=sub->next_node;
2437 }//while ((sub!=NULL)&&(subs_count<max_sub_num))
2438
2439 if (subs_count==0) /*ûÓÃÇëÇó¿ÉÒÔ·þÎñ£¬·µ»ØNULL*/
2440 {
2441 for(i=0;i<max_sub_num;i++)
2442 {
2443 subs[i]=NULL;
2444 }
2445 free(subs);
2446 subs=NULL;
2447 free(plane_bits);
2448 return NULL;
2449 }
2450
2451 flag=0;
2452 if (ssd->parameter->advanced_commands!=0)
2453 {
2454 if ((ssd->parameter->advanced_commands&AD_COPYBACK)==AD_COPYBACK) /*È«²¿¸ß¼¶ÃüÃî¶¼¿ÉÒÔʹÓÃ*/
2455 {
2456 if (subs_count>1) /*ÓÃ1¸öÒÔÉÿÉÒÔÖ±½Ó·þÎñµÄôÇëÇó*/
2457 {
2458 get_ppn_for_advanced_commands(ssd,channel,chip,subs,subs_count,COPY_BACK);
2459 }
2460 else
2461 {
2462 for(i=0;i<max_sub_num;i++)
2463 {
2464 if(subs[i]!=NULL)
2465 {
2466 break;
2467 }
2468 }
2469 get_ppn_for_normal_command(ssd,channel,chip,subs[i]);
2470 }
2471
2472 }// if ((ssd->parameter->advanced_commands&AD_COPYBACK)==AD_COPYBACK)
2473 else /*²»ÄÜÖ´ÃÃcopyback*/
2474 {
2475 if (subs_count>1) /*ÓÃ1¸öÒÔÉÿÉÒÔÖ±½Ó·þÎñµÄôÇëÇó*/
2476 {
2477 if (((ssd->parameter->advanced_commands&AD_INTERLEAVE)==AD_INTERLEAVE)&&((ssd->parameter->advanced_commands&AD_TWOPLANE)==AD_TWOPLANE))
2478 {
2479 get_ppn_for_advanced_commands(ssd,channel,chip,subs,subs_count,INTERLEAVE_TWO_PLANE);
2480 }
2481 else if (((ssd->parameter->advanced_commands&AD_INTERLEAVE)==AD_INTERLEAVE)&&((ssd->parameter->advanced_commands&AD_TWOPLANE)!=AD_TWOPLANE))
2482 {
2483 for(die=0;die<ssd->parameter->die_chip;die++)
2484 {
2485 if(plane_bits[die]!=0x00000000)
2486 {
2487 for(i=0;i<ssd->parameter->plane_die;i++)
2488 {
2489 plane_token=ssd->channel_head[channel].chip_head[chip].die_head[die].token;
2490 ssd->channel_head[channel].chip_head[chip].die_head[die].token=(plane_token+1)%ssd->parameter->plane_die;
2491 mask=0x00000001<<plane_token;
2492 if((plane_bits[die]&mask)==mask)
2493 {
2494 plane_bits[die]=mask;
2495 break;
2496 }
2497 }
2498 for(i=i+1;i<ssd->parameter->plane_die;i++)
2499 {
2500 plane=(plane_token+1)%ssd->parameter->plane_die;
2501 subs[die*ssd->parameter->plane_die+plane]=NULL;
2502 subs_count--;
2503 }
2504 interleaver_count++;
2505 }//if(plane_bits[die]!=0x00000000)
2506 }//for(die=0;die<ssd->parameter->die_chip;die++)
2507 if(interleaver_count>=2)
2508 {
2509 get_ppn_for_advanced_commands(ssd,channel,chip,subs,subs_count,INTERLEAVE);
2510 }
2511 else
2512 {
2513 for(i=0;i<max_sub_num;i++)
2514 {
2515 if(subs[i]!=NULL)
2516 {
2517 break;
2518 }
2519 }
2520 get_ppn_for_normal_command(ssd,channel,chip,subs[i]);
2521 }
2522 }//else if (((ssd->parameter->advanced_commands&AD_INTERLEAVE)==AD_INTERLEAVE)&&((ssd->parameter->advanced_commands&AD_TWOPLANE)!=AD_TWOPLANE))
2523 else if (((ssd->parameter->advanced_commands&AD_INTERLEAVE)!=AD_INTERLEAVE)&&((ssd->parameter->advanced_commands&AD_TWOPLANE)==AD_TWOPLANE))
2524 {
2525 for(i=0;i<ssd->parameter->die_chip;i++)
2526 {
2527 die_token=ssd->channel_head[channel].chip_head[chip].token;
2528 ssd->channel_head[channel].chip_head[chip].token=(die_token+1)%ssd->parameter->die_chip;
2529 if(size(plane_bits[die_token])>1)
2530 {
2531 break;
2532 }
2533
2534 }
2535
2536 if(i<ssd->parameter->die_chip)
2537 {
2538 for(die=0;die<ssd->parameter->die_chip;die++)
2539 {
2540 if(die!=die_token)
2541 {
2542 for(plane=0;plane<ssd->parameter->plane_die;plane++)
2543 {
2544 if(subs[die*ssd->parameter->plane_die+plane]!=NULL)
2545 {
2546 subs[die*ssd->parameter->plane_die+plane]=NULL;
2547 subs_count--;
2548 }
2549 }
2550 }
2551 }
2552 get_ppn_for_advanced_commands(ssd,channel,chip,subs,subs_count,TWO_PLANE);
2553 }//if(i<ssd->parameter->die_chip)
2554 else
2555 {
2556 for(i=0;i<ssd->parameter->die_chip;i++)
2557 {
2558 die_token=ssd->channel_head[channel].chip_head[chip].token;
2559 ssd->channel_head[channel].chip_head[chip].token=(die_token+1)%ssd->parameter->die_chip;
2560 if(plane_bits[die_token]!=0x00000000)
2561 {
2562 for(j=0;j<ssd->parameter->plane_die;j++)
2563 {
2564 plane_token=ssd->channel_head[channel].chip_head[chip].die_head[die_token].token;
2565 ssd->channel_head[channel].chip_head[chip].die_head[die_token].token=(plane_token+1)%ssd->parameter->plane_die;
2566 if(((plane_bits[die_token])&(0x00000001<<plane_token))!=0x00000000)
2567 {
2568 sub=subs[die_token*ssd->parameter->plane_die+plane_token];
2569 break;
2570 }
2571 }
2572 }
2573 }//for(i=0;i<ssd->parameter->die_chip;i++)
2574 get_ppn_for_normal_command(ssd,channel,chip,sub);
2575 }//else
2576 }//else if (((ssd->parameter->advanced_commands&AD_INTERLEAVE)!=AD_INTERLEAVE)&&((ssd->parameter->advanced_commands&AD_TWOPLANE)==AD_TWOPLANE))
2577 }//if (subs_count>1)
2578 else
2579 {
2580 for(i=0;i<ssd->parameter->die_chip;i++)
2581 {
2582 die_token=ssd->channel_head[channel].chip_head[chip].token;
2583 ssd->channel_head[channel].chip_head[chip].token=(die_token+1)%ssd->parameter->die_chip;
2584 if(plane_bits[die_token]!=0x00000000)
2585 {
2586 for(j=0;j<ssd->parameter->plane_die;j++)
2587 {
2588 plane_token=ssd->channel_head[channel].chip_head[chip].die_head[die_token].token;
2589 ssd->channel_head[channel].chip_head[chip].die_head[die_token].token=(plane_token+1)%ssd->parameter->plane_die;
2590 if(((plane_bits[die_token])&(0x00000001<<plane_token))!=0x00000000)
2591 {
2592 sub=subs[die_token*ssd->parameter->plane_die+plane_token];
2593 break;
2594 }
2595 }
2596 if(sub!=NULL)
2597 {
2598 break;
2599 }
2600 }
2601 }//for(i=0;i<ssd->parameter->die_chip;i++)
2602 get_ppn_for_normal_command(ssd,channel,chip,sub);
2603 }//else
2604 }
2605 }//if (ssd->parameter->advanced_commands!=0)
2606 else
2607 {
2608 for(i=0;i<ssd->parameter->die_chip;i++)
2609 {
2610 die_token=ssd->channel_head[channel].chip_head[chip].token;
2611 ssd->channel_head[channel].chip_head[chip].token=(die_token+1)%ssd->parameter->die_chip;
2612 if(plane_bits[die_token]!=0x00000000)
2613 {
2614 for(j=0;j<ssd->parameter->plane_die;j++)
2615 {
2616 plane_token=ssd->channel_head[channel].chip_head[chip].die_head[die_token].token;
2617 ssd->channel_head[channel].chip_head[chip].die_head[die].token=(plane_token+1)%ssd->parameter->plane_die;
2618 if(((plane_bits[die_token])&(0x00000001<<plane_token))!=0x00000000)
2619 {
2620 sub=subs[die_token*ssd->parameter->plane_die+plane_token];
2621 break;
2622 }
2623 }
2624 if(sub!=NULL)
2625 {
2626 break;
2627 }
2628 }
2629 }//for(i=0;i<ssd->parameter->die_chip;i++)
2630 get_ppn_for_normal_command(ssd,channel,chip,sub);
2631 }//else
2632
2633 }//else
2634
2635 for(i=0;i<max_sub_num;i++)
2636 {
2637 subs[i]=NULL;
2638 }
2639 free(subs);
2640 subs=NULL;
2641 free(plane_bits);
2642 return ssd;
2643}
2644
2645/****************************************
2646*Ö´ÃÃô×ÓÇëÇóʱ£¬ÎªÆÕèµÄô×ÓÇëÇó»ñÈ¡ppn
2647*****************************************/
2648Status get_ppn_for_normal_command(struct ssd_info * ssd, unsigned int channel,unsigned int chip, struct sub_request * sub)
2649{
2650 unsigned int die=0;
2651 unsigned int plane=0;
2652 if(sub==NULL)
2653 {
2654 return ERROR;
2655 }
2656
2657 if (ssd->parameter->allocation_scheme==DYNAMIC_ALLOCATION)
2658 {
2659 die=ssd->channel_head[channel].chip_head[chip].token;
2660 plane=ssd->channel_head[channel].chip_head[chip].die_head[die].token;
2661 get_ppn(ssd,channel,chip,die,plane,sub);
2662 ssd->channel_head[channel].chip_head[chip].die_head[die].token=(plane+1)%ssd->parameter->plane_die;
2663 ssd->channel_head[channel].chip_head[chip].token=(die+1)%ssd->parameter->die_chip;
2664
2665 compute_serve_time(ssd,channel,chip,die,&sub,1,NORMAL);
2666 return SUCCESS;
2667 }
2668 else
2669 {
2670 die=sub->location->die;
2671 plane=sub->location->plane;
2672 get_ppn(ssd,channel,chip,die,plane,sub);
2673 compute_serve_time(ssd,channel,chip,die,&sub,1,NORMAL);
2674 return SUCCESS;
2675 }
2676
2677}
2678
2679
2680
2681/************************************************************************************************
2682*Get ppn for advanced commands
2683* According to different commands, follow the requirements of sequential writing in the same block, select the ppn that can be written, and the skipped ppn is all disabled.
2684* When using the two plane operation, in order to find pages in the same horizontal position, you may need to find two completely blank blocks directly.
2685* The block is not used up, can only be placed here, waiting for the next use, and at the same time modify the method of finding the blank page, will be the first to find the free block, only
2686*To invalid block!=64.
2687*except find aim page, we should modify token and decide gc operation
2688*************************************************************************************************/
2689Status get_ppn_for_advanced_commands(struct ssd_info *ssd,unsigned int channel,unsigned int chip,struct sub_request * * subs ,unsigned int subs_count,unsigned int command)
2690{
2691 unsigned int die=0,plane=0;
2692 unsigned int die_token=0,plane_token=0;
2693 struct sub_request * sub=NULL;
2694 unsigned int i=0,j=0,k=0;
2695 unsigned int unvalid_subs_count=0;
2696 unsigned int valid_subs_count=0;
2697 unsigned int interleave_flag=FALSE;
2698 unsigned int multi_plane_falg=FALSE;
2699 unsigned int max_subs_num=0;
2700 struct sub_request * first_sub_in_chip=NULL;
2701 struct sub_request * first_sub_in_die=NULL;
2702 struct sub_request * second_sub_in_die=NULL;
2703 unsigned int state=SUCCESS;
2704 unsigned int multi_plane_flag=FALSE;
2705
2706 max_subs_num=ssd->parameter->die_chip*ssd->parameter->plane_die;
2707
2708 if (ssd->parameter->allocation_scheme==DYNAMIC_ALLOCATION) /*¶¯Ì¬·ÖÅä²Ù×÷*/
2709 {
2710 if((command==INTERLEAVE_TWO_PLANE)||(command==COPY_BACK)) /*INTERLEAVE_TWO_PLANEÒÔ¼°COPY_BACKµÄÇé¿ö*/
2711 {
2712 for(i=0;i<subs_count;i++)
2713 {
2714 die=ssd->channel_head[channel].chip_head[chip].token;
2715 if(i<ssd->parameter->die_chip) /*Ϊÿ¸ösubs[i]»ñÈ¡ppn£¬iáÓÚdie_chip*/
2716 {
2717 plane=ssd->channel_head[channel].chip_head[chip].die_head[die].token;
2718 get_ppn(ssd,channel,chip,die,plane,subs[i]);
2719 ssd->channel_head[channel].chip_head[chip].die_head[die].token=(plane+1)%ssd->parameter->plane_die;
2720 }
2721 else
2722 {
2723 /*********************************************************************************************************************************
2724 * Subs[i] and subs[i%ssd->parameter->die_chip] pointed to by i of die_chip get the same position ppn
2725* If successful, let multi_plane_flag = TRUE and execute compute_serve_time(ssd, channel, chip, 0, subs, valid_subs_count, INTERLEAVE_TWO_PLANE);
2726* Otherwise execute compute_serve_time(ssd, channel, chip, 0, subs, valid_subs_count, INTERLEAVE);
2727 ***********************************************************************************************************************************/
2728 state=make_level_page(ssd,subs[i%ssd->parameter->die_chip],subs[i]);
2729 if(state!=SUCCESS)
2730 {
2731 subs[i]=NULL;
2732 unvalid_subs_count++;
2733 }
2734 else
2735 {
2736 multi_plane_flag=TRUE;
2737 }
2738 }
2739 ssd->channel_head[channel].chip_head[chip].token=(die+1)%ssd->parameter->die_chip;
2740 }
2741 valid_subs_count=subs_count-unvalid_subs_count;
2742 ssd->interleave_count++;
2743 if(multi_plane_flag==TRUE)
2744 {
2745 ssd->inter_mplane_count++;
2746 compute_serve_time(ssd,channel,chip,0,subs,valid_subs_count,INTERLEAVE_TWO_PLANE);/*¼ÆËãô×ÓÇëÇóµÄ´¦ÀÃʱ¼ä£¬ÒÔô×ÓÇëÇóµÄ״̬ת±ä*/
2747 }
2748 else
2749 {
2750 compute_serve_time(ssd,channel,chip,0,subs,valid_subs_count,INTERLEAVE);
2751 }
2752 return SUCCESS;
2753 }//if((command==INTERLEAVE_TWO_PLANE)||(command==COPY_BACK))
2754 else if(command==INTERLEAVE)
2755 {
2756 /***********************************************************************************************
2757 *INTERLEAVE¸ß¼¶ÃüÃîµÄ´¦Àã¬Õâ¸ö´¦ÀñÈTWO_PLANE¸ß¼¶ÃüÃîµÄ´¦Àüòµ¥
2758 *ÒòΪtwo_planeµÄÒªÇóÊÇìһ¸ödieÀïÃæ²»Ã¬planeµÄìһλÖõÄpage£¬¶øinterleaveÒªÇóÔòÊDz»Ã¬dieÀïÃæµÄ¡£
2759 ************************************************************************************************/
2760 for(i=0;(i<subs_count)&&(i<ssd->parameter->die_chip);i++)
2761 {
2762 die=ssd->channel_head[channel].chip_head[chip].token;
2763 plane=ssd->channel_head[channel].chip_head[chip].die_head[die].token;
2764 get_ppn(ssd,channel,chip,die,plane,subs[i]);
2765 ssd->channel_head[channel].chip_head[chip].die_head[die].token=(plane+1)%ssd->parameter->plane_die;
2766 ssd->channel_head[channel].chip_head[chip].token=(die+1)%ssd->parameter->die_chip;
2767 valid_subs_count++;
2768 }
2769 ssd->interleave_count++;
2770 compute_serve_time(ssd,channel,chip,0,subs,valid_subs_count,INTERLEAVE);
2771 return SUCCESS;
2772 }//else if(command==INTERLEAVE)
2773 else if(command==TWO_PLANE)
2774 {
2775 if(subs_count<2)
2776 {
2777 return ERROR;
2778 }
2779 die=ssd->channel_head[channel].chip_head[chip].token;
2780 for(j=0;j<subs_count;j++)
2781 {
2782 if(j==1)
2783 {
2784 state=find_level_page(ssd,channel,chip,die,subs[0],subs[1]); /*ѰÕÒÓësubs[0]µÄppnλÖÃÃà ìµÄsubs[1]£¬Ö´ÃÃTWO_PLANE¸ß¼¶ÃüÃî*/
2785 if(state!=SUCCESS)
2786 {
2787 get_ppn_for_normal_command(ssd,channel,chip,subs[0]); /*ûÕÒµ½£¬ÄÇô¾Ãµ±ÆÕèÃüÃîÀ´´¦ÀÃ*/
2788 return FAILURE;
2789 }
2790 else
2791 {
2792 valid_subs_count=2;
2793 }
2794 }
2795 else if(j>1)
2796 {
2797 state=make_level_page(ssd,subs[0],subs[j]); /*ѰÕÒÓësubs[0]µÄppnλÖÃÃà ìµÄsubs[j]£¬Ö´ÃÃTWO_PLANE¸ß¼¶ÃüÃî*/
2798 if(state!=SUCCESS)
2799 {
2800 for(k=j;k<subs_count;k++)
2801 {
2802 subs[k]=NULL;
2803 }
2804 subs_count=j;
2805 break;
2806 }
2807 else
2808 {
2809 valid_subs_count++;
2810 }
2811 }
2812 }//for(j=0;j<subs_count;j++)
2813 ssd->channel_head[channel].chip_head[chip].token=(die+1)%ssd->parameter->die_chip;
2814 ssd->m_plane_prog_count++;
2815 compute_serve_time(ssd,channel,chip,die,subs,valid_subs_count,TWO_PLANE);
2816 return SUCCESS;
2817 }//else if(command==TWO_PLANE)
2818 else
2819 {
2820 return ERROR;
2821 }
2822 }//if (ssd->parameter->allocation_scheme==DYNAMIC_ALLOCATION)
2823 else /*¾²Ì¬·ÖÅäµÄÇé¿ö*/
2824 {
2825 if((command==INTERLEAVE_TWO_PLANE)||(command==COPY_BACK))
2826 {
2827 for(die=0;die<ssd->parameter->die_chip;die++)
2828 {
2829 first_sub_in_die=NULL;
2830 for(plane=0;plane<ssd->parameter->plane_die;plane++)
2831 {
2832 sub=subs[die*ssd->parameter->plane_die+plane];
2833 if(sub!=NULL)
2834 {
2835 if(first_sub_in_die==NULL)
2836 {
2837 first_sub_in_die=sub;
2838 get_ppn(ssd,channel,chip,die,plane,sub);
2839 }
2840 else
2841 {
2842 state=make_level_page(ssd,first_sub_in_die,sub);
2843 if(state!=SUCCESS)
2844 {
2845 subs[die*ssd->parameter->plane_die+plane]=NULL;
2846 subs_count--;
2847 sub=NULL;
2848 }
2849 else
2850 {
2851 multi_plane_flag=TRUE;
2852 }
2853 }
2854 }
2855 }
2856 }
2857 if(multi_plane_flag==TRUE)
2858 {
2859 ssd->inter_mplane_count++;
2860 compute_serve_time(ssd,channel,chip,0,subs,valid_subs_count,INTERLEAVE_TWO_PLANE);
2861 return SUCCESS;
2862 }
2863 else
2864 {
2865 compute_serve_time(ssd,channel,chip,0,subs,valid_subs_count,INTERLEAVE);
2866 return SUCCESS;
2867 }
2868 }//if((command==INTERLEAVE_TWO_PLANE)||(command==COPY_BACK))
2869 else if(command==INTERLEAVE)
2870 {
2871 for(die=0;die<ssd->parameter->die_chip;die++)
2872 {
2873 first_sub_in_die=NULL;
2874 for(plane=0;plane<ssd->parameter->plane_die;plane++)
2875 {
2876 sub=subs[die*ssd->parameter->plane_die+plane];
2877 if(sub!=NULL)
2878 {
2879 if(first_sub_in_die==NULL)
2880 {
2881 first_sub_in_die=sub;
2882 get_ppn(ssd,channel,chip,die,plane,sub);
2883 valid_subs_count++;
2884 }
2885 else
2886 {
2887 subs[die*ssd->parameter->plane_die+plane]=NULL;
2888 subs_count--;
2889 sub=NULL;
2890 }
2891 }
2892 }
2893 }
2894 if(valid_subs_count>1)
2895 {
2896 ssd->interleave_count++;
2897 }
2898 compute_serve_time(ssd,channel,chip,0,subs,valid_subs_count,INTERLEAVE);
2899 }//else if(command==INTERLEAVE)
2900 else if(command==TWO_PLANE)
2901 {
2902 for(die=0;die<ssd->parameter->die_chip;die++)
2903 {
2904 first_sub_in_die=NULL;
2905 second_sub_in_die=NULL;
2906 for(plane=0;plane<ssd->parameter->plane_die;plane++)
2907 {
2908 sub=subs[die*ssd->parameter->plane_die+plane];
2909 if(sub!=NULL)
2910 {
2911 if(first_sub_in_die==NULL)
2912 {
2913 first_sub_in_die=sub;
2914 }
2915 else if(second_sub_in_die==NULL)
2916 {
2917 second_sub_in_die=sub;
2918 state=find_level_page(ssd,channel,chip,die,first_sub_in_die,second_sub_in_die);
2919 if(state!=SUCCESS)
2920 {
2921 subs[die*ssd->parameter->plane_die+plane]=NULL;
2922 subs_count--;
2923 second_sub_in_die=NULL;
2924 sub=NULL;
2925 }
2926 else
2927 {
2928 valid_subs_count=2;
2929 }
2930 }
2931 else
2932 {
2933 state=make_level_page(ssd,first_sub_in_die,sub);
2934 if(state!=SUCCESS)
2935 {
2936 subs[die*ssd->parameter->plane_die+plane]=NULL;
2937 subs_count--;
2938 sub=NULL;
2939 }
2940 else
2941 {
2942 valid_subs_count++;
2943 }
2944 }
2945 }//if(sub!=NULL)
2946 }//for(plane=0;plane<ssd->parameter->plane_die;plane++)
2947 if(second_sub_in_die!=NULL)
2948 {
2949 multi_plane_flag=TRUE;
2950 break;
2951 }
2952 }//for(die=0;die<ssd->parameter->die_chip;die++)
2953 if(multi_plane_flag==TRUE)
2954 {
2955 ssd->m_plane_prog_count++;
2956 compute_serve_time(ssd,channel,chip,die,subs,valid_subs_count,TWO_PLANE);
2957 return SUCCESS;
2958 }//if(multi_plane_flag==TRUE)
2959 else
2960 {
2961 i=0;
2962 sub=NULL;
2963 while((sub==NULL)&&(i<max_subs_num))
2964 {
2965 sub=subs[i];
2966 i++;
2967 }
2968 if(sub!=NULL)
2969 {
2970 get_ppn_for_normal_command(ssd,channel,chip,sub);
2971 return FAILURE;
2972 }
2973 else
2974 {
2975 return ERROR;
2976 }
2977 }//else
2978 }//else if(command==TWO_PLANE)
2979 else
2980 {
2981 return ERROR;
2982 }
2983 }//elseb ¾²Ì¬·ÖÅäµÄÇé¿ö
2984}
2985
2986
2987/***********************************************
2988*º¯ÊýµÄ×÷ÓÃÊÇÈÃsub0£¬sub1µÄppnËùÔÚµÄpageλÖÃÃà ì
2989************************************************/
2990Status make_level_page(struct ssd_info * ssd, struct sub_request * sub0,struct sub_request * sub1)
2991{
2992 unsigned int i=0,j=0,k=0;
2993 unsigned int channel=0,chip=0,die=0,plane0=0,plane1=0,block0=0,block1=0,page0=0,page1=0;
2994 unsigned int active_block0=0,active_block1=0;
2995 unsigned int old_plane_token=0;
2996
2997 if((sub0==NULL)||(sub1==NULL)||(sub0->location==NULL))
2998 {
2999 return ERROR;
3000 }
3001 channel=sub0->location->channel;
3002 chip=sub0->location->chip;
3003 die=sub0->location->die;
3004 plane0=sub0->location->plane;
3005 block0=sub0->location->block;
3006 page0=sub0->location->page;
3007 old_plane_token=ssd->channel_head[channel].chip_head[chip].die_head[die].token;
3008
3009 /***********************************************************************************************
3010 *¶¯Ì¬·ÖÅäµÄÇé¿öÃÂ
3011 *sub1µÄplaneÊǸù¾Ãsub0µÄssd->channel_head[channel].chip_head[chip].die_head[die].tokenÃîÅÆ»ñÈ¡µÄ
3012 *sub1µÄchannel£¬chip£¬die£¬block£¬page¶¼ºÃsub0µÄÃà ì
3013 ************************************************************************************************/
3014 if(ssd->parameter->allocation_scheme==DYNAMIC_ALLOCATION)
3015 {
3016 old_plane_token=ssd->channel_head[channel].chip_head[chip].die_head[die].token;
3017 for(i=0;i<ssd->parameter->plane_die;i++)
3018 {
3019 plane1=ssd->channel_head[channel].chip_head[chip].die_head[die].token;
3020 if(ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane1].add_reg_ppn==-1)
3021 {
3022 find_active_block(ssd,channel,chip,die,plane1); /*ÔÚplane1ÖÃÕÒµ½»îÔ¾¿é*/
3023 block1=ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane1].active_block;
3024
3025 /*********************************************************************************************
3026 *Ö»ÓÃÕÒµ½µÄblock1Óëblock0Ãà 죬²ÅÄܼÌÃøÃùÃÂѰÕÒÃà ìµÄpage
3027 *ÔÚѰÕÒpageʱ±È½Ã¼òµ¥£¬Ö±½ÓÓÃlast_write_page£¨ÉÃÒ»´ÎôµÄpage£©+1¾Ã¿ÉÒÔÃË¡£
3028 *Èç¹ûÕÒµ½µÄpage²»Ãà 죬ÄÇôÈç¹ûssdÔÊÃÃ̰À·µÄʹÓø߼¶ÃüÃÕâÑù¾Ã¿ÉÒÔÈÃáµÄpage Ãù´óµÄpage¿¿Â£
3029 *********************************************************************************************/
3030 if(block1==block0)
3031 {
3032 page1=ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane1].blk_head[block1].last_write_page+1;
3033 if(page1==page0)
3034 {
3035 break;
3036 }
3037 else if(page1<page0)
3038 {
3039 if (ssd->parameter->greed_MPW_ad==1) /*ÔÊÃÃ̰À·µÄʹÓø߼¶ÃüÃî*/
3040 {
3041 //make_same_level(ssd,channel,chip,die,plane1,active_block1,page0); /*áµÄpageµØÖ·Ãù´óµÄpageµØÖ·¿¿*/
3042 make_same_level(ssd,channel,chip,die,plane1,block1,page0);
3043 break;
3044 }
3045 }
3046 }//if(block1==block0)
3047 }
3048 ssd->channel_head[channel].chip_head[chip].die_head[die].token=(plane1+1)%ssd->parameter->plane_die;
3049 }//for(i=0;i<ssd->parameter->plane_die;i++)
3050 if(i<ssd->parameter->plane_die)
3051 {
3052 flash_page_state_modify(ssd,sub1,channel,chip,die,plane1,block1,page0); /*Õâ¸öº¯ÊýµÄ×÷ÓþÃÊǸüÃÂpage1Ëù¶ÔÓ¦µÄÎïÀÃÒ³ÒÔ¼°location»¹ÓÃmap±Ã*/
3053 //flash_page_state_modify(ssd,sub1,channel,chip,die,plane1,block1,page1);
3054 ssd->channel_head[channel].chip_head[chip].die_head[die].token=(plane1+1)%ssd->parameter->plane_die;
3055 return SUCCESS;
3056 }
3057 else
3058 {
3059 ssd->channel_head[channel].chip_head[chip].die_head[die].token=old_plane_token;
3060 return FAILURE;
3061 }
3062 }
3063 else /*¾²Ì¬·ÖÅäµÄÇé¿ö*/
3064 {
3065 if((sub1->location==NULL)||(sub1->location->channel!=channel)||(sub1->location->chip!=chip)||(sub1->location->die!=die))
3066 {
3067 return ERROR;
3068 }
3069 plane1=sub1->location->plane;
3070 if(ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane1].add_reg_ppn==-1)
3071 {
3072 find_active_block(ssd,channel,chip,die,plane1);
3073 block1=ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane1].active_block;
3074 if(block1==block0)
3075 {
3076 page1=ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane1].blk_head[block1].last_write_page+1;
3077 if(page1>page0)
3078 {
3079 return FAILURE;
3080 }
3081 else if(page1<page0)
3082 {
3083 if (ssd->parameter->greed_MPW_ad==1)
3084 {
3085 //make_same_level(ssd,channel,chip,die,plane1,active_block1,page0); /*áµÄpageµØÖ·Ãù´óµÄpageµØÖ·¿¿*/
3086 make_same_level(ssd,channel,chip,die,plane1,block1,page0);
3087 flash_page_state_modify(ssd,sub1,channel,chip,die,plane1,block1,page0);
3088 //flash_page_state_modify(ssd,sub1,channel,chip,die,plane1,block1,page1);
3089 return SUCCESS;
3090 }
3091 else
3092 {
3093 return FAILURE;
3094 }
3095 }
3096 else
3097 {
3098 flash_page_state_modify(ssd,sub1,channel,chip,die,plane1,block1,page0);
3099 //flash_page_state_modify(ssd,sub1,channel,chip,die,plane1,block1,page1);
3100 return SUCCESS;
3101 }
3102
3103 }
3104 else
3105 {
3106 return FAILURE;
3107 }
3108
3109 }
3110 else
3111 {
3112 return ERROR;
3113 }
3114 }
3115
3116}
3117
3118/******************************************************************************************************
3119*º¯ÊýµÄ¹¦ÄÜÊÇΪtwo planeÃüÃîѰÕÒ³öý¸öÃà ìˮƽλÖõÄÒ³£¬²¢ÇÒÃÞ¸Äó¼ÆÖµ£¬ÃÞ¸ÄÒ³µÄ״̬
3120*×¢ÒâÕâ¸öº¯ÊýÓëÉÃÒ»¸öº¯Êýmake_level_pageº¯ÊýµÄÇø±ð£¬make_level_pageÕâ¸öº¯ÊýÊÇÈÃsub1Óësub0µÄpageλÖÃÃà ì
3121*¶øfind_level_pageº¯ÊýµÄ×÷ÓÃÊÇÔÚ¸ø¶¨µÄchannel£¬chip£¬dieÖÃÕÒý¸öλÖÃÃà ìµÄsubAºÃsubB¡£
3122*******************************************************************************************************/
3123Status find_level_page(struct ssd_info *ssd,unsigned int channel,unsigned int chip,unsigned int die,struct sub_request *subA,struct sub_request *subB)
3124{
3125 unsigned int i,planeA,planeB,active_blockA,active_blockB,pageA,pageB,aim_page,old_plane;
3126 struct gc_operation *gc_node;
3127
3128 old_plane=ssd->channel_head[channel].chip_head[chip].die_head[die].token;
3129
3130 /************************************************************
3131 *ÔÚ¶¯Ì¬·ÖÅäµÄÇé¿öÃÂ
3132 *planeA¸³³õֵΪdieµÄÃîÅÆ£¬Èç¹ûplaneAÊÇżÊýÄÇôplaneB=planeA+1
3133 *planeAÊÇÆæÊý£¬ÄÇôplaneA+1±äΪżÊý£¬ÔÙÃîplaneB=planeA+1
3134 *************************************************************/
3135 if (ssd->parameter->allocation_scheme==0)
3136 {
3137 planeA=ssd->channel_head[channel].chip_head[chip].die_head[die].token;
3138 if (planeA%2==0)
3139 {
3140 planeB=planeA+1;
3141 ssd->channel_head[channel].chip_head[chip].die_head[die].token=(ssd->channel_head[channel].chip_head[chip].die_head[die].token+2)%ssd->parameter->plane_die;
3142 }
3143 else
3144 {
3145 planeA=(planeA+1)%ssd->parameter->plane_die;
3146 planeB=planeA+1;
3147 ssd->channel_head[channel].chip_head[chip].die_head[die].token=(ssd->channel_head[channel].chip_head[chip].die_head[die].token+3)%ssd->parameter->plane_die;
3148 }
3149 }
3150 else /*¾²Ì¬·ÖÅäµÄÇé¿ö£¬¾ÃÖ±½Ó¸³Öµ¸øplaneAºÃplaneB*/
3151 {
3152 planeA=subA->location->plane;
3153 planeB=subB->location->plane;
3154 }
3155 find_active_block(ssd,channel,chip,die,planeA); /*ѰÕÒactive_block*/
3156 find_active_block(ssd,channel,chip,die,planeB);
3157 active_blockA=ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[planeA].active_block;
3158 active_blockB=ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[planeB].active_block;
3159
3160
3161
3162 /*****************************************************
3163 *Èç¹ûactive_blockÃà 죬ÄÇô¾ÃÔÚÕâý¸ö¿éÖÃÕÒÃà ìµÄpage
3164 *»òÕßʹÓÃ̰À·µÄ·½·¨ÕÒµ½Ã½¸öÃà ìµÄpage
3165 ******************************************************/
3166 if (active_blockA==active_blockB)
3167 {
3168 pageA=ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[planeA].blk_head[active_blockA].last_write_page+1;
3169 pageB=ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[planeB].blk_head[active_blockB].last_write_page+1;
3170 if (pageA==pageB) /*ý¸ö¿ÉÓõÄÒ³ÕýºÃÔÚìһ¸öˮƽλÖÃÉÃ*/
3171 {
3172 flash_page_state_modify(ssd,subA,channel,chip,die,planeA,active_blockA,pageA);
3173 flash_page_state_modify(ssd,subB,channel,chip,die,planeB,active_blockB,pageB);
3174 }
3175 else
3176 {
3177 if (ssd->parameter->greed_MPW_ad==1) /*̰À·µØÊ¹Óø߼¶ÃüÃî*/
3178 {
3179 if (pageA<pageB)
3180 {
3181 aim_page=pageB;
3182 make_same_level(ssd,channel,chip,die,planeA,active_blockA,aim_page); /*áµÄpageµØÖ·Ãù´óµÄpageµØÖ·¿¿*/
3183 }
3184 else
3185 {
3186 aim_page=pageA;
3187 make_same_level(ssd,channel,chip,die,planeB,active_blockB,aim_page);
3188 }
3189 flash_page_state_modify(ssd,subA,channel,chip,die,planeA,active_blockA,aim_page);
3190 flash_page_state_modify(ssd,subB,channel,chip,die,planeB,active_blockB,aim_page);
3191 }
3192 else /*²»ÄṴ̈À·µÄʹÓø߼¶ÃüÃî*/
3193 {
3194 subA=NULL;
3195 subB=NULL;
3196 ssd->channel_head[channel].chip_head[chip].die_head[die].token=old_plane;
3197 return FAILURE;
3198 }
3199 }
3200 }
3201 /*********************************
3202 *Èç¹ûÕÒµ½µÄý¸öactive_block²»Ãà ì
3203 **********************************/
3204 else
3205 {
3206 pageA=ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[planeA].blk_head[active_blockA].last_write_page+1;
3207 pageB=ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[planeB].blk_head[active_blockB].last_write_page+1;
3208 if (pageA<pageB)
3209 {
3210 if (ssd->parameter->greed_MPW_ad==1) /*̰À·µØÊ¹Óø߼¶ÃüÃî*/
3211 {
3212 /*******************************************************************************
3213 *ÔÚplaneAÖã¬Óëactive_blockBÃà ìλÖõĵÄblockÖã¬ÓëpageBÃà ìλÖõÄpageÊÇ¿ÉÓõġ£
3214 *Ò²¾ÃÊÇpalneAÖõÄÃà ӦˮƽλÖÃÊÇ¿ÉÓõ쬽«Æä×îΪÓëplaneBÖöÔÓ¦µÄÒ³¡£
3215 *ÄÇô¿ÉÒ²ÈÃplaneA£¬active_blockBÖõÄpageÃùpageB¿¿Â£
3216 ********************************************************************************/
3217 if (ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[planeA].blk_head[active_blockB].page_head[pageB].free_state==PG_SUB)
3218 {
3219 make_same_level(ssd,channel,chip,die,planeA,active_blockB,pageB);
3220 flash_page_state_modify(ssd,subA,channel,chip,die,planeA,active_blockB,pageB);
3221 flash_page_state_modify(ssd,subB,channel,chip,die,planeB,active_blockB,pageB);
3222 }
3223 /********************************************************************************
3224 *ÔÚplaneAÖã¬Óëactive_blockBÃà ìλÖõĵÄblockÖã¬ÓëpageBÃà ìλÖõÄpageÊÇ¿ÉÓõġ£
3225 *ÄÇô¾ÃÒªÖØÃÂѰÕÒblock£¬ÃèÒªÖØÃÂÕÒˮƽλÖÃÃà ìµÄÒ»¶ÔÒ³
3226 *********************************************************************************/
3227 else
3228 {
3229 for (i=0;i<ssd->parameter->block_plane;i++)
3230 {
3231 pageA=ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[planeA].blk_head[i].last_write_page+1;
3232 pageB=ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[planeB].blk_head[i].last_write_page+1;
3233 if ((pageA<ssd->parameter->page_block)&&(pageB<ssd->parameter->page_block))
3234 {
3235 if (pageA<pageB)
3236 {
3237 if (ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[planeA].blk_head[i].page_head[pageB].free_state==PG_SUB)
3238 {
3239 aim_page=pageB;
3240 make_same_level(ssd,channel,chip,die,planeA,i,aim_page);
3241 break;
3242 }
3243 }
3244 else
3245 {
3246 if (ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[planeB].blk_head[i].page_head[pageA].free_state==PG_SUB)
3247 {
3248 aim_page=pageA;
3249 make_same_level(ssd,channel,chip,die,planeB,i,aim_page);
3250 break;
3251 }
3252 }
3253 }
3254 }//for (i=0;i<ssd->parameter->block_plane;i++)
3255 if (i<ssd->parameter->block_plane)
3256 {
3257 flash_page_state_modify(ssd,subA,channel,chip,die,planeA,i,aim_page);
3258 flash_page_state_modify(ssd,subB,channel,chip,die,planeB,i,aim_page);
3259 }
3260 else
3261 {
3262 subA=NULL;
3263 subB=NULL;
3264 ssd->channel_head[channel].chip_head[chip].die_head[die].token=old_plane;
3265 return FAILURE;
3266 }
3267 }
3268 }//if (ssd->parameter->greed_MPW_ad==1)
3269 else
3270 {
3271 subA=NULL;
3272 subB=NULL;
3273 ssd->channel_head[channel].chip_head[chip].die_head[die].token=old_plane;
3274 return FAILURE;
3275 }
3276 }//if (pageA<pageB)
3277 else
3278 {
3279 if (ssd->parameter->greed_MPW_ad==1)
3280 {
3281 if (ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[planeB].blk_head[active_blockA].page_head[pageA].free_state==PG_SUB)
3282 {
3283 make_same_level(ssd,channel,chip,die,planeB,active_blockA,pageA);
3284 flash_page_state_modify(ssd,subA,channel,chip,die,planeA,active_blockA,pageA);
3285 flash_page_state_modify(ssd,subB,channel,chip,die,planeB,active_blockA,pageA);
3286 }
3287 else
3288 {
3289 for (i=0;i<ssd->parameter->block_plane;i++)
3290 {
3291 pageA=ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[planeA].blk_head[i].last_write_page+1;
3292 pageB=ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[planeB].blk_head[i].last_write_page+1;
3293 if ((pageA<ssd->parameter->page_block)&&(pageB<ssd->parameter->page_block))
3294 {
3295 if (pageA<pageB)
3296 {
3297 if (ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[planeA].blk_head[i].page_head[pageB].free_state==PG_SUB)
3298 {
3299 aim_page=pageB;
3300 make_same_level(ssd,channel,chip,die,planeA,i,aim_page);
3301 break;
3302 }
3303 }
3304 else
3305 {
3306 if (ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[planeB].blk_head[i].page_head[pageA].free_state==PG_SUB)
3307 {
3308 aim_page=pageA;
3309 make_same_level(ssd,channel,chip,die,planeB,i,aim_page);
3310 break;
3311 }
3312 }
3313 }
3314 }//for (i=0;i<ssd->parameter->block_plane;i++)
3315 if (i<ssd->parameter->block_plane)
3316 {
3317 flash_page_state_modify(ssd,subA,channel,chip,die,planeA,i,aim_page);
3318 flash_page_state_modify(ssd,subB,channel,chip,die,planeB,i,aim_page);
3319 }
3320 else
3321 {
3322 subA=NULL;
3323 subB=NULL;
3324 ssd->channel_head[channel].chip_head[chip].die_head[die].token=old_plane;
3325 return FAILURE;
3326 }
3327 }
3328 } //if (ssd->parameter->greed_MPW_ad==1)
3329 else
3330 {
3331 if ((pageA==pageB)&&(pageA==0))
3332 {
3333 /*******************************************************************************************
3334 *ÃÂÃæÊÇýÖÖÇé¿ö
3335 *1£¬planeA£¬planeBÖõÄactive_blockA£¬pageAλÖö¼¿ÉÓã¬ÄÇô²»Ã¬plane µÄÃà ìλÖã¬ÒÔblockAΪ׼
3336 *2£¬planeA£¬planeBÖõÄactive_blockB£¬pageAλÖö¼¿ÉÓã¬ÄÇô²»Ã¬plane µÄÃà ìλÖã¬ÒÔblockBΪ׼
3337 ********************************************************************************************/
3338 if ((ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[planeA].blk_head[active_blockA].page_head[pageA].free_state==PG_SUB)
3339 &&(ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[planeB].blk_head[active_blockA].page_head[pageA].free_state==PG_SUB))
3340 {
3341 flash_page_state_modify(ssd,subA,channel,chip,die,planeA,active_blockA,pageA);
3342 flash_page_state_modify(ssd,subB,channel,chip,die,planeB,active_blockA,pageA);
3343 }
3344 else if ((ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[planeA].blk_head[active_blockB].page_head[pageA].free_state==PG_SUB)
3345 &&(ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[planeB].blk_head[active_blockB].page_head[pageA].free_state==PG_SUB))
3346 {
3347 flash_page_state_modify(ssd,subA,channel,chip,die,planeA,active_blockB,pageA);
3348 flash_page_state_modify(ssd,subB,channel,chip,die,planeB,active_blockB,pageA);
3349 }
3350 else
3351 {
3352 subA=NULL;
3353 subB=NULL;
3354 ssd->channel_head[channel].chip_head[chip].die_head[die].token=old_plane;
3355 return FAILURE;
3356 }
3357 }
3358 else
3359 {
3360 subA=NULL;
3361 subB=NULL;
3362 ssd->channel_head[channel].chip_head[chip].die_head[die].token=old_plane;
3363 return ERROR;
3364 }
3365 }
3366 }
3367 }
3368
3369 if (ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[planeA].free_page<(ssd->parameter->page_block*ssd->parameter->block_plane*ssd->parameter->gc_hard_threshold))
3370 {
3371 gc_node=(struct gc_operation *)malloc(sizeof(struct gc_operation));
3372 alloc_assert(gc_node,"gc_node");
3373 memset(gc_node,0, sizeof(struct gc_operation));
3374
3375 gc_node->next_node=NULL;
3376 gc_node->chip=chip;
3377 gc_node->die=die;
3378 gc_node->plane=planeA;
3379 gc_node->block=0xffffffff;
3380 gc_node->page=0;
3381 gc_node->state=GC_WAIT;
3382 gc_node->priority=GC_UNINTERRUPT;
3383 gc_node->next_node=ssd->channel_head[channel].gc_command;
3384 ssd->channel_head[channel].gc_command=gc_node;
3385 ssd->gc_request++;
3386 }
3387 if (ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[planeB].free_page<(ssd->parameter->page_block*ssd->parameter->block_plane*ssd->parameter->gc_hard_threshold))
3388 {
3389 gc_node=(struct gc_operation *)malloc(sizeof(struct gc_operation));
3390 alloc_assert(gc_node,"gc_node");
3391 memset(gc_node,0, sizeof(struct gc_operation));
3392
3393 gc_node->next_node=NULL;
3394 gc_node->chip=chip;
3395 gc_node->die=die;
3396 gc_node->plane=planeB;
3397 gc_node->block=0xffffffff;
3398 gc_node->page=0;
3399 gc_node->state=GC_WAIT;
3400 gc_node->priority=GC_UNINTERRUPT;
3401 gc_node->next_node=ssd->channel_head[channel].gc_command;
3402 ssd->channel_head[channel].gc_command=gc_node;
3403 ssd->gc_request++;
3404 }
3405
3406 return SUCCESS;
3407}
3408
3409/*
3410*º¯ÊýµÄ¹¦ÄÜÊÇÃÞ¸ÄÕÒµ½µÄpageÒ³µÄ״̬ÒÔ¼°Ãà Ó¦µÄdramÖÃÓ³Éä±ÃµÄÖµ
3411*/
3412struct ssd_info *flash_page_state_modify(struct ssd_info *ssd,struct sub_request *sub,unsigned int channel,unsigned int chip,unsigned int die,unsigned int plane,unsigned int block,unsigned int page)
3413{
3414 unsigned int ppn,full_page;
3415 struct local *location;
3416 struct direct_erase *new_direct_erase,*direct_erase_node;
3417
3418 full_page=~(0xffffffff<<ssd->parameter->subpage_page);
3419 ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[block].last_write_page=page;
3420 ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[block].free_page_num--;
3421
3422 if(ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[block].last_write_page>63)
3423 {
3424 printf("error! the last write page larger than 64!!\n");
3425 while(1){}
3426 }
3427
3428 if(ssd->dram->map->map_entry[sub->lpn].state==0) /*this is the first logical page*/
3429 {
3430 ssd->dram->map->map_entry[sub->lpn].pn=find_ppn(ssd,channel,chip,die,plane,block,page);
3431 ssd->dram->map->map_entry[sub->lpn].state=sub->state;
3432 }
3433 else /*Õâ¸öÂß¼ÂÒ³½øÃÃÃ˸üã¬ÃèÒª½«ÔÂÀ´µÄÒ³ÖÃΪʧç*/
3434 {
3435 ppn=ssd->dram->map->map_entry[sub->lpn].pn;
3436 location=find_location(ssd,ppn);
3437 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; //±Ãʾijһҳʧ磬ìʱ±ê¼ÇvalidºÃfree״̬¶¼Îª0
3438 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; //±Ãʾijһҳʧ磬ìʱ±ê¼ÇvalidºÃfree״̬¶¼Îª0
3439 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;
3440 ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].blk_head[location->block].invalid_page_num++;
3441 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) //¸ÃblockÖÃÈ«ÊÇinvalidµÄÒ³£¬¿ÉÒÔÖ±½Óɾ³ý
3442 {
3443 new_direct_erase=(struct direct_erase *)malloc(sizeof(struct direct_erase));
3444 alloc_assert(new_direct_erase,"new_direct_erase");
3445 memset(new_direct_erase,0, sizeof(struct direct_erase));
3446
3447 new_direct_erase->block=location->block;
3448 new_direct_erase->next_node=NULL;
3449 direct_erase_node=ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].erase_node;
3450 if (direct_erase_node==NULL)
3451 {
3452 ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].erase_node=new_direct_erase;
3453 }
3454 else
3455 {
3456 new_direct_erase->next_node=ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].erase_node;
3457 ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].erase_node=new_direct_erase;
3458 }
3459 }
3460 free(location);
3461 location=NULL;
3462 ssd->dram->map->map_entry[sub->lpn].pn=find_ppn(ssd,channel,chip,die,plane,block,page);
3463 ssd->dram->map->map_entry[sub->lpn].state=(ssd->dram->map->map_entry[sub->lpn].state|sub->state);
3464 }
3465
3466 sub->ppn=ssd->dram->map->map_entry[sub->lpn].pn;
3467 sub->location->channel=channel;
3468 sub->location->chip=chip;
3469 sub->location->die=die;
3470 sub->location->plane=plane;
3471 sub->location->block=block;
3472 sub->location->page=page;
3473
3474 ssd->program_count++;
3475 ssd->channel_head[channel].program_count++;
3476 ssd->channel_head[channel].chip_head[chip].program_count++;
3477 ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].free_page--;
3478 ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[block].page_head[page].lpn=sub->lpn;
3479 ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[block].page_head[page].valid_state=sub->state;
3480 ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[block].page_head[page].free_state=((~(sub->state))&full_page);
3481 ssd->write_flash_count++;
3482
3483 return ssd;
3484}
3485
3486
3487/********************************************
3488*º¯ÊýµÄ¹¦ÄܾÃÊÇÈÃý¸öλÖò»Ã¬µÄpageλÖÃÃà ì
3489*********************************************/
3490struct ssd_info *make_same_level(struct ssd_info *ssd,unsigned int channel,unsigned int chip,unsigned int die,unsigned int plane,unsigned int block,unsigned int aim_page)
3491{
3492 int i=0,step,page;
3493 struct direct_erase *new_direct_erase,*direct_erase_node;
3494
3495 page=ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[block].last_write_page+1; /*ÃèÒªµ÷ÕûµÄµ±Ç°¿éµÄ¿ÉôҳºÅ*/
3496 step=aim_page-page;
3497 while (i<step)
3498 {
3499 ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[block].page_head[page+i].valid_state=0; /*±Ãʾijһҳʧ磬ìʱ±ê¼ÇvalidºÃfree״̬¶¼Îª0*/
3500 ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[block].page_head[page+i].free_state=0; /*±Ãʾijһҳʧ磬ìʱ±ê¼ÇvalidºÃfree״̬¶¼Îª0*/
3501 ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[block].page_head[page+i].lpn=0;
3502
3503 ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[block].invalid_page_num++;
3504
3505 ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[block].free_page_num--;
3506
3507 ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].free_page--;
3508
3509 i++;
3510 }
3511
3512 ssd->waste_page_count+=step;
3513
3514 ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[block].last_write_page=aim_page-1;
3515
3516 if (ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[block].invalid_page_num==ssd->parameter->page_block) /*¸ÃblockÖÃÈ«ÊÇinvalidµÄÒ³£¬¿ÉÒÔÖ±½Óɾ³ý*/
3517 {
3518 new_direct_erase=(struct direct_erase *)malloc(sizeof(struct direct_erase));
3519 alloc_assert(new_direct_erase,"new_direct_erase");
3520 memset(new_direct_erase,0, sizeof(struct direct_erase));
3521
3522 direct_erase_node=ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].erase_node;
3523 if (direct_erase_node==NULL)
3524 {
3525 ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].erase_node=new_direct_erase;
3526 }
3527 else
3528 {
3529 new_direct_erase->next_node=ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].erase_node;
3530 ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].erase_node=new_direct_erase;
3531 }
3532 }
3533
3534 if(ssd->channel_head[channel].chip_head[chip].die_head[die].plane_head[plane].blk_head[block].last_write_page>63)
3535 {
3536 printf("error! the last write page larger than 64!!\n");
3537 while(1){}
3538 }
3539
3540 return ssd;
3541}
3542
3543
3544/****************************************************************************
3545*ÔÚ´¦Àø߼¶ÃüÃîµÄô×ÓÇëÇóʱ£¬Õâ¸öº¯ÊýµÄ¹¦ÄܾÃÊǼÆËã´¦ÀÃʱ¼äÒÔ¼°´¦ÀõÄ״̬ת±ä
3546*¹¦ÄÜ»¹²»ÊǺÜÃêÉÆ£¬ÃèÒªÃêÉÆ£¬ÃÞ¸ÄʱעÒâÒª·ÖΪ¾²Ì¬·ÖÅäºÃ¶¯Ì¬·ÖÅäýÖÖÇé¿ö
3547*****************************************************************************/
3548struct ssd_info *compute_serve_time(struct ssd_info *ssd,unsigned int channel,unsigned int chip,unsigned int die,struct sub_request **subs, unsigned int subs_count,unsigned int command)
3549{
3550 unsigned int i=0;
3551 unsigned int max_subs_num=0;
3552 struct sub_request *sub=NULL,*p=NULL;
3553 struct sub_request * last_sub=NULL;
3554 max_subs_num=ssd->parameter->die_chip*ssd->parameter->plane_die;
3555
3556 if((command==INTERLEAVE_TWO_PLANE)||(command==COPY_BACK))
3557 {
3558 for(i=0;i<max_subs_num;i++)
3559 {
3560 if(subs[i]!=NULL)
3561 {
3562 last_sub=subs[i];
3563 subs[i]->current_state=SR_W_TRANSFER;
3564 subs[i]->current_time=ssd->current_time;
3565 subs[i]->next_state=SR_COMPLETE;
3566 subs[i]->next_state_predict_time=ssd->current_time+7*ssd->parameter->time_characteristics.tWC+(subs[i]->size*ssd->parameter->subpage_capacity)*ssd->parameter->time_characteristics.tWC;
3567 subs[i]->complete_time=subs[i]->next_state_predict_time;
3568
3569 delete_from_channel(ssd,channel,subs[i]);
3570 }
3571 }
3572 ssd->channel_head[channel].current_state=CHANNEL_TRANSFER;
3573 ssd->channel_head[channel].current_time=ssd->current_time;
3574 ssd->channel_head[channel].next_state=CHANNEL_IDLE;
3575 ssd->channel_head[channel].next_state_predict_time=last_sub->complete_time;
3576
3577 ssd->channel_head[channel].chip_head[chip].current_state=CHIP_WRITE_BUSY;
3578 ssd->channel_head[channel].chip_head[chip].current_time=ssd->current_time;
3579 ssd->channel_head[channel].chip_head[chip].next_state=CHIP_IDLE;
3580 ssd->channel_head[channel].chip_head[chip].next_state_predict_time=ssd->channel_head[channel].next_state_predict_time+ssd->parameter->time_characteristics.tPROG;
3581 }
3582 else if(command==TWO_PLANE)
3583 {
3584 for(i=0;i<max_subs_num;i++)
3585 {
3586 if(subs[i]!=NULL)
3587 {
3588
3589 subs[i]->current_state=SR_W_TRANSFER;
3590 if(last_sub==NULL)
3591 {
3592 subs[i]->current_time=ssd->current_time;
3593 }
3594 else
3595 {
3596 subs[i]->current_time=last_sub->complete_time+ssd->parameter->time_characteristics.tDBSY;
3597 }
3598
3599 subs[i]->next_state=SR_COMPLETE;
3600 subs[i]->next_state_predict_time=subs[i]->current_time+7*ssd->parameter->time_characteristics.tWC+(subs[i]->size*ssd->parameter->subpage_capacity)*ssd->parameter->time_characteristics.tWC;
3601 subs[i]->complete_time=subs[i]->next_state_predict_time;
3602 last_sub=subs[i];
3603
3604 delete_from_channel(ssd,channel,subs[i]);
3605 }
3606 }
3607 ssd->channel_head[channel].current_state=CHANNEL_TRANSFER;
3608 ssd->channel_head[channel].current_time=ssd->current_time;
3609 ssd->channel_head[channel].next_state=CHANNEL_IDLE;
3610 ssd->channel_head[channel].next_state_predict_time=last_sub->complete_time;
3611
3612 ssd->channel_head[channel].chip_head[chip].current_state=CHIP_WRITE_BUSY;
3613 ssd->channel_head[channel].chip_head[chip].current_time=ssd->current_time;
3614 ssd->channel_head[channel].chip_head[chip].next_state=CHIP_IDLE;
3615 ssd->channel_head[channel].chip_head[chip].next_state_predict_time=ssd->channel_head[channel].next_state_predict_time+ssd->parameter->time_characteristics.tPROG;
3616 }
3617 else if(command==INTERLEAVE)
3618 {
3619 for(i=0;i<max_subs_num;i++)
3620 {
3621 if(subs[i]!=NULL)
3622 {
3623
3624 subs[i]->current_state=SR_W_TRANSFER;
3625 if(last_sub==NULL)
3626 {
3627 subs[i]->current_time=ssd->current_time;
3628 }
3629 else
3630 {
3631 subs[i]->current_time=last_sub->complete_time;
3632 }
3633 subs[i]->next_state=SR_COMPLETE;
3634 subs[i]->next_state_predict_time=subs[i]->current_time+7*ssd->parameter->time_characteristics.tWC+(subs[i]->size*ssd->parameter->subpage_capacity)*ssd->parameter->time_characteristics.tWC;
3635 subs[i]->complete_time=subs[i]->next_state_predict_time;
3636 last_sub=subs[i];
3637
3638 delete_from_channel(ssd,channel,subs[i]);
3639 }
3640 }
3641 ssd->channel_head[channel].current_state=CHANNEL_TRANSFER;
3642 ssd->channel_head[channel].current_time=ssd->current_time;
3643 ssd->channel_head[channel].next_state=CHANNEL_IDLE;
3644 ssd->channel_head[channel].next_state_predict_time=last_sub->complete_time;
3645
3646 ssd->channel_head[channel].chip_head[chip].current_state=CHIP_WRITE_BUSY;
3647 ssd->channel_head[channel].chip_head[chip].current_time=ssd->current_time;
3648 ssd->channel_head[channel].chip_head[chip].next_state=CHIP_IDLE;
3649 ssd->channel_head[channel].chip_head[chip].next_state_predict_time=ssd->channel_head[channel].next_state_predict_time+ssd->parameter->time_characteristics.tPROG;
3650 }
3651 else if(command==NORMAL)
3652 {
3653 subs[0]->current_state=SR_W_TRANSFER;
3654 subs[0]->current_time=ssd->current_time;
3655 subs[0]->next_state=SR_COMPLETE;
3656 subs[0]->next_state_predict_time=ssd->current_time+7*ssd->parameter->time_characteristics.tWC+(subs[0]->size*ssd->parameter->subpage_capacity)*ssd->parameter->time_characteristics.tWC;
3657 subs[0]->complete_time=subs[0]->next_state_predict_time;
3658
3659 delete_from_channel(ssd,channel,subs[0]);
3660
3661 ssd->channel_head[channel].current_state=CHANNEL_TRANSFER;
3662 ssd->channel_head[channel].current_time=ssd->current_time;
3663 ssd->channel_head[channel].next_state=CHANNEL_IDLE;
3664 ssd->channel_head[channel].next_state_predict_time=subs[0]->complete_time;
3665
3666 ssd->channel_head[channel].chip_head[chip].current_state=CHIP_WRITE_BUSY;
3667 ssd->channel_head[channel].chip_head[chip].current_time=ssd->current_time;
3668 ssd->channel_head[channel].chip_head[chip].next_state=CHIP_IDLE;
3669 ssd->channel_head[channel].chip_head[chip].next_state_predict_time=ssd->channel_head[channel].next_state_predict_time+ssd->parameter->time_characteristics.tPROG;
3670 }
3671 else
3672 {
3673 return NULL;
3674 }
3675
3676 return ssd;
3677
3678}
3679
3680
3681/*****************************************************************************************
3682*º¯ÊýµÄ¹¦ÄܾÃÊǰÑ×ÓÇëÇó´Óssd->subs_w_head»òÕßssd->channel_head[channel].subs_w_headÉÃɾ³ý
3683******************************************************************************************/
3684struct ssd_info *delete_from_channel(struct ssd_info *ssd,unsigned int channel,struct sub_request * sub_req)
3685{
3686 struct sub_request *sub,*p;
3687
3688 /******************************************************************
3689 *ÃêÈ«¶¯Ì¬·ÖÅä×ÓÇëÇó¾ÃÔÚssd->subs_w_headÉÃ
3690 *²»ÊÇÃêÈ«¶¯Ì¬·ÖÅä×ÓÇëÇó¾ÃÔÚssd->channel_head[channel].subs_w_headÉÃ
3691 *******************************************************************/
3692 if ((ssd->parameter->allocation_scheme==0)&&(ssd->parameter->dynamic_allocation==0))
3693 {
3694 sub=ssd->subs_w_head;
3695 }
3696 else
3697 {
3698 sub=ssd->channel_head[channel].subs_w_head;
3699 }
3700 p=sub;
3701
3702 while (sub!=NULL)
3703 {
3704 if (sub==sub_req)
3705 {
3706 if ((ssd->parameter->allocation_scheme==0)&&(ssd->parameter->dynamic_allocation==0))
3707 {
3708 if(ssd->parameter->ad_priority2==0)
3709 {
3710 ssd->real_time_subreq--;
3711 }
3712
3713 if (sub==ssd->subs_w_head) /*½«Õâ¸ö×ÓÇëÇó´Ósub request¶ÓÃÃÖÃɾ³ý*/
3714 {
3715 if (ssd->subs_w_head!=ssd->subs_w_tail)
3716 {
3717 ssd->subs_w_head=sub->next_node;
3718 sub=ssd->subs_w_head;
3719 continue;
3720 }
3721 else
3722 {
3723 ssd->subs_w_head=NULL;
3724 ssd->subs_w_tail=NULL;
3725 p=NULL;
3726 break;
3727 }
3728 }//if (sub==ssd->subs_w_head)
3729 else
3730 {
3731 if (sub->next_node!=NULL)
3732 {
3733 p->next_node=sub->next_node;
3734 sub=p->next_node;
3735 continue;
3736 }
3737 else
3738 {
3739 ssd->subs_w_tail=p;
3740 ssd->subs_w_tail->next_node=NULL;
3741 break;
3742 }
3743 }
3744 }//if ((ssd->parameter->allocation_scheme==0)&&(ssd->parameter->dynamic_allocation==0))
3745 else
3746 {
3747 if (sub==ssd->channel_head[channel].subs_w_head) /*½«Õâ¸ö×ÓÇëÇó´Óchannel¶ÓÃÃÖÃɾ³ý*/
3748 {
3749 if (ssd->channel_head[channel].subs_w_head!=ssd->channel_head[channel].subs_w_tail)
3750 {
3751 ssd->channel_head[channel].subs_w_head=sub->next_node;
3752 sub=ssd->channel_head[channel].subs_w_head;
3753 continue;;
3754 }
3755 else
3756 {
3757 ssd->channel_head[channel].subs_w_head=NULL;
3758 ssd->channel_head[channel].subs_w_tail=NULL;
3759 p=NULL;
3760 break;
3761 }
3762 }//if (sub==ssd->channel_head[channel].subs_w_head)
3763 else
3764 {
3765 if (sub->next_node!=NULL)
3766 {
3767 p->next_node=sub->next_node;
3768 sub=p->next_node;
3769 continue;
3770 }
3771 else
3772 {
3773 ssd->channel_head[channel].subs_w_tail=p;
3774 ssd->channel_head[channel].subs_w_tail->next_node=NULL;
3775 break;
3776 }
3777 }//else
3778 }//else
3779 }//if (sub==sub_req)
3780 p=sub;
3781 sub=sub->next_node;
3782 }//while (sub!=NULL)
3783
3784 return ssd;
3785}
3786
3787
3788struct ssd_info *un_greed_interleave_copyback(struct ssd_info *ssd,unsigned int channel,unsigned int chip,unsigned int die,struct sub_request *sub1,struct sub_request *sub2)
3789{
3790 unsigned int old_ppn1,ppn1,old_ppn2,ppn2,greed_flag=0;
3791
3792 old_ppn1=ssd->dram->map->map_entry[sub1->lpn].pn;
3793 get_ppn(ssd,channel,chip,die,sub1->location->plane,sub1); /*ÕÒ³öÀ´µÄppnÒ»¶¨ÊÇ·¢ÉúÔÚÓë×ÓÇëÇóÃà ìµÄplaneÖÃ,²ÅÄÜʹÓÃcopyback²Ù×÷*/
3794 ppn1=sub1->ppn;
3795
3796 old_ppn2=ssd->dram->map->map_entry[sub2->lpn].pn;
3797 get_ppn(ssd,channel,chip,die,sub2->location->plane,sub2); /*ÕÒ³öÀ´µÄppnÒ»¶¨ÊÇ·¢ÉúÔÚÓë×ÓÇëÇóÃà ìµÄplaneÖÃ,²ÅÄÜʹÓÃcopyback²Ù×÷*/
3798 ppn2=sub2->ppn;
3799
3800 if ((old_ppn1%2==ppn1%2)&&(old_ppn2%2==ppn2%2))
3801 {
3802 ssd->copy_back_count++;
3803 ssd->copy_back_count++;
3804
3805 sub1->current_state=SR_W_TRANSFER;
3806 sub1->current_time=ssd->current_time;
3807 sub1->next_state=SR_COMPLETE;
3808 sub1->next_state_predict_time=ssd->current_time+14*ssd->parameter->time_characteristics.tWC+ssd->parameter->time_characteristics.tR+(sub1->size*ssd->parameter->subpage_capacity)*ssd->parameter->time_characteristics.tWC;
3809 sub1->complete_time=sub1->next_state_predict_time;
3810
3811 sub2->current_state=SR_W_TRANSFER;
3812 sub2->current_time=sub1->complete_time;
3813 sub2->next_state=SR_COMPLETE;
3814 sub2->next_state_predict_time=sub2->current_time+14*ssd->parameter->time_characteristics.tWC+ssd->parameter->time_characteristics.tR+(sub2->size*ssd->parameter->subpage_capacity)*ssd->parameter->time_characteristics.tWC;
3815 sub2->complete_time=sub2->next_state_predict_time;
3816
3817 ssd->channel_head[channel].current_state=CHANNEL_TRANSFER;
3818 ssd->channel_head[channel].current_time=ssd->current_time;
3819 ssd->channel_head[channel].next_state=CHANNEL_IDLE;
3820 ssd->channel_head[channel].next_state_predict_time=sub2->complete_time;
3821
3822 ssd->channel_head[channel].chip_head[chip].current_state=CHIP_WRITE_BUSY;
3823 ssd->channel_head[channel].chip_head[chip].current_time=ssd->current_time;
3824 ssd->channel_head[channel].chip_head[chip].next_state=CHIP_IDLE;
3825 ssd->channel_head[channel].chip_head[chip].next_state_predict_time=ssd->channel_head[channel].next_state_predict_time+ssd->parameter->time_characteristics.tPROG;
3826
3827 delete_from_channel(ssd,channel,sub1);
3828 delete_from_channel(ssd,channel,sub2);
3829 } //if ((old_ppn1%2==ppn1%2)&&(old_ppn2%2==ppn2%2))
3830 else if ((old_ppn1%2==ppn1%2)&&(old_ppn2%2!=ppn2%2))
3831 {
3832 ssd->interleave_count--;
3833 ssd->copy_back_count++;
3834
3835 sub1->current_state=SR_W_TRANSFER;
3836 sub1->current_time=ssd->current_time;
3837 sub1->next_state=SR_COMPLETE;
3838 sub1->next_state_predict_time=ssd->current_time+14*ssd->parameter->time_characteristics.tWC+ssd->parameter->time_characteristics.tR+(sub1->size*ssd->parameter->subpage_capacity)*ssd->parameter->time_characteristics.tWC;
3839 sub1->complete_time=sub1->next_state_predict_time;
3840
3841 ssd->channel_head[channel].current_state=CHANNEL_TRANSFER;
3842 ssd->channel_head[channel].current_time=ssd->current_time;
3843 ssd->channel_head[channel].next_state=CHANNEL_IDLE;
3844 ssd->channel_head[channel].next_state_predict_time=sub1->complete_time;
3845
3846 ssd->channel_head[channel].chip_head[chip].current_state=CHIP_WRITE_BUSY;
3847 ssd->channel_head[channel].chip_head[chip].current_time=ssd->current_time;
3848 ssd->channel_head[channel].chip_head[chip].next_state=CHIP_IDLE;
3849 ssd->channel_head[channel].chip_head[chip].next_state_predict_time=ssd->channel_head[channel].next_state_predict_time+ssd->parameter->time_characteristics.tPROG;
3850
3851 delete_from_channel(ssd,channel,sub1);
3852 }//else if ((old_ppn1%2==ppn1%2)&&(old_ppn2%2!=ppn2%2))
3853 else if ((old_ppn1%2!=ppn1%2)&&(old_ppn2%2==ppn2%2))
3854 {
3855 ssd->interleave_count--;
3856 ssd->copy_back_count++;
3857
3858 sub2->current_state=SR_W_TRANSFER;
3859 sub2->current_time=ssd->current_time;
3860 sub2->next_state=SR_COMPLETE;
3861 sub2->next_state_predict_time=ssd->current_time+14*ssd->parameter->time_characteristics.tWC+ssd->parameter->time_characteristics.tR+(sub2->size*ssd->parameter->subpage_capacity)*ssd->parameter->time_characteristics.tWC;
3862 sub2->complete_time=sub2->next_state_predict_time;
3863
3864 ssd->channel_head[channel].current_state=CHANNEL_TRANSFER;
3865 ssd->channel_head[channel].current_time=ssd->current_time;
3866 ssd->channel_head[channel].next_state=CHANNEL_IDLE;
3867 ssd->channel_head[channel].next_state_predict_time=sub2->complete_time;
3868
3869 ssd->channel_head[channel].chip_head[chip].current_state=CHIP_WRITE_BUSY;
3870 ssd->channel_head[channel].chip_head[chip].current_time=ssd->current_time;
3871 ssd->channel_head[channel].chip_head[chip].next_state=CHIP_IDLE;
3872 ssd->channel_head[channel].chip_head[chip].next_state_predict_time=ssd->channel_head[channel].next_state_predict_time+ssd->parameter->time_characteristics.tPROG;
3873
3874 delete_from_channel(ssd,channel,sub2);
3875 }//else if ((old_ppn1%2!=ppn1%2)&&(old_ppn2%2==ppn2%2))
3876 else
3877 {
3878 ssd->interleave_count--;
3879
3880 sub1->current_state=SR_W_TRANSFER;
3881 sub1->current_time=ssd->current_time;
3882 sub1->next_state=SR_COMPLETE;
3883 sub1->next_state_predict_time=ssd->current_time+14*ssd->parameter->time_characteristics.tWC+ssd->parameter->time_characteristics.tR+2*(ssd->parameter->subpage_page*ssd->parameter->subpage_capacity)*ssd->parameter->time_characteristics.tWC;
3884 sub1->complete_time=sub1->next_state_predict_time;
3885
3886 ssd->channel_head[channel].current_state=CHANNEL_TRANSFER;
3887 ssd->channel_head[channel].current_time=ssd->current_time;
3888 ssd->channel_head[channel].next_state=CHANNEL_IDLE;
3889 ssd->channel_head[channel].next_state_predict_time=sub1->complete_time;
3890
3891 ssd->channel_head[channel].chip_head[chip].current_state=CHIP_WRITE_BUSY;
3892 ssd->channel_head[channel].chip_head[chip].current_time=ssd->current_time;
3893 ssd->channel_head[channel].chip_head[chip].next_state=CHIP_IDLE;
3894 ssd->channel_head[channel].chip_head[chip].next_state_predict_time=ssd->channel_head[channel].next_state_predict_time+ssd->parameter->time_characteristics.tPROG;
3895
3896 delete_from_channel(ssd,channel,sub1);
3897 }//else
3898
3899 return ssd;
3900}
3901
3902
3903struct ssd_info *un_greed_copyback(struct ssd_info *ssd,unsigned int channel,unsigned int chip,unsigned int die,struct sub_request *sub1)
3904{
3905 unsigned int old_ppn,ppn;
3906
3907 old_ppn=ssd->dram->map->map_entry[sub1->lpn].pn;
3908 get_ppn(ssd,channel,chip,die,0,sub1); /*ÕÒ³öÀ´µÄppnÒ»¶¨ÊÇ·¢ÉúÔÚÓë×ÓÇëÇóÃà ìµÄplaneÖÃ,²ÅÄÜʹÓÃcopyback²Ù×÷*/
3909 ppn=sub1->ppn;
3910
3911 if (old_ppn%2==ppn%2)
3912 {
3913 ssd->copy_back_count++;
3914 sub1->current_state=SR_W_TRANSFER;
3915 sub1->current_time=ssd->current_time;
3916 sub1->next_state=SR_COMPLETE;
3917 sub1->next_state_predict_time=ssd->current_time+14*ssd->parameter->time_characteristics.tWC+ssd->parameter->time_characteristics.tR+(sub1->size*ssd->parameter->subpage_capacity)*ssd->parameter->time_characteristics.tWC;
3918 sub1->complete_time=sub1->next_state_predict_time;
3919
3920 ssd->channel_head[channel].current_state=CHANNEL_TRANSFER;
3921 ssd->channel_head[channel].current_time=ssd->current_time;
3922 ssd->channel_head[channel].next_state=CHANNEL_IDLE;
3923 ssd->channel_head[channel].next_state_predict_time=sub1->complete_time;
3924
3925 ssd->channel_head[channel].chip_head[chip].current_state=CHIP_WRITE_BUSY;
3926 ssd->channel_head[channel].chip_head[chip].current_time=ssd->current_time;
3927 ssd->channel_head[channel].chip_head[chip].next_state=CHIP_IDLE;
3928 ssd->channel_head[channel].chip_head[chip].next_state_predict_time=ssd->channel_head[channel].next_state_predict_time+ssd->parameter->time_characteristics.tPROG;
3929 }//if (old_ppn%2==ppn%2)
3930 else
3931 {
3932 sub1->current_state=SR_W_TRANSFER;
3933 sub1->current_time=ssd->current_time;
3934 sub1->next_state=SR_COMPLETE;
3935 sub1->next_state_predict_time=ssd->current_time+14*ssd->parameter->time_characteristics.tWC+ssd->parameter->time_characteristics.tR+2*(ssd->parameter->subpage_page*ssd->parameter->subpage_capacity)*ssd->parameter->time_characteristics.tWC;
3936 sub1->complete_time=sub1->next_state_predict_time;
3937
3938 ssd->channel_head[channel].current_state=CHANNEL_TRANSFER;
3939 ssd->channel_head[channel].current_time=ssd->current_time;
3940 ssd->channel_head[channel].next_state=CHANNEL_IDLE;
3941 ssd->channel_head[channel].next_state_predict_time=sub1->complete_time;
3942
3943 ssd->channel_head[channel].chip_head[chip].current_state=CHIP_WRITE_BUSY;
3944 ssd->channel_head[channel].chip_head[chip].current_time=ssd->current_time;
3945 ssd->channel_head[channel].chip_head[chip].next_state=CHIP_IDLE;
3946 ssd->channel_head[channel].chip_head[chip].next_state_predict_time=ssd->channel_head[channel].next_state_predict_time+ssd->parameter->time_characteristics.tPROG;
3947 }//else
3948
3949 delete_from_channel(ssd,channel,sub1);
3950
3951 return ssd;
3952}
3953
3954
3955/****************************************************************************************
3956*º¯ÊýµÄ¹¦ÄÜÊÇÔÚ´¦ÀöÃ×ÓÇëÇóµÄ¸ß¼¶ÃüÃîʱ£¬ÃèÒªÕÒÓëone_pageÃà Æ¥ÅäµÄÃÃÃâÒ»¸öpage¼´two_page
3957*ûÓÃÕÒµ½¿ÉÒÔºÃone_pageÖ´ÃÃtwo plane»òÕßinterleave²Ù×÷µÄÒ³,ÃèÒª½«one_pageÃòºóÒÆÒ»¸ö½Úµã
3958*****************************************************************************************/
3959struct sub_request *find_interleave_twoplane_page(struct ssd_info *ssd, struct sub_request *one_page,unsigned int command)
3960{
3961 struct sub_request *two_page;
3962
3963 if (one_page->current_state!=SR_WAIT)
3964 {
3965 return NULL;
3966 }
3967 if (((ssd->channel_head[one_page->location->channel].chip_head[one_page->location->chip].current_state==CHIP_IDLE)||((ssd->channel_head[one_page->location->channel].chip_head[one_page->location->chip].next_state==CHIP_IDLE)&&
3968 (ssd->channel_head[one_page->location->channel].chip_head[one_page->location->chip].next_state_predict_time<=ssd->current_time))))
3969 {
3970 two_page=one_page->next_node;
3971 if(command==TWO_PLANE)
3972 {
3973 while (two_page!=NULL)
3974 {
3975 if (two_page->current_state!=SR_WAIT)
3976 {
3977 two_page=two_page->next_node;
3978 }
3979 else if ((one_page->location->chip==two_page->location->chip)&&(one_page->location->die==two_page->location->die)&&(one_page->location->block==two_page->location->block)&&(one_page->location->page==two_page->location->page))
3980 {
3981 if (one_page->location->plane!=two_page->location->plane)
3982 {
3983 return two_page; /*ÕÒµ½ÃËÓëone_page¿ÉÒÔÖ´ÃÃtwo plane²Ù×÷µÄÒ³*/
3984 }
3985 else
3986 {
3987 two_page=two_page->next_node;
3988 }
3989 }
3990 else
3991 {
3992 two_page=two_page->next_node;
3993 }
3994 }//while (two_page!=NULL)
3995 if (two_page==NULL) /*ûÓÃÕÒµ½¿ÉÒÔºÃone_pageÖ´ÃÃtwo_plane²Ù×÷µÄÒ³,ÃèÒª½«one_pageÃòºóÒÆÒ»¸ö½Úµã*/
3996 {
3997 return NULL;
3998 }
3999 }//if(command==TWO_PLANE)
4000 else if(command==INTERLEAVE)
4001 {
4002 while (two_page!=NULL)
4003 {
4004 if (two_page->current_state!=SR_WAIT)
4005 {
4006 two_page=two_page->next_node;
4007 }
4008 else if ((one_page->location->chip==two_page->location->chip)&&(one_page->location->die!=two_page->location->die))
4009 {
4010 return two_page; /*ÕÒµ½ÃËÓëone_page¿ÉÒÔÖ´ÃÃinterleave²Ù×÷µÄÒ³*/
4011 }
4012 else
4013 {
4014 two_page=two_page->next_node;
4015 }
4016 }
4017 if (two_page==NULL) /*ûÓÃÕÒµ½¿ÉÒÔºÃone_pageÖ´ÃÃinterleave²Ù×÷µÄÒ³,ÃèÒª½«one_pageÃòºóÒÆÒ»¸ö½Úµã*/
4018 {
4019 return NULL;
4020 }//while (two_page!=NULL)
4021 }//else if(command==INTERLEAVE)
4022
4023 }
4024 {
4025 return NULL;
4026 }
4027}
4028
4029
4030/*************************************************************************
4031*ÔÚ´¦ÀöÃ×ÓÇëÇó¸ß¼¶ÃüÃîʱ£¬ÀûÓÃÕâ¸ö»¹ÊDzéÕÒ¿ÉÒÔÖ´Ãø߼¶ÃüÃîµÄsub_request
4032**************************************************************************/
4033int find_interleave_twoplane_sub_request(struct ssd_info * ssd, unsigned int channel,struct sub_request * sub_request_one,struct sub_request * sub_request_two,unsigned int command)
4034{
4035 sub_request_one=ssd->channel_head[channel].subs_r_head;
4036 while (sub_request_one!=NULL)
4037 {
4038 sub_request_two=find_interleave_twoplane_page(ssd,sub_request_one,command); /*ÕÒ³öý¸ö¿ÉÒÔ×ötwo_plane»òÕßinterleaveµÄread×ÓÇëÇ󣬰üÀ¨Î»ÖÃÌõ¼þºÃʱ¼äÌõ¼þ*/
4039 if (sub_request_two==NULL)
4040 {
4041 sub_request_one=sub_request_one->next_node;
4042 }
4043 else if (sub_request_two!=NULL) /*ÕÒµ½ÃËý¸ö¿ÉÒÔÖ´ÃÃtwo plane²Ù×÷µÄÒ³*/
4044 {
4045 break;
4046 }
4047 }
4048
4049 if (sub_request_two!=NULL)
4050 {
4051 if (ssd->request_queue!=ssd->request_tail)
4052 { /*È·±£interleave readµÄ×ÓÇëÇóÊǵÚÒ»¸öÇëÇóµÄ×ÓÇëÇó*/
4053 if ((ssd->request_queue->lsn-ssd->parameter->subpage_page)<(sub_request_one->lpn*ssd->parameter->subpage_page))
4054 {
4055 if ((ssd->request_queue->lsn+ssd->request_queue->size+ssd->parameter->subpage_page)>(sub_request_one->lpn*ssd->parameter->subpage_page))
4056 {
4057 }
4058 else
4059 {
4060 sub_request_two=NULL;
4061 }
4062 }
4063 else
4064 {
4065 sub_request_two=NULL;
4066 }
4067 }//if (ssd->request_queue!=ssd->request_tail)
4068 }//if (sub_request_two!=NULL)
4069
4070 if(sub_request_two!=NULL)
4071 {
4072 return SUCCESS;
4073 }
4074 else
4075 {
4076 return FAILURE;
4077 }
4078
4079}
4080
4081
4082/**************************************************************************
4083*Õâ¸öº¯Êý·Ç³£ÖØÒª£¬¶Ã×ÓÇëÇóµÄ״̬ת±ä£¬ÒÔ¼°Ê±¼äµÄ¼ÆË㶼è¹ýÕâ¸öº¯ÊýÀ´´¦ÀÃ
4084*»¹ÓÃô×ÓÇëÇóµÄÖ´ÃÃÆÕèÃüÃîʱµÄ״̬£¬ÒÔ¼°Ê±¼äµÄ¼ÆËãÒ²ÊÇè¹ýÕâ¸öº¯ÊýÀ´´¦ÀõÄ
4085****************************************************************************/
4086Status go_one_step(struct ssd_info * ssd, struct sub_request * sub1,struct sub_request *sub2, unsigned int aim_state,unsigned int command)
4087{
4088 unsigned int i=0,j=0,k=0,m=0;
4089 long long time=0;
4090 struct sub_request * sub=NULL ;
4091 struct sub_request * sub_twoplane_one=NULL, * sub_twoplane_two=NULL;
4092 struct sub_request * sub_interleave_one=NULL, * sub_interleave_two=NULL;
4093 struct local * location=NULL;
4094 if(sub1==NULL)
4095 {
4096 return ERROR;
4097 }
4098
4099 /***************************************************************************************************
4100 *´¦ÀÃÆÕèÃüÃîʱ£¬¶Ã×ÓÇëÇóµÄÄ¿±ê״̬·ÖΪÒÔü¸ÖÖÇé¿öSR_R_READ£¬SR_R_C_A_TRANSFER£¬SR_R_DATA_TRANSFER
4101 *ô×ÓÇëÇóµÄÄ¿±ê״ֻ̬ÓÃSR_W_TRANSFER
4102 ****************************************************************************************************/
4103 if(command==NORMAL)
4104 {
4105 sub=sub1;
4106 location=sub1->location;
4107 switch(aim_state)
4108 {
4109 case SR_R_READ:
4110 {
4111 /*****************************************************************************************************
4112 *Õâ¸öÄ¿±ê״̬ÊÇÖ¸flash´¦ÓÚ¶ÃÊý¾ÃµÄ״̬£¬subµÄÃÂһ״̬¾ÃÓ¦¸ÃÊÇ´«ËÃÊý¾ÃSR_R_DATA_TRANSFER
4113 *ÕâʱÓëchannelÎ޹أ¬Ö»ÓëchipÓùØËùÒÔÒªÃÞ¸ÄchipµÄ״̬ΪCHIP_READ_BUSY£¬ÃÂÒ»¸ö״̬¾ÃÊÇCHIP_DATA_TRANSFER
4114 ******************************************************************************************************/
4115 sub->current_time=ssd->current_time;
4116 sub->current_state=SR_R_READ;
4117 sub->next_state=SR_R_DATA_TRANSFER;
4118 sub->next_state_predict_time=ssd->current_time+ssd->parameter->time_characteristics.tR;
4119
4120 ssd->channel_head[location->channel].chip_head[location->chip].current_state=CHIP_READ_BUSY;
4121 ssd->channel_head[location->channel].chip_head[location->chip].current_time=ssd->current_time;
4122 ssd->channel_head[location->channel].chip_head[location->chip].next_state=CHIP_DATA_TRANSFER;
4123 ssd->channel_head[location->channel].chip_head[location->chip].next_state_predict_time=ssd->current_time+ssd->parameter->time_characteristics.tR;
4124
4125 break;
4126 }
4127 case SR_R_C_A_TRANSFER:
4128 {
4129 /*******************************************************************************************************
4130 *Ä¿±ê״̬ÊÇÃüÃîµØÖ·´«Êäʱ£¬subµÄÃÂÒ»¸ö״̬¾ÃÊÇSR_R_READ
4131 *Õâ¸ö״̬Óëchannel£¬chipÓùأ¬ËùÒÔÒªÃÞ¸Ächannel£¬chipµÄ״̬·Ö±ðΪCHANNEL_C_A_TRANSFER£¬CHIP_C_A_TRANSFER
4132 *ÃÂһ״̬·Ö±ðΪCHANNEL_IDLE£¬CHIP_READ_BUSY
4133 *******************************************************************************************************/
4134 sub->current_time=ssd->current_time;
4135 sub->current_state=SR_R_C_A_TRANSFER;
4136 sub->next_state=SR_R_READ;
4137 sub->next_state_predict_time=ssd->current_time+7*ssd->parameter->time_characteristics.tWC;
4138 sub->begin_time=ssd->current_time;
4139
4140 ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].add_reg_ppn=sub->ppn;
4141 ssd->read_count++;
4142
4143 ssd->channel_head[location->channel].current_state=CHANNEL_C_A_TRANSFER;
4144 ssd->channel_head[location->channel].current_time=ssd->current_time;
4145 ssd->channel_head[location->channel].next_state=CHANNEL_IDLE;
4146 ssd->channel_head[location->channel].next_state_predict_time=ssd->current_time+7*ssd->parameter->time_characteristics.tWC;
4147
4148 ssd->channel_head[location->channel].chip_head[location->chip].current_state=CHIP_C_A_TRANSFER;
4149 ssd->channel_head[location->channel].chip_head[location->chip].current_time=ssd->current_time;
4150 ssd->channel_head[location->channel].chip_head[location->chip].next_state=CHIP_READ_BUSY;
4151 ssd->channel_head[location->channel].chip_head[location->chip].next_state_predict_time=ssd->current_time+7*ssd->parameter->time_characteristics.tWC;
4152
4153 break;
4154
4155 }
4156 case SR_R_DATA_TRANSFER:
4157 {
4158 /**************************************************************************************************************
4159 *Ä¿±ê״̬ÊÇÊý¾Ã´«Êäʱ£¬subµÄÃÂÒ»¸ö״̬¾ÃÊÇÃê³É״̬SR_COMPLETE
4160 *Õâ¸ö״̬µÄ´¦ÀÃÒ²Óëchannel£¬chipÓùأ¬ËùÒÔchannel£¬chipµÄµ±Ç°×´Ì¬±äΪCHANNEL_DATA_TRANSFER£¬CHIP_DATA_TRANSFER
4161 *ÃÂÒ»¸ö״̬·Ö±ðΪCHANNEL_IDLE£¬CHIP_IDLE¡£
4162 ***************************************************************************************************************/
4163 sub->current_time=ssd->current_time;
4164 sub->current_state=SR_R_DATA_TRANSFER;
4165 sub->next_state=SR_COMPLETE;
4166 sub->next_state_predict_time=ssd->current_time+(sub->size*ssd->parameter->subpage_capacity)*ssd->parameter->time_characteristics.tRC;
4167 sub->complete_time=sub->next_state_predict_time;
4168
4169 ssd->channel_head[location->channel].current_state=CHANNEL_DATA_TRANSFER;
4170 ssd->channel_head[location->channel].current_time=ssd->current_time;
4171 ssd->channel_head[location->channel].next_state=CHANNEL_IDLE;
4172 ssd->channel_head[location->channel].next_state_predict_time=sub->next_state_predict_time;
4173
4174 ssd->channel_head[location->channel].chip_head[location->chip].current_state=CHIP_DATA_TRANSFER;
4175 ssd->channel_head[location->channel].chip_head[location->chip].current_time=ssd->current_time;
4176 ssd->channel_head[location->channel].chip_head[location->chip].next_state=CHIP_IDLE;
4177 ssd->channel_head[location->channel].chip_head[location->chip].next_state_predict_time=sub->next_state_predict_time;
4178
4179 ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].add_reg_ppn=-1;
4180
4181 break;
4182 }
4183 case SR_W_TRANSFER:
4184 {
4185 /******************************************************************************************************
4186 *ÕâÊÇ´¦ÀÃô×ÓÇëÇóʱ£¬×´Ì¬µÄת±äÒÔ¼°Ê±¼äµÄ¼ÆËã
4187 *ËäȻô×ÓÇëÇóµÄ´¦ÀÃ״̬ҲÃñ¶Ã×ÓÇëÇóÄÇô¶à £¬µ«ÊÇôÇëÇó¶¼ÊÇ´ÓÉÃÃùplaneÖô«ÊäÊý¾Ã
4188 *ÕâÑù¾Ã¿ÉÒ԰Ѽ¸¸ö״̬µ±Ò»¸ö״̬À´´¦À㬾õ±³ÉSR_W_TRANSFERÕâ¸ö״̬À´´¦Àã¬subµÄÃÂÒ»¸ö״̬¾ÃÊÇÃê³É״̬ÃË
4189 *´Ëʱchannel£¬chipµÄµ±Ç°×´Ì¬±äΪCHANNEL_TRANSFER£¬CHIP_WRITE_BUSY
4190 *ÃÂÒ»¸ö״̬±äΪCHANNEL_IDLE£¬CHIP_IDLE
4191 *******************************************************************************************************/
4192 sub->current_time=ssd->current_time;
4193 sub->current_state=SR_W_TRANSFER;
4194 sub->next_state=SR_COMPLETE;
4195 sub->next_state_predict_time=ssd->current_time+7*ssd->parameter->time_characteristics.tWC+(sub->size*ssd->parameter->subpage_capacity)*ssd->parameter->time_characteristics.tWC;
4196 sub->complete_time=sub->next_state_predict_time;
4197 time=sub->complete_time;
4198
4199 ssd->channel_head[location->channel].current_state=CHANNEL_TRANSFER;
4200 ssd->channel_head[location->channel].current_time=ssd->current_time;
4201 ssd->channel_head[location->channel].next_state=CHANNEL_IDLE;
4202 ssd->channel_head[location->channel].next_state_predict_time=time;
4203
4204 ssd->channel_head[location->channel].chip_head[location->chip].current_state=CHIP_WRITE_BUSY;
4205 ssd->channel_head[location->channel].chip_head[location->chip].current_time=ssd->current_time;
4206 ssd->channel_head[location->channel].chip_head[location->chip].next_state=CHIP_IDLE;
4207 ssd->channel_head[location->channel].chip_head[location->chip].next_state_predict_time=time+ssd->parameter->time_characteristics.tPROG;
4208
4209 break;
4210 }
4211 default : return ERROR;
4212
4213 }//switch(aim_state)
4214 }//if(command==NORMAL)
4215 else if(command==TWO_PLANE)
4216 {
4217 /**********************************************************************************************
4218 *¸ß¼¶ÃüÃîTWO_PLANEµÄ´¦Àã¬ÕâÀïµÄTWO_PLANE¸ß¼¶ÃüÃîÊǶÃ×ÓÇëÇóµÄ¸ß¼¶ÃüÃî
4219 *״̬ת±äÓëÆÕèÃüÃîÒ»Ñù£¬²»Ã¬µÄÊÇÔÚSR_R_C_A_TRANSFERʱ¼ÆËãʱ¼äÊÇ´®Ãõģ¬ÒòΪ¹²ÓÃÒ»¸öèµÀchannel
4220 *»¹ÓÃSR_R_DATA_TRANSFERÒ²Êǹ²ÓÃÒ»¸öèµÀ
4221 **********************************************************************************************/
4222 if((sub1==NULL)||(sub2==NULL))
4223 {
4224 return ERROR;
4225 }
4226 sub_twoplane_one=sub1;
4227 sub_twoplane_two=sub2;
4228 location=sub1->location;
4229
4230 switch(aim_state)
4231 {
4232 case SR_R_C_A_TRANSFER:
4233 {
4234 sub_twoplane_one->current_time=ssd->current_time;
4235 sub_twoplane_one->current_state=SR_R_C_A_TRANSFER;
4236 sub_twoplane_one->next_state=SR_R_READ;
4237 sub_twoplane_one->next_state_predict_time=ssd->current_time+14*ssd->parameter->time_characteristics.tWC;
4238 sub_twoplane_one->begin_time=ssd->current_time;
4239
4240 ssd->channel_head[sub_twoplane_one->location->channel].chip_head[sub_twoplane_one->location->chip].die_head[sub_twoplane_one->location->die].plane_head[sub_twoplane_one->location->plane].add_reg_ppn=sub_twoplane_one->ppn;
4241 ssd->read_count++;
4242
4243 sub_twoplane_two->current_time=ssd->current_time;
4244 sub_twoplane_two->current_state=SR_R_C_A_TRANSFER;
4245 sub_twoplane_two->next_state=SR_R_READ;
4246 sub_twoplane_two->next_state_predict_time=sub_twoplane_one->next_state_predict_time;
4247 sub_twoplane_two->begin_time=ssd->current_time;
4248
4249 ssd->channel_head[sub_twoplane_two->location->channel].chip_head[sub_twoplane_two->location->chip].die_head[sub_twoplane_two->location->die].plane_head[sub_twoplane_two->location->plane].add_reg_ppn=sub_twoplane_two->ppn;
4250 ssd->read_count++;
4251 ssd->m_plane_read_count++;
4252
4253 ssd->channel_head[location->channel].current_state=CHANNEL_C_A_TRANSFER;
4254 ssd->channel_head[location->channel].current_time=ssd->current_time;
4255 ssd->channel_head[location->channel].next_state=CHANNEL_IDLE;
4256 ssd->channel_head[location->channel].next_state_predict_time=ssd->current_time+14*ssd->parameter->time_characteristics.tWC;
4257
4258 ssd->channel_head[location->channel].chip_head[location->chip].current_state=CHIP_C_A_TRANSFER;
4259 ssd->channel_head[location->channel].chip_head[location->chip].current_time=ssd->current_time;
4260 ssd->channel_head[location->channel].chip_head[location->chip].next_state=CHIP_READ_BUSY;
4261 ssd->channel_head[location->channel].chip_head[location->chip].next_state_predict_time=ssd->current_time+14*ssd->parameter->time_characteristics.tWC;
4262
4263
4264 break;
4265 }
4266 case SR_R_DATA_TRANSFER:
4267 {
4268 sub_twoplane_one->current_time=ssd->current_time;
4269 sub_twoplane_one->current_state=SR_R_DATA_TRANSFER;
4270 sub_twoplane_one->next_state=SR_COMPLETE;
4271 sub_twoplane_one->next_state_predict_time=ssd->current_time+(sub_twoplane_one->size*ssd->parameter->subpage_capacity)*ssd->parameter->time_characteristics.tRC;
4272 sub_twoplane_one->complete_time=sub_twoplane_one->next_state_predict_time;
4273
4274 sub_twoplane_two->current_time=sub_twoplane_one->next_state_predict_time;
4275 sub_twoplane_two->current_state=SR_R_DATA_TRANSFER;
4276 sub_twoplane_two->next_state=SR_COMPLETE;
4277 sub_twoplane_two->next_state_predict_time=sub_twoplane_two->current_time+(sub_twoplane_two->size*ssd->parameter->subpage_capacity)*ssd->parameter->time_characteristics.tRC;
4278 sub_twoplane_two->complete_time=sub_twoplane_two->next_state_predict_time;
4279
4280 ssd->channel_head[location->channel].current_state=CHANNEL_DATA_TRANSFER;
4281 ssd->channel_head[location->channel].current_time=ssd->current_time;
4282 ssd->channel_head[location->channel].next_state=CHANNEL_IDLE;
4283 ssd->channel_head[location->channel].next_state_predict_time=sub_twoplane_one->next_state_predict_time;
4284
4285 ssd->channel_head[location->channel].chip_head[location->chip].current_state=CHIP_DATA_TRANSFER;
4286 ssd->channel_head[location->channel].chip_head[location->chip].current_time=ssd->current_time;
4287 ssd->channel_head[location->channel].chip_head[location->chip].next_state=CHIP_IDLE;
4288 ssd->channel_head[location->channel].chip_head[location->chip].next_state_predict_time=sub_twoplane_one->next_state_predict_time;
4289
4290 ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].add_reg_ppn=-1;
4291
4292 break;
4293 }
4294 default : return ERROR;
4295 }//switch(aim_state)
4296 }//else if(command==TWO_PLANE)
4297 else if(command==INTERLEAVE)
4298 {
4299 if((sub1==NULL)||(sub2==NULL))
4300 {
4301 return ERROR;
4302 }
4303 sub_interleave_one=sub1;
4304 sub_interleave_two=sub2;
4305 location=sub1->location;
4306
4307 switch(aim_state)
4308 {
4309 case SR_R_C_A_TRANSFER:
4310 {
4311 sub_interleave_one->current_time=ssd->current_time;
4312 sub_interleave_one->current_state=SR_R_C_A_TRANSFER;
4313 sub_interleave_one->next_state=SR_R_READ;
4314 sub_interleave_one->next_state_predict_time=ssd->current_time+14*ssd->parameter->time_characteristics.tWC;
4315 sub_interleave_one->begin_time=ssd->current_time;
4316
4317 ssd->channel_head[sub_interleave_one->location->channel].chip_head[sub_interleave_one->location->chip].die_head[sub_interleave_one->location->die].plane_head[sub_interleave_one->location->plane].add_reg_ppn=sub_interleave_one->ppn;
4318 ssd->read_count++;
4319
4320 sub_interleave_two->current_time=ssd->current_time;
4321 sub_interleave_two->current_state=SR_R_C_A_TRANSFER;
4322 sub_interleave_two->next_state=SR_R_READ;
4323 sub_interleave_two->next_state_predict_time=sub_interleave_one->next_state_predict_time;
4324 sub_interleave_two->begin_time=ssd->current_time;
4325
4326 ssd->channel_head[sub_interleave_two->location->channel].chip_head[sub_interleave_two->location->chip].die_head[sub_interleave_two->location->die].plane_head[sub_interleave_two->location->plane].add_reg_ppn=sub_interleave_two->ppn;
4327 ssd->read_count++;
4328 ssd->interleave_read_count++;
4329
4330 ssd->channel_head[location->channel].current_state=CHANNEL_C_A_TRANSFER;
4331 ssd->channel_head[location->channel].current_time=ssd->current_time;
4332 ssd->channel_head[location->channel].next_state=CHANNEL_IDLE;
4333 ssd->channel_head[location->channel].next_state_predict_time=ssd->current_time+14*ssd->parameter->time_characteristics.tWC;
4334
4335 ssd->channel_head[location->channel].chip_head[location->chip].current_state=CHIP_C_A_TRANSFER;
4336 ssd->channel_head[location->channel].chip_head[location->chip].current_time=ssd->current_time;
4337 ssd->channel_head[location->channel].chip_head[location->chip].next_state=CHIP_READ_BUSY;
4338 ssd->channel_head[location->channel].chip_head[location->chip].next_state_predict_time=ssd->current_time+14*ssd->parameter->time_characteristics.tWC;
4339
4340 break;
4341
4342 }
4343 case SR_R_DATA_TRANSFER:
4344 {
4345 sub_interleave_one->current_time=ssd->current_time;
4346 sub_interleave_one->current_state=SR_R_DATA_TRANSFER;
4347 sub_interleave_one->next_state=SR_COMPLETE;
4348 sub_interleave_one->next_state_predict_time=ssd->current_time+(sub_interleave_one->size*ssd->parameter->subpage_capacity)*ssd->parameter->time_characteristics.tRC;
4349 sub_interleave_one->complete_time=sub_interleave_one->next_state_predict_time;
4350
4351 sub_interleave_two->current_time=sub_interleave_one->next_state_predict_time;
4352 sub_interleave_two->current_state=SR_R_DATA_TRANSFER;
4353 sub_interleave_two->next_state=SR_COMPLETE;
4354 sub_interleave_two->next_state_predict_time=sub_interleave_two->current_time+(sub_interleave_two->size*ssd->parameter->subpage_capacity)*ssd->parameter->time_characteristics.tRC;
4355 sub_interleave_two->complete_time=sub_interleave_two->next_state_predict_time;
4356
4357 ssd->channel_head[location->channel].current_state=CHANNEL_DATA_TRANSFER;
4358 ssd->channel_head[location->channel].current_time=ssd->current_time;
4359 ssd->channel_head[location->channel].next_state=CHANNEL_IDLE;
4360 ssd->channel_head[location->channel].next_state_predict_time=sub_interleave_two->next_state_predict_time;
4361
4362 ssd->channel_head[location->channel].chip_head[location->chip].current_state=CHIP_DATA_TRANSFER;
4363 ssd->channel_head[location->channel].chip_head[location->chip].current_time=ssd->current_time;
4364 ssd->channel_head[location->channel].chip_head[location->chip].next_state=CHIP_IDLE;
4365 ssd->channel_head[location->channel].chip_head[location->chip].next_state_predict_time=sub_interleave_two->next_state_predict_time;
4366
4367 ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[location->plane].add_reg_ppn=-1;
4368
4369 break;
4370 }
4371 default : return ERROR;
4372 }//switch(aim_state)
4373 }//else if(command==INTERLEAVE)
4374 else
4375 {
4376 printf("\nERROR: Unexpected command !\n" );
4377 return ERROR;
4378 }
4379
4380 return SUCCESS;
4381}