OpenSSD Cosmos+ Platform Firmware  0.0.2
The firmware of Cosmos+ OpenSSD Platform for TOSHIBA nand flash module.
request_allocation.c
Go to the documentation of this file.
1
2// request_allocation.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: Request Allocator
31// File Name: request_allocation.c
32//
33// Version: v1.0.0
34//
35// Description:
36// - allocate requests to each request queue
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
57
59unsigned int blockedReqCnt;
60
78{
79 int chNo, wayNo, reqSlotTag;
80
81 reqPoolPtr = (P_REQ_POOL)REQ_POOL_ADDR; // revise address
82
83 freeReqQ.headReq = 0;
85
88 sliceReqQ.reqCnt = 0;
89
93
97
98 for (chNo = 0; chNo < USER_CHANNELS; chNo++)
99 for (wayNo = 0; wayNo < USER_WAYS; wayNo++)
100 {
103 blockedByRowAddrDepReqQ[chNo][wayNo].reqCnt = 0;
104
105 nandReqQ[chNo][wayNo].headReq = REQ_SLOT_TAG_NONE;
106 nandReqQ[chNo][wayNo].tailReq = REQ_SLOT_TAG_NONE;
107 nandReqQ[chNo][wayNo].reqCnt = 0;
108 }
109
110 for (reqSlotTag = 0; reqSlotTag < AVAILABLE_OUNTSTANDING_REQ_COUNT; reqSlotTag++)
111 {
115 reqPoolPtr->reqPool[reqSlotTag].prevReq = reqSlotTag - 1;
116 reqPoolPtr->reqPool[reqSlotTag].nextReq = reqSlotTag + 1;
117 }
118
121 freeReqQ.reqCnt = AVAILABLE_OUNTSTANDING_REQ_COUNT; // TODO: move this up ?
122
124 blockedReqCnt = 0;
125}
126
142void PutToFreeReqQ(unsigned int reqSlotTag)
143{
145 {
149 freeReqQ.tailReq = reqSlotTag;
150 }
151 else
152 {
155 freeReqQ.headReq = reqSlotTag;
156 freeReqQ.tailReq = reqSlotTag;
157 }
158
161}
162
172unsigned int GetFromFreeReqQ()
173{
174 unsigned int reqSlotTag;
175
176 reqSlotTag = freeReqQ.headReq;
177
178 // try to release some request entries by doing scheduling
179 if (reqSlotTag == REQ_SLOT_TAG_NONE)
180 {
182 reqSlotTag = freeReqQ.headReq;
183 }
184
185 // if the free queue becomes empty, don't forget to update its tail pointer
186 if (reqPoolPtr->reqPool[reqSlotTag].nextReq != REQ_SLOT_TAG_NONE)
187 {
190 }
191 else
192 {
195 }
196
199
200 return reqSlotTag;
201}
202
210void PutToSliceReqQ(unsigned int reqSlotTag)
211{
213 {
217 sliceReqQ.tailReq = reqSlotTag;
218 }
219 else
220 {
223 sliceReqQ.headReq = reqSlotTag;
224 sliceReqQ.tailReq = reqSlotTag;
225 }
226
229}
230
241unsigned int GetFromSliceReqQ()
242{
243 unsigned int reqSlotTag;
244
245 reqSlotTag = sliceReqQ.headReq;
246
247 if (reqSlotTag == REQ_SLOT_TAG_NONE)
248 return REQ_SLOT_TAG_FAIL;
249
250 if (reqPoolPtr->reqPool[reqSlotTag].nextReq != REQ_SLOT_TAG_NONE)
251 {
254 }
255 else
256 {
259 }
260
263
264 return reqSlotTag;
265}
266
277void PutToBlockedByBufDepReqQ(unsigned int reqSlotTag)
278{
280 {
284 blockedByBufDepReqQ.tailReq = reqSlotTag;
285 }
286 else
287 {
290 blockedByBufDepReqQ.headReq = reqSlotTag;
291 blockedByBufDepReqQ.tailReq = reqSlotTag;
292 }
293
297}
298
309void SelectiveGetFromBlockedByBufDepReqQ(unsigned int reqSlotTag)
310{
311 unsigned int prevReq, nextReq;
312
313 if (reqSlotTag == REQ_SLOT_TAG_NONE)
314 assert(!"[WARNING] Wrong reqSlotTag [WARNING]");
315
316 prevReq = reqPoolPtr->reqPool[reqSlotTag].prevReq;
317 nextReq = reqPoolPtr->reqPool[reqSlotTag].nextReq;
318
319 if ((nextReq != REQ_SLOT_TAG_NONE) && (prevReq != REQ_SLOT_TAG_NONE))
320 {
321 reqPoolPtr->reqPool[prevReq].nextReq = nextReq;
322 reqPoolPtr->reqPool[nextReq].prevReq = prevReq;
323 }
324 else if ((nextReq == REQ_SLOT_TAG_NONE) && (prevReq != REQ_SLOT_TAG_NONE))
325 {
328 }
329 else if ((nextReq != REQ_SLOT_TAG_NONE) && (prevReq == REQ_SLOT_TAG_NONE))
330 {
333 }
334 else
335 {
338 }
339
343}
344
357void PutToBlockedByRowAddrDepReqQ(unsigned int reqSlotTag, unsigned int chNo, unsigned int wayNo)
358{
359 if (blockedByRowAddrDepReqQ[chNo][wayNo].tailReq != REQ_SLOT_TAG_NONE)
360 {
361 reqPoolPtr->reqPool[reqSlotTag].prevReq = blockedByRowAddrDepReqQ[chNo][wayNo].tailReq;
363 reqPoolPtr->reqPool[blockedByRowAddrDepReqQ[chNo][wayNo].tailReq].nextReq = reqSlotTag;
364 blockedByRowAddrDepReqQ[chNo][wayNo].tailReq = reqSlotTag;
365 }
366 else
367 {
370 blockedByRowAddrDepReqQ[chNo][wayNo].headReq = reqSlotTag;
371 blockedByRowAddrDepReqQ[chNo][wayNo].tailReq = reqSlotTag;
372 }
373
375 blockedByRowAddrDepReqQ[chNo][wayNo].reqCnt++;
377}
378
388void SelectiveGetFromBlockedByRowAddrDepReqQ(unsigned int reqSlotTag, unsigned int chNo, unsigned int wayNo)
389{
390 unsigned int prevReq, nextReq;
391
392 if (reqSlotTag == REQ_SLOT_TAG_NONE)
393 assert(!"[WARNING] Wrong reqSlotTag [WARNING]");
394
395 prevReq = reqPoolPtr->reqPool[reqSlotTag].prevReq;
396 nextReq = reqPoolPtr->reqPool[reqSlotTag].nextReq;
397
398 if ((nextReq != REQ_SLOT_TAG_NONE) && (prevReq != REQ_SLOT_TAG_NONE))
399 {
400 reqPoolPtr->reqPool[prevReq].nextReq = nextReq;
401 reqPoolPtr->reqPool[nextReq].prevReq = prevReq;
402 }
403 else if ((nextReq == REQ_SLOT_TAG_NONE) && (prevReq != REQ_SLOT_TAG_NONE))
404 {
406 blockedByRowAddrDepReqQ[chNo][wayNo].tailReq = prevReq;
407 }
408 else if ((nextReq != REQ_SLOT_TAG_NONE) && (prevReq == REQ_SLOT_TAG_NONE))
409 {
411 blockedByRowAddrDepReqQ[chNo][wayNo].headReq = nextReq;
412 }
413 else
414 {
417 }
418
420 blockedByRowAddrDepReqQ[chNo][wayNo].reqCnt--;
422}
423
431void PutToNvmeDmaReqQ(unsigned int reqSlotTag)
432{
434 {
438 nvmeDmaReqQ.tailReq = reqSlotTag;
439 }
440 else
441 {
444 nvmeDmaReqQ.headReq = reqSlotTag;
445 nvmeDmaReqQ.tailReq = reqSlotTag;
446 }
447
450}
451
465void SelectiveGetFromNvmeDmaReqQ(unsigned int reqSlotTag)
466{
467 unsigned int prevReq, nextReq;
468
469 prevReq = reqPoolPtr->reqPool[reqSlotTag].prevReq;
470 nextReq = reqPoolPtr->reqPool[reqSlotTag].nextReq;
471
472 if ((nextReq != REQ_SLOT_TAG_NONE) && (prevReq != REQ_SLOT_TAG_NONE))
473 {
474 reqPoolPtr->reqPool[prevReq].nextReq = nextReq;
475 reqPoolPtr->reqPool[nextReq].prevReq = prevReq;
476 }
477 else if ((nextReq == REQ_SLOT_TAG_NONE) && (prevReq != REQ_SLOT_TAG_NONE))
478 {
480 nvmeDmaReqQ.tailReq = prevReq;
481 }
482 else if ((nextReq != REQ_SLOT_TAG_NONE) && (prevReq == REQ_SLOT_TAG_NONE))
483 {
485 nvmeDmaReqQ.headReq = nextReq;
486 }
487 else
488 {
491 }
492
495
496 PutToFreeReqQ(reqSlotTag);
497 ReleaseBlockedByBufDepReq(reqSlotTag); // release the request from blocking request if needed
498}
499
512void PutToNandReqQ(unsigned int reqSlotTag, unsigned chNo, unsigned wayNo)
513{
514 if (nandReqQ[chNo][wayNo].tailReq != REQ_SLOT_TAG_NONE)
515 {
516 reqPoolPtr->reqPool[reqSlotTag].prevReq = nandReqQ[chNo][wayNo].tailReq;
518 reqPoolPtr->reqPool[nandReqQ[chNo][wayNo].tailReq].nextReq = reqSlotTag;
519 nandReqQ[chNo][wayNo].tailReq = reqSlotTag;
520 }
521 else
522 {
525 nandReqQ[chNo][wayNo].headReq = reqSlotTag;
526 nandReqQ[chNo][wayNo].tailReq = reqSlotTag;
527 }
528
530 nandReqQ[chNo][wayNo].reqCnt++;
532}
533
548void GetFromNandReqQ(unsigned int chNo, unsigned int wayNo, unsigned int reqStatus, unsigned int reqCode)
549{
550 unsigned int reqSlotTag;
551
552 reqSlotTag = nandReqQ[chNo][wayNo].headReq;
553 if (reqSlotTag == REQ_SLOT_TAG_NONE)
554 assert(!"[WARNING] there is no request in Nand-req-queue[WARNING]");
555
556 if (reqPoolPtr->reqPool[reqSlotTag].nextReq != REQ_SLOT_TAG_NONE)
557 {
558 nandReqQ[chNo][wayNo].headReq = reqPoolPtr->reqPool[reqSlotTag].nextReq;
560 }
561 else
562 {
563 nandReqQ[chNo][wayNo].headReq = REQ_SLOT_TAG_NONE;
564 nandReqQ[chNo][wayNo].tailReq = REQ_SLOT_TAG_NONE;
565 }
566
568 nandReqQ[chNo][wayNo].reqCnt--;
570
571 PutToFreeReqQ(reqSlotTag);
572 ReleaseBlockedByBufDepReq(reqSlotTag);
573}
#define USER_CHANNELS
Definition: ftl_config.h:207
#define USER_WAYS
Definition: ftl_config.h:208
#define REQ_POOL_ADDR
Definition: memory_map.h:109
unsigned int GetFromFreeReqQ()
Get a free request from the free request queue.
SLICE_REQUEST_QUEUE sliceReqQ
unsigned int blockedReqCnt
void SelectiveGetFromBlockedByRowAddrDepReqQ(unsigned int reqSlotTag, unsigned int chNo, unsigned int wayNo)
Remove the given request from the blockedByRowAddrDepReqQ.
void PutToFreeReqQ(unsigned int reqSlotTag)
Add the given request to the free request queue.
NVME_DMA_REQUEST_QUEUE nvmeDmaReqQ
unsigned int GetFromSliceReqQ()
Get a slice request from the slice request queue.
void PutToNandReqQ(unsigned int reqSlotTag, unsigned chNo, unsigned wayNo)
Add the given request to nandReqQ of the specified die.
void PutToBlockedByBufDepReqQ(unsigned int reqSlotTag)
Add the given request to blockedByBufDepReqQ.
void PutToNvmeDmaReqQ(unsigned int reqSlotTag)
Add the given request to the NVMe DMA request queue and update its status.
void GetFromNandReqQ(unsigned int chNo, unsigned int wayNo, unsigned int reqStatus, unsigned int reqCode)
Move the head request of the specified nandReqQ queue to freeReqQ.
void InitReqPool()
Initialize the request pool and the request queues.
unsigned int notCompletedNandReqCnt
void PutToBlockedByRowAddrDepReqQ(unsigned int reqSlotTag, unsigned int chNo, unsigned int wayNo)
Add the given request to blockedByRowAddrDepReqQ.
void SelectiveGetFromBlockedByBufDepReqQ(unsigned int reqSlotTag)
Remove the given request from the blockedByBufDepReqQ.
BLOCKED_BY_BUFFER_DEPENDENCY_REQUEST_QUEUE blockedByBufDepReqQ
void SelectiveGetFromNvmeDmaReqQ(unsigned int reqSlotTag)
Move the specified entry from the nvmeDmaReqQ to the freeReqQ.
void PutToSliceReqQ(unsigned int reqSlotTag)
Add the given request to the slice request queue.
P_REQ_POOL reqPoolPtr
NAND_REQUEST_QUEUE nandReqQ[USER_CHANNELS][USER_WAYS]
FREE_REQUEST_QUEUE freeReqQ
BLOCKED_BY_ROW_ADDR_DEPENDENCY_REQUEST_QUEUE blockedByRowAddrDepReqQ[USER_CHANNELS][USER_WAYS]
#define AVAILABLE_OUNTSTANDING_REQ_COUNT
#define REQ_SLOT_TAG_FAIL
#define REQ_SLOT_TAG_NONE
struct _REQ_POOL * P_REQ_POOL
#define REQ_QUEUE_TYPE_BLOCKED_BY_ROW_ADDR_DEP
#define REQ_QUEUE_TYPE_BLOCKED_BY_BUF_DEP
#define REQ_QUEUE_TYPE_NVME_DMA
#define REQ_QUEUE_TYPE_NONE
#define REQ_QUEUE_TYPE_NAND
#define REQ_QUEUE_TYPE_SLICE
#define REQ_QUEUE_TYPE_FREE
void SyncAvailFreeReq()
Try release request entries by doing scheduling (both NVMe and NAND).
void ReleaseBlockedByBufDepReq(unsigned int reqSlotTag)
Pop the specified request from the buffer dependency queue.
unsigned int reqCnt
Definition: request_queue.h:54
unsigned int headReq
Definition: request_queue.h:52
unsigned int tailReq
Definition: request_queue.h:53
unsigned int tailReq
Definition: request_queue.h:93
unsigned int headReq
Definition: request_queue.h:92
unsigned int reqCnt
Definition: request_queue.h:94
The request entries pool for both NVMe and NAND requests.
SSD_REQ_FORMAT reqPool[AVAILABLE_OUNTSTANDING_REQ_COUNT]
unsigned int headReq
Definition: request_queue.h:60
unsigned int reqCnt
Definition: request_queue.h:62
unsigned int tailReq
Definition: request_queue.h:61
unsigned int nextReq
unsigned int nextBlockingReq
unsigned int prevBlockingReq
unsigned int reqQueueType
unsigned int prevReq