OpenSSD Cosmos+ Platform Firmware  0.0.2
The firmware of Cosmos+ OpenSSD Platform for TOSHIBA nand flash module.
address_translation.h File Reference
#include "ftl_config.h"
#include "nvme/nvme.h"
Include dependency graph for address_translation.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  _LOGICAL_SLICE_ENTRY
 Exactly the Virtual Slice Address. More...
 
struct  _LOGICAL_SLICE_MAP
 The Logical -> Virtual Slice Address mapping table. More...
 
struct  _VIRTUAL_SLICE_ENTRY
 Exactly the Logical Slice Address. More...
 
struct  _VIRTUAL_SLICE_MAP
 The Virtual -> Logical Slice mapping table. More...
 
struct  _VIRTUAL_BLOCK_ENTRY
 The metadata for this block. More...
 
struct  _VIRTUAL_BLOCK_MAP
 The block metadata table for all the blocks. More...
 
struct  _VIRTUAL_DIE_ENTRY
 The metadata for this die. More...
 
struct  _VIRTUAL_DIE_MAP
 The metadata table for all user dies. More...
 
struct  _FRRE_BLOCK_ALLOCATION_LIST
 
struct  _BAD_BLOCK_TABLE_INFO_ENTRY
 The bad block table for this die. More...
 
struct  _BAD_BLOCK_TABLE_INFO_MAP
 The bad block tables. More...
 
struct  _PHY_BLOCK_ENTRY
 The metadata of the physical block. More...
 
struct  _PHY_BLOCK_MAP
 The metadata table for all the physical blocks. More...
 

Macros

#define LSA_NONE   0xffffffff
 
#define LSA_FAIL   0xffffffff
 
#define VSA_NONE   0xffffffff
 
#define VSA_FAIL   0xffffffff
 
#define PAGE_NONE   0xffff
 
#define BLOCK_NONE   0xffff
 
#define BLOCK_FAIL   0xffff
 
#define DIE_NONE   0xff
 
#define DIE_FAIL   0xff
 
#define RESERVED_FREE_BLOCK_COUNT   0x1
 
#define GET_FREE_BLOCK_NORMAL   0x0
 
#define GET_FREE_BLOCK_GC   0x1
 
#define BLOCK_STATE_NORMAL   0
 
#define BLOCK_STATE_BAD   1
 
#define DIE_STATE_BAD_BLOCK_TABLE_NOT_EXIST   0
 
#define DIE_STATE_BAD_BLOCK_TABLE_EXIST   1
 
#define DIE_STATE_BAD_BLOCK_TABLE_HOLD   2
 
#define DIE_STATE_BAD_BLOCK_TABLE_UPDATE   3
 
#define BAD_BLOCK_TABLE_MAKER_IDLE   0
 
#define BAD_BLOCK_TABLE_MAKER_TRIGGER   1
 
#define CLEAN_DATA_IN_BYTE   0xff
 
#define USED_PAGES_FOR_BAD_BLOCK_TABLE_PER_DIE   (TOTAL_BLOCKS_PER_DIE / BYTES_PER_DATA_REGION_OF_PAGE + 1)
 
#define DATA_SIZE_OF_BAD_BLOCK_TABLE_PER_DIE   (TOTAL_BLOCKS_PER_DIE)
 
#define START_PAGE_NO_OF_BAD_BLOCK_TABLE_BLOCK   (1)
 The start physical page number that stored the bbt of this die. More...
 
#define BBT_INFO_GROWN_BAD_UPDATE_NONE   0
 
#define BBT_INFO_GROWN_BAD_UPDATE_BOOKED   1
 
#define Vsa2VdieTranslation(virtualSliceAddr)   ((virtualSliceAddr) % (USER_DIES))
 
#define Vsa2VblockTranslation(virtualSliceAddr)   (((virtualSliceAddr) / (USER_DIES)) / (SLICES_PER_BLOCK))
 
#define Vsa2VpageTranslation(virtualSliceAddr)   (((virtualSliceAddr) / (USER_DIES)) % (SLICES_PER_BLOCK))
 
#define Vorg2VsaTranslation(dieNo, blockNo, pageNo)    ((dieNo) + (USER_DIES) * ((blockNo) * (SLICES_PER_BLOCK) + (pageNo)))
 Translate virtual NAND organization (location vector) into VSA. More...
 
#define Vdie2PchTranslation(dieNo)   ((dieNo) % (USER_CHANNELS))
 
#define Vdie2PwayTranslation(dieNo)   ((dieNo) / (USER_CHANNELS))
 
#define Vblock2PblockOfTbsTranslation(blockNo)    (((blockNo) / (USER_BLOCKS_PER_LUN)) * (TOTAL_BLOCKS_PER_LUN) + ((blockNo) % (USER_BLOCKS_PER_LUN)))
 Get the PBA (in total block space) of the given VBN. More...
 
#define Vblock2PblockOfMbsTranslation(blockNo)    (((blockNo) / (USER_BLOCKS_PER_LUN)) * (MAIN_BLOCKS_PER_LUN) + ((blockNo) % (USER_BLOCKS_PER_LUN)))
 The V2P block mapping rule (main block space). More...
 
#define Vpage2PlsbPageTranslation(pageNo)   ((pageNo) > (0) ? (2 * (pageNo)-1) : (0))
 Map the virtual page to the physical LSB page in SLC mode. More...
 
#define Pcw2VdieTranslation(chNo, wayNo)   ((chNo) + (wayNo) * (USER_CHANNELS))
 Get die number from physical channel number and way number. More...
 
#define PlsbPage2VpageTranslation(pageNo)   ((pageNo) > (0) ? (((pageNo) + 1) / 2) : (0))
 Get the corresponding virtual page number of the given LSB page number. More...
 
#define VDIE_ENTRY(iDie)   (&virtualDieMapPtr->die[(iDie)])
 
#define VDIE_PREV_IDX(iDie)   (VDIE_ENTRY((iDie))->prevDie)
 
#define VDIE_NEXT_IDX(iDie)   (VDIE_ENTRY((iDie))->nextDie)
 
#define VDIE_PREV_ENTRY(iDie)   (VDIE_ENTRY(VDIE_PREV_IDX((iDie))))
 
#define VDIE_NEXT_ENTRY(iDie)   (VDIE_ENTRY(VDIE_NEXT_IDX((iDie))))
 
#define VBLK_ENTRY(iDie, iBlk)   (&virtualBlockMapPtr->block[(iDie)][(iBlk)])
 
#define VBLK_PREV_IDX(iDie, iBlk)   (VBLK_ENTRY((iDie), (iBlk))->prevBlock)
 
#define VBLK_NEXT_IDX(iDie, iBlk)   (VBLK_ENTRY((iDie), (iBlk))->nextBlock)
 
#define VBLK_PREV_ENTRY(iDie, iBlk)   (VBLK_ENTRY((iDie), VBLK_PREV_IDX((iDie), (iBlk))))
 
#define VBLK_NEXT_ENTRY(iDie, iBlk)   (VBLK_ENTRY((iDie), VBLK_NEXT_IDX((iDie), (iBlk))))
 
#define PBLK_ENTRY(iDie, iBlk)   (&phyBlockMapPtr->phyBlock[(iDie)][(iBlk)])
 
#define LSA_ENTRY(lsa)   (&logicalSliceMapPtr->logicalSlice[(lsa)])
 
#define VSA_ENTRY(vsa)   (&virtualSliceMapPtr->virtualSlice[(vsa)])
 
#define LSA2VSA(lsa)   (LSA_ENTRY((lsa))->virtualSliceAddr)
 
