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!");
193 assert(row < Bank::NO_ROW);
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),
626 ADD_STAT(readBursts, statistics::units::Count::get(),
627 "Number of NVM read bursts"),
628 ADD_STAT(writeBursts, statistics::units::Count::get(),
629 "Number of NVM write bursts"),
631 ADD_STAT(perBankRdBursts, statistics::units::Count::get(),
632 "Per bank write bursts"),
633 ADD_STAT(perBankWrBursts, statistics::units::Count::get(),
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(nvmBytesRead, statistics::units::Byte::get(),
655 ADD_STAT(nvmBytesWritten, statistics::units::Byte::get(),
656 "Total bytes written"),
658 ADD_STAT(avgRdBW, statistics::units::Rate<
659 statistics::units::Byte, statistics::units::Second>::get(),
660 "Average DRAM read bandwidth in MiBytes/s"),
661 ADD_STAT(avgWrBW, statistics::units::Rate<
662 statistics::units::Byte, statistics::units::Second>::get(),
663 "Average DRAM write bandwidth in MiBytes/s"),
664 ADD_STAT(peakBW, statistics::units::Rate<
665 statistics::units::Byte, statistics::units::Second>::get(),
666 "Theoretical peak bandwidth in MiByte/s"),
667 ADD_STAT(busUtil, statistics::units::Ratio::get(),
668 "NVM Data bus utilization in percentage"),
669 ADD_STAT(busUtilRead, statistics::units::Ratio::get(),
670 "NVM Data bus read utilization in percentage"),
671 ADD_STAT(busUtilWrite, statistics::units::Ratio::get(),
672 "NVM Data bus write utilization in percentage"),
674 ADD_STAT(pendingReads, statistics::units::Count::get(),
675 "Reads issued to NVM for which data has not been transferred"),
676 ADD_STAT(pendingWrites, statistics::units::Count::get(),
677 "Number of outstanding writes to NVM"),
678 ADD_STAT(bytesPerBank, statistics::units::Byte::get(),
679 "Bytes read within a bank before loading new bank")
687 using namespace statistics;
689 perBankRdBursts.init(nvm.ranksPerChannel == 0 ? 1 :
690 nvm.banksPerRank * nvm.ranksPerChannel);
692 perBankWrBursts.init(nvm.ranksPerChannel == 0 ? 1 :
693 nvm.banksPerRank * nvm.ranksPerChannel);
695 avgQLat.precision(2);
696 avgBusLat.precision(2);
697 avgMemAccLat.precision(2);
699 avgRdBW.precision(2);
700 avgWrBW.precision(2);
703 busUtil.precision(2);
704 busUtilRead.precision(2);
705 busUtilWrite.precision(2);
708 .init(nvm.maxPendingReads)
712 .init(nvm.maxPendingWrites)
716 .init(nvm.rowBufferSize)
719 avgQLat = totQLat / readBursts;
720 avgBusLat = totBusLat / readBursts;
721 avgMemAccLat = totMemAccLat / readBursts;
723 avgRdBW = (nvmBytesRead / 1000000) /
simSeconds;
724 avgWrBW = (nvmBytesWritten / 1000000) /
simSeconds;
726 nvm.burstSize / 1000000;
728 busUtil = (avgRdBW + avgWrBW) / peakBW * 100;
729 busUtilRead = avgRdBW / peakBW * 100;
730 busUtilWrite = avgWrBW / peakBW * 100;
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
uint64_t size() const
Get the memory size.
bool inReadBusState(bool next_state, const MemInterface *mem_intr) const
Check the current direction of the memory channel.
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.
virtual bool requestEventScheduled(uint8_t pseudo_channel=0) const
Is there a read/write burst Event scheduled?
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...
virtual Tick verifySingleCmd(Tick cmd_tick, Tick max_cmds_per_burst, bool row_cmd)
Check for command bus contention for single cycle command.
A basic class to track the bank state, i.e.
General interface to memory device Includes functions and parameters shared across media types.
const uint32_t burstsPerStripe
enums::AddrMap addrMapping
Memory controller configuration initialized based on parameter values.
virtual Tick writeToReadDelay() const
MemCtrl * ctrl
A pointer to the parent memory controller instance.
const uint32_t ranksPerChannel
Addr getCtrlAddr(Addr addr)
Get an address in a dense range which starts from 0.
Tick rankToRankDelay() const
const uint32_t burstSize
General device and channel characteristics The rowsPerBank is determined based on the capacity,...
const uint32_t banksPerRank
unsigned int maxCommandsPerWindow
Number of commands that can issue in the defined controller command window, used to verify command ba...
const uint32_t burstsPerRowBuffer
GEM5_CLASS_VAR_USED const Tick tCK
General timing requirements.
Tick readToWriteDelay() const
uint32_t numWritesQueued
NVM specific variable, but declaring it here allows treating different interfaces in a more genral wa...
A memory packet stores packets along with the timestamp of when the packet entered the queue,...
Tick readyTime
When will request leave the controller.
const uint16_t bankId
Bank id is calculated considering banks in all the ranks eg: 2 ranks each with 8 banks,...
Addr addr
The starting address of the packet.
bool isDram() const
Return true if its a DRAM access.
bool isRead() const
Return true if its a read packet (interface compatibility with Packet)
const Tick entryTime
When did request enter the controller.
const uint8_t rank
Will be populated by address decoder.
Rank(const NVMInterfaceParams &_p, int _rank, NVMInterface &_nvm)
std::vector< Bank > banks
Vector of NVM banks.
Interface to NVM devices with media specific parameters, statistics, and functions.
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.
std::pair< Tick, Tick > doBurstAccess(MemPacket *pkt, Tick next_burst_at, const std::vector< MemPacketQueue > &queue) override
Actually do the burst and update stats.
void init() override
Initialize the NVM interface and verify parameters.
void setupRank(const uint8_t rank, const bool is_read) override
Setup the rank based on packet received.
void chooseRead(MemPacketQueue &queue) override
Select read command to issue asynchronously.
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.
Tick nextReadAt
Till when must we wait before issuing next read command?
void processReadReadyEvent()
NVMInterface(const NVMInterfaceParams &_p)
std::vector< Rank * > ranks
Vector of nvm ranks.
const uint32_t maxPendingReads
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...
bool isBusy(bool read_queue_empty, bool all_writes_nvm) override
This function checks if ranks are busy.
std::list< Tick > writeRespQueue
Holding queue for non-deterministic write commands, which maintains writes that have been issued but ...
bool writeRespQueueFull() const override
Check if the write response queue has reached defined threshold.
void processWriteRespondEvent()
std::deque< Tick > readReadyQueue
bool burstReady(MemPacket *pkt) const override
Check if a burst operation can be issued to the NVM.
const Tick tREAD
NVM specific timing requirements.
uint16_t numReadDataReady
EventFunctionWrapper writeRespondEvent
bool writeRespQueueEmpty() const
Check if the write response queue is empty.
EventFunctionWrapper readReadyEvent
void sample(const U &v, int n=1)
Add a value to the distribtion n times.
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
static constexpr int ceilLog2(const T &n)
static constexpr bool isPowerOf2(const T &n)
bool scheduled() const
Determine if the current event is scheduled.
void schedule(Event &event, Tick when)
void reschedule(Event &event, Tick when, bool always=false)
Tick when() const
Get the time that the event is scheduled.
#define panic(...)
This implements a cprintf based panic() function.
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
virtual void init()
init() is called after all C++ SimObjects have been created and all ports are connected.
Tick Frequency
The simulated frequency of curTick(). (In ticks per second)
const FlagsType nozero
Don't print if this is zero.
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Tick curTick()
The universal simulation clock.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
uint64_t Tick
Tick count type.
statistics::Formula & simSeconds
NVMInterface declaration.
statistics::Scalar totBusLat
statistics::Scalar writeBursts
statistics::Histogram bytesPerBank
statistics::Vector perBankRdBursts
statistics::Scalar totMemAccLat
statistics::Scalar totQLat
void regStats() override
Callback to set stat parameters.
NVMStats(NVMInterface &nvm)
statistics::Histogram pendingReads
NVM stats.
statistics::Scalar nvmBytesWritten
statistics::Scalar nvmBytesRead
statistics::Histogram pendingWrites
statistics::Vector perBankWrBursts
statistics::Scalar readBursts
NVM stats.
const std::string & name()