gem5  v20.1.0.0
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 
63 FlashDeviceParams::create()
64 {
65  return new FlashDevice(this);
66 }
67 
68 
73 FlashDevice::FlashDevice(const FlashDeviceParams* p):
74  AbstractNVM(p),
75  diskSize(0),
76  blockSize(p->blk_size),
77  pageSize(p->page_size),
78  GCActivePercentage(p->GC_active),
79  readLatency(p->read_lat),
80  writeLatency(p->write_lat),
81  eraseLatency(p->erase_lat),
82  dataDistribution(p->data_distribution),
83  numPlanes(p->num_planes),
84  pagesPerBlock(0),
85  pagesPerDisk(0),
86  blocksPerDisk(0),
87  planeMask(numPlanes - 1),
88  planeEventQueue(numPlanes),
89  planeEvent([this]{ actionComplete(); }, name())
90 {
91 
92  /*
93  * Let 'a' be a power of two of n bits, written such that a-n is the msb
94  * and a-0 is the lsb. Since it is a power of two, only one bit (a-x,
95  * with 0 <= x <= n) is set. If we subtract one from this number the bits
96  * a-(x-1) to a-0 are set and all the other bits are cleared. Hence a
97  * bitwise AND with those two numbers results in an integer with all bits
98  * cleared.
99  */
100  if (numPlanes & planeMask)
101  fatal("Number of planes is not a power of 2 in flash device.\n");
102 }
103 
109 void
110 FlashDevice::initializeFlash(uint64_t disk_size, uint32_t sector_size)
111 {
112  diskSize = disk_size * sector_size;
116 
118  DPRINTF(FlashDevice, "diskSize: %d Bytes; %d pages per block, %d pages "
119  "per disk\n", diskSize, pagesPerBlock, pagesPerDisk);
120 
121  locationTable.resize(pagesPerDisk);
122 
124  blockValidEntries.resize(blocksPerDisk, 0);
126 
136  unknownPages.resize((pagesPerDisk >> 5) + 1, 0xFFFFFFFF);
137 
138  for (uint32_t count = 0; count < pagesPerDisk; count++) {
139  //setup lookup table + physical aspects
140 
141  if (dataDistribution == Enums::stripe) {
144 
145  } else {
148  }
149  }
150 }
151 
153 {
154  DPRINTF(FlashDevice, "Remove FlashDevice\n");
155 }
156 
162 void
163 FlashDevice::accessDevice(uint64_t address, uint32_t amount,
164  const std::function<void()> &event, Actions action)
165 {
166  DPRINTF(FlashDevice, "Flash calculation for %d bytes in %d pages\n"
167  , amount, pageSize);
168 
169  std::vector<Tick> time(numPlanes, 0);
170  uint64_t logic_page_addr = address / pageSize;
171  uint32_t plane_address = 0;
172 
180  for (uint32_t count = 0; amount > (count * pageSize); count++) {
181  uint32_t index = (locationTable[logic_page_addr].block *
182  pagesPerBlock) + (logic_page_addr % pagesPerBlock);
183 
184  DPRINTF(FlashDevice, "Index 0x%8x, Block 0x%8x, pages/block %d,"
185  " logic address 0x%8x\n", index,
186  locationTable[logic_page_addr].block, pagesPerBlock,
187  logic_page_addr);
188  DPRINTF(FlashDevice, "Page %d; %d bytes up to this point\n", count,
189  (count * pageSize));
190 
191  plane_address = locationTable[logic_page_addr].block & planeMask;
192 
193  if (action == ActionRead) {
194  //lookup
195  //call accessTimes
196  time[plane_address] += accessTimes(locationTable[logic_page_addr]
197  .block, ActionRead);
198 
199  /*stats*/
200  stats.readAccess.sample(logic_page_addr);
201  stats.readLatency.sample(time[plane_address]);
202  } else { //write
203  //lookup
204  //call accessTimes if appropriate, page may be unknown, so lets
205  //give it the benefit of the doubt
206 
207  if (getUnknownPages(index))
208  time[plane_address] += accessTimes
209  (locationTable[logic_page_addr].block, ActionWrite);
210 
211  else //A remap is needed
212  time[plane_address] += remap(logic_page_addr);
213 
214  /*stats*/
215  stats.writeAccess.sample(logic_page_addr);
216  stats.writeLatency.sample(time[plane_address]);
217  }
218 
226  if (getUnknownPages(index)) {
228  --blockEmptyEntries[locationTable[logic_page_addr].block];
229  ++blockValidEntries[locationTable[logic_page_addr].block];
230  }
231 
232  stats.fileSystemAccess.sample(address);
233  ++logic_page_addr;
234  }
235 
240  for (uint32_t count = 0; count < numPlanes; count++){
241  plane_address = (time[plane_address] > time[count]) ? plane_address
242  : count;
243 
244  DPRINTF(FlashDevice, "Plane %d is busy for %d ticks\n", count,
245  time[count]);
246 
247  if (time[count] != 0) {
248 
249  struct CallBackEntry cbe;
256  if (planeEventQueue[count].empty())
257  cbe.time = time[count] + curTick();
258  else
259  cbe.time = time[count] +
260  planeEventQueue[count].back().time;
261  planeEventQueue[count].push_back(cbe);
262 
263  DPRINTF(FlashDevice, "scheduled at: %ld\n", cbe.time);
264 
265  if (!planeEvent.scheduled())
266  schedule(planeEvent, planeEventQueue[count].back().time);
267  else if (planeEventQueue[count].back().time < planeEvent.when())
269  planeEventQueue[plane_address].back().time, true);
270  }
271  }
272 
273  //worst case two plane finish at the same time, each triggers an event
274  //and this callback will be called once. Maybe before the other plane
275  //could execute its event, but in the same tick.
276  planeEventQueue[plane_address].back().function = event;
277  DPRINTF(FlashDevice, "Callback queued for plane %d; %d in queue\n",
278  plane_address, planeEventQueue[plane_address].size());
279  DPRINTF(FlashDevice, "first event @ %d\n", planeEvent.when());
280 }
281 
287 void
289 {
290  DPRINTF(FlashDevice, "Plane action completed\n");
291  uint8_t plane_address = 0;
292 
293  uint8_t next_event = 0;
294 
296  for (plane_address = 0; plane_address < numPlanes; plane_address++) {
297  if (!planeEventQueue[plane_address].empty()) {
302  assert(planeEventQueue[plane_address].front().time >= curTick());
303 
304  if (planeEventQueue[plane_address].front().time == curTick()) {
310  auto temp = planeEventQueue[plane_address].front().function;
311  planeEventQueue[plane_address].pop_front();
312 
314  if (temp) {
315  DPRINTF(FlashDevice, "Callback, %d\n", plane_address);
316  temp();
317  }
318  }
319  }
320  }
321 
323  for (plane_address = 0; plane_address < numPlanes; plane_address++) {
324  if (!planeEventQueue[plane_address].empty())
325  if (planeEventQueue[next_event].empty() ||
326  (planeEventQueue[plane_address].front().time <
327  planeEventQueue[next_event].front().time))
328  next_event = plane_address;
329  }
330 
332  if (!planeEventQueue[next_event].empty()) {
333  DPRINTF(FlashDevice, "Schedule plane: %d\n", plane_address);
334  reschedule(planeEvent, planeEventQueue[next_event].front().time, true);
335  }
336 
337  checkDrain();
338 
339  DPRINTF(FlashDevice, "returing from flash event\n");
340  DPRINTF(FlashDevice, "first event @ %d\n", planeEvent.when());
341 }
342 
348 Tick
349 FlashDevice::remap(uint64_t logic_page_addr)
350 {
354  if (blockEmptyEntries[locationTable[logic_page_addr].block] > 0) {
355  //just a remap
356  //update tables
357  --blockEmptyEntries[locationTable[logic_page_addr].block];
358  //access to this table won't be sequential anymore
359  locationTable[logic_page_addr].page = pagesPerBlock + 2;
360  //access new block
361  Tick time = accessTimes(locationTable[logic_page_addr].block,
362  ActionWrite);
363 
364  DPRINTF(FlashDevice, "Remap returns %d ticks\n", time);
365  return time;
366 
367  } else {
368  //calculate how much time GC would have taken
369  uint32_t block = locationTable[logic_page_addr].block;
370  Tick time = ((GCActivePercentage *
371  (accessTimes(block, ActionCopy) +
372  accessTimes(block, ActionErase)))
373  / 100);
374 
375  //use block as the logical start address of the block
376  block = locationTable[logic_page_addr].block * pagesPerBlock;
377 
378  //assumption: clean will improve locality
379  for (uint32_t count = 0; count < pagesPerBlock; count++) {
380  assert(block + count < pagesPerDisk);
381  locationTable[block + count].page = (block + count) %
383  }
384 
385  blockEmptyEntries[locationTable[logic_page_addr].block] =
387  /*stats*/
389 
390  DPRINTF(FlashDevice, "Remap with erase action returns %d ticks\n",
391  time);
392 
393  return time;
394  }
395 
396 }
397 
401 Tick
402 FlashDevice::accessTimes(uint64_t block, Actions action)
403 {
404  Tick time = 0;
405 
406  switch(action) {
407  case ActionRead: {
409  time = readLatency;
410  } break;
411 
412  case ActionWrite: {
414  time = writeLatency + readLatency;
415  } break;
416 
417  case ActionErase: {
419  time = eraseLatency + readLatency;
420  } break;
421 
422  case ActionCopy: {
424  uint32_t validpages = blockValidEntries[block];
425  time = validpages * (readLatency + writeLatency);
426  } break;
427 
428  default: break;
429  }
430 
431  //Used to determine sequential action.
432  DPRINTF(FlashDevice, "Access returns %d ticks\n", time);
433  return time;
434 }
435 
450 inline
451 void
453 {
454  unknownPages[index >> 5] &= ~(0x01 << (index % 32));
455 }
456 
461 inline
462 bool
464 {
465  return unknownPages[index >> 5] & (0x01 << (index % 32));
466 }
467 
468 void
470 {
472 
473  using namespace Stats;
474 
475  std::string fd_name = name() + ".FlashDevice";
476 
477  // Register the stats
480  .name(fd_name + ".totalGCActivations")
481  .desc("Number of Garbage collector activations")
482  .flags(none);
483 
486  .init(2)
487  .name(fd_name + ".writeAccessHist")
488  .desc("Histogram of write addresses")
489  .flags(pdf);
491  .init(2)
492  .name(fd_name + ".readAccessHist")
493  .desc("Histogram of read addresses")
494  .flags(pdf);
496  .init(100)
497  .name(fd_name + ".fileSystemAccessHist")
498  .desc("Histogram of file system accesses")
499  .flags(pdf);
500 
503  .init(100)
504  .name(fd_name + ".writeLatencyHist")
505  .desc("Histogram of write latency")
506  .flags(pdf);
508  .init(100)
509  .name(fd_name + ".readLatencyHist")
510  .desc("Histogram of read latency")
511  .flags(pdf);
512 }
513 
518 void
520 {
522 
526 
527  int location_table_size = locationTable.size();
528  SERIALIZE_SCALAR(location_table_size);
529  for (uint32_t count = 0; count < location_table_size; count++) {
530  paramOut(cp, csprintf("locationTable[%d].page", count),
531  locationTable[count].page);
532  paramOut(cp, csprintf("locationTable[%d].block", count),
533  locationTable[count].block);
534  }
535 };
536 
541 void
543 {
545 
549 
550  int location_table_size;
551  UNSERIALIZE_SCALAR(location_table_size);
552  locationTable.resize(location_table_size);
553  for (uint32_t count = 0; count < location_table_size; count++) {
554  paramIn(cp, csprintf("locationTable[%d].page", count),
555  locationTable[count].page);
556  paramIn(cp, csprintf("locationTable[%d].block", count),
557  locationTable[count].block);
558  }
559 };
560 
567 {
568  if (planeEvent.scheduled()) {
569  DPRINTF(Drain, "Flash device is draining...\n");
570  return DrainState::Draining;
571  } else {
572  DPRINTF(Drain, "Flash device in drained state\n");
573  return DrainState::Drained;
574  }
575 }
576 
581 void
583 {
585  return;
586 
587  if (planeEvent.when() > curTick()) {
588  DPRINTF(Drain, "Flash device is still draining\n");
589  } else {
590  DPRINTF(Drain, "Flash device is done draining\n");
591  signalDrainDone();
592  }
593 }
FlashDevice::FlashDeviceStats::readLatency
Stats::Histogram readLatency
Definition: flash_device.hh:104
FlashDevice::locationTable
std::vector< struct PageMapEntry > locationTable
address to logic place has a block and a page field
Definition: flash_device.hh:186
FlashDevice::regStats
void regStats() override
Stats register function.
Definition: flash_device.cc:469
fatal
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:183
Stats::Group::regStats
virtual void regStats()
Callback to set stat parameters.
Definition: group.cc:64
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:460
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:797
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:856
EventManager::reschedule
void reschedule(Event &event, Tick when, bool always=false)
Definition: eventq.hh:1023
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:452
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:542
FlashDevice::actionComplete
void actionComplete()
Event rescheduler.
Definition: flash_device.cc:288
QARMA::amount
int amount
Definition: qarma.hh:67
Tick
uint64_t Tick
Tick count type.
Definition: types.hh:63
FlashDevice::accessDevice
void accessDevice(uint64_t address, uint32_t amount, const std::function< void()> &event, Actions action)
Flash action function.
Definition: flash_device.cc:163
std::vector< Tick >
X86ISA::count
count
Definition: misc.hh:703
FlashDevice::drain
DrainState drain() override
Checkpoint functions.
Definition: flash_device.cc:566
Event::when
Tick when() const
Get the time that the event is scheduled.
Definition: eventq.hh:503
paramOut
void paramOut(CheckpointOut &cp, const string &name, ExtMachInst const &machInst)
Definition: types.cc:38
Stats::none
const FlagsType none
Nothing extra to print.
Definition: info.hh:43
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:331
DrainState::Drained
@ Drained
Buffers drained, ready for serialization/handover.
DrainState
DrainState
Object drain/handover states.
Definition: drain.hh:71
FlashDevice::FlashDevice
FlashDevice(const FlashDeviceParams *)
Initialize functions.
Definition: flash_device.cc:73
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:98
FlashDevice::accessTimes
Tick accessTimes(uint64_t address, Actions accesstype)
Access time calculator.
Definition: flash_device.cc:402
cp
Definition: cprintf.cc:40
EventManager::schedule
void schedule(Event &event, Tick when)
Definition: eventq.hh:1005
FlashDevice::checkDrain
void checkDrain()
Checkdrain; needed to enable checkpoints.
Definition: flash_device.cc:582
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:234
FlashDevice::FlashDeviceStats::fileSystemAccess
Stats::Histogram fileSystemAccess
Definition: flash_device.hh:100
MipsISA::event
Bitfield< 10, 5 > event
Definition: pra_constants.hh:297
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
Stats::DataWrap::name
Derived & name(const std::string &name)
Set the name and marks this stat to print at the end of simulation.
Definition: statistics.hh:274
name
const std::string & name()
Definition: trace.cc:50
SERIALIZE_SCALAR
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:790
Drainable::drainState
DrainState drainState() const
Return the current drain state of an object.
Definition: drain.hh:320
SimObject::name
virtual const std::string name() const
Definition: sim_object.hh:133
FlashDevice::GCActivePercentage
const uint32_t GCActivePercentage
Garbage collection algorithm emulator.
Definition: flash_device.hh:159
FlashDevice::~FlashDevice
~FlashDevice()
Definition: flash_device.cc:152
FlashDevice::remap
Tick remap(uint64_t logic_page_addr)
FTL functionality.
Definition: flash_device.cc:349
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:103
FlashDevice::FlashDeviceStats::readAccess
Stats::Histogram readAccess
Definition: flash_device.hh:99
Stats::pdf
const FlagsType pdf
Print the percent of the total that this entry represents.
Definition: info.hh:51
SERIALIZE_CONTAINER
#define SERIALIZE_CONTAINER(member)
Definition: serialize.hh:848
FlashDevice::pageSize
const uint32_t pageSize
Definition: flash_device.hh:156
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
paramIn
void paramIn(CheckpointIn &cp, const string &name, ExtMachInst &machInst)
Definition: types.cc:69
Stats::DistBase::sample
void sample(const U &v, int n=1)
Add a value to the distribtion n times.
Definition: statistics.hh:1924
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:63
Stats
Definition: statistics.cc:61
FlashDevice::planeMask
uint32_t planeMask
Definition: flash_device.hh:178
FlashDevice::ActionErase
@ ActionErase
Definition: flash_device.hh:74
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:110
trace.hh
Stats::Histogram::init
Histogram & init(size_type size)
Set the parameters of this histogram.
Definition: statistics.hh:2669
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
FlashDevice::numPlanes
const uint32_t numPlanes
Definition: flash_device.hh:168
CheckpointIn
Definition: serialize.hh:67
FlashDevice::getUnknownPages
bool getUnknownPages(uint32_t index)
Function to test if a page is known.
Definition: flash_device.cc:463
Stats::DataWrap::desc
Derived & desc(const std::string &_desc)
Set the description and marks this stat to print at the end of simulation.
Definition: statistics.hh:307
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:519
DrainState::Draining
@ Draining
Draining buffers pending serialization/handover.
curTick
Tick curTick()
The current simulated tick.
Definition: core.hh:45
FlashDevice::FlashDeviceStats::totalGCActivations
Stats::Scalar totalGCActivations
Amount of GC activations.
Definition: flash_device.hh:95

Generated on Wed Sep 30 2020 14:02:10 for gem5 by doxygen 1.8.17