#define VSA2LSA(vsa)   (VSA_ENTRY((vsa))->logicalSliceAddr)
 
#define VDIE2PCH(iDie)   (Vdie2PchTranslation((iDie)))
 
#define VDIE2PWAY(iDie)   (Vdie2PwayTranslation((iDie)))
 
#define VSA2VDIE(vsa)   (Vsa2VdieTranslation((vsa)))
 
#define VSA2VBLK(vsa)   (Vsa2VblockTranslation((vsa)))
 
#define VSA2VPAGE(vsa)   (Vsa2VpageTranslation((vsa)))
 
#define VBA2PBA_MBS(vba)   (Vblock2PblockOfMbsTranslation((vba)))
 
#define VBA2PBA_TBS(vba)   (Vblock2PblockOfTbsTranslation((vba)))
 
#define VORG2VSA(iDie, iBlk, iPage)   (Vorg2VsaTranslation((iDie), (iBlk), (iPage)))
 
#define PCH2VDIE(iCh, iWay)   (Pcw2VdieTranslation((iCh), (iWay)))
 

Typedefs

typedef struct _LOGICAL_SLICE_ENTRY LOGICAL_SLICE_ENTRY
 Exactly the Virtual Slice Address. More...
 
typedef struct _LOGICAL_SLICE_ENTRYP_LOGICAL_SLICE_ENTRY
 
typedef struct _LOGICAL_SLICE_MAP LOGICAL_SLICE_MAP
 The Logical -> Virtual Slice Address mapping table. More...
 
typedef struct _LOGICAL_SLICE_MAPP_LOGICAL_SLICE_MAP
 
typedef struct _VIRTUAL_SLICE_ENTRY VIRTUAL_SLICE_ENTRY
 Exactly the Logical Slice Address. More...
 
typedef struct _VIRTUAL_SLICE_ENTRYP_VIRTUAL_SLICE_ENTRY
 
typedef struct _VIRTUAL_SLICE_MAP VIRTUAL_SLICE_MAP
 The Virtual -> Logical Slice mapping table. More...
 
typedef struct _VIRTUAL_SLICE_MAPP_VIRTUAL_SLICE_MAP
 
typedef struct _VIRTUAL_BLOCK_ENTRY VIRTUAL_BLOCK_ENTRY
 The metadata for this block. More...
 
typedef struct _VIRTUAL_BLOCK_ENTRYP_VIRTUAL_BLOCK_ENTRY
 
typedef struct _VIRTUAL_BLOCK_MAP VIRTUAL_BLOCK_MAP
 The block metadata table for all the blocks. More...
 
typedef struct _VIRTUAL_BLOCK_MAPP_VIRTUAL_BLOCK_MAP
 
typedef struct _VIRTUAL_DIE_ENTRY VIRTUAL_DIE_ENTRY
 The metadata for this die. More...
 
typedef struct _VIRTUAL_DIE_ENTRYP_VIRTUAL_DIE_ENTRY
 
typedef struct _VIRTUAL_DIE_MAP VIRTUAL_DIE_MAP
 The metadata table for all user dies. More...
 
typedef struct _VIRTUAL_DIE_MAPP_VIRTUAL_DIE_MAP
 
typedef struct _FRRE_BLOCK_ALLOCATION_LIST FRRE_BLOCK_ALLOCATION_LIST
 
typedef struct _FRRE_BLOCK_ALLOCATION_LISTP_FRRE_BLOCK_ALLOCATION_LIST
 
typedef struct _BAD_BLOCK_TABLE_INFO_ENTRY BAD_BLOCK_TABLE_INFO_ENTRY
 The bad block table for this die. More...
 
typedef struct _BAD_BLOCK_TABLE_INFO_ENTRYP_BAD_BLOCK_TABLE_ENTRY
 
typedef struct _BAD_BLOCK_TABLE_INFO_MAP BAD_BLOCK_TABLE_INFO_MAP
 The bad block tables. More...
 
typedef struct _BAD_BLOCK_TABLE_INFO_MAPP_BAD_BLOCK_TABLE_INFO_MAP
 
typedef struct _PHY_BLOCK_ENTRY PHY_BLOCK_ENTRY
 The metadata of the physical block. More...
 
typedef struct _PHY_BLOCK_ENTRYP_PHY_BLOCK_ENTRY
 
typedef struct _PHY_BLOCK_MAP PHY_BLOCK_MAP
 The metadata table for all the physical blocks. More...
 
typedef struct _PHY_BLOCK_MAPP_PHY_BLOCK_MAP
 

Functions

void InitAddressMap ()
 Initialize the translation related maps. More...
 
void InitSliceMap ()
 Initialize Logical and Virtual Slick Map. More...
 
void InitBlockDieMap ()
 Build the bad block table and V2P block mapping of each user die. More...
 
unsigned int AddrTransRead (unsigned int logicalSliceAddr)
 Get the virtual slice address of the given logical slice. More...
 
unsigned int AddrTransWrite (unsigned int logicalSliceAddr)
 Assign a new virtual (physical) page to the specified logical page. More...
 
unsigned int FindFreeVirtualSlice ()
 Select a free physical page (virtual slice). More...
 
unsigned int FindFreeVirtualSliceForGc (unsigned int copyTargetDieNo, unsigned int victimBlockNo)
 
unsigned int FindDieForFreeSliceAllocation ()
 Update and get the die number to serve the next write request. More...
 
void InvalidateOldVsa (unsigned int logicalSliceAddr)
 Invalidate the specified virtual page. More...
 
void EraseBlock (unsigned int dieNo, unsigned int blockNo)
 Erase the specified block of the specified die and discard its LSAs. More...
 
void PutToFbList (unsigned int dieNo, unsigned int blockNo)
 Append the given virtual block to the free block list of its die. More...
 
unsigned int GetFromFbList (unsigned int dieNo, unsigned int getFreeBlockOption)
 Pop the first block in the free block list of the specified die. More...
 
void UpdatePhyBlockMapForGrownBadBlock (unsigned int dieNo, unsigned int phyBlockNo)
 Mark the given physical block bad block and update the bbt later. More...
 
void UpdateBadBlockTableForGrownBadBlock (unsigned int tempBufAddr)
 Update the bad block table and persist to the specified block. More...
 

Variables

P_LOGICAL_SLICE_MAP logicalSliceMapPtr
 
P_VIRTUAL_SLICE_MAP virtualSliceMapPtr
 
P_VIRTUAL_BLOCK_MAP virtualBlockMapPtr
 
P_VIRTUAL_DIE_MAP virtualDieMapPtr
 
P_PHY_BLOCK_MAP phyBlockMapPtr
 
P_BAD_BLOCK_TABLE_INFO_MAP bbtInfoMapPtr
 
unsigned char sliceAllocationTargetDie
 
unsigned int mbPerbadBlockSpace
 

Macro Definition Documentation

◆ BAD_BLOCK_TABLE_MAKER_IDLE

#define BAD_BLOCK_TABLE_MAKER_IDLE   0

Definition at line 81 of file address_translation.h.

◆ BAD_BLOCK_TABLE_MAKER_TRIGGER

#define BAD_BLOCK_TABLE_MAKER_TRIGGER   1

Definition at line 82 of file address_translation.h.

◆ BBT_INFO_GROWN_BAD_UPDATE_BOOKED

#define BBT_INFO_GROWN_BAD_UPDATE_BOOKED   1

Definition at line 101 of file address_translation.h.

◆ BBT_INFO_GROWN_BAD_UPDATE_NONE

#define BBT_INFO_GROWN_BAD_UPDATE_NONE   0

