OpenSSD Cosmos+ Platform Firmware  0.0.2
The firmware of Cosmos+ OpenSSD Platform for TOSHIBA nand flash module.
address_translation.h
Go to the documentation of this file.
1
2// address_translation.h 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: Address Translator
31// File Name: address translation.h
32//
33// Version: v1.0.0
34//
35// Description:
36// - define parameters, data structure and functions of address translator
38
40// Revision History:
41//
42// * v1.0.0
43// - First draft
45
46#ifndef ADDRESS_TRANSLATION_H_
47#define ADDRESS_TRANSLATION_H_
48
49#include "ftl_config.h"
50#include "nvme/nvme.h"
51
52/* LSA for Logical Slice Address */
53
54#define LSA_NONE 0xffffffff
55#define LSA_FAIL 0xffffffff
56
57#define VSA_NONE 0xffffffff
58#define VSA_FAIL 0xffffffff
59
60#define PAGE_NONE 0xffff
61
62#define BLOCK_NONE 0xffff
63#define BLOCK_FAIL 0xffff
64
65#define DIE_NONE 0xff
66#define DIE_FAIL 0xff
67
68#define RESERVED_FREE_BLOCK_COUNT 0x1
69
70#define GET_FREE_BLOCK_NORMAL 0x0 // get free block for normal request
71#define GET_FREE_BLOCK_GC 0x1 // get free block for gc request
72
73#define BLOCK_STATE_NORMAL 0 // this block is not bad block
74#define BLOCK_STATE_BAD 1 // this block is bad block
75
76#define DIE_STATE_BAD_BLOCK_TABLE_NOT_EXIST 0 // no bbt, do build and persist the bbt (initialize)
77#define DIE_STATE_BAD_BLOCK_TABLE_EXIST 1 // bbt exists, don't build and persist the bbt (initialize)
78#define DIE_STATE_BAD_BLOCK_TABLE_HOLD 2 // no unpersisted bad block, don't update the bbt (runtime)
79#define DIE_STATE_BAD_BLOCK_TABLE_UPDATE 3 // unpersisted bad blocks exist, do update the bbt (runtime)
80
81#define BAD_BLOCK_TABLE_MAKER_IDLE 0 // no need to rebuilt to bbt
82#define BAD_BLOCK_TABLE_MAKER_TRIGGER 1 // rebuild the bbt, only used in initialization
83
84#define CLEAN_DATA_IN_BYTE 0xff // the bit pattern for determining bad block
85
86/* how many pages are used for storing the bbt of that die */
87#define USED_PAGES_FOR_BAD_BLOCK_TABLE_PER_DIE (TOTAL_BLOCKS_PER_DIE / BYTES_PER_DATA_REGION_OF_PAGE + 1)
88#define DATA_SIZE_OF_BAD_BLOCK_TABLE_PER_DIE (TOTAL_BLOCKS_PER_DIE)
89
98#define START_PAGE_NO_OF_BAD_BLOCK_TABLE_BLOCK (1)
99
100#define BBT_INFO_GROWN_BAD_UPDATE_NONE 0 // the bbt no need to be updated
101#define BBT_INFO_GROWN_BAD_UPDATE_BOOKED 1 // the bbt should be updated
102
103/* -------------------------------------------------------------------------- */
104/* NAND Address Translation (Virtual -> Virtual) */
105/* -------------------------------------------------------------------------- */
106
107#define Vsa2VdieTranslation(virtualSliceAddr) ((virtualSliceAddr) % (USER_DIES))
108#define Vsa2VblockTranslation(virtualSliceAddr) (((virtualSliceAddr) / (USER_DIES)) / (SLICES_PER_BLOCK))
109#define Vsa2VpageTranslation(virtualSliceAddr) (((virtualSliceAddr) / (USER_DIES)) % (SLICES_PER_BLOCK))
110
131#define Vorg2VsaTranslation(dieNo, blockNo, pageNo) \
132 ((dieNo) + (USER_DIES) * ((blockNo) * (SLICES_PER_BLOCK) + (pageNo)))
133
134/* -------------------------------------------------------------------------- */
135/* NAND Address Translation (Virtual -> Physical) */
136/* -------------------------------------------------------------------------- */
137
138#define Vdie2PchTranslation(dieNo) ((dieNo) % (USER_CHANNELS))
139#define Vdie2PwayTranslation(dieNo) ((dieNo) / (USER_CHANNELS))
140
150#define Vblock2PblockOfTbsTranslation(blockNo) \
151 (((blockNo) / (USER_BLOCKS_PER_LUN)) * (TOTAL_BLOCKS_PER_LUN) + ((blockNo) % (USER_BLOCKS_PER_LUN)))
152
159#define Vblock2PblockOfMbsTranslation(blockNo) \
160 (((blockNo) / (USER_BLOCKS_PER_LUN)) * (MAIN_BLOCKS_PER_LUN) + ((blockNo) % (USER_BLOCKS_PER_LUN)))
161
168#define Vpage2PlsbPageTranslation(pageNo) ((pageNo) > (0) ? (2 * (pageNo)-1) : (0))
169
170/* -------------------------------------------------------------------------- */
171/* NAND Address Translation (Physical -> Virtual) */
172/* -------------------------------------------------------------------------- */
173
179#define Pcw2VdieTranslation(chNo, wayNo) ((chNo) + (wayNo) * (USER_CHANNELS))
180
186#define PlsbPage2VpageTranslation(pageNo) ((pageNo) > (0) ? (((pageNo) + 1) / 2) : (0))
187
188/* -------------------------------------------------------------------------- */
189/* Logical <-> Virtual Slice Address Mapping Table */
190/* -------------------------------------------------------------------------- */
191
196{
197 /* The corresponding virtual slice address (index) of the logical slice. */
198 unsigned int virtualSliceAddr;
200
204typedef struct _LOGICAL_SLICE_MAP
205{
208
213{
214 /* The corresponding logical slice address (index) of the virtual slice. */
215 unsigned int logicalSliceAddr;
217
221typedef struct _VIRTUAL_SLICE_MAP
222{
225
226/* -------------------------------------------------------------------------- */
227/* Structures for managing Virtual Block Metadata */
228/* -------------------------------------------------------------------------- */
229
234{
235 unsigned int bad : 1; // 1 indicates that this block is bad block
236 unsigned int free : 1; // 1 indicates that this block is free block
237 unsigned int invalidSliceCnt : 16; // how many invalid slices in this block
238 unsigned int reserved0 : 10; //
239 unsigned int currentPage : 16; // the current working page number of this block
240 unsigned int eraseCnt : 16; // how many times this block have been erased
241 unsigned int prevBlock : 16; // VBN of the prev block in free/victim block list
242 unsigned int nextBlock : 16; // VBN of the next block in free/victim block list
244
248typedef struct _VIRTUAL_BLOCK_MAP
249{
252
258typedef struct _VIRTUAL_DIE_ENTRY
259{
260 unsigned int currentBlock : 16; // the current working block number of this die
261 unsigned int headFreeBlock : 16; // virtual block map index of the first free block of this die
262 unsigned int tailFreeBlock : 16; // virtual block map index of the last free block of this die
263 unsigned int freeBlockCnt : 16; // how many free blocks on this die
264 unsigned int prevDie : 8;
265 unsigned int nextDie : 8;
266 unsigned int reserved0 : 16;
268
272typedef struct _VIRTUAL_DIE_MAP
273{
276
282{ // free block allocation die sequence list
283 unsigned int headDie : 8;
284 unsigned int tailDie : 8;
285 unsigned int reserved0 : 16;
287
292{
293 unsigned int phyBlock : 16; // which block in this die contains the bbt
294 unsigned int grownBadUpdate : 1; // whether the bbt of this die should be updated
295 unsigned int reserved0 : 15;
297
302{
305
309typedef struct _PHY_BLOCK_ENTRY
310{
311 /* the origin block was remapped to this physical block */
312 unsigned int remappedPhyBlock : 16;
313 /* the origin block is a bad block, check the remapped block */
314 unsigned int bad : 1;
315 unsigned int reserved0 : 15;
317
321typedef struct _PHY_BLOCK_MAP
322{
325
326void InitAddressMap();
327void InitSliceMap();
328void InitBlockDieMap();
329
330unsigned int AddrTransRead(unsigned int logicalSliceAddr);
331unsigned int AddrTransWrite(unsigned int logicalSliceAddr);
332unsigned int FindFreeVirtualSlice();
333unsigned int FindFreeVirtualSliceForGc(unsigned int copyTargetDieNo, unsigned int victimBlockNo);
334unsigned int FindDieForFreeSliceAllocation();
335
336void InvalidateOldVsa(unsigned int logicalSliceAddr);
337void EraseBlock(unsigned int dieNo, unsigned int blockNo);
338
339void PutToFbList(unsigned int dieNo, unsigned int blockNo);
340unsigned int GetFromFbList(unsigned int dieNo, unsigned int getFreeBlockOption);
341
342void UpdatePhyBlockMapForGrownBadBlock(unsigned int dieNo, unsigned int phyBlockNo);
343void UpdateBadBlockTableForGrownBadBlock(unsigned int tempBufAddr);
344
351
352extern unsigned char sliceAllocationTargetDie;
353extern unsigned int mbPerbadBlockSpace;
354
355/* -------------------------------------------------------------------------- */
356/* util macros for translation related ops */
357/* -------------------------------------------------------------------------- */
358
359#define VDIE_ENTRY(iDie) (&virtualDieMapPtr->die[(iDie)])
360#define VDIE_PREV_IDX(iDie) (VDIE_ENTRY((iDie))->prevDie)
361#define VDIE_NEXT_IDX(iDie) (VDIE_ENTRY((iDie))->nextDie)
362#define VDIE_PREV_ENTRY(iDie) (VDIE_ENTRY(VDIE_PREV_IDX((iDie))))
363#define VDIE_NEXT_ENTRY(iDie) (VDIE_ENTRY(VDIE_NEXT_IDX((iDie))))
364
365#define VBLK_ENTRY(iDie, iBlk) (&virtualBlockMapPtr->block[(iDie)][(iBlk)])
366#define VBLK_PREV_IDX(iDie, iBlk) (VBLK_ENTRY((iDie), (iBlk))->prevBlock)
367#define VBLK_NEXT_IDX(iDie, iBlk) (VBLK_ENTRY((iDie), (iBlk))->nextBlock)
368#define VBLK_PREV_ENTRY(iDie, iBlk) (VBLK_ENTRY((iDie), VBLK_PREV_IDX((iDie), (iBlk))))
369#define VBLK_NEXT_ENTRY(iDie, iBlk) (VBLK_ENTRY((iDie), VBLK_NEXT_IDX((iDie), (iBlk))))
370#define PBLK_ENTRY(iDie, iBlk) (&phyBlockMapPtr->phyBlock[(iDie)][(iBlk)])
371
372#define LSA_ENTRY(lsa) (&logicalSliceMapPtr->logicalSlice[(lsa)])
373#define VSA_ENTRY(vsa) (&virtualSliceMapPtr->virtualSlice[(vsa)])
374#define LSA2VSA(lsa) (LSA_ENTRY((lsa))->virtualSliceAddr)
375#define VSA2LSA(vsa) (VSA_ENTRY((vsa))->logicalSliceAddr)
376
377#define VDIE2PCH(iDie) (Vdie2PchTranslation((iDie)))
378#define VDIE2PWAY(iDie) (Vdie2PwayTranslation((iDie)))
379#define VSA2VDIE(vsa) (Vsa2VdieTranslation((vsa)))
380#define VSA2VBLK(vsa) (Vsa2VblockTranslation((vsa)))
381#define VSA2VPAGE(vsa) (Vsa2VpageTranslation((vsa)))
382#define VBA2PBA_MBS(vba) (Vblock2PblockOfMbsTranslation((vba)))
383#define VBA2PBA_TBS(vba) (Vblock2PblockOfTbsTranslation((vba)))
384#define VORG2VSA(iDie, iBlk, iPage) (Vorg2VsaTranslation((iDie), (iBlk), (iPage)))
385
386#define PCH2VDIE(iCh, iWay) (Pcw2VdieTranslation((iCh), (iWay)))
387
388#endif /* ADDRESS_TRANSLATION_H_ */
unsigned char sliceAllocationTargetDie
struct _PHY_BLOCK_MAP * P_PHY_BLOCK_MAP
unsigned int AddrTransRead(unsigned int logicalSliceAddr)
Get the virtual slice address of the given logical slice.
struct _BAD_BLOCK_TABLE_INFO_MAP * P_BAD_BLOCK_TABLE_INFO_MAP
unsigned int FindDieForFreeSliceAllocation()
Update and get the die number to serve the next write request.
struct _VIRTUAL_DIE_ENTRY * P_VIRTUAL_DIE_ENTRY
unsigned int GetFromFbList(unsigned int dieNo, unsigned int getFreeBlockOption)
Pop the first block in the free block list of the specified die.
void InitSliceMap()
Initialize Logical and Virtual Slick Map.
struct _BAD_BLOCK_TABLE_INFO_ENTRY * P_BAD_BLOCK_TABLE_ENTRY
struct _BAD_BLOCK_TABLE_INFO_MAP BAD_BLOCK_TABLE_INFO_MAP
The bad block tables.
struct _VIRTUAL_DIE_MAP VIRTUAL_DIE_MAP
The metadata table for all user dies.
struct _LOGICAL_SLICE_ENTRY LOGICAL_SLICE_ENTRY
Exactly the Virtual Slice Address.
void InitAddressMap()
Initialize the translation related maps.
struct _VIRTUAL_SLICE_ENTRY VIRTUAL_SLICE_ENTRY
Exactly the Logical Slice Address.
P_BAD_BLOCK_TABLE_INFO_MAP bbtInfoMapPtr
struct _FRRE_BLOCK_ALLOCATION_LIST * P_FRRE_BLOCK_ALLOCATION_LIST
void UpdatePhyBlockMapForGrownBadBlock(unsigned int dieNo, unsigned int phyBlockNo)
Mark the given physical block bad block and update the bbt later.
struct _PHY_BLOCK_ENTRY * P_PHY_BLOCK_ENTRY
struct _VIRTUAL_BLOCK_MAP VIRTUAL_BLOCK_MAP
The block metadata table for all the blocks.
P_LOGICAL_SLICE_MAP logicalSliceMapPtr
unsigned int FindFreeVirtualSlice()
Select a free physical page (virtual slice).
struct _LOGICAL_SLICE_ENTRY * P_LOGICAL_SLICE_ENTRY
struct _VIRTUAL_SLICE_MAP * P_VIRTUAL_SLICE_MAP
void EraseBlock(unsigned int dieNo, unsigned int blockNo)
Erase the specified block of the specified die and discard its LSAs.
P_VIRTUAL_DIE_MAP virtualDieMapPtr
void PutToFbList(unsigned int dieNo, unsigned int blockNo)
Append the given virtual block to the free block list of its die.
struct _BAD_BLOCK_TABLE_INFO_ENTRY BAD_BLOCK_TABLE_INFO_ENTRY
The bad block table for this die.
struct _FRRE_BLOCK_ALLOCATION_LIST FRRE_BLOCK_ALLOCATION_LIST
void UpdateBadBlockTableForGrownBadBlock(unsigned int tempBufAddr)
Update the bad block table and persist to the specified block.
struct _PHY_BLOCK_MAP PHY_BLOCK_MAP
The metadata table for all the physical blocks.
struct _PHY_BLOCK_ENTRY PHY_BLOCK_ENTRY
The metadata of the physical block.
struct _VIRTUAL_BLOCK_MAP * P_VIRTUAL_BLOCK_MAP
P_PHY_BLOCK_MAP phyBlockMapPtr
struct _VIRTUAL_SLICE_ENTRY * P_VIRTUAL_SLICE_ENTRY
struct _LOGICAL_SLICE_MAP * P_LOGICAL_SLICE_MAP
unsigned int FindFreeVirtualSliceForGc(unsigned int copyTargetDieNo, unsigned int victimBlockNo)
struct _VIRTUAL_DIE_ENTRY VIRTUAL_DIE_ENTRY
The metadata for this die.
void InvalidateOldVsa(unsigned int logicalSliceAddr)
Invalidate the specified virtual page.
struct _VIRTUAL_BLOCK_ENTRY VIRTUAL_BLOCK_ENTRY
The metadata for this block.
P_VIRTUAL_SLICE_MAP virtualSliceMapPtr
void InitBlockDieMap()
Build the bad block table and V2P block mapping of each user die.
struct _VIRTUAL_BLOCK_ENTRY * P_VIRTUAL_BLOCK_ENTRY
struct _LOGICAL_SLICE_MAP LOGICAL_SLICE_MAP
The Logical -> Virtual Slice Address mapping table.
P_VIRTUAL_BLOCK_MAP virtualBlockMapPtr
struct _VIRTUAL_DIE_MAP * P_VIRTUAL_DIE_MAP
unsigned int mbPerbadBlockSpace
struct _VIRTUAL_SLICE_MAP VIRTUAL_SLICE_MAP
The Virtual -> Logical Slice mapping table.
unsigned int AddrTransWrite(unsigned int logicalSliceAddr)
Assign a new virtual (physical) page to the specified logical page.
#define USER_DIES
Definition: ftl_config.h:219
#define USER_BLOCKS_PER_DIE
Definition: ftl_config.h:233
#define TOTAL_BLOCKS_PER_DIE
Definition: ftl_config.h:163
#define SLICES_PER_SSD
Definition: ftl_config.h:231
The bad block table for this die.
unsigned int reserved0
unsigned int phyBlock
unsigned int grownBadUpdate
BAD_BLOCK_TABLE_INFO_ENTRY bbtInfo[USER_DIES]
Exactly the Virtual Slice Address.
unsigned int virtualSliceAddr
The Logical -> Virtual Slice Address mapping table.
LOGICAL_SLICE_ENTRY logicalSlice[SLICES_PER_SSD]
The metadata of the physical block.
unsigned int reserved0
unsigned int bad
unsigned int remappedPhyBlock
The metadata table for all the physical blocks.
PHY_BLOCK_ENTRY phyBlock[USER_DIES][TOTAL_BLOCKS_PER_DIE]
The metadata for this block.
unsigned int currentPage
unsigned int prevBlock
unsigned int eraseCnt
unsigned int reserved0
unsigned int bad
unsigned int free
unsigned int nextBlock
unsigned int invalidSliceCnt
The block metadata table for all the blocks.
VIRTUAL_BLOCK_ENTRY block[USER_DIES][USER_BLOCKS_PER_DIE]
The metadata for this die.
unsigned int headFreeBlock
unsigned int currentBlock
unsigned int freeBlockCnt
unsigned int nextDie
unsigned int reserved0
unsigned int prevDie
unsigned int tailFreeBlock
The metadata table for all user dies.
VIRTUAL_DIE_ENTRY die[USER_DIES]
Exactly the Logical Slice Address.
unsigned int logicalSliceAddr
The Virtual -> Logical Slice mapping table.
VIRTUAL_SLICE_ENTRY virtualSlice[SLICES_PER_SSD]