gem5  v21.0.0.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
flash_device.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013-2015 ARM Limited
3  * All rights reserved
4  *
5  * The license below extends only to copyright in the software and shall
6  * not be construed as granting a license to any other intellectual
7  * property including but not limited to intellectual property relating
8  * to a hardware implementation of the functionality of the software
9  * licensed hereunder. You may use the software subject to the license
10  * terms below provided that you ensure that this notice is replicated
11  * unmodified and in its entirety in all distributions of the software,
12  * modified or unmodified, in source code or in binary form.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions are
16  * met: redistributions of source code must retain the above copyright
17  * notice, this list of conditions and the following disclaimer;
18  * redistributions in binary form must reproduce the above copyright
19  * notice, this list of conditions and the following disclaimer in the
20  * documentation and/or other materials provided with the distribution;
21  * neither the name of the copyright holders nor the names of its
22  * contributors may be used to endorse or promote products derived from
23  * this software without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36  */
37 
53 #include "dev/arm/flash_device.hh"
54 
55 #include "base/trace.hh"
56 #include "debug/Drain.hh"
57 
62 FlashDevice::FlashDevice(const FlashDeviceParams &p):
63  AbstractNVM(p),
64  diskSize(0),
65  blockSize(p.blk_size),
66  pageSize(p.page_size),
67  GCActivePercentage(p.GC_active),
68  readLatency(p.read_lat),
69  writeLatency(p.write_lat),
70  eraseLatency(p.erase_lat),
71  dataDistribution(p.data_distribution),
72  numPlanes(p.num_planes),
73  stats(this),
74  pagesPerBlock(0),
75  pagesPerDisk(0),
76  blocksPerDisk(0),
77  planeMask(numPlanes - 1),
78  planeEventQueue(numPlanes),
79  planeEvent([this]{ actionComplete(); }, name())
80 {
81 
82  /*
83  * Let 'a' be a power of two of n bits, written such that a-n is the msb
84  * and a-0 is the lsb. Since it is a power of two, only one bit (a-x,
85  * with 0 <= x <= n) is set. If we subtract one from this number the bits
86  * a-(x-1) to a-0 are set and all the other bits are cleared. Hence a
87  * bitwise AND with those two numbers results in an integer with all bits
88  * cleared.
89  */
90  if (numPlanes & planeMask)
91  fatal("Number of planes is not a power of 2 in flash device.\n");
92 }
93 
99 void
100 FlashDevice::initializeFlash(uint64_t disk_size, uint32_t sector_size)
101 {
102  diskSize = disk_size * sector_size;
106 
108  DPRINTF(FlashDevice, "diskSize: %d Bytes; %d pages per block, %d pages "
109  "per disk\n", diskSize, pagesPerBlock, pagesPerDisk);
110 
111  locationTable.resize(pagesPerDisk);
112 
114  blockValidEntries.resize(blocksPerDisk, 0);
116 
126  unknownPages.resize((pagesPerDisk >> 5) + 1, 0xFFFFFFFF);
127 
128  for (uint32_t count = 0; count < pagesPerDisk; count++) {
129  //setup lookup table + physical aspects
130 
131  if (dataDistribution == Enums::stripe) {
134 
135  } else {
138  }
139  }
140 }
141 
143 {
144  DPRINTF(FlashDevice, "Remove FlashDevice\n");
145 }
146 
152 void
153 FlashDevice::accessDevice(uint64_t address, uint32_t amount,
154  const std::function<void()> &event, Actions action)
155 {
156  DPRINTF(FlashDevice, "Flash calculation for %d bytes in %d pages\n"
157  , amount, pageSize);
158 
159  std::vector<Tick> time(numPlanes, 0);
160  uint64_t logic_page_addr = address / pageSize;
161  uint32_t plane_address = 0;
162 
170  for (uint32_t count = 0; amount > (count * pageSize); count++) {
171  uint32_t index = (locationTable[logic_page_addr].block *
172  pagesPerBlock) + (logic_page_addr % pagesPerBlock);
173 
174  DPRINTF(FlashDevice, "Index 0x%8x, Block 0x%8x, pages/block %d,"
175  " logic address 0x%8x\n", index,
176  locationTable[logic_page_addr].block, pagesPerBlock,
177  logic_page_addr);
178  DPRINTF(FlashDevice, "Page %d; %d bytes up to this point\n", count,
179  (count * pageSize));
180 
181  plane_address = locationTable[logic_page_addr].block & planeMask;
182 
183  if (action == ActionRead) {
184  //lookup
185  //call accessTimes
186  time[plane_address] += accessTimes(locationTable[logic_page_addr]
187  .block, ActionRead);
188 
189  /*stats*/
190  stats.readAccess.sample(logic_page_addr);
191  stats.readLatency.sample(time[plane_address]);
192  } else { //write
193  //lookup
194  //call accessTimes if appropriate, page may be unknown, so lets
195  //give it the benefit of the doubt
196 
197  if (getUnknownPages(index))
198  time[plane_address] += accessTimes
199  (locationTable[logic_page_addr].block, ActionWrite);
200 
201  else //A remap is needed
202  time[plane_address] += remap(logic_page_addr);
203 
204  /*stats*/
205  stats.writeAccess.sample(logic_page_addr);
206  stats.writeLatency.sample(time[plane_address]);
207  }
208 
216  if (getUnknownPages(index)) {
218  --blockEmptyEntries[locationTable[logic_page_addr].block];
219  ++blockValidEntries[locationTable[logic_page_addr].block];
220  }
221 
222  stats.fileSystemAccess.sample(address);
223  ++logic_page_addr;
224  }
225 
230  for (uint32_t count = 0; count < numPlanes; count++){
231  plane_address = (time[plane_address] > time[count]) ? plane_address
232  : count;
233 
234  DPRINTF(FlashDevice, "Plane %d is busy for %d ticks\n", count,
235  time[count]);
236 
237  if (time[count] != 0) {
238 
239  struct CallBackEntry cbe;
246  if (planeEventQueue[count].empty())
247  cbe.time = time[count] + curTick();
248  else
249  cbe.time = time[count] +
250  planeEventQueue[count].back().time;
251  planeEventQueue[count].push_back(cbe);
252 
253  DPRINTF(FlashDevice, "scheduled at: %ld\n", cbe.time);
254 
255  if (!planeEvent.scheduled())
256  schedule(planeEvent, planeEventQueue[count].back().time);
257  else if (planeEventQueue[count].back().time < planeEvent.when())
259  planeEventQueue[plane_address].back().time, true);
260  }
261  }
262 
263  //worst case two plane finish at the same time, each triggers an event
264  //and this callback will be called once. Maybe before the other plane
265  //could execute its event, but in the same tick.
266  planeEventQueue[plane_address].back().function = event;
267  DPRINTF(FlashDevice, "Callback queued for plane %d; %d in queue\n",
268  plane_address, planeEventQueue[plane_address].size());
269  DPRINTF(FlashDevice, "first event @ %d\n", planeEvent.when());
270 }
271 
277 void
279 {
280  DPRINTF(FlashDevice, "Plane action completed\n");
281  uint8_t plane_address = 0;
282 
283  uint8_t next_event = 0;
284 
286  for (plane_address = 0; plane_address < numPlanes; plane_address++) {
287  if (!planeEventQueue[plane_address].empty()) {
292  assert(planeEventQueue[plane_address].front().time >= curTick());
293 
294  if (planeEventQueue[plane_address].front().time == curTick()) {
300  auto temp = planeEventQueue[plane_address].front().function;
301  planeEventQueue[plane_address].pop_front();
302 
304  if (temp) {
305  DPRINTF(FlashDevice, "Callback, %d\n", plane_address);
306  temp();
307  }
308  }
309  }
310  }
311 
313  for (plane_address = 0; plane_address < numPlanes; plane_address++) {
314  if (!planeEventQueue[plane_address].empty())
315  if (planeEventQueue[next_event].empty() ||
316  (planeEventQueue[plane_address].front().time <
317  planeEventQueue[next_event].front().time))
318  next_event = plane_address;
319  }
320 
322  if (!planeEventQueue[next_event].empty()) {
323  DPRINTF(FlashDevice, "Schedule plane: %d\n", plane_address);
324  reschedule(planeEvent, planeEventQueue[next_event].front().time, true);
325  }
326 
327  checkDrain();
328 
329  DPRINTF(FlashDevice, "returing from flash event\n");
330  DPRINTF(FlashDevice, "first event @ %d\n", planeEvent.when());
331 }
332 
338 Tick
339 FlashDevice::remap(uint64_t logic_page_addr)
340 {
344  if (blockEmptyEntries[locationTable[logic_page_addr].block] > 0) {
345  //just a remap
346  //update tables
347  --blockEmptyEntries[locationTable[logic_page_addr].block];
348  //access to this table won't be sequential anymore
349  locationTable[logic_page_addr].page = pagesPerBlock + 2;
350  //access new block
351  Tick time = accessTimes(locationTable[logic_page_addr].block,
352  ActionWrite);
353 
354  DPRINTF(FlashDevice, "Remap returns %d ticks\n", time);
355  return time;
356 
357  } else {
358  //calculate how much time GC would have taken
359  uint32_t block = locationTable[logic_page_addr].block;
360  Tick time = ((GCActivePercentage *
361  (accessTimes(block, ActionCopy) +
362  accessTimes(block, ActionErase)))
363  / 100);
364 
365  //use block as the logical start address of the block
366  block = locationTable[logic_page_addr].block * pagesPerBlock;
367 
368  //assumption: clean will improve locality
369  for (uint32_t count = 0; count < pagesPerBlock; count++) {
370  assert(block + count < pagesPerDisk);
371  locationTable[block + count].page = (block + count) %
373  }
374 
375  blockEmptyEntries[locationTable[logic_page_addr].block] =
377  /*stats*/
379 
380  DPRINTF(FlashDevice, "Remap with erase action returns %d ticks\n",
381  time);
382 
383  return time;
384  }
385 
386 }
387 
391 Tick
392 FlashDevice::accessTimes(uint64_t block, Actions action)
393 {
394  Tick time = 0;
395 
396  switch(action) {
397  case ActionRead: {
399  time = readLatency;
400  } break;
401 
402  case ActionWrite: {
404  time = writeLatency + readLatency;
405  } break;
406 
407  case ActionErase: {
409  time = eraseLatency + readLatency;
410  } break;
411 
412  case ActionCopy: {
414  uint32_t validpages = blockValidEntries[block];
415  time = validpages * (readLatency + writeLatency);
416  } break;
417 
418  default: break;
419  }
420 
421  //Used to determine sequential action.
422  DPRINTF(FlashDevice, "Access returns %d ticks\n", time);
423  return time;
424 }
425 
440 inline
441 void
443 {
444  unknownPages[index >> 5] &= ~(0x01 << (index % 32));
445 }
446 
451 inline
452 bool
454 {
455  return unknownPages[index >> 5] & (0x01 << (index % 32));
456 }
457 
460  : Stats::Group(parent, "FlashDevice"),
461  ADD_STAT(totalGCActivations, UNIT_COUNT,
462  "Number of Garbage collector activations"),
463  ADD_STAT(writeAccess, UNIT_COUNT, "Histogram of write addresses"),
464  ADD_STAT(readAccess, UNIT_COUNT, "Histogram of read addresses"),
465  ADD_STAT(fileSystemAccess, UNIT_COUNT,
466  "Histogram of file system accesses"),
467  ADD_STAT(writeLatency, UNIT_TICK, "Histogram of write latency"),
468  ADD_STAT(readLatency, UNIT_TICK, "Histogram of read latency")
469 {
470  using namespace Stats;
471 
474  .flags(none);
475 
478  .init(2)
479  .flags(pdf);
480  readAccess
481  .init(2)
482  .flags(pdf);
484  .init(100)
485  .flags(pdf);
486 
489  .init(100)
490  .flags(pdf);
492  .init(100)
493  .flags(pdf);
494 }
495 
500 void
502 {
504 
508 
509  int location_table_size = locationTable.size();
510  SERIALIZE_SCALAR(location_table_size);
511  for (uint32_t count = 0; count < location_table_size; count++) {
512  paramOut(cp, csprintf("locationTable[%d].page", count),
513  locationTable[count].page);
514  paramOut(cp, csprintf("locationTable[%d].block", count),
515  locationTable[count].block);
516  }
517 };
518 
523 void
525 {
527 
531 
532  int location_table_size;
533  UNSERIALIZE_SCALAR(location_table_size);
534  locationTable.resize(location_table_size);
535  for (uint32_t count = 0; count < location_table_size; count++) {
536  paramIn(cp, csprintf("locationTable[%d].page", count),
537  locationTable[count].page);
538  paramIn(cp, csprintf("locationTable[%d].block", count),
539  locationTable[count].block);
540  }
541 };
542 
549 {
550  if (planeEvent.scheduled()) {
551  DPRINTF(Drain, "Flash device is draining...\n");
552  return DrainState::Draining;
553  } else {
554  DPRINTF(Drain, "Flash device in drained state\n");
555  return DrainState::Drained;
556  }
557 }
558 
563 void
565 {
567  return;
568 
569  if (planeEvent.when() > curTick()) {
570  DPRINTF(Drain, "Flash device is still draining\n");
571  } else {
572  DPRINTF(Drain, "Flash device is done draining\n");
573  signalDrainDone();
574  }
575 }
FlashDevice::FlashDeviceStats::readLatency
Stats::Histogram readLatency
Definition: flash_device.hh:107
FlashDevice::locationTable
std::vector< struct PageMapEntry > locationTable
address to logic place has a block and a page field
Definition: flash_device.hh:186
fatal
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:183
FlashDevice::ActionCopy
@ ActionCopy
A copy involves taking all the used pages from a block and store it in another.
Definition: flash_device.hh:79
Event::scheduled
bool scheduled() const
Determine if the current event is scheduled.
Definition: eventq.hh:462
FlashDevice::unknownPages
std::vector< uint32_t > unknownPages
when the disk is first started we are unsure of the number of used pages, this variable will help det...
Definition: flash_device.hh:184
FlashDevice::pagesPerBlock
uint32_t pagesPerBlock
Disk dimensions in pages and blocks.
Definition: flash_device.hh:174
FlashDevice::CallBackEntry
Definition: flash_device.hh:88
FlashDevice::ActionRead
@ ActionRead
Definition: flash_device.hh:72
MipsISA::index
Bitfield< 30, 0 > index
Definition: pra_constants.hh:44
UNSERIALIZE_SCALAR
#define UNSERIALIZE_SCALAR(scalar)
Definition: serialize.hh:591
FlashDevice::blockEmptyEntries
std::vector< uint32_t > blockEmptyEntries
number of empty entries
Definition: flash_device.hh:190
FlashDevice::dataDistribution
const Enums::DataDistribution dataDistribution
Flash organization.
Definition: flash_device.hh:167
FlashDevice::pagesPerDisk
uint32_t pagesPerDisk
Definition: flash_device.hh:175
UNSERIALIZE_CONTAINER
#define UNSERIALIZE_CONTAINER(member)
Definition: serialize.hh:650
EventManager::reschedule
void reschedule(Event &event, Tick when, bool always=false)
Definition: eventq.hh:1034
flash_device.hh
FlashDevice::writeLatency
const Tick writeLatency
Definition: flash_device.hh:163
FlashDevice::clearUnknownPages
void clearUnknownPages(uint32_t index)
Function to indicate that a page is known.
Definition: flash_device.cc:442
AbstractNVM
This is an interface between the disk interface (which will handle the disk data transactions) and th...
Definition: abstract_nvm.hh:53
FlashDevice::ActionWrite
@ ActionWrite
Definition: flash_device.hh:73
FlashDevice::unserialize
void unserialize(CheckpointIn &cp) override
Unserialize; needed to restore from checkpoints.
Definition: flash_device.cc:524
FlashDevice::actionComplete
void actionComplete()
Event rescheduler.
Definition: flash_device.cc:278
QARMA::amount
int amount
Definition: qarma.hh:67
UNIT_TICK
#define UNIT_TICK
Definition: units.hh:40
Tick
uint64_t Tick
Tick count type.
Definition: types.hh:59
FlashDevice::accessDevice
void accessDevice(uint64_t address, uint32_t amount, const std::function< void()> &event, Actions action)
Flash action function.
Definition: flash_device.cc:153
std::vector< Tick >
X86ISA::count
count
Definition: misc.hh:703
FlashDevice::drain
DrainState drain() override
Checkpoint functions.
Definition: flash_device.cc:548
Event::when
Tick when() const
Get the time that the event is scheduled.
Definition: eventq.hh:505
Stats::none
const FlagsType none
Nothing extra to print.
Definition: info.hh:44
FlashDevice::readLatency
const Tick readLatency
Access latencies.
Definition: flash_device.hh:162
Stats::DataWrap::flags
Derived & flags(Flags _flags)
Set the flags and marks this stat to print at the end of simulation.
Definition: statistics.hh:339
DrainState::Drained
@ Drained
Buffers drained, ready for serialization/handover.
DrainState
DrainState
Object drain/handover states.
Definition: drain.hh:71
FlashDevice::stats
struct FlashDeviceStats stats
RequestHandler stats.
Definition: flash_device.hh:171
FlashDevice::FlashDeviceStats::writeAccess
Stats::Histogram writeAccess
Histogram of address accesses.
Definition: flash_device.hh:101
FlashDevice::accessTimes
Tick accessTimes(uint64_t address, Actions accesstype)
Access time calculator.
Definition: flash_device.cc:392
cp
Definition: cprintf.cc:37
EventManager::schedule
void schedule(Event &event, Tick when)
Definition: eventq.hh:1016
FlashDevice::checkDrain
void checkDrain()
Checkdrain; needed to enable checkpoints.
Definition: flash_device.cc:564
FlashDevice::blockValidEntries
std::vector< uint32_t > blockValidEntries
number of valid entries per block
Definition: flash_device.hh:188
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:237
ADD_STAT
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition: group.hh:71
FlashDevice::FlashDeviceStats::fileSystemAccess
Stats::Histogram fileSystemAccess
Definition: flash_device.hh:103
MipsISA::event
Bitfield< 10, 5 > event
Definition: pra_constants.hh:297
FlashDevice::FlashDevice
FlashDevice(const FlashDeviceParams &)
Initialize functions.
Definition: flash_device.cc:62
FlashDevice::CallBackEntry::time
Tick time
Definition: flash_device.hh:89
Drainable::signalDrainDone
void signalDrainDone() const
Signal that an object is drained.
Definition: drain.hh:301
FlashDevice::FlashDeviceStats::FlashDeviceStats
FlashDeviceStats(Stats::Group *parent)
Definition: flash_device.cc:459
UNIT_COUNT
#define UNIT_COUNT
Definition: units.hh:49
name
const std::string & name()
Definition: trace.cc:48
SERIALIZE_SCALAR
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:584
paramOut
void paramOut(CheckpointOut &cp, const std::string &name, ExtMachInst const &machInst)
Definition: types.cc:37
Drainable::drainState
DrainState drainState() const
Return the current drain state of an object.
Definition: drain.hh:320
FlashDevice::GCActivePercentage
const uint32_t GCActivePercentage
Garbage collection algorithm emulator.
Definition: flash_device.hh:159
FlashDevice::~FlashDevice
~FlashDevice()
Definition: flash_device.cc:142
FlashDevice::remap
Tick remap(uint64_t logic_page_addr)
FTL functionality.
Definition: flash_device.cc:339
FlashDevice::planeEvent
EventFunctionWrapper planeEvent
Completion event.
Definition: flash_device.hh:196
FlashDevice::FlashDeviceStats::writeLatency
Stats::Histogram writeLatency
Histogram of access latencies.
Definition: flash_device.hh:106
FlashDevice::FlashDeviceStats::readAccess
Stats::Histogram readAccess
Definition: flash_device.hh:102
Stats::pdf
const FlagsType pdf
Print the percent of the total that this entry represents.
Definition: info.hh:52
SERIALIZE_CONTAINER
#define SERIALIZE_CONTAINER(member)
Definition: serialize.hh:642
FlashDevice::pageSize
const uint32_t pageSize
Definition: flash_device.hh:156
Stats::Group
Statistics container.
Definition: group.hh:87
FlashDevice::Actions
Actions
Defines the possible actions to the flash.
Definition: flash_device.hh:71
FlashDevice
Flash Device model The Flash Device model is a timing model for a NAND flash device.
Definition: flash_device.hh:54
Stats::DistBase::sample
void sample(const U &v, int n=1)
Add a value to the distribtion n times.
Definition: statistics.hh:1323
FlashDevice::planeEventQueue
std::vector< std::deque< struct CallBackEntry > > planeEventQueue
This vector of queues keeps track of all the callbacks per plane.
Definition: flash_device.hh:193
CheckpointOut
std::ostream CheckpointOut
Definition: serialize.hh:64
Stats
Definition: statistics.cc:53
FlashDevice::planeMask
uint32_t planeMask
Definition: flash_device.hh:178
FlashDevice::ActionErase
@ ActionErase
Definition: flash_device.hh:74
curTick
Tick curTick()
The universal simulation clock.
Definition: cur_tick.hh:43
FlashDevice::initializeFlash
void initializeFlash(uint64_t disk_size, uint32_t sector_size)
Initialization function; called when all disk specifics are known.
Definition: flash_device.cc:100
trace.hh
Stats::Histogram::init
Histogram & init(size_type size)
Set the parameters of this histogram.
Definition: statistics.hh:2153
MipsISA::p
Bitfield< 0 > p
Definition: pra_constants.hh:323
FlashDevice::blockSize
const uint32_t blockSize
Definition: flash_device.hh:155
FlashDevice::blocksPerDisk
uint32_t blocksPerDisk
Definition: flash_device.hh:176
paramIn
void paramIn(CheckpointIn &cp, const std::string &name, ExtMachInst &machInst)
Definition: types.cc:69
FlashDevice::numPlanes
const uint32_t numPlanes
Definition: flash_device.hh:168
CheckpointIn
Definition: serialize.hh:68
FlashDevice::getUnknownPages
bool getUnknownPages(uint32_t index)
Function to test if a page is known.
Definition: flash_device.cc:453
FlashDevice::diskSize
uint64_t diskSize
Disk sizes in bytes.
Definition: flash_device.hh:154
csprintf
std::string csprintf(const char *format, const Args &...args)
Definition: cprintf.hh:158
FlashDevice::eraseLatency
const Tick eraseLatency
Definition: flash_device.hh:164
FlashDevice::serialize
void serialize(CheckpointOut &cp) const override
Serialize; needed to create checkpoints.
Definition: flash_device.cc:501
DrainState::Draining
@ Draining
Draining buffers pending serialization/handover.
FlashDevice::FlashDeviceStats::totalGCActivations
Stats::Scalar totalGCActivations
Amount of GC activations.
Definition: flash_device.hh:98

Generated on Tue Mar 23 2021 19:41:25 for gem5 by doxygen 1.8.17