Definition at line 100 of file address_translation.h.

◆ BLOCK_FAIL

#define BLOCK_FAIL   0xffff

Definition at line 63 of file address_translation.h.

◆ BLOCK_NONE

#define BLOCK_NONE   0xffff

Definition at line 62 of file address_translation.h.

◆ BLOCK_STATE_BAD

#define BLOCK_STATE_BAD   1

Definition at line 74 of file address_translation.h.

◆ BLOCK_STATE_NORMAL

#define BLOCK_STATE_NORMAL   0

Definition at line 73 of file address_translation.h.

◆ CLEAN_DATA_IN_BYTE

#define CLEAN_DATA_IN_BYTE   0xff

Definition at line 84 of file address_translation.h.

◆ DATA_SIZE_OF_BAD_BLOCK_TABLE_PER_DIE

#define DATA_SIZE_OF_BAD_BLOCK_TABLE_PER_DIE   (TOTAL_BLOCKS_PER_DIE)

Definition at line 88 of file address_translation.h.

◆ DIE_FAIL

#define DIE_FAIL   0xff

Definition at line 66 of file address_translation.h.

◆ DIE_NONE

#define DIE_NONE   0xff

Definition at line 65 of file address_translation.h.

◆ DIE_STATE_BAD_BLOCK_TABLE_EXIST

#define DIE_STATE_BAD_BLOCK_TABLE_EXIST   1

Definition at line 77 of file address_translation.h.

◆ DIE_STATE_BAD_BLOCK_TABLE_HOLD

#define DIE_STATE_BAD_BLOCK_TABLE_HOLD   2

Definition at line 78 of file address_translation.h.

◆ DIE_STATE_BAD_BLOCK_TABLE_NOT_EXIST

#define DIE_STATE_BAD_BLOCK_TABLE_NOT_EXIST   0

Definition at line 76 of file address_translation.h.

◆ DIE_STATE_BAD_BLOCK_TABLE_UPDATE

#define DIE_STATE_BAD_BLOCK_TABLE_UPDATE   3

Definition at line 79 of file address_translation.h.

◆ GET_FREE_BLOCK_GC

#define GET_FREE_BLOCK_GC   0x1

Definition at line 71 of file address_translation.h.

◆ GET_FREE_BLOCK_NORMAL

#define GET_FREE_BLOCK_NORMAL   0x0

Definition at line 70 of file address_translation.h.

◆ LSA2VSA

#define LSA2VSA (   lsa)    (LSA_ENTRY((lsa))->virtualSliceAddr)

Definition at line 374 of file address_translation.h.

◆ LSA_ENTRY

#define LSA_ENTRY (   lsa)    (&logicalSliceMapPtr->logicalSlice[(lsa)])

Definition at line 372 of file address_translation.h.

◆ LSA_FAIL

#define LSA_FAIL   0xffffffff

Definition at line 55 of file address_translation.h.

◆ LSA_NONE

#define LSA_NONE   0xffffffff

Definition at line 54 of file address_translation.h.

◆ PAGE_NONE

#define PAGE_NONE   0xffff

Definition at line 60 of file address_translation.h.

◆ PBLK_ENTRY

#define PBLK_ENTRY (   iDie,
  iBlk 
)    (&phyBlockMapPtr->phyBlock[(iDie)][(iBlk)])

Definition at line 370 of file address_translation.h.

◆ PCH2VDIE

#define PCH2VDIE (   iCh,
  iWay 
)    (Pcw2VdieTranslation((iCh), (iWay)))

Definition at line 386 of file address_translation.h.

◆ Pcw2VdieTranslation

#define Pcw2VdieTranslation (   chNo,
  wayNo 
)    ((chNo) + (wayNo) * (USER_CHANNELS))

Get die number from physical channel number and way number.

Warning
: Why the LSB page is at odd page ??

Definition at line 179 of file address_translation.h.

◆ PlsbPage2VpageTranslation

#define PlsbPage2VpageTranslation (   pageNo)    ((pageNo) > (0) ? (((pageNo) + 1) / 2) : (0))

Get the corresponding virtual page number of the given LSB page number.

Warning
: No need to check if pageNo > 0 or not.

Definition at line 186 of file address_translation.h.

◆ RESERVED_FREE_BLOCK_COUNT

#define RESERVED_FREE_BLOCK_COUNT   0x1

Definition at line 68 of file address_translation.h.

◆ START_PAGE_NO_OF_BAD_BLOCK_TABLE_BLOCK

#define START_PAGE_NO_OF_BAD_BLOCK_TABLE_BLOCK   (1)

The start physical page number that stored the bbt of this die.

The first page will be used for checking the bad block mark, so start putting the bbt from second page.

Note
the bad block table should be saved at lsb pages

Definition at line 98 of file address_translation.h.

◆ USED_PAGES_FOR_BAD_BLOCK_TABLE_PER_DIE

#define USED_PAGES_FOR_BAD_BLOCK_TABLE_PER_DIE   (TOTAL_BLOCKS_PER_DIE / BYTES_PER_DATA_REGION_OF_PAGE + 1)

Definition at line 87 of file address_translation.h.

◆ VBA2PBA_MBS

#define VBA2PBA_MBS (   vba)    (Vblock2PblockOfMbsTranslation((vba)))

Definition at line 382 of file address_translation.h.

◆ VBA2PBA_TBS

#define VBA2PBA_TBS (   vba)    (Vblock2PblockOfTbsTranslation((vba)))

Definition at line 383 of file address_translation.h.

◆ VBLK_ENTRY

#define VBLK_ENTRY (   iDie,
  iBlk 
)    (&virtualBlockMapPtr->block[(iDie)][(iBlk)])

Definition at line 365 of file address_translation.h.

◆ VBLK_NEXT_ENTRY

#define VBLK_NEXT_ENTRY (   iDie,
  iBlk 
)    (VBLK_ENTRY((iDie), VBLK_NEXT_IDX((iDie), (iBlk))))

Definition at line 369 of file address_translation.h.

◆ VBLK_NEXT_IDX

#define VBLK_NEXT_IDX (   iDie,
  iBlk 
)    (VBLK_ENTRY((iDie), (iBlk))->nextBlock)

Definition at line 367 of file address_translation.h.

◆ VBLK_PREV_ENTRY

#define VBLK_PREV_ENTRY (   iDie,
  iBlk 
)    (VBLK_ENTRY((iDie), VBLK_PREV_IDX((iDie), (iBlk))))

Definition at line 368 of file address_translation.h.

◆ VBLK_PREV_IDX

#define VBLK_PREV_IDX (   iDie,
  iBlk 
)    (VBLK_ENTRY((iDie), (iBlk))->prevBlock)

Definition at line 366 of file address_translation.h.

◆ Vblock2PblockOfMbsTranslation

#define Vblock2PblockOfMbsTranslation (   blockNo)     (((blockNo) / (USER_BLOCKS_PER_LUN)) * (MAIN_BLOCKS_PER_LUN) + ((blockNo) % (USER_BLOCKS_PER_LUN)))

The V2P block mapping rule (main block space).

Note
Mbs = Main block space
Warning
why this needed?

Definition at line 159 of file address_translation.h.

◆ Vblock2PblockOfTbsTranslation

#define Vblock2PblockOfTbsTranslation (   blockNo)     (((blockNo) / (USER_BLOCKS_PER_LUN)) * (TOTAL_BLOCKS_PER_LUN) + ((blockNo) % (USER_BLOCKS_PER_LUN)))

Get the PBA (in total block space) of the given VBN.

