Ssdsim source code Analysis of Pre_process_page

Source: Internet
Author: User

Pre_process_page ()

Starting with this blog post, we will analyze and annotate the core parts of Ssdsim in detail, and the core part of the Ssdsim emulator is the three main functions:

pre_preocess_page () page read request preprocessing function
simmulate () Core simulation function
Statistic_output () Statistical Output information function

One of the most important and large functions is the simmulate () core simulation function, this function is responsible for the entire SSD function simulation, we will be in the later part of the detailed description and analysis, and this blog post first parse pre_preocess_page () Function of the main function and detailed role, which will involve a lot of ssdsim work principle and architecture knowledge, can be combined with the program source code and analysis.

Pre_process_page () main function and function

pre_process_page () read request preprocessing function, the main function is that when the read request to read the page in the pages without data, the function needs to write to the page first to complete the read operation.

The function first defines some related parameters, including a buf buffer of length 200char, and calls fopen () to open the Tracefile file as read-only, and returns an error directly if the open fails (the file does not exist or the filename is incorrect).

If the read tracefile succeeds, the program will first set full_page that is, the sub-page screen code is 1 (the initial screen code of each page under the default status of all subpage is 1), calculated Largest_lsn:

Maximum logical Sector Code = (number of chip in SSD x number of die per chip x number of plane per die × number of blocks under each plane x number of blocks under each block X number of subpage under each page) x Reserved Space op Ratio.

Note: SSDs will have a concept of op headroom , and this op reserve space can greatly improve SSD performance.

The program then calls Fget () to open all iotrace information in the Tracefile row by line into the BUF buffer, reading a row of up to 200 char at a time;

In the process of opening the read trace, the program takes advantage of the sscanf () function as follows:

Time (long Long) device (type int) LSN (int) size (int) ope (int).

This fixed trace format reads the Iotrace data line by row, and then counts FL as the number of Io, and every time a iotrace is read, it needs to call the Trace_assert () function for the correctness of IO. Then initialize add_size that the IO has completed a size count of 0, judging the ope operand :

If 0 is the write request, but because the pre_process_page is only servicing the read request, the program flow ignores the write request to continue calling Fget () to read the next iotrace for the read request.

When the ope is 1, the IO is read request, the program will determine whether the completed IO length add_size is less than the IO length size, if greater than or equal to size , the read IO has been processed to continue the next IO read, otherwise the IO read has not been processed, To continue with the following steps:

First the program adjusts the LSN (prevents the LSN from being larger than the maximum LSN ), and then calculates the length of the actual IO required for the sub_size, which is the page where the LSN resides:

This Part length = page number of child pages-LSN is the starting sub-page position in the page;

Then determine the length of the io that has been processed add_size and the actual operation length in the current page sub_size if the sum of the iotrace is greater than size:

If you have exceeded the actual length of the description sub_size need to adjust (in fact, it is not possible to exceed the size specified by Iotrace, otherwise it is wrong operation, and here the sub_size is mainly for the first LSN and the last LSN, Because the LSN of the rest of the middle section will basically start at the start of the page, the length of the operation will be the entire page size)

So the LSN that is usually the last page may need to be sub_size adjusted at this time

sub_size = io Length Size-The length that has been processed add_size

At the same time to update the length has been processed add_size so that it plus adjusted sub_size;

If the judgment does not exceed the time to indicate that the length of processing has not reached the last page , then you can directly skip the above adjustment steps directly determine the legality of the Sub_size (that is, whether the page size is exceeded) and the length has been processed add_ Size is reasonable (that is, if the length of the iotrace is exceeded size)

If it is illegal, print the sub_size information, and the program will continue to count the LPN of the current LSN, and determine if the associated sub-page mapping of the LPN in memory dram MAP_ENTRY[LPN] is valid:

If map_entry[lpn].state is not 0 then the LPN's sub-page mapping may be valid at this point, there may be directly available sub-pages, the program will then determine whether the state is >0.

