参考论文阅读
参考论文:Flashsim:A Simulator for NAND Flash-based Solid-State Drives。
为了更好的理解该仿真器,去阅读了该仿真器设计者写的一篇学术论文,以下内容是我个人阅读原文理解和翻译的。
摘要部分:
该文献在摘要部分就说明Flashsim仿真器是event驱动类型的仿真器。Flashsim是与公认的硬盘仿真器Disksim良好兼容,能相互操作。因此可以在该仿真器上实现SSD和HDD的混合存储模型仿真,或者是SSD替换HDD的模型仿真。该仿真器是面向对象设计的仿真器,便于理解和拓展。
正文:
关于NAND flash的读写最小操作粒度是页(page),擦除粒度是块(block),页不仅存数据还有一个OOB(out-of-band area)带外区,里面包含数据纠错ECC,存放该数据对应的逻辑页地址(LPN),数据页的当前状态(有效,无效,空闲),下表是不同类型flash的访问响应时间和最小单位:
设计flashsim的FTL层也考虑了FTL应该包含三个部分:地址映射,垃圾回收,磨损均衡。
仿真器的设计
该仿真器的设计是依据下图的硬件结构体系:
第一版的仿真器注重软件实现部分(FTL机制,垃圾回收,磨损均衡)。考虑用的是简化的模型:单个plane配一个简化的channel。但是第一版受限于过于简化的硬件模型和与DiskSim的高度耦合难以拓展,所以才用面向对象的设计方法重新设计了仿真器。该仿真器用C++编写,是完全靠event驱动。
硬件模块设计
**SSD:**SSD类提供了对DiskSim操作的接口,通过例化该类能够创建一个SSD仿真模型。重点来了!!!这个SSD类创建的event对象包含了Disksim的ioreq_event结构体,并能反馈给Disksim该event的时间。
**Package(闪存颗粒封装):**package类是共用一个bus channel的一组flash dies。Package在其构造函数里分配其所包含的dies且将dies连接到bus channel上。这个Package也便于寻址。
**Die(闪存颗粒):**Die就是一个flash闪存片,包含多个面(plane)。Dies是直接连接在bus channel上的。但是每一个plane都包含一个die bus发送缓存,这是为了以后flash闪存发展可能在die这个更高的层面上进行合并操作,那么相应的event对象也会更新合并时延。
**Plane:**plane由多个块构成,且提供一个页大小的寄存器用来缓存发给bus发送缓存的页数据。当然这个寄存器也可作为plane内部合并操作的缓存。相应的event对象依据合并操作和寄存器时延更新合并时延。
Block:块包含若干的页,是最小的擦除单位。当块被擦除时,块里的页中所有数据都被擦除,之后可以重新被写入数据。对应的event对象会更新相应的擦除操作。
Page:每一个页都维持其页状态(有效,无效,空闲),在这个层面更新event对象的读写时延,这个时延依据具体的flash类型设置。
Controller(控制器):控制器类的例化对象从SSD类实例化对象中接受event对象,查询FTL决定如何处理每一个event对象。控制器先将有关event的虚拟数据发送给RAM缓冲,再将event对象发送给bus总线。
RAM: RAM类用来计算从中读取数据或向其写数据的时间(这就是缓冲区啊!!!!),RAM缓存控制器发送给bus的event的有关虚拟数据。
Bus: bus类包含若干channel,每个channel被同属一个package的所有dies共享。Bus核实event类中的address地址,根据这个地址将event发送到合适的channel上。
Channel: channel调度处理event和更新event的时间。每一个channel都维系了一个调度表,该调度表记录该channel当前的使用状态。新的event在满足一定相关条件下在下一个空闲时隙被调用处理。调度表的大小等同于队列的大小。
软件模块设计
Event: event类对应的是Disksim中的ioreq_event结构体。Event保持其方式和属性去记录反应SSD仿真器的状态,包括SSD的地址。仿真器对象处理event对象和更新event对象的统计信息。
Address: address由一个单独的字段组成,这个字段的地址包含从package到page层级(一个字段不同位置表示不同层次地址)。用字段表示地址而不是结构体,是因为字段能够提供分配和验证地址的清晰接口。
FTL:主要完成LPN到PPN地址的转化(其实仿真器内部是按扇区操作的)。FTL将包含多个页的event对象转化成单一页级的列表,再用controller按列表顺序处理页级event。FTL负责充分利用硬件的并行性能。FTL也包含垃圾回收和磨损均衡。
Wear Leveler: wear leveler 类将块擦除的操作分布在全部的SSD的块上,实现SSD上大量的块能够尽可能工作很久。
Garbage Collector:当请求不能被响应(所选的块不能写或者没有足够的空闲块选取写入时)出发垃圾回收。垃圾回收器搜寻合并部分已使用的数据块,将其擦除转化为新的空闲块。其他的GC算法也可以进行仿真。
总线交叉(Bus Channel Interleaving)
图中展示的是一个bus channel连接同属一个package的多个dies的情况。提一点,每个bus channel的工作是独立的,也就是多个bus channel可以同时并行操作。图a展示了bus channel上的读请求交叉。Crtl表示控制信号,Rd表示从dies的指定位置读取数据,Data表示将该数据经由bus channel 发送出(给control?)。
读请求交叉:
首先,控制时间(图中的Ctrl部分)表示,当控制信号到来时,总线通道会被锁住,请求 die 从给定的页中准备数据。
然后,die 处理读取数据的请求。这里面读出的数据就是放到刚刚上面所说的die buffer bus transfers。
这个时候总线是空闲的,可以处理其他请求。
最后,控制信号又会锁住总线通道,请求 die 从指定的页发送数据,并把这个数据发送出去。一个有趣的现象是,在 R2 的第一次 ctrl time 的结束到 R1 的第二次 ctrl time 的开始之间的这段总线空闲时间并不能被 R3 所利用,所以第三个请求(R3)必须要等到第二个请求(R2)结束后才能开始。
写请求交叉:
首先,控制信号会独占总线通道,总线通道被锁住,控制信号会通知相应的 die 它将要接收数据。
然后,总线通道仍然处于锁住状态,这个时候总线通道上会进行数据传输。这时候相应的die的buffer bus transfer 接受写入的数据。之后从buffer数据写入到对应的die的位置。
最后,相应的 die 写入数据,这个时候总线通道是空闲的,可以处理其他请求。
因为写请求只需要占用连续的总线通道时间,所以写请求总是先来先服务(FIFO)。
Event flow(时间流)
SSD类实例化的SSD对象接受来自Disksim的ioreq_event。其处理函数由算法1给出:
Input: Disksim’s I/O Request Structure (ioreq_event)
Output: Device Service Time
for each ioreq event do
begin SSD process ioreq event
wrap in event object;
begin controller, FTL process event
consult wearleveler and garbagecollector;
create page-sized list of event objects;
for each e in event list do
begin SSD, bus, channel process e
lock for next available transfer time;
etime ← etime + channel delay;
end
Package(e);
end
if etype = erase then
update SSD wear stats;
end
begin inform bus, channel: e finished
channel update scheduling table for event dependencies;
end
end
end
end
Algorithm 1: SSD simulator functionality
SSD的控制器处理用FTL软件模型针对多个页请求产生一个events列表。控制器通过处理数据对应的bus channel处理列表中的每一个event。Bus channel为控制器完成events的调度和交叉访问。
算法1里面一开始的event是包含多个页操作的,经过处理以后变成了一串以页为大小的event对象,之后control调用该页所属的channel bus处理。返回的是器件响应时间。
算法2中event持续的经过package后,在die层面上开始被处理。Events的合并操作可以是在flash的die层面也可以是plane内部。擦除操作在block层面,读写操作在page层面。
Input: Event object (e)
Output: NULL
begin package, die process e
/* Merge event e in die */
if etype = mergeandeaddr.plane "= eaddr merge.plane then
foreach valid page v in eaddr.block x do
foreach empty page t in eaddr merge.block y do
t ← v;
vstate ← invalid;
tstate ← valid;
end
etime ← etime + die merge delay;
end
end
/* Merge event e in plane */
else plane process e
planeregister ← edata;
if etype = merge then
foreach valid page v in eaddr.block x do
foreach empty page t in eaddr merge.block y do
t ← v;
vstate ← invalid;
tstate ← valid;
end
etime ← etime + die merge delay;
end
end
/* etype = read or write or erase */
else
begin block process e
if etype = erase then
for each page in block x do
pagestate ← empty;
end
etime ← etime + erase delay;
update wear stats;
end
/* etype = read or write */
else page process e
if etype = read then
etime ← etime + read delay;
end
else if etype = write then
etime ← etime + write delay;
end
end
end
if etype = erase then
update plane, die, package wear stats;
end
end
Algorithm 2: Package (event object) - SSD hardware functionality inside a package. This function is being called in
Algorithm 1.
文末展望写到:
Since the simulator has only been validated with a simple behavioral model for a single plane and simplified channel implementation, we will continue with more thorough validation methods that include bus channel interleaving effects. Caching and I/O scheduling effects will be added and examined.
这个仿真器目前是单一plane单总线的仿真?缓冲区的内容没有添加?