The mapping rule is basically use static mapping, but since the number of user blocks on a die may be less than the number of total blocks (MAIN + EXTENDED) on that die, we must use USER_BLOCKS_PER_LUN to calculate the offset of the given VBN.

Note
Tbs = Total block space = MAIN + EXTENDED

Definition at line 150 of file address_translation.h.

◆ VDIE2PCH

#define VDIE2PCH (   iDie)    (Vdie2PchTranslation((iDie)))

Definition at line 377 of file address_translation.h.

◆ Vdie2PchTranslation

#define Vdie2PchTranslation (   dieNo)    ((dieNo) % (USER_CHANNELS))

Definition at line 138 of file address_translation.h.

◆ VDIE2PWAY

#define VDIE2PWAY (   iDie)    (Vdie2PwayTranslation((iDie)))

Definition at line 378 of file address_translation.h.

◆ Vdie2PwayTranslation

#define Vdie2PwayTranslation (   dieNo)    ((dieNo) / (USER_CHANNELS))

Definition at line 139 of file address_translation.h.

◆ VDIE_ENTRY

#define VDIE_ENTRY (   iDie)    (&virtualDieMapPtr->die[(iDie)])

Definition at line 359 of file address_translation.h.

◆ VDIE_NEXT_ENTRY

#define VDIE_NEXT_ENTRY (   iDie)    (VDIE_ENTRY(VDIE_NEXT_IDX((iDie))))

Definition at line 363 of file address_translation.h.

◆ VDIE_NEXT_IDX

#define VDIE_NEXT_IDX (   iDie)    (VDIE_ENTRY((iDie))->nextDie)

Definition at line 361 of file address_translation.h.

◆ VDIE_PREV_ENTRY

#define VDIE_PREV_ENTRY (   iDie)    (VDIE_ENTRY(VDIE_PREV_IDX((iDie))))

Definition at line 362 of file address_translation.h.

◆ VDIE_PREV_IDX

#define VDIE_PREV_IDX (   iDie)    (VDIE_ENTRY((iDie))->prevDie)

Definition at line 360 of file address_translation.h.

◆ VORG2VSA

#define VORG2VSA (   iDie,
  iBlk,
  iPage 
)    (Vorg2VsaTranslation((iDie), (iBlk), (iPage)))

Definition at line 384 of file address_translation.h.

◆ Vorg2VsaTranslation

#define Vorg2VsaTranslation (   dieNo,
  blockNo,
  pageNo 
)     ((dieNo) + (USER_DIES) * ((blockNo) * (SLICES_PER_BLOCK) + (pageNo)))

Translate virtual NAND organization (location vector) into VSA.

Warning
why the pages with same offset but on different die are grouped together?

The virtual slices with same page offset but on different die are grouped together, that is the virtual slice address 0 ~ (USER_DIES - 1) will be mapped to the page 0 of each user die, the virtual slice address USER_DIES ~ (2 x USER_DIES - 1) will be mapped to the page 1 of each user die, and so on.

Therefore, in order to translate the virtual organization into VSA, we should:

  1. Calculate the page offset within a die
  2. Use the page offset to find the group within all the groups
  3. Use dieNo to get the VSA for this die in the target group
Parameters
dieNothe die number for this slice request.
blockNothe block number for this slice request.
pageNothe page offset in this block for this slice request.

Definition at line 131 of file address_translation.h.

◆ Vpage2PlsbPageTranslation

#define Vpage2PlsbPageTranslation (   pageNo)    ((pageNo) > (0) ? (2 * (pageNo)-1) : (0))

Map the virtual page to the physical LSB page in SLC mode.

Warning
This may reduce the flash lifetime since this is not true SLC mode.
Why the LSB page is at odd page ??

Definition at line 168 of file address_translation.h.

◆ VSA2LSA

#define VSA2LSA (   vsa)    (VSA_ENTRY((vsa))->logicalSliceAddr)

Definition at line 375 of file address_translation.h.

◆ VSA2VBLK

#define VSA2VBLK (   vsa)    (Vsa2VblockTranslation((vsa)))

Definition at line 380 of file address_translation.h.

◆ Vsa2VblockTranslation

#define Vsa2VblockTranslation (   virtualSliceAddr)    (((virtualSliceAddr) / (USER_DIES)) / (SLICES_PER_BLOCK))

Definition at line 108 of file address_translation.h.

◆ VSA2VDIE

#define VSA2VDIE (   vsa)    (Vsa2VdieTranslation((vsa)))

Definition at line 379 of file address_translation.h.

◆ Vsa2VdieTranslation

#define Vsa2VdieTranslation (   virtualSliceAddr)    ((virtualSliceAddr) % (USER_DIES))

Definition at line 107 of file address_translation.h.

◆ VSA2VPAGE

#define VSA2VPAGE (   vsa)    (Vsa2VpageTranslation((vsa)))

Definition at line 381 of file address_translation.h.

◆ Vsa2VpageTranslation

#define Vsa2VpageTranslation (   virtualSliceAddr)    (((virtualSliceAddr) / (USER_DIES)) % (SLICES_PER_BLOCK))

Definition at line 109 of file address_translation.h.

◆ VSA_ENTRY

#define VSA_ENTRY (   vsa)    (&virtualSliceMapPtr->virtualSlice[(vsa)])

Definition at line 373 of file address_translation.h.

◆ VSA_FAIL

#define VSA_FAIL   0xffffffff

Definition at line 58 of file address_translation.h.

◆ VSA_NONE

#define VSA_NONE   0xffffffff

Definition at line 57 of file address_translation.h.

Typedef Documentation

◆ BAD_BLOCK_TABLE_INFO_ENTRY

The bad block table for this die.

◆ BAD_BLOCK_TABLE_INFO_MAP

The bad block tables.

◆ FRRE_BLOCK_ALLOCATION_LIST

Warning
typo (FRRE -> FREE)
not used

◆ LOGICAL_SLICE_ENTRY

Exactly the Virtual Slice Address.

◆ LOGICAL_SLICE_MAP

The Logical -> Virtual Slice Address mapping table.

◆ P_BAD_BLOCK_TABLE_ENTRY

◆ P_BAD_BLOCK_TABLE_INFO_MAP

◆ P_FRRE_BLOCK_ALLOCATION_LIST

◆ P_LOGICAL_SLICE_ENTRY

◆ P_LOGICAL_SLICE_MAP

◆ P_PHY_BLOCK_ENTRY

◆ P_PHY_BLOCK_MAP

typedef struct _PHY_BLOCK_MAP * P_PHY_BLOCK_MAP

◆ P_VIRTUAL_BLOCK_ENTRY

◆ P_VIRTUAL_BLOCK_MAP

◆ P_VIRTUAL_DIE_ENTRY

◆ P_VIRTUAL_DIE_MAP

◆ P_VIRTUAL_SLICE_ENTRY

◆ P_VIRTUAL_SLICE_MAP

◆ PHY_BLOCK_ENTRY

The metadata of the physical block.

◆ PHY_BLOCK_MAP

typedef struct _PHY_BLOCK_MAP PHY_BLOCK_MAP

The metadata table for all the physical blocks.

◆ VIRTUAL_BLOCK_ENTRY

The metadata for this block.

◆ VIRTUAL_BLOCK_MAP

The block metadata table for all the blocks.

◆ VIRTUAL_DIE_ENTRY

The metadata for this die.

Todo:
There are

◆ VIRTUAL_DIE_MAP

The metadata table for all user dies.

◆ VIRTUAL_SLICE_ENTRY

Exactly the Logical Slice Address.

◆ VIRTUAL_SLICE_MAP

The Virtual -> Logical Slice mapping table.

Function Documentation

◆ AddrTransRead()

