46#include "debug/NVM.hh"
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);
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) {
298 cmd_at =
ctrl->verifyMultiCmd(cmd_at,
301 cmd_at =
ctrl->verifySingleCmd(cmd_at,
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());
397 if (!
ctrl->requestEventScheduled()) {
398 DPRINTF(NVM,
"Restart controller scheduler immediately\n");
405 bool read_rdy = pkt->
isRead() && (
ctrl->inReadBusState(
true,
this)) &&
407 bool write_rdy = !pkt->
isRead() && !
ctrl->inReadBusState(
true,
this) &&
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. "
581 if (!
ctrl->requestEventScheduled()) {
582 DPRINTF(NVM,
"Restart controller scheduler immediately\n");
597 n->banks[
i].rdAllowedAt);
599 n->banks[
i].wrAllowedAt);
616 return (
ctrl->inReadBusState(
true,
this) ?
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 "
645 "Average queueing delay per NVM burst"),
648 "Average bus latency per NVM burst"),
651 "Average memory access latency per NVM burst"),
656 "Total bytes written"),
660 "Average DRAM read bandwidth in MiBytes/s"),
663 "Average DRAM write bandwidth in MiBytes/s"),
666 "Theoretical peak bandwidth in MiByte/s"),
668 "NVM Data bus utilization in percentage"),
670 "NVM Data bus read utilization in percentage"),
672 "NVM Data bus write utilization in percentage"),
675 "Reads issued to NVM for which data has not been transferred"),
677 "Number of outstanding writes to NVM"),
679 "Bytes read within a bank before loading new bank")
690 nvm.banksPerRank *
nvm.ranksPerChannel);
693 nvm.banksPerRank *
nvm.ranksPerChannel);
708 .init(
nvm.maxPendingReads)
712 .init(
nvm.maxPendingWrites)
716 .init(
nvm.rowBufferSize)
726 nvm.burstSize / 1000000;
uint64_t size() const
Get the memory size.
A basic class to track the bank state, i.e.
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.
MemInterface(const Params &_p)
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.
uint8_t rank
Current Rank index.
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
const uint32_t maxPendingWrites
NVM specific device and channel characteristics.
#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)
void schedule(Event &event, Tick when)
EventManager(EventManager &em)
Event manger manages events in the event queue.
void reschedule(Event &event, Tick when, bool always=false)
#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.
std::deque< MemPacket * > MemPacketQueue
Tick Frequency
The simulated frequency of curTick(). (In ticks per second)
const FlagsType nozero
Don't print if this is zero.
Copyright (c) 2024 Arm Limited 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::Formula avgRdBW
statistics::Scalar totMemAccLat
statistics::Formula busUtilRead
statistics::Scalar totQLat
void regStats() override
Callback to set stat parameters.
statistics::Formula avgWrBW
statistics::Formula avgMemAccLat
NVMStats(NVMInterface &nvm)
statistics::Formula avgBusLat
statistics::Histogram pendingReads
NVM stats.
statistics::Formula avgQLat
statistics::Scalar nvmBytesWritten
statistics::Scalar nvmBytesRead
statistics::Histogram pendingWrites
statistics::Formula busUtil
statistics::Formula busUtilWrite
statistics::Formula peakBW
statistics::Vector perBankWrBursts
statistics::Scalar readBursts
NVM stats.
const std::string & name()