Go to the documentation of this file.
46 #include "debug/NVM.hh"
57 maxPendingWrites(_p.max_pending_writes),
58 maxPendingReads(_p.max_pending_reads),
59 twoCycleRdWr(_p.two_cycle_rdwr),
60 tREAD(_p.tREAD), tWRITE(_p.tWRITE), tSEND(_p.tSEND),
63 readReadyEvent([
this]{ processReadReadyEvent(); },
name()),
64 nextReadAt(0), numPendingReads(0), numReadDataReady(0),
67 DPRINTF(NVM,
"Setting up NVM Interface\n");
70 "must be a power of two\n", burstSize);
75 "not allowed, must be a power of two\n", ranksPerChannel);
77 for (
int i =0;
i < ranksPerChannel;
i++) {
79 DPRINTF(NVM,
"Creating NVM rank %d \n",
i);
80 Rank* rank =
new Rank(_p,
i, *
this);
81 ranks.push_back(rank);
86 DPRINTF(NVM,
"NVM capacity %lld (%lld) bytes\n", capacity,
89 rowsPerBank = capacity / (rowBufferSize *
90 banksPerRank * ranksPerChannel);
95 :
EventManager(&_nvm), rank(_rank), banks(_p.banks_per_rank)
97 for (
int b = 0;
b < _p.banks_per_rank;
b++) {
123 unsigned size,
bool is_read, uint8_t pseudo_channel)
188 panic(
"Unknown address mapping policy chosen!");
195 DPRINTF(NVM,
"Address: %#x Rank %d Bank %d Row %d\n",
196 pkt_addr, rank, bank, row);
203 return new MemPacket(pkt, is_read,
false, pseudo_channel, rank, bank, row,
204 bank_id, pkt_addr,
size);
211 bool found_prepped_pkt =
false;
213 auto selected_pkt_it = queue.end();
216 for (
auto i = queue.begin();
i != queue.end() ; ++
i) {
228 DPRINTF(NVM,
"%s bank %d - Rank %d available\n", __func__,
232 if (col_allowed_at <= min_col_at) {
237 selected_col_at = col_allowed_at;
239 DPRINTF(NVM,
"%s Seamless buffer hit\n", __func__);
241 }
else if (!found_prepped_pkt) {
245 selected_col_at = col_allowed_at;
246 DPRINTF(NVM,
"%s Prepped packet found \n", __func__);
247 found_prepped_pkt =
true;
250 DPRINTF(NVM,
"%s bank %d - Rank %d not available\n", __func__,
256 if (selected_pkt_it == queue.end()) {
257 DPRINTF(NVM,
"%s no available NVM ranks found\n", __func__);
260 return std::make_pair(selected_pkt_it, selected_col_at);
273 assert(!queue.empty());
278 for (
auto i = queue.begin();
i != queue.end() ; ++
i) {
335 DPRINTF(NVM,
"Issuing NVM Read to bank %d at tick %d. "
336 "Data ready at %d\n",
365 "processReadReadyEvent(): Data for an NVM read is ready. "
366 "numReadDataReady is %d\t numPendingReads is %d\n",
375 if (*ready_it > *
i) {
376 next_ready_at = *ready_it;
378 }
else if ((next_ready_at > *
i) && (
i != ready_it)) {
384 assert(*ready_it ==
curTick());
398 DPRINTF(NVM,
"Restart controller scheduler immediately\n");
409 return (read_rdy || write_rdy);
416 DPRINTF(NVM,
"NVM Timing access to addr %#x, rank/bank/row %d %d %d\n",
432 cmd_at = std::max(cmd_at, next_burst_at);
455 if (pkt->
rank !=
n->rank) {
461 n->banks[
i].rdAllowedAt = std::max(cmd_at + dly_to_rd_cmd,
462 n->banks[
i].rdAllowedAt);
464 n->banks[
i].wrAllowedAt = std::max(cmd_at + dly_to_wr_cmd,
465 n->banks[
i].wrAllowedAt);
469 DPRINTF(NVM,
"NVM Access to %#x, ready at %lld.\n",
529 DPRINTF(NVM,
"Rescheduled respond event from %lld to %11d\n",
531 DPRINTF(NVM,
"Front of response queue is %11d\n",
555 return std::make_pair(cmd_at, cmd_at +
tBURST);
562 "processWriteRespondEvent(): A NVM write reached its readyTime. "
582 DPRINTF(NVM,
"Restart controller scheduler immediately\n");
597 n->banks[
i].rdAllowedAt);
599 n->banks[
i].wrAllowedAt);
623 : statistics::
Group(&_nvm),
627 "Number of NVM read bursts"),
629 "Number of NVM write bursts"),
632 "Per bank write bursts"),
634 "Per bank write bursts"),
637 "Total ticks spent queuing"),
639 "Total ticks spent in databus transfers"),
641 "Total ticks spent from burst creation until serviced "
643 ADD_STAT(avgQLat, statistics::units::Rate<
644 statistics::units::
Tick, statistics::units::
Count>::get(),
645 "Average queueing delay per NVM burst"),
646 ADD_STAT(avgBusLat, statistics::units::Rate<
647 statistics::units::
Tick, statistics::units::
Count>::get(),
648 "Average bus latency per NVM burst"),
649 ADD_STAT(avgMemAccLat, statistics::units::Rate<
650 statistics::units::
Tick, statistics::units::
Count>::get(),
651 "Average memory access latency per NVM burst"),
653 ADD_STAT(avgRdBW, statistics::units::Rate<
654 statistics::units::Byte, statistics::units::Second>::get(),
655 "Average DRAM read bandwidth in MiBytes/s"),
656 ADD_STAT(avgWrBW, statistics::units::Rate<
657 statistics::units::Byte, statistics::units::Second>::get(),
658 "Average DRAM write bandwidth in MiBytes/s"),
659 ADD_STAT(peakBW, statistics::units::Rate<
660 statistics::units::Byte, statistics::units::Second>::get(),
661 "Theoretical peak bandwidth in MiByte/s"),
662 ADD_STAT(busUtil, statistics::units::Ratio::get(),
663 "NVM Data bus utilization in percentage"),
664 ADD_STAT(busUtilRead, statistics::units::Ratio::get(),
665 "NVM Data bus read utilization in percentage"),
666 ADD_STAT(busUtilWrite, statistics::units::Ratio::get(),
667 "NVM Data bus write utilization in percentage"),
670 "Reads issued to NVM for which data has not been transferred"),
672 "Number of outstanding writes to NVM"),
673 ADD_STAT(bytesPerBank, statistics::units::Byte::get(),
674 "Bytes read within a bank before loading new bank")
682 using namespace statistics;
684 perBankRdBursts.init(nvm.ranksPerChannel == 0 ? 1 :
685 nvm.banksPerRank * nvm.ranksPerChannel);
687 perBankWrBursts.init(nvm.ranksPerChannel == 0 ? 1 :
688 nvm.banksPerRank * nvm.ranksPerChannel);
690 avgQLat.precision(2);
691 avgBusLat.precision(2);
692 avgMemAccLat.precision(2);
694 avgRdBW.precision(2);
695 avgWrBW.precision(2);
698 busUtil.precision(2);
699 busUtilRead.precision(2);
700 busUtilWrite.precision(2);
703 .init(nvm.maxPendingReads)
707 .init(nvm.maxPendingWrites)
711 .init(nvm.rowBufferSize)
714 avgQLat = totQLat / readBursts;
715 avgBusLat = totBusLat / readBursts;
716 avgMemAccLat = totMemAccLat / readBursts;
719 avgWrBW = (bytesWritten / 1000000) /
simSeconds;
721 nvm.burstSize / 1000000;
723 busUtil = (avgRdBW + avgWrBW) / peakBW * 100;
724 busUtilRead = avgRdBW / peakBW * 100;
725 busUtilWrite = avgWrBW / peakBW * 100;
Tick curTick()
The universal simulation clock.
std::pair< MemPacketQueue::iterator, Tick > chooseNextFRFCFS(MemPacketQueue &queue, Tick min_col_at) const override
For FR-FCFS policy, find first NVM command that can issue default to first command to prepped region.
Interface to NVM devices with media specific parameters, statistics, and functions.
Tick when() const
Get the time that the event is scheduled.
const uint32_t maxPendingReads
Tick readToWriteDelay() const
virtual Tick verifySingleCmd(Tick cmd_tick, Tick max_cmds_per_burst, bool row_cmd)
Check for command bus contention for single cycle command.
Tick readyTime
When will request leave the controller.
uint32_t numWritesQueued
NVM specific variable, but declaring it here allows treating different interfaces in a more genral wa...
bool writeRespQueueFull() const override
Check if the write response queue has reached defined threshold.
NVMInterface(const NVMInterfaceParams &_p)
EventFunctionWrapper readReadyEvent
void chooseRead(MemPacketQueue &queue) override
Select read command to issue asynchronously.
std::vector< Bank > banks
Vector of NVM banks.
const FlagsType nozero
Don't print if this is zero.
virtual void init()
init() is called after all C++ SimObjects have been created and all ports are connected.
Rank(const NVMInterfaceParams &_p, int _rank, NVMInterface &_nvm)
virtual void restartScheduler(Tick tick, uint8_t pseudo_channel=0)
restart the controller This can be used by interfaces to restart the scheduler after maintainence com...
A basic class to track the bank state, i.e.
void addRankToRankDelay(Tick cmd_at) override
Add rank to rank delay to bus timing to all NVM banks in alli ranks when access to an alternate inter...
const uint32_t burstsPerStripe
Tick Frequency
The simulated frequency of curTick(). (In ticks per second)
virtual bool requestEventScheduled(uint8_t pseudo_channel=0) const
Is there a read/write burst Event scheduled?
void processWriteRespondEvent()
void setupRank(const uint8_t rank, const bool is_read) override
Setup the rank based on packet received.
statistics::Histogram pendingReads
NVM stats.
void schedule(Event &event, Tick when)
const Tick tREAD
NVM specific timing requirements.
static constexpr bool isPowerOf2(const T &n)
void sample(const U &v, int n=1)
Add a value to the distribtion n times.
const uint32_t burstsPerRowBuffer
std::deque< Tick > readReadyQueue
statistics::Scalar totBusLat
const Tick entryTime
When did request enter the controller.
enums::AddrMap addrMapping
Memory controller configuration initialized based on parameter values.
statistics::Scalar totMemAccLat
Addr addr
The starting address of the packet.
General interface to memory device Includes functions and parameters shared across media types.
statistics::Scalar bytesRead
const uint32_t banksPerRank
MemPacket * decodePacket(const PacketPtr pkt, Addr pkt_addr, unsigned int size, bool is_read, uint8_t pseudo_channel=0) override
Address decoder to figure out physical mapping onto ranks, banks, and rows.
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
EventFunctionWrapper writeRespondEvent
uint64_t Tick
Tick count type.
bool isDram() const
Return true if its a DRAM access.
A memory packet stores packets along with the timestamp of when the packet entered the queue,...
statistics::Scalar totQLat
NVMStats(NVMInterface &nvm)
void processReadReadyEvent()
void reschedule(Event &event, Tick when, bool always=false)
MemCtrl * ctrl
A pointer to the parent memory controller instance.
bool isBusy(bool read_queue_empty, bool all_writes_nvm) override
This function checks if ranks are busy.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
const std::string & name()
Tick rankToRankDelay() const
virtual Tick writeToReadDelay() const
void init() override
Initialize the NVM interface and verify parameters.
statistics::Scalar writeBursts
bool burstReady(MemPacket *pkt) const override
Check if a burst operation can be issued to the NVM.
uint64_t size() const
Get the memory size.
statistics::Histogram bytesPerBank
const uint32_t ranksPerChannel
static constexpr int ceilLog2(const T &n)
std::vector< Rank * > ranks
Vector of nvm ranks.
std::pair< Tick, Tick > doBurstAccess(MemPacket *pkt, Tick next_burst_at, const std::vector< MemPacketQueue > &queue) override
Actually do the burst and update stats.
virtual Tick verifyMultiCmd(Tick cmd_tick, Tick max_cmds_per_burst, Tick max_multi_cmd_split=0)
Check for command bus contention for multi-cycle (2 currently) command.
statistics::Vector perBankWrBursts
void regStats() override
Callback to set stat parameters.
const uint8_t rank
Will be populated by address decoder.
statistics::Scalar readBursts
NVM stats.
statistics::Formula & simSeconds
bool inReadBusState(bool next_state, const MemInterface *mem_intr) const
Check the current direction of the memory channel.
statistics::Vector perBankRdBursts
statistics::Histogram pendingWrites
Addr getCtrlAddr(Addr addr)
Get an address in a dense range which starts from 0.
Tick nextReadAt
Till when must we wait before issuing next read command?
static const uint32_t NO_ROW
std::list< Tick > writeRespQueue
Holding queue for non-deterministic write commands, which maintains writes that have been issued but ...
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
unsigned int maxCommandsPerWindow
Number of commands that can issue in the defined controller command window, used to verify command ba...
bool isRead() const
Return true if its a read packet (interface compatibility with Packet)
uint16_t numReadDataReady
statistics::Scalar bytesWritten
const uint32_t burstSize
General device and channel characteristics The rowsPerBank is determined based on the capacity,...
bool writeRespQueueEmpty() const
Check if the write response queue is empty.
const uint16_t bankId
Bank id is calculated considering banks in all the ranks eg: 2 ranks each with 8 banks,...
const GEM5_CLASS_VAR_USED Tick tCK
General timing requirements.
bool scheduled() const
Determine if the current event is scheduled.
#define panic(...)
This implements a cprintf based panic() function.
Generated on Sun Jul 30 2023 01:56:58 for gem5 by doxygen 1.8.17