unsigned int AddrTransRead ( unsigned int  logicalSliceAddr)

Get the virtual slice address of the given logical slice.

Parameters
logicalSliceAddrthe logical address of the target slice.
Returns
unsigned int the virtual address of the target slice.

Definition at line 871 of file address_translation.c.

872{
873 unsigned int virtualSliceAddr;
874
875 if (logicalSliceAddr < SLICES_PER_SSD)
876 {
877 virtualSliceAddr = logicalSliceMapPtr->logicalSlice[logicalSliceAddr].virtualSliceAddr;
878
879 if (virtualSliceAddr != VSA_NONE)
880 return virtualSliceAddr;
881 else
882 return VSA_FAIL;
883 }
884 else
885 assert(!"[WARNING] Logical address is larger than maximum logical address served by SSD [WARNING]");
886}
P_LOGICAL_SLICE_MAP logicalSliceMapPtr
#define VSA_FAIL
#define VSA_NONE
#define SLICES_PER_SSD
Definition: ftl_config.h:231
unsigned int virtualSliceAddr
LOGICAL_SLICE_ENTRY logicalSlice[SLICES_PER_SSD]
Here is the caller graph for this function:

◆ AddrTransWrite()

unsigned int AddrTransWrite ( unsigned int  logicalSliceAddr)

Assign a new virtual (physical) page to the specified logical page.

Before issuing the write request, we should allocate a physical page for the specified logical page and invalidate the old physical page if it exists.

Note
In current implementation, if the target page of a write request is not empty, a read request on the target page will be issued automatically before the write request, therefore, we don't have to handle data migration in this function.
See also
ReqTransSliceToLowLevel().
Parameters
logicalSliceAddrthe logical address of the target slice.
Returns
unsigned int the renewed virtual slice address for the given logical slice.

Definition at line 903 of file address_translation.c.

904{
905 unsigned int virtualSliceAddr;
906
907 if (logicalSliceAddr < SLICES_PER_SSD)
908 {
909 InvalidateOldVsa(logicalSliceAddr);
910
911 virtualSliceAddr = FindFreeVirtualSlice();
912
913 logicalSliceMapPtr->logicalSlice[logicalSliceAddr].virtualSliceAddr = virtualSliceAddr;
914 virtualSliceMapPtr->virtualSlice[virtualSliceAddr].logicalSliceAddr = logicalSliceAddr;
915
916 return virtualSliceAddr;
917 }
918 else
919 assert(!"[WARNING] Logical address is larger than maximum logical address served by SSD [WARNING]");
920}
unsigned int FindFreeVirtualSlice()
Select a free physical page (virtual slice).
void InvalidateOldVsa(unsigned int logicalSliceAddr)
Invalidate the specified virtual page.
P_VIRTUAL_SLICE_MAP virtualSliceMapPtr
unsigned int logicalSliceAddr
VIRTUAL_SLICE_ENTRY virtualSlice[SLICES_PER_SSD]
Here is the call graph for this function:
Here is the caller graph for this function:

◆ EraseBlock()

void EraseBlock ( unsigned int  dieNo,
unsigned int  blockNo 
)

Erase the specified block of the specified die and discard its LSAs.

This function will:

  • Send a ERASE request to erase the specified block
  • Move the specified block to free block list
  • Discard all the logical slice addresses of the origin block

    Todo:
    programmedPageCnt
Note
The specified block may not be invalidated immediately.
Parameters
dieNothe die number of the specified block.
blockNothe block number on the specified die.

Definition at line 1122 of file address_translation.c.

1123{
1124 unsigned int pageNo, virtualSliceAddr, reqSlotTag;
1125
1126 reqSlotTag = GetFromFreeReqQ();
1127
1128 reqPoolPtr->reqPool[reqSlotTag].reqType = REQ_TYPE_NAND;
1134 reqPoolPtr->reqPool[reqSlotTag].nandInfo.virtualSliceAddr = Vorg2VsaTranslation(dieNo, blockNo, 0);
1136 virtualBlockMapPtr->block[dieNo][blockNo].currentPage;
1137
1138 SelectLowLevelReqQ(reqSlotTag);
1139
1140 // block map indicated blockNo initialization
1141 virtualBlockMapPtr->block[dieNo][blockNo].free = 1;
1142 virtualBlockMapPtr->block[dieNo][blockNo].eraseCnt++;
1143 virtualBlockMapPtr->block[dieNo][blockNo].invalidSliceCnt = 0;
1144 virtualBlockMapPtr->block[dieNo][blockNo].currentPage = 0;
1145
1146 PutToFbList(dieNo, blockNo);
1147
1148 for (pageNo = 0; pageNo < USER_PAGES_PER_BLOCK; pageNo++)
1149 {
1150 virtualSliceAddr = Vorg2VsaTranslation(dieNo, blockNo, pageNo);
1152 }
1153}
void PutToFbList(unsigned int dieNo, unsigned int blockNo)
Append the given virtual block to the free block list of its die.
P_VIRTUAL_BLOCK_MAP virtualBlockMapPtr
#define Vorg2VsaTranslation(dieNo, blockNo, pageNo)
Translate virtual NAND organization (location vector) into VSA.
#define LSA_NONE
#define USER_PAGES_PER_BLOCK
Definition: ftl_config.h:221
unsigned int GetFromFreeReqQ()
Get a free request from the free request queue.
P_REQ_POOL reqPoolPtr
#define REQ_OPT_BLOCK_SPACE_MAIN
for the 1 bit flag REQ_OPTION::blockSpace.
#define REQ_OPT_ROW_ADDR_DEPENDENCY_CHECK
#define REQ_OPT_DATA_BUF_NONE
#define REQ_OPT_NAND_ADDR_VSA
#define REQ_CODE_ERASE
#define REQ_TYPE_NAND
void SelectLowLevelReqQ(unsigned int reqSlotTag)
Dispatch given NVMe/NAND request to corresponding request queue.
unsigned int programmedPageCnt
unsigned int virtualSliceAddr
unsigned int dataBufFormat
Type of address stored in the SSD_REQ_FORMAT::dataBufInfo.
unsigned int nandAddr
Type of address stored in the SSD_REQ_FORMAT::nandInfo.
unsigned int blockSpace
unsigned int rowAddrDependencyCheck
SSD_REQ_FORMAT reqPool[AVAILABLE_OUNTSTANDING_REQ_COUNT]
REQ_OPTION reqOpt
unsigned int reqCode
NAND_INFO nandInfo
unsigned int reqType
unsigned int currentPage
unsigned int eraseCnt
unsigned int free
unsigned int invalidSliceCnt
VIRTUAL_BLOCK_ENTRY block[USER_DIES][USER_BLOCKS_PER_DIE]
Here is the call graph for this function:
Here is the caller graph for this function:

◆ FindDieForFreeSliceAllocation()

unsigned int FindDieForFreeSliceAllocation ( )

Update and get the die number to serve the next write request.

To exploit the parallelism, the write request should first be interleaved on different channels to take advantage of the channel parallelism. If all the channels' same way are used, select the next way of each channel to use the die parallelism.

Warning
As paper the mentioned, may not perform well if latency largely varied.
Returns
unsigned int The target die number.

Definition at line 1051 of file address_translation.c.

