OpenSSD Cosmos+ Platform Firmware  0.0.2
The firmware of Cosmos+ OpenSSD Platform for TOSHIBA nand flash module.
data_buffer.c
Go to the documentation of this file.
1
2// data_buffer.c for Cosmos+ OpenSSD
3// Copyright (c) 2017 Hanyang University ENC Lab.
4// Contributed by Yong Ho Song <yhsong@enc.hanyang.ac.kr>
5// Jaewook Kwak <jwkwak@enc.hanyang.ac.kr>
6//
7// This file is part of Cosmos+ OpenSSD.
8//
9// Cosmos+ OpenSSD is free software; you can redistribute it and/or modify
10// it under the terms of the GNU General Public License as published by
11// the Free Software Foundation; either version 3, or (at your option)
12// any later version.
13//
14// Cosmos+ OpenSSD is distributed in the hope that it will be useful,
15// but WITHOUT ANY WARRANTY; without even the implied warranty of
16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17// See the GNU General Public License for more details.
18//
19// You should have received a copy of the GNU General Public License
20// along with Cosmos+ OpenSSD; see the file COPYING.
21// If not, see <http://www.gnu.org/licenses/>.
23
25// Company: ENC Lab. <http://enc.hanyang.ac.kr>
26// Engineer: Jaewook Kwak <jwkwak@enc.hanyang.ac.kr>
27//
28// Project Name: Cosmos+ OpenSSD
29// Design Name: Cosmos+ Firmware
30// Module Name: Data Buffer Manager
31// File Name: data_buffer.c
32//
33// Version: v1.0.0
34//
35// Description:
36// - manage data buffer used to transfer data between host system and NAND device
38
40// Revision History:
41//
42// * v1.0.0
43// - First draft
45
46#include "xil_printf.h"
47#include <assert.h>
48#include "memory_map.h"
49
54
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}
115
127unsigned int CheckDataBufHit(unsigned int reqSlotTag)
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}
195
220unsigned int AllocateDataBuf()
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}
249
268void UpdateDataBufEntryInfoBlockingReq(unsigned int bufEntry, unsigned int reqSlotTag)
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}
279
288unsigned int AllocateTempDataBuf(unsigned int dieNo) { return dieNo; }
289
298void UpdateTempDataBufEntryInfoBlockingReq(unsigned int bufEntry, unsigned int reqSlotTag)
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}
309
319void PutToDataBufHashList(unsigned int bufEntry)
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}
340
349void SelectiveGetFromDataBufHashList(unsigned int bufEntry)
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}
#define LSA_NONE
void UpdateTempDataBufEntryInfoBlockingReq(unsigned int bufEntry, unsigned int reqSlotTag)
Append the request to the blocking queue specified by given temp buffer entry.
Definition: data_buffer.c:298
void PutToDataBufHashList(unsigned int bufEntry)
Insert the given data buffer entry into the hash table.
Definition: data_buffer.c:319
void UpdateDataBufEntryInfoBlockingReq(unsigned int bufEntry, unsigned int reqSlotTag)
Append the request to the blocking queue of the specified data buffer entry.
Definition: data_buffer.c:268
void InitDataBuf()
Initialization process of the Data buffer.
Definition: data_buffer.c:85
unsigned int AllocateTempDataBuf(unsigned int dieNo)
Retrieve the index of temp buffer entry of the target die.
Definition: data_buffer.c:288
P_DATA_BUF_HASH_TABLE dataBufHashTablePtr
Definition: data_buffer.c:52
void SelectiveGetFromDataBufHashList(unsigned int bufEntry)
Remove the given data buffer entry from the hash table.
Definition: data_buffer.c:349
P_TEMPORARY_DATA_BUF_MAP tempDataBufMapPtr
Definition: data_buffer.c:53
unsigned int CheckDataBufHit(unsigned int reqSlotTag)
Get the data buffer entry index of the given request.
Definition: data_buffer.c:127
P_DATA_BUF_MAP dataBufMapPtr
Definition: data_buffer.c:50
DATA_BUF_LRU_LIST dataBufLruList
Definition: data_buffer.c:51
unsigned int AllocateDataBuf()
Retrieve a LRU data buffer entry from the LRU list.
Definition: data_buffer.c:220
#define DATA_BUF_NONE
Definition: data_buffer.h:57
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_FAIL
Definition: data_buffer.h:58
#define FindDataBufHashTableEntry(logicalSliceAddr)
Definition: data_buffer.h:62
#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
P_REQ_POOL reqPoolPtr
#define REQ_SLOT_TAG_NONE
unsigned int nextEntry
Definition: data_buffer.h:106
unsigned int dirty
Definition: data_buffer.h:110
unsigned int hashNextEntry
Definition: data_buffer.h:109
unsigned int prevEntry
Definition: data_buffer.h:105
unsigned int hashPrevEntry
Definition: data_buffer.h:108
unsigned int blockingReqTail
Definition: data_buffer.h:107
unsigned int logicalSliceAddr
Definition: data_buffer.h:104
unsigned int headEntry
Definition: data_buffer.h:149
unsigned int tailEntry
Definition: data_buffer.h:150
The structure of data buffer hash table.
Definition: data_buffer.h:160
DATA_BUF_HASH_ENTRY dataBufHash[AVAILABLE_DATA_BUFFER_ENTRY_COUNT]
Definition: data_buffer.h:161
The structure of LRU list that records the head and tail data buffer entry index of the LRU list.
Definition: data_buffer.h:134
unsigned int headEntry
Definition: data_buffer.h:135
unsigned int tailEntry
Definition: data_buffer.h:136
The structure of data buffer table.
Definition: data_buffer.h:121
DATA_BUF_ENTRY dataBuf[AVAILABLE_DATA_BUFFER_ENTRY_COUNT]
Definition: data_buffer.h:122
SSD_REQ_FORMAT reqPool[AVAILABLE_OUNTSTANDING_REQ_COUNT]
unsigned int logicalSliceAddr
unsigned int nextBlockingReq
unsigned int prevBlockingReq
unsigned int blockingReqTail
Definition: data_buffer.h:166
The structure of the temp data buffer table.
Definition: data_buffer.h:178
TEMPORARY_DATA_BUF_ENTRY tempDataBuf[AVAILABLE_TEMPORARY_DATA_BUFFER_ENTRY_COUNT]
Definition: data_buffer.h:179