OpenSSD Cosmos+ Platform Firmware  0.0.2
The firmware of Cosmos+ OpenSSD Platform for TOSHIBA nand flash module.
data_buffer.c File Reference
#include "xil_printf.h"
#include <assert.h>
#include "memory_map.h"
Include dependency graph for data_buffer.c:

Go to the source code of this file.

Functions

void InitDataBuf ()
 Initialization process of the Data buffer. More...
 
unsigned int CheckDataBufHit (unsigned int reqSlotTag)
 Get the data buffer entry index of the given request. More...
 
unsigned int AllocateDataBuf ()
 Retrieve a LRU data buffer entry from the LRU list. More...
 
void UpdateDataBufEntryInfoBlockingReq (unsigned int bufEntry, unsigned int reqSlotTag)
 Append the request to the blocking queue of the specified data buffer entry. More...
 
unsigned int AllocateTempDataBuf (unsigned int dieNo)
 Retrieve the index of temp buffer entry of the target die. More...
 
void UpdateTempDataBufEntryInfoBlockingReq (unsigned int bufEntry, unsigned int reqSlotTag)
 Append the request to the blocking queue specified by given temp buffer entry. More...
 
void PutToDataBufHashList (unsigned int bufEntry)
 Insert the given data buffer entry into the hash table. More...
 
void SelectiveGetFromDataBufHashList (unsigned int bufEntry)
 Remove the given data buffer entry from the hash table. More...
 

Variables

P_DATA_BUF_MAP dataBufMapPtr
 
DATA_BUF_LRU_LIST dataBufLruList
 
P_DATA_BUF_HASH_TABLE dataBufHashTablePtr
 
P_TEMPORARY_DATA_BUF_MAP tempDataBufMapPtr
 

Function Documentation

◆ AllocateDataBuf()

unsigned int AllocateDataBuf ( )

Retrieve a LRU data buffer entry from the LRU list.

Choose the LRU data buffer entry from the LRU list, and return it's index.

If the evictedEntry is DATA_BUF_NONE, that's an error or the dataBufLruList is empty.

If the evictedEntry, namely the last entry of LRU list, exists and:

  • it's also the head of LRU list:

    this means that there is only entry in the LRU list, therefore we don't need to modify the prev/next entry of evictedEntry.

  • it's the body of LRU list:

    we have to make the prev entry be the new tail of LRU list, and make the evicted entry be the new head of the LRU list.

After the evicted entry being moved from the tail of LRU entry to head, we have to call the function SelectiveGetFromDataBufHashList to remove the evictedEntry from its bucket of hash table.

Definition at line 220 of file data_buffer.c.

221{
222 unsigned int evictedEntry = dataBufLruList.tailEntry;
223
224 if (evictedEntry == DATA_BUF_NONE)
225 assert(!"[WARNING] There is no valid buffer entry [WARNING]");
226
227 if (dataBufMapPtr->dataBuf[evictedEntry].prevEntry != DATA_BUF_NONE)
228 {
231
235 dataBufLruList.headEntry = evictedEntry;
236 }
237 else
238 {
241 dataBufLruList.headEntry = evictedEntry;
242 dataBufLruList.tailEntry = evictedEntry;
243 }
244
246
247 return evictedEntry;
248}
void SelectiveGetFromDataBufHashList(unsigned int bufEntry)
Remove the given data buffer entry from the hash table.
Definition: data_buffer.c:349
P_DATA_BUF_MAP dataBufMapPtr
Definition: data_buffer.c:50
DATA_BUF_LRU_LIST dataBufLruList
Definition: data_buffer.c:51
#define DATA_BUF_NONE
Definition: data_buffer.h:57
unsigned int nextEntry
Definition: data_buffer.h:106
unsigned int prevEntry
Definition: data_buffer.h:105
unsigned int headEntry
Definition: data_buffer.h:135
unsigned int tailEntry
Definition: data_buffer.h:136
DATA_BUF_ENTRY dataBuf[AVAILABLE_DATA_BUFFER_ENTRY_COUNT]
Definition: data_buffer.h:122
Here is the call graph for this function:
Here is the caller graph for this function:

◆ AllocateTempDataBuf()