1052{
1053 static unsigned char targetCh = 0;
1054 static unsigned char targetWay = 0;
1055 unsigned int targetDie;
1056
1057 targetDie = Pcw2VdieTranslation(targetCh, targetWay);
1058
1059 if (targetCh != (USER_CHANNELS - 1))
1060 targetCh = targetCh + 1;
1061 else
1062 {
1063 targetCh = 0;
1064 targetWay = (targetWay + 1) % USER_WAYS;
1065 }
1066
1067 return targetDie;
1068}
#define Pcw2VdieTranslation(chNo, wayNo)
Get die number from physical channel number and way number.
#define USER_CHANNELS
Definition: ftl_config.h:207
#define USER_WAYS
Definition: ftl_config.h:208
Here is the caller graph for this function:

◆ FindFreeVirtualSlice()

unsigned int FindFreeVirtualSlice ( )

Select a free physical page (virtual slice).

In current implementation, the target page to serve the write request is determined by checking the following three variables:

  • sliceAllocationTargetDie:

    The die where the next request should be issued to.

    To exploit the parallelism of each die, especially under write-intensive workload, the write requests will be interleaved to each die.

    Check FindDieForFreeSliceAllocation() for details.

  • VIRTUAL_DIE_ENTRY::currentBlock:

    The current working block of the target die.

    Each die maintains a current working block and will select a page from the current working block of target die to serve the write request. Once all the pages of the current working block are used, the fw will select a new free block from the free block list as the new current working block of that die.

    If there the free block list of that die is empty, the fw will try to release invalid blocks by doing GC.

    Check GetFromFbList() and GarbageCollection() for the details.

  • VIRTUAL_BLOCK_ENTRY::currentPage:

    The current working page of the current working block on the die.

    Current implementation just selects the free page sequentially from the current working block.

See also
VIRTUAL_DIE_ENTRY, VIRTUAL_BLOCK_ENTRY, FindDieForFreeSliceAllocation().
Warning
why the currentPage might be full after GC?
why assign dieNo before return? redundant?
Returns
unsigned int the VSA for the request.

Definition at line 965 of file address_translation.c.

966{
967 unsigned int currentBlock, virtualSliceAddr, dieNo;
968
970 currentBlock = virtualDieMapPtr->die[dieNo].currentBlock;
971
972 // if the currently used block is full, assign a free block as new current block
973 if (virtualBlockMapPtr->block[dieNo][currentBlock].currentPage == USER_PAGES_PER_BLOCK)
974 {
975 currentBlock = GetFromFbList(dieNo, GET_FREE_BLOCK_NORMAL);
976
977 if (currentBlock != BLOCK_FAIL)
978 virtualDieMapPtr->die[dieNo].currentBlock = currentBlock;
979 else
980 {
981 GarbageCollection(dieNo);
982 currentBlock = virtualDieMapPtr->die[dieNo].currentBlock;
983
984 // FIXME: why need to check whether `currentPage` is full?
985 if (virtualBlockMapPtr->block[dieNo][currentBlock].currentPage == USER_PAGES_PER_BLOCK)
986 {
987 currentBlock = GetFromFbList(dieNo, GET_FREE_BLOCK_NORMAL);
988 if (currentBlock != BLOCK_FAIL)
989 virtualDieMapPtr->die[dieNo].currentBlock = currentBlock;
990 else
991 assert(!"[WARNING] There is no available block [WARNING]");
992 }
993 else if (virtualBlockMapPtr->block[dieNo][currentBlock].currentPage > USER_PAGES_PER_BLOCK)
994 assert(!"[WARNING] Current page management fail [WARNING]");
995 }
996 }
997 else if (virtualBlockMapPtr->block[dieNo][currentBlock].currentPage > USER_PAGES_PER_BLOCK)
998 assert(!"[WARNING] Current page management fail [WARNING]");
999
1000 virtualSliceAddr =
1001 Vorg2VsaTranslation(dieNo, currentBlock, virtualBlockMapPtr->block[dieNo][currentBlock].currentPage);
1002 virtualBlockMapPtr->block[dieNo][currentBlock].currentPage++;
1003 sliceAllocationTargetDie = FindDieForFreeSliceAllocation(); // sliceAllocationTargetDie should be updated
1004 dieNo = sliceAllocationTargetDie; // don't merge the 2 lines
1005 return virtualSliceAddr;
1006}
unsigned char sliceAllocationTargetDie
unsigned int FindDieForFreeSliceAllocation()
Update and get the die number to serve the next write request.
unsigned int GetFromFbList(unsigned int dieNo, unsigned int getFreeBlockOption)
Pop the first block in the free block list of the specified die.
P_VIRTUAL_DIE_MAP virtualDieMapPtr
#define GET_FREE_BLOCK_NORMAL
#define BLOCK_FAIL
void GarbageCollection(unsigned int dieNo)
unsigned int currentBlock
VIRTUAL_DIE_ENTRY die[USER_DIES]
Here is the call graph for this function:
Here is the caller graph for this function:

◆ FindFreeVirtualSliceForGc()

unsigned int FindFreeVirtualSliceForGc ( unsigned int  copyTargetDieNo,
unsigned int  victimBlockNo 
)

Definition at line 1008 of file address_translation.c.

1009{
1010 unsigned int currentBlock, virtualSliceAddr, dieNo;
1011
1012 dieNo = copyTargetDieNo;
1013 if (victimBlockNo == virtualDieMapPtr->die[dieNo].currentBlock)
1014 {
1017 assert(!"[WARNING] There is no available block [WARNING]");
1018 }
1019 currentBlock = virtualDieMapPtr->die[dieNo].currentBlock;
1020
1021 if (virtualBlockMapPtr->block[dieNo][currentBlock].currentPage == USER_PAGES_PER_BLOCK)
1022 {
1023
1024 currentBlock = GetFromFbList(dieNo, GET_FREE_BLOCK_GC);
1025
1026 if (currentBlock != BLOCK_FAIL)
1027 virtualDieMapPtr->die[dieNo].currentBlock = currentBlock;
1028 else
1029 assert(!"[WARNING] There is no available block [WARNING]");
1030 }
1031 else if (virtualBlockMapPtr->block[dieNo][currentBlock].currentPage > USER_PAGES_PER_BLOCK)
1032 assert(!"[WARNING] Current page management fail [WARNING]");
1033
1034 virtualSliceAddr =
1035 Vorg2VsaTranslation(dieNo, currentBlock, virtualBlockMapPtr->block[dieNo][currentBlock].currentPage);
1036 virtualBlockMapPtr->block[dieNo][currentBlock].currentPage++;
1037 return virtualSliceAddr;
1038}
#define GET_FREE_BLOCK_GC
Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetFromFbList()

unsigned int GetFromFbList ( unsigned int  dieNo,
unsigned int  getFreeBlockOption 
)

Pop the first block in the free block list of the specified die.

Note
Each die will reserve some free blocks (VIRTUAL_DIE_ENTRY::freeBlockCnt), so if the number of free blocks is less then the number of preserved blocks, BLOCK_FAIL will be returned.
Todo:
Difference between GET_FREE_BLOCK_NORMAL and GET_FREE_BLOCK_GC.
Parameters
dieNoThe target die number.
getFreeBlockOption//TODO
Returns
unsigned int The virtual block address of the evicted block.

Definition at line 1194 of file address_translation.c.