If not, only then state<0 is the child page map is all valid ( here is because map_entry[lpn].state is an int type, the default should be a signed integer value range, Therefore, if the state<0 is converted to a binary value that is all 1, then all the sub-pages are valid .

You can skip the following steps to update LSN and add_size directly.

If state>0 indicates that it is possible that only some of the sub-pages are valid, and that there is no dram and buffer in the child pages that might need to read the data, it is necessary to write the sub-pages from the SSD to the DRAM to do the appropriate operation. However, you must verify which child pages need to be written.

Therefore, the program is further confirmed, the function will call set_entry_state () to the sub-page mapping status bit settings, the results are saved in map_entry_new

The Set_entry_state () function marks the state position 1, based on the parameters of the LSN and sub_size for the portion of the child page length that starts at the LSN position of Sub_size, representing the need to re-MAP_ENTRY[LPN]. A valid mapping of the child pages that are set in the state.

The function will then use Map_entry_old to save map_entry[lpn].state bit mapping state information in the current DRAM, and map_entry_new and map_entry_old will be Bitwise or calculation operation to update the mapping status bit and save the results in modify

The mapping physical page pn of LPN is then saved to PPN, and the completion of the mapping update represents that the program has completed the read operation of the LSN under the current LPN .

The program then calls the find_location () function to find the physical address, followed by statistics on the relevant SSD information:

Updates the Program_count count in the entire SSD, current channel, and chip currently in the channel, indicating the completion of a write page operation count;

The mapping update information saved in modify is then assigned to the map_entry[lpn].state corresponding to the LPN of the current LSN, indicating that the data has been written to the corresponding page sub-page of the SSD and has been read into the DRAM ;

At the same time, according to the information of the location physical address structure, the child pages in the page are effectively mapped bits valid_state is also modify to maintain synchronization with the DRAM;

and set up a sub-page that updates the remaining Free State in the page, and then releases and empties the location.

On the other hand, if map_entry[lpn].state is 0 then the LPN corresponding sub-page mapping is invalid, the program needs to reassign the physical sub-page of the valid state to the read operation request. Therefore, the data needs to be written to the sub-page from the SSD and then read the request operation.

The function calls the get_ppn_for_pre_process () function to obtain the physical page number corresponding to the LSN of the current Iotrace ppn, followed by PPN call find_location () The function obtains the corresponding physical address information.

Then the statistics update the Program_count count in chip in the SSD, current channel and channel, indicating that the data has been successfully written from the SSD and read into DRAM , and that the LPN corresponding MAP_ needs to be updated at this time ENTRY[LPN].PN for the newly acquired PPN.

Then the program calls the set_entry_state () function to reset the status bit of the updated sub-page and assigns it to map_entry[lpn].state

and the corresponding parameters of the physical page that update the LSN according to the location physical address, mainly the lpn, the valid_state valid state bit and the Free_state idle status bit flag , finally releasing and emptying the location.

When the function completes the above procedure, it proves that the LPN read operation for the current Iotrace LSN has been successfully completed , at this time it is only read to complete the size of at most one page, So the program needs to update the LSN location at this time even if LSN plus the sub_size size already read, and update the IO length already processed add_size

The flow of the program then continues to determine whether the iotrace is currently being processed , and if not, repeat the process. When the Iotrace read request processing is completed, the program goes back to the fgets () function to continue reading the next IO in Tracefile, and the week begins repeatedly until all iotrace are read.

When the program finishes processing all of the read requests in Tracefile, it begins printing processing completion information and calls fclose () to close the Tracefile file stream

A multiple nested for loop is used to write the number of free idle state pages per plane in the current state of the SSD to ssd->outputfile in a fixed format.
Each time a plane is written to the OutputFile file , the fflush () function is immediately used for each of the data stream updates in the buffer . When all of the above actions have been completed,Pre_process_page completes its task and returns to the SSD structure.

source code and related annotations
structSsd_info *pre_process_page (struct ssd_info *ssd) {int fl=0;     unsigned int device,lsn,size,ope,lpn,full_page; //IOThe relevant parameters of the operation are target device number, logical sector area code, operation length, operation type, logical page number unsigned int largest_lsn,sub_size,ppn,add_size=0; The maximum logical sector code, the sub-page operation length, the physical page number, theIOLength processed unsigned int i=0, J,k;    int map_entry_new,map_entry_old,modify; int flag=0; Char buffer_request[ $];     Request queue buffer struct local *location;                   Local is the physical page number related to the structure of the body int64_t time; printf"\ n"); printf"Begin pre_process_page.................\n"); Ssd->tracefile=fopen (Ssd->tracefilename,"R"); /* Open a trace file to read in read-only modeIORequest */if(Ssd->tracefile = =NULL) {printf ("The trace file can ' t open\n"); Prints an error message and returns a null pointer return if open failsNULL; The value of//full_page is based on the number of logical child pagesNFigure out the2^N-1The code shows that the full_page here is a mask that represents the status of the child page, and the default setting is all1Full_page=~ (0xFFFFFFFF<< (Ssd->parameter->subpage_page)); /* Calculates the maximum logical sector code for this SSD * This is the reason to multiply the total number of logical pages (1-ssd->parameter->overprovide) is due to a part of the space asSSDThe reserved spaceOPTo improveSSDPerformance */largest_lsn= (unsigned int) (ssd->parameter->chip_num*ssd->parameter->die_chip*ssd->parameter ->plane_die*ssd->parameter->block_plane*ssd->parameter->page_block*ssd->parameter-> Subpage_page) * (1-ssd->parameter->overprovide)); while (Fgets (Buffer_request, $, ssd->tracefile))//per-line read from Tracefile file199Character until the entire trace is read {sscanf (buffer_request,"%lld %d%d%d%d", &time,&device,&lsn,&size,&ope); Read inIOThe relevant parameter value fl++; Read-IOQuantity Count Trace_assert (Time,device,lsn,size,ope); /* asserts that it will be processed when the read Time,device,lsn,size,ope is not valid */add_size=0; /*add_size is the size of this request already preprocessed */if(ope==1*/* Here is just the preprocessing of the read request, the corresponding location information needs to be modified in advance */{Whil                                                                           E (add_size<size)//operation not completed before entering the loop body {                  LSN=LSN%LARGEST_LSN; /* Prevents the obtained LSN from being larger than the maximum LSN */sub_size=ssd->parameter->subpage_page-(l                       Sn%ssd->parameter->subpage_page);  /* * Here the sub_size is mainly to locate the sub-request operation position, this position is relative to a particular page, from the page's first sub_page to calculate to this specific operation location *                 As a result, sub_size is actually the part that starts from the LSN sector position to the end of the page, which needs to be read in this page. * So the subpage_page here should be the so-called number of sectors within a page, and each sector typically defaults to +B */if(add_size+sub_size>=size)/* This occurs only when the size of a request is smaller than the size of a page, or when the last page of a request is processed */                                                                                                     {sub_size=size-add_size;                    The reason why sub_size here is equal to size-add_size is that when the size of the request is smaller than the page, the original sub_size area is actually larger than the actual request size.                                                 Add_size+=sub_size; }if((sub_size>ssd->parameter->subpage_page) | | (add_size>size)) /* When preprocessing a sub-size, this size is larger than a page or has been processed larger than size error */{printf ("Pre_process sub_size:%d\n", sub_size);                }                /******************************************************************************************************* * Use logical Sector area code LSN to calculate the logical page number LPN * Determine the status of the mapping table map in the DRAM in LPN position *A, this state = =0, indicating that it has not been written before, and now needs to write the sub_size size directly into the page *B, this status >0, indicating that there have been previously written, this requires a further comparison of the state, because the state of the new write can overlap with the previous state of the sector where * therefore, state = =0, because the in-memory mapping state is invalid, it is necessary to reassign the state-valid physical page to the read operation request, the calling function get_ppn_for_pre_process the valid physical page information * and then the physical page by Find_location ()                Store and update the mapping table information for the LPN. * Similarly, when the state >0, it proves that the mapping state in the Memory mapping table at the LPN location is valid and has a valid physical page that can be used directly, so PPN can use the PN ************************************************ in the mapping table directly.                       /lpn=lsn/ssd->parameter->subpage_page; The Subpage_page preliminary inference here should refer to the number of sectors in each page, which is the unit of operation for each of the child requestsif(ssd->dram->map->map_entry[lpn].state==0)/* Status is0, all pages are in an invalid state */{/************************************************************** * obtained using the get_ppn_for_pre_process function to obtain PPN, and then get location * To modify the relevant parameters of the SSD, the DRAM mapping table map, and the location of the page under the shape State ***************************************************************/Ppn=get_ppn_for_                                      Pre_process (SSD,LSN);                    Location=find_location (SSD,PPN);                       ssd->program_count++;                       ssd->channel_head[location->channel].program_count++;                             ssd->channel_head[location->channel].chip_head[location->chip].program_count++;                      ssd->dram->map->map_entry[lpn].pn=ppn;   Ssd->dram->map->map_entry[lpn].state=set_entry_state (ssd,lsn,sub_size); //0001ssd->channel_head[location->channel].chip_head[location->chip].die_head[location->die].plane_head[                    location->plane].blk_head[location->block].page_head[location->page].lpn=lpn; 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=ssd->dram->    map->map_entry[lpn].state; Gets the child page state after the read operation is completed Ssd->channel_head[location->channel].chip_head[location->chip].die_head[loc Ation->die].plane_head[location->plane].blk_head[location->block].page_head[location->page].free_                     State= ((~ssd->dram->map->map_entry[lpn].state) &full_page);                    All child pages that identify the page are used state free (location); location=NULL; Avoid wild hands}//if(ssd->dram->map->map_entry[lpn].state==0)/* Status not for0(where a child page is valid) */{map_entry_new=set_entry_state (ssd,lsn,sub_size);                       /* Get new status and go to a state with the original state or to a status */map_entry_old=ssd->dram->map->map_entry[lpn].state;                                     Modify=map_entry_new|map_entry_old;                      ppn=ssd->dram->map->map_entry[lpn].pn;                        Location=find_location (SSD,PPN);                       ssd->program_count++;                    ssd->channel_head[location->channel].program_count++;                         ssd->channel_head[location->channel].chip_head[location->chip].program_count++;                     ssd->dram->map->map_entry[lsn/ssd->parameter->subpage_page].state=modify; 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=modify; 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= ((~modify) &full_                    page);                    Free (location); location=NULL;                   } lsn=lsn+sub_size;                 /* The starting position of the sub-request */add_size+=sub_size; /* Already processed add_size size change */}}} printf ("\ n"); printf"Pre_process is complete!\n");    Fclose (Ssd->tracefile); for (i=0; i<ssd->parameter->channel_number;i++) for (j=0; j<ssd->parameter->die_chip;j++) for (k=0; k<ssd->parameter->plane_die;k++) {fprintf (Ssd->outputfile,"chip:%d,die:%d,plane:%d has free page:%d\n", i,j,k,ssd->channel_head[i].chip_head[0].die_head[j].plane_head[k].free_page);    Fflush (Ssd->outputfile); } return SSD;}

Ssdsim source code Analysis of Pre_process_page

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.