unsigned int AllocateTempDataBuf ( unsigned int  dieNo)

Retrieve the index of temp buffer entry of the target die.

By default, there is only NUM_DIES entries in the tempDataBuf, so we can just use the serial number of each die to determine which temp entry should be used.

Parameters
dieNoan unique number of the specified die

Definition at line 288 of file data_buffer.c.

288{ return dieNo; }
Here is the caller graph for this function:

◆ CheckDataBufHit()

unsigned int CheckDataBufHit ( unsigned int  reqSlotTag)

Get the data buffer entry index of the given request.

Try to find the data buffer entry of the given request (with same logicalSliceAddr) by traversing the correspoding bucket of the given request.

If the request found, the corresponding data buffer entry become the Most Recently Used entry and should be moved to the head of LRU list.

Parameters
reqSlotTagthe request pool entry index of the request to be check

Definition at line 127 of file data_buffer.c.

128{
129 unsigned int bufEntry, logicalSliceAddr;
130
131 // get the bucket index of the given request
132 logicalSliceAddr = reqPoolPtr->reqPool[reqSlotTag].logicalSliceAddr;
134
135 // traverse the bucket and try to find the data buffer entry of target request
136 while (bufEntry != DATA_BUF_NONE)
137 {
138 if (dataBufMapPtr->dataBuf[bufEntry].logicalSliceAddr == logicalSliceAddr)
139 {
140 // remove from the LRU list before making it MRU
141 if ((dataBufMapPtr->dataBuf[bufEntry].nextEntry != DATA_BUF_NONE) &&
143 {
144 // body of LRU list
149 }
150 else if ((dataBufMapPtr->dataBuf[bufEntry].nextEntry == DATA_BUF_NONE) &&
152 {
153 // tail of LRU list, modify the LRU tail
156 }
157 else if ((dataBufMapPtr->dataBuf[bufEntry].nextEntry != DATA_BUF_NONE) &&
159 {
160 // head of LRU list, modify the LRU head
163 }
164 else
165 {
166 // the only entry in LRU list, make LRU list empty
169 }
170
171 // make this entry the MRU entry (move to the head of LRU list)
173 {
177 dataBufLruList.headEntry = bufEntry;
178 }
179 else
180 {
183 dataBufLruList.headEntry = bufEntry;
184 dataBufLruList.tailEntry = bufEntry;
185 }
186
187 return bufEntry;
188 }
189 else
190 bufEntry = dataBufMapPtr->dataBuf[bufEntry].hashNextEntry;
191 }
192
193 return DATA_BUF_FAIL;
194}
P_DATA_BUF_HASH_TABLE dataBufHashTablePtr
Definition: data_buffer.c:52
#define DATA_BUF_FAIL
Definition: data_buffer.h:58
#define FindDataBufHashTableEntry(logicalSliceAddr)
Definition: data_buffer.h:62
P_REQ_POOL reqPoolPtr
unsigned int hashNextEntry
Definition: data_buffer.h:109
unsigned int logicalSliceAddr
Definition: data_buffer.h:104
unsigned int headEntry
Definition: data_buffer.h:149
DATA_BUF_HASH_ENTRY dataBufHash[AVAILABLE_DATA_BUFFER_ENTRY_COUNT]
Definition: data_buffer.h:161
SSD_REQ_FORMAT reqPool[AVAILABLE_OUNTSTANDING_REQ_COUNT]
unsigned int logicalSliceAddr
Here is the caller graph for this function:

◆ InitDataBuf()

void InitDataBuf ( )

Initialization process of the Data buffer.

Three buffer related lists will be initialized in this function

There are 16 x NUM_DIES entries in the dataBuf, and all the elements of dataBuf will be initialized to:

  • logicalSliceAddr: not belongs to any request yet, thus just point to LSA_NONE (0xffffffff)
  • prevEntry points to prev element of the dataBuf array (except for head)
  • nextEntry points to next element of the dataBuf array (except for tail)
  • hashPrevEntry points to DATA_BUF_NONE, because it doesn't belongs to any bucket yet
  • hashNextEntry points to DATA_BUF_NONE, because it doesn't belongs to any bucket yet
  • dirty flag is not set
  • blockingReqTail: no blocking request at the beginning, thus points to none

There are 16 x NUM_DIES entries in the dataBufHashTable, and all the elements will be initialized to empty bucket, so:

  • headEntry and tailEntry both point to DATA_BUF_NONE (0xffff = 65535)

There are NUM_DIES entries in the tempDataBuf, and all the elements of it will be initialized to:

  • blockingReqTail: no blocking request at the beginning, thus points to none

And the head/tail of dataBufLruList points to the first/last entry of dataBuf, this means the initial dataBufLruList contains all the data buffer entries, therefore the data buffer should be allocated from the last element of dataBuf array.

Definition at line 85 of file data_buffer.c.

86{
87 int bufEntry;
88
92
93 for (bufEntry = 0; bufEntry < AVAILABLE_DATA_BUFFER_ENTRY_COUNT; bufEntry++)
94 {
96 dataBufMapPtr->dataBuf[bufEntry].prevEntry = bufEntry - 1;
97 dataBufMapPtr->dataBuf[bufEntry].nextEntry = bufEntry + 1;
100
105 }
106
111
112 for (bufEntry = 0; bufEntry < AVAILABLE_TEMPORARY_DATA_BUFFER_ENTRY_COUNT; bufEntry++)
114}
#define LSA_NONE
P_TEMPORARY_DATA_BUF_MAP tempDataBufMapPtr
Definition: data_buffer.c:53
struct _DATA_BUF_HASH_TABLE * P_DATA_BUF_HASH_TABLE
struct _DATA_BUF_MAP * P_DATA_BUF_MAP
#define AVAILABLE_DATA_BUFFER_ENTRY_COUNT
Definition: data_buffer.h:54
#define DATA_BUF_CLEAN
Definition: data_buffer.h:60
struct _TEMPORARY_DATA_BUF_MAP * P_TEMPORARY_DATA_BUF_MAP
#define AVAILABLE_TEMPORARY_DATA_BUFFER_ENTRY_COUNT
Definition: data_buffer.h:55
#define TEMPORARY_DATA_BUFFER_MAP_ADDR
Definition: memory_map.h:97
#define DATA_BUFFFER_HASH_TABLE_ADDR
Definition: memory_map.h:96
#define DATA_BUFFER_MAP_ADDR
Definition: memory_map.h:95
#define REQ_SLOT_TAG_NONE
unsigned int dirty
Definition: data_buffer.h:110
unsigned int hashPrevEntry
Definition: data_buffer.h:108
unsigned int blockingReqTail
Definition: data_buffer.h:107
unsigned int tailEntry
Definition: data_buffer.h:150
unsigned int blockingReqTail
Definition: data_buffer.h:166
TEMPORARY_DATA_BUF_ENTRY tempDataBuf[AVAILABLE_TEMPORARY_DATA_BUFFER_ENTRY_COUNT]
Definition: data_buffer.h:179
Here is the caller graph for this function:

◆ PutToDataBufHashList()

void PutToDataBufHashList ( unsigned int  bufEntry)

Insert the given data buffer entry into the hash table.

Insert the given data buffer entry into the tail of hash table bucket specified by the logicalSliceAddr of the given entry, and modify the tail (head as well, if needed) of target hash table bucket.

Parameters
bufEntrythe index of the data buffer entry to be inserted

Definition at line 319 of file data_buffer.c.

320{
321 unsigned int hashEntry;
322
324
326 {
330 dataBufHashTablePtr->dataBufHash[hashEntry].tailEntry = bufEntry;
331 }
332 else
333 {
336 dataBufHashTablePtr->dataBufHash[hashEntry].headEntry = bufEntry;
337 dataBufHashTablePtr->dataBufHash[hashEntry].tailEntry = bufEntry;
338 }
339}
Here is the caller graph for this function:

◆ SelectiveGetFromDataBufHashList()

void SelectiveGetFromDataBufHashList ( unsigned int  bufEntry)

Remove the given data buffer entry from the hash table.

We may need to modify the head/tail index of corresponding bucket specified by the logicalSliceAddr of the given data buffer entry.

Parameters
bufEntrythe index of the data buffer entry to be removed

Definition at line 349 of file data_buffer.c.

350{
352 {
353 unsigned int prevBufEntry, nextBufEntry, hashEntry;
354
355 prevBufEntry = dataBufMapPtr->dataBuf[bufEntry].hashPrevEntry;
356 nextBufEntry = dataBufMapPtr->dataBuf[bufEntry].hashNextEntry;
358
359 // body, no need to modify the head or tail index of this bucket
360 if ((nextBufEntry != DATA_BUF_NONE) && (prevBufEntry != DATA_BUF_NONE))
361 {
362 dataBufMapPtr->dataBuf[prevBufEntry].hashNextEntry = nextBufEntry;
363 dataBufMapPtr->dataBuf[nextBufEntry].hashPrevEntry = prevBufEntry;
364 }
365
366 // tail, don't forget to modify the tail index of this bucket
367 else if ((nextBufEntry == DATA_BUF_NONE) && (prevBufEntry != DATA_BUF_NONE))
368 {
370 dataBufHashTablePtr->dataBufHash[hashEntry].tailEntry = prevBufEntry;
371 }
372
373 // head, don't forget to modify the head index of this bucket
374 else if ((nextBufEntry != DATA_BUF_NONE) && (prevBufEntry == DATA_BUF_NONE))
375 {
377 dataBufHashTablePtr->dataBufHash[hashEntry].headEntry = nextBufEntry;
378 }
379
380 // bucket with only one entry, both the head and tail index should be modified
381 else
382 {
385 }
386 }
387}
Here is the caller graph for this function:

◆ UpdateDataBufEntryInfoBlockingReq()

void UpdateDataBufEntryInfoBlockingReq ( unsigned int  bufEntry,
unsigned int  reqSlotTag 
)

Append the request to the blocking queue of the specified data buffer entry.

In current fw implementation, a slice request may be split into several sub-requests, and these sub-requests can share the same data buffer since they must be executed in correct order.

However, since the scheduler may reorder the requests base on the priority, the fw must make sure these sub-requests are executed in the correct order. To do this, each data buffer entry maintains a blocking request queue (DATA_BUF_ENTRY::blockingReqTail). Whenever a new request is created, its request entry index will be appended to the blocking queue of the data buffer allocated for it.

See also
ReqTransSliceToLowLevel(), CheckBufDep(), SelectLowLevelReqQ() and DATA_BUF_ENTRY.
Parameters
byfEntryThe data buffer entry index of the newly created request.
reqSlotTagThe request pool entry index of the newly created request.

Definition at line 268 of file data_buffer.c.

269{
270 // don't forget to update the original tail blocking request if it exists
272 {
275 }
276
277 dataBufMapPtr->dataBuf[bufEntry].blockingReqTail = reqSlotTag;
278}
unsigned int nextBlockingReq
unsigned int prevBlockingReq
Here is the caller graph for this function:

◆ UpdateTempDataBufEntryInfoBlockingReq()

void UpdateTempDataBufEntryInfoBlockingReq ( unsigned int  bufEntry,
unsigned int  reqSlotTag 
)

Append the request to the blocking queue specified by given temp buffer entry.

Similar to UpdateDataBufEntryInfoBlockingReq(), but the data buffer is temp buffer.

Parameters
byfEntrythe temp data buffer entry index of the specified request
reqSlotTagthe request pool entry index of the request to be

Definition at line 298 of file data_buffer.c.

299{
300 // don't forget to update the original tail blocking request if it exists
302 {
305 }
306
307 tempDataBufMapPtr->tempDataBuf[bufEntry].blockingReqTail = reqSlotTag;
308}
Here is the caller graph for this function:

Variable Documentation

◆ dataBufHashTablePtr

P_DATA_BUF_HASH_TABLE dataBufHashTablePtr

Definition at line 52 of file data_buffer.c.

◆ dataBufLruList

DATA_BUF_LRU_LIST dataBufLruList

Definition at line 51 of file data_buffer.c.

◆ dataBufMapPtr

P_DATA_BUF_MAP dataBufMapPtr

Definition at line 50 of file data_buffer.c.

◆ tempDataBufMapPtr

P_TEMPORARY_DATA_BUF_MAP tempDataBufMapPtr

Definition at line 53 of file data_buffer.c.