1195{
1196 unsigned int evictedBlockNo;
1197
1198 evictedBlockNo = virtualDieMapPtr->die[dieNo].headFreeBlock;
1199
1200 if (getFreeBlockOption == GET_FREE_BLOCK_NORMAL)
1201 {
1203 return BLOCK_FAIL;
1204 }
1205 else if (getFreeBlockOption == GET_FREE_BLOCK_GC)
1206 {
1207 if (evictedBlockNo == BLOCK_NONE)
1208 return BLOCK_FAIL;
1209 }
1210 else
1211 assert(!"[WARNING] Wrong getFreeBlockOption [WARNING]");
1212
1213 if (virtualBlockMapPtr->block[dieNo][evictedBlockNo].nextBlock != BLOCK_NONE)
1214 {
1215 virtualDieMapPtr->die[dieNo].headFreeBlock = virtualBlockMapPtr->block[dieNo][evictedBlockNo].nextBlock;
1216 virtualBlockMapPtr->block[dieNo][virtualBlockMapPtr->block[dieNo][evictedBlockNo].nextBlock].prevBlock =
1217 BLOCK_NONE;
1218 }
1219 else
1220 {
1223 }
1224
1225 virtualBlockMapPtr->block[dieNo][evictedBlockNo].free = 0;
1227
1228 virtualBlockMapPtr->block[dieNo][evictedBlockNo].nextBlock = BLOCK_NONE;
1229 virtualBlockMapPtr->block[dieNo][evictedBlockNo].prevBlock = BLOCK_NONE;
1230
1231 return evictedBlockNo;
1232}
#define RESERVED_FREE_BLOCK_COUNT
#define BLOCK_NONE
unsigned int prevBlock
unsigned int nextBlock
unsigned int headFreeBlock
unsigned int freeBlockCnt
unsigned int tailFreeBlock
Here is the caller graph for this function:

◆ InitAddressMap()

void InitAddressMap ( )

Initialize the translation related maps.

The following tasks will be finished in the function:

  • Initialize logical and virtual slice map (all entries map to NONE)
  • Read/Remake the bad block table of each die
  • Replace bad blocks with the reserved blocks in the same die
  • Initialize V2P table and free block list
  • Choose a free block as the current working block for each die

This function, only initialize the base addresses of these maps, the physical block map and some bad blocks info. The other maps will be initialized in InitBlockDieMap() and InitSliceMap(), check the two functions for further initialization.

Todo:
To initialize the physical block map,

Definition at line 82 of file address_translation.c.

83{
84 unsigned int blockNo, dieNo;
85
92
93 // reset physical block mapping and bad block info
94 for (dieNo = 0; dieNo < USER_DIES; dieNo++)
95 {
96 // the blocks should not be remapped to any other blocks before remmaping
97 for (blockNo = 0; blockNo < TOTAL_BLOCKS_PER_DIE; blockNo++)
98 phyBlockMapPtr->phyBlock[dieNo][blockNo].remappedPhyBlock = blockNo;
99
100 bbtInfoMapPtr->bbtInfo[dieNo].phyBlock = 0;
102 }
103
104 // by default, the request start from the first die
106
107 InitSliceMap();
109}
void InitSliceMap()
Initialize Logical and Virtual Slick Map.
P_BAD_BLOCK_TABLE_INFO_MAP bbtInfoMapPtr
P_PHY_BLOCK_MAP phyBlockMapPtr
void InitBlockDieMap()
Build the bad block table and V2P block mapping of each user die.
struct _PHY_BLOCK_MAP * P_PHY_BLOCK_MAP
struct _BAD_BLOCK_TABLE_INFO_MAP * P_BAD_BLOCK_TABLE_INFO_MAP
#define BBT_INFO_GROWN_BAD_UPDATE_NONE
struct _VIRTUAL_SLICE_MAP * P_VIRTUAL_SLICE_MAP
struct _VIRTUAL_BLOCK_MAP * P_VIRTUAL_BLOCK_MAP
struct _LOGICAL_SLICE_MAP * P_LOGICAL_SLICE_MAP
struct _VIRTUAL_DIE_MAP * P_VIRTUAL_DIE_MAP
#define USER_DIES
Definition: ftl_config.h:219
#define TOTAL_BLOCKS_PER_DIE
Definition: ftl_config.h:163
#define VIRTUAL_BLOCK_MAP_ADDR
Definition: memory_map.h:101
#define PHY_BLOCK_MAP_ADDR
Definition: memory_map.h:102
#define BAD_BLOCK_TABLE_INFO_MAP_ADDR
Definition: memory_map.h:103
#define VIRTUAL_SLICE_MAP_ADDR
Definition: memory_map.h:100
#define VIRTUAL_DIE_MAP_ADDR
Definition: memory_map.h:104
#define LOGICAL_SLICE_MAP_ADDR
Definition: memory_map.h:99
unsigned int phyBlock
unsigned int grownBadUpdate
BAD_BLOCK_TABLE_INFO_ENTRY bbtInfo[USER_DIES]
unsigned int remappedPhyBlock
PHY_BLOCK_ENTRY phyBlock[USER_DIES][TOTAL_BLOCKS_PER_DIE]
Here is the call graph for this function:
Here is the caller graph for this function:

◆ InitBlockDieMap()

void InitBlockDieMap ( )

Build the bad block table and V2P block mapping of each user die.

To create the V2P mapping, we have to:

  1. Build the bad block table by reading or remaking the bad block table
  2. Replace bad blocks with reserved blocks
  3. Map virtual blocks to available physical blocks
  4. Add available virtual blocks into free block list

Definition at line 815 of file address_translation.c.

816{
817 unsigned int dieNo;
818 unsigned char eraseFlag = 1;
819
820 xil_printf("Press 'X' to re-make the bad block table.\r\n");
821
822 char input = inbyte();
823 if (input == 'X')
824 {
825 xil_printf("[WARNING!!!] Start re-making bad block table\r\n");
827 eraseFlag = 0;
828 }
829 else
830 {
831 xil_printf("[WARNING!!!] Skip re-making bad block table\r\n");
832 }
833
834 // empty the free block list of each die
835 InitDieMap();
836
837 // read bbt from flash [, create bbt, persist new bbt to flash]
839
840 /*
841 * Since the block specified by `BAD_BLOCK_TABLE_INFO_ENTRY::phyBlock` is used for
842 * storing the bbt of that die, so we have to mark that block bad and let it to be
843 * remapped to another block for using.
844 *
845 * And because we have at least one bad block on each die, the remapping process thus
846 * should not be skipped.
847 */
848 for (dieNo = 0; dieNo < USER_DIES; dieNo++)
851
852 // create V2P table and initialize free block list
853 InitBlockMap();
854
855 if (eraseFlag)
857
859}
void InitDieMap()
Reset the free block list of each die.
void EraseUserBlockSpace()
Erase all the non-bad main blocks on user dies and wait until done.
void InitBlockMap()
Create V2P table and free block list.
void EraseTotalBlockSpace()
Erase all the blocks on user dies and wait until done.
void InitCurrentBlockOfDieMap()
Get a default free block for each die.
void RecoverBadBlockTable(unsigned int tempBufAddr)
Read the bbt from flash and re-create if not exists.
void RemapBadBlock()
Try to remap the bad blocks in the main block space.
char inbyte()
Definition: bsp.c:4
#define RESERVED_DATA_BUFFER_BASE_ADDR
Definition: memory_map.h:85
unsigned int bad
Here is the call graph for this function:
Here is the caller graph for this function:

◆ InitSliceMap()

void InitSliceMap ( )

Initialize Logical and Virtual Slick Map.

This function simply initialize all the slice addresses in the both map to NONE.

Definition at line 116 of file address_translation.c.

117{
118 int sliceAddr;
119 for (sliceAddr = 0; sliceAddr < SLICES_PER_SSD; sliceAddr++)
120 {
123 }
124}
Here is the caller graph for this function:

◆ InvalidateOldVsa()

void InvalidateOldVsa ( unsigned int  logicalSliceAddr)

Invalidate the specified virtual page.

Overwriting cannot perform on physical flash cell, so the fw must handle out-of-place update.

This function is used for invalidate the corresponding physical page of the specified logical page, but in case there was no physical page allocated on the logical page before, we should check if the corresponding physical page exists before doing GC on the invalidated physical page.

Parameters
logicalSliceAddrLSA that specifies the virtual slice to be invalidated.

Definition at line 1083 of file address_translation.c.

1084{
1085 unsigned int virtualSliceAddr, dieNo, blockNo;
1086
1087 virtualSliceAddr = logicalSliceMapPtr->logicalSlice[logicalSliceAddr].virtualSliceAddr;
1088
1089 if (virtualSliceAddr != VSA_NONE)
1090 {
1091 if (virtualSliceMapPtr->virtualSlice[virtualSliceAddr].logicalSliceAddr != logicalSliceAddr)
1092 return;
1093
1094 dieNo = Vsa2VdieTranslation(virtualSliceAddr);
1095 blockNo = Vsa2VblockTranslation(virtualSliceAddr);
1096
1097 // unlink
1098 SelectiveGetFromGcVictimList(dieNo, blockNo);
1099 virtualBlockMapPtr->block[dieNo][blockNo].invalidSliceCnt++;
1101
1102 PutToGcVictimList(dieNo, blockNo, virtualBlockMapPtr->block[dieNo][blockNo].invalidSliceCnt);
1103 }
1104}
#define Vsa2VdieTranslation(virtualSliceAddr)
#define Vsa2VblockTranslation(virtualSliceAddr)
void PutToGcVictimList(unsigned int dieNo, unsigned int blockNo, unsigned int invalidSliceCnt)
void SelectiveGetFromGcVictimList(unsigned int dieNo, unsigned int blockNo)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ PutToFbList()

void PutToFbList ( unsigned int  dieNo,
unsigned int  blockNo 
)

Append the given virtual block to the free block list of its die.

Parameters
dieNothe die number of the given block.
blockNoVBN of the specified block.

Definition at line 1161 of file address_translation.c.

1162{
1164 {
1166 virtualBlockMapPtr->block[dieNo][blockNo].nextBlock = BLOCK_NONE;
1168 virtualDieMapPtr->die[dieNo].tailFreeBlock = blockNo;
1169 }
1170 else
1171 {
1172 virtualBlockMapPtr->block[dieNo][blockNo].prevBlock = BLOCK_NONE;
1173 virtualBlockMapPtr->block[dieNo][blockNo].nextBlock = BLOCK_NONE;
1174 virtualDieMapPtr->die[dieNo].headFreeBlock = blockNo;
1175 virtualDieMapPtr->die[dieNo].tailFreeBlock = blockNo;
1176 }
1177
1179}
Here is the caller graph for this function:

◆ UpdateBadBlockTableForGrownBadBlock()

void UpdateBadBlockTableForGrownBadBlock ( unsigned int  tempBufAddr)

Update the bad block table and persist to the specified block.

A little bit similar to FindBadBlock(), but this function use the bad block flag to mark bad blocks, instead of reading the bad block marks.

Parameters
tempBufAddrthe base address of the bad block tables.

Definition at line 1254 of file address_translation.c.

1255{
1256 unsigned int dieNo, phyBlockNo, tempBbtBufBaseAddr, tempBbtBufEntrySize;
1257 unsigned int tempBbtBufAddr[USER_DIES];
1258 unsigned char dieState[USER_DIES];
1259 unsigned char *bbtUpdater;
1260
1261 // data buffer allocation
1262 tempBbtBufBaseAddr = tempBufAddr;
1264 for (dieNo = 0; dieNo < USER_DIES; dieNo++)
1265 tempBbtBufAddr[dieNo] =
1266 tempBbtBufBaseAddr + dieNo * USED_PAGES_FOR_BAD_BLOCK_TABLE_PER_DIE * tempBbtBufEntrySize;
1267
1268 // create new bad block table
1269 for (dieNo = 0; dieNo < USER_DIES; dieNo++)
1270 {
1272 {
1273 for (phyBlockNo = 0; phyBlockNo < TOTAL_BLOCKS_PER_DIE; phyBlockNo++)
1274 {
1275 bbtUpdater = (unsigned char *)(tempBbtBufAddr[dieNo] + phyBlockNo);
1276
1277 if (phyBlockNo != bbtInfoMapPtr->bbtInfo[dieNo].phyBlock)
1278 *bbtUpdater = phyBlockMapPtr->phyBlock[dieNo][phyBlockNo].bad;
1279 else
1280 *bbtUpdater = BLOCK_STATE_NORMAL;
1281 }
1282
1283 dieState[dieNo] = DIE_STATE_BAD_BLOCK_TABLE_UPDATE;
1284 }
1285 else
1286 dieState[dieNo] = DIE_STATE_BAD_BLOCK_TABLE_HOLD;
1287 }
1288
1289 // update bad block tables in flash
1290 SaveBadBlockTable(dieState, tempBbtBufAddr, tempBbtBufEntrySize);
1291}
void SaveBadBlockTable(unsigned char dieState[], unsigned int tempBbtBufAddr[], unsigned int tempBbtBufEntrySize)
Persist the newly created bbt for those dies whose bbt not exists.
#define BLOCK_STATE_NORMAL
#define USED_PAGES_FOR_BAD_BLOCK_TABLE_PER_DIE
#define DIE_STATE_BAD_BLOCK_TABLE_UPDATE
#define DIE_STATE_BAD_BLOCK_TABLE_HOLD
#define BBT_INFO_GROWN_BAD_UPDATE_BOOKED
#define BYTES_PER_DATA_REGION_OF_PAGE
Definition: ftl_config.h:179
#define BYTES_PER_SPARE_REGION_OF_PAGE
Definition: ftl_config.h:180
Here is the call graph for this function:
Here is the caller graph for this function:

◆ UpdatePhyBlockMapForGrownBadBlock()

void UpdatePhyBlockMapForGrownBadBlock ( unsigned int  dieNo,
unsigned int  phyBlockNo 
)

Mark the given physical block bad block and update the bbt later.

Parameters
dieNothe die number of the given block.
phyBlockNothe physical address of the block to be marked as bad block.

Definition at line 1240 of file address_translation.c.

1241{
1242 phyBlockMapPtr->phyBlock[dieNo][phyBlockNo].bad = BLOCK_STATE_BAD;
1244}
#define BLOCK_STATE_BAD
Here is the caller graph for this function:

Variable Documentation

◆ bbtInfoMapPtr

P_BAD_BLOCK_TABLE_INFO_MAP bbtInfoMapPtr
extern

Definition at line 59 of file address_translation.c.

◆ logicalSliceMapPtr

P_LOGICAL_SLICE_MAP logicalSliceMapPtr
extern

Definition at line 54 of file address_translation.c.

◆ mbPerbadBlockSpace

unsigned int mbPerbadBlockSpace
extern

Definition at line 62 of file address_translation.c.

◆ phyBlockMapPtr

P_PHY_BLOCK_MAP phyBlockMapPtr
extern

Definition at line 58 of file address_translation.c.

◆ sliceAllocationTargetDie

unsigned char sliceAllocationTargetDie
extern

Definition at line 61 of file address_translation.c.

◆ virtualBlockMapPtr

P_VIRTUAL_BLOCK_MAP virtualBlockMapPtr
extern

Definition at line 56 of file address_translation.c.

◆ virtualDieMapPtr

P_VIRTUAL_DIE_MAP virtualDieMapPtr
extern

Definition at line 57 of file address_translation.c.

◆ virtualSliceMapPtr

P_VIRTUAL_SLICE_MAP virtualSliceMapPtr
extern

Definition at line 55 of file address_translation.c.