44 #include "debug/DRAM.hh"
45 #include "debug/Drain.hh"
46 #include "debug/MemCtrl.hh"
47 #include "debug/NVM.hh"
48 #include "debug/QOS.hh"
62 port(
name() +
".port", *this), isTimingMode(false),
63 retryRdReq(false), retryWrReq(false),
66 respondEvent([
this] {processRespondEvent(dram, respQueue,
67 respondEvent, retryRdReq); },
name()),
69 readBufferSize(dram->readBufferSize),
70 writeBufferSize(dram->writeBufferSize),
71 writeHighThreshold(writeBufferSize *
p.write_high_thresh_perc / 100.0),
72 writeLowThreshold(writeBufferSize *
p.write_low_thresh_perc / 100.0),
73 minWritesPerSwitch(
p.min_writes_per_switch),
74 minReadsPerSwitch(
p.min_reads_per_switch),
75 writesThisTime(0), readsThisTime(0),
76 memSchedPolicy(
p.mem_sched_policy),
77 frontendLatency(
p.static_frontend_latency),
78 backendLatency(
p.static_backend_latency),
79 commandWindow(
p.command_window),
83 DPRINTF(MemCtrl,
"Setting up controller\n");
85 readQueue.resize(
p.qos_priorities);
86 writeQueue.resize(
p.qos_priorities);
88 dram->setCtrl(
this, commandWindow);
91 if (
p.write_low_thresh_perc >=
p.write_high_thresh_perc)
92 fatal(
"Write buffer low threshold %d must be smaller than the "
93 "high threshold %d\n",
p.write_low_thresh_perc,
94 p.write_high_thresh_perc);
95 if (
p.disable_sanity_check) {
96 port.disableSanityCheck();
104 fatal(
"MemCtrl %s is unconnected!\n",
name());
129 panic(
"Can't handle address range for packet %s\n", pkt->
print());
170 "Read queue limit %d, current size %d, entries needed %d\n",
182 "Write queue limit %d, current size %d, entries needed %d\n",
197 assert(pkt_count != 0);
207 unsigned pktsServicedByWrQ = 0;
212 for (
int cnt = 0; cnt < pkt_count; ++cnt) {
213 unsigned size = std::min((
addr | (burst_size - 1)) + 1,
221 bool foundInWrQ =
false;
227 for (
const auto&
p :
vec) {
230 if (
p->addr <=
addr &&
231 ((
addr + size) <= (
p->addr +
p->size))) {
237 "Read to addr %#x with size %d serviced by "
252 if (pkt_count > 1 && burst_helper == NULL) {
254 "memory requests\n", pkt->
getAddr(), pkt_count);
285 addr = (
addr | (burst_size - 1)) + 1;
289 if (pktsServicedByWrQ == pkt_count) {
295 if (burst_helper != NULL)
316 for (
int cnt = 0; cnt < pkt_count; ++cnt) {
317 unsigned size = std::min((
addr | (burst_size - 1)) + 1,
359 "Merging write burst with existing queue entry\n");
367 addr = (
addr | (burst_size - 1)) + 1;
384 for (
const auto& packet : queue) {
396 for (
const auto& packet : queue) {
414 "Should only see read and writes at memory controller\n");
423 "Can't handle address range for packet %s\n", pkt->
print());
429 unsigned size = pkt->
getSize();
492 "processRespondEvent(): Some req has reached its readyTime\n");
522 if (!queue.empty()) {
523 assert(queue.front()->readyTime >=
curTick());
525 schedule(resp_event, queue.front()->readyTime);
532 DPRINTF(Drain,
"Controller done draining\n");
548 retry_rd_req =
false;
553 MemPacketQueue::iterator
559 MemPacketQueue::iterator ret = queue.end();
561 if (!queue.empty()) {
562 if (queue.size() == 1) {
576 for (
auto i = queue.begin();
i != queue.end(); ++
i) {
585 std::tie(ret, col_allowed_at)
588 panic(
"No scheduling policy chosen\n");
598 auto selected_pkt_it = queue.end();
602 const Tick min_col_at = std::max(mem_intr->
nextBurstAt + extra_col_delay,
605 std::tie(selected_pkt_it, col_allowed_at) =
608 if (selected_pkt_it == queue.end()) {
612 return std::make_pair(selected_pkt_it, col_allowed_at);
625 "Can't handle address range for packet %s\n", pkt->
print());
660 auto current_it = it++;
673 return (cmd_tick - burst_offset);
680 Tick cmd_at = cmd_tick;
687 while (
burstTicks.count(burst_tick) >= max_cmds_per_burst) {
701 Tick max_multi_cmd_split)
704 Tick cmd_at = cmd_tick;
714 Tick burst_offset = 0;
716 while (max_multi_cmd_split > (first_cmd_offset + burst_offset)) {
721 Tick first_cmd_tick = burst_tick - std::min(burst_offset, burst_tick);
724 bool first_can_issue =
false;
725 bool second_can_issue =
false;
727 while (!first_can_issue || !second_can_issue) {
728 bool same_burst = (burst_tick == first_cmd_tick);
729 auto first_cmd_count =
burstTicks.count(first_cmd_tick);
730 auto second_cmd_count = same_burst ? first_cmd_count + 1 :
733 first_can_issue = first_cmd_count < max_cmds_per_burst;
734 second_can_issue = second_cmd_count < max_cmds_per_burst;
736 if (!second_can_issue) {
737 DPRINTF(
MemCtrl,
"Contention (cmd2) found on command bus at %d\n",
746 bool gap_violated = !same_burst &&
747 ((burst_tick - first_cmd_tick) > max_multi_cmd_split);
749 if (!first_can_issue || (!second_can_issue && gap_violated)) {
750 DPRINTF(
MemCtrl,
"Contention (cmd1) found on command bus at %d\n",
805 DPRINTF(
MemCtrl,
"Access to %#x, ready at %lld next burst at %lld.\n",
838 bool mem_busy =
true;
841 mem_busy = mem_intr->
isBusy(read_queue_empty, all_writes_nvm);
879 bool& retry_wr_req) {
893 switched_cmd_type?
"[turnaround triggered]":
"");
895 if (switched_cmd_type) {
898 "Switching to writes after %d reads with %d reads "
904 "Switching to reads after %d writes with %d writes "
924 bool switch_to_writes =
false;
935 "Switching to writes due to read queue empty\n");
936 switch_to_writes =
true;
945 DPRINTF(Drain,
"MemCtrl controller done draining\n");
955 bool read_found =
false;
956 MemPacketQueue::iterator to_read;
965 "Checking READ queue [%d] priority [%d elements]\n",
966 prio, queue->size());
971 to_read =
chooseNext((*queue), switched_cmd_type ?
974 if (to_read != queue->end()) {
991 auto mem_pkt = *to_read;
996 "Command for %#x, issued at %lld.\n", mem_pkt->addr, cmd_at);
1000 assert(mem_pkt->readyTime >=
curTick());
1004 mem_pkt->qosValue(), mem_pkt->getAddr(), 1,
1005 mem_pkt->readyTime - mem_pkt->entryTime);
1010 if (resp_queue.empty()) {
1012 schedule(resp_event, mem_pkt->readyTime);
1014 assert(resp_queue.back()->readyTime <= mem_pkt->readyTime);
1018 resp_queue.push_back(mem_pkt);
1028 switch_to_writes =
true;
1033 readQueue[mem_pkt->qosValue()].erase(to_read);
1039 if (switch_to_writes) {
1045 bool write_found =
false;
1046 MemPacketQueue::iterator to_write;
1055 "Checking WRITE queue [%d] priority [%d elements]\n",
1056 prio, queue->size());
1063 if (to_write != queue->end()) {
1079 auto mem_pkt = *to_write;
1086 "Command for %#x, issued at %lld.\n", mem_pkt->addr, cmd_at);
1092 mem_pkt->qosValue(), mem_pkt->getAddr(), 1,
1093 mem_pkt->readyTime - mem_pkt->entryTime);
1097 writeQueue[mem_pkt->qosValue()].erase(to_write);
1107 bool below_threshold =
1130 retry_wr_req =
false;
1166 : statistics::
Group(&_ctrl),
1170 "Number of read requests accepted"),
1172 "Number of write requests accepted"),
1175 "Number of controller read bursts, including those serviced by "
1178 "Number of controller write bursts, including those merged in "
1181 "Number of controller read bursts serviced by the write queue"),
1183 "Number of controller write bursts merged with an existing one"),
1185 ADD_STAT(neitherReadNorWriteReqs, statistics::units::
Count::get(),
1186 "Number of requests that are neither read nor write"),
1188 ADD_STAT(avgRdQLen, statistics::units::Rate<
1189 statistics::units::
Count, statistics::units::
Tick>::get(),
1190 "Average read queue length when enqueuing"),
1191 ADD_STAT(avgWrQLen, statistics::units::Rate<
1192 statistics::units::
Count, statistics::units::
Tick>::get(),
1193 "Average write queue length when enqueuing"),
1196 "Number of times read queue was full causing retry"),
1198 "Number of times write queue was full causing retry"),
1201 "Read request sizes (log2)"),
1203 "Write request sizes (log2)"),
1206 "What read queue length does an incoming req see"),
1208 "What write queue length does an incoming req see"),
1211 "Reads before turning the bus around for writes"),
1213 "Writes before turning the bus around for reads"),
1215 ADD_STAT(bytesReadWrQ, statistics::units::Byte::get(),
1216 "Total number of bytes read from write queue"),
1217 ADD_STAT(bytesReadSys, statistics::units::Byte::get(),
1218 "Total read bytes from the system interface side"),
1219 ADD_STAT(bytesWrittenSys, statistics::units::Byte::get(),
1220 "Total written bytes from the system interface side"),
1222 ADD_STAT(avgRdBWSys, statistics::units::Rate<
1223 statistics::units::Byte, statistics::units::Second>::get(),
1224 "Average system read bandwidth in Byte/s"),
1225 ADD_STAT(avgWrBWSys, statistics::units::Rate<
1226 statistics::units::Byte, statistics::units::Second>::get(),
1227 "Average system write bandwidth in Byte/s"),
1230 "Total gap between requests"),
1231 ADD_STAT(avgGap, statistics::units::Rate<
1232 statistics::units::
Tick, statistics::units::
Count>::get(),
1233 "Average gap between requests"),
1235 ADD_STAT(requestorReadBytes, statistics::units::Byte::get(),
1236 "Per-requestor bytes read from memory"),
1237 ADD_STAT(requestorWriteBytes, statistics::units::Byte::get(),
1238 "Per-requestor bytes write to memory"),
1239 ADD_STAT(requestorReadRate, statistics::units::Rate<
1240 statistics::units::Byte, statistics::units::Second>::get(),
1241 "Per-requestor bytes read from memory rate"),
1242 ADD_STAT(requestorWriteRate, statistics::units::Rate<
1243 statistics::units::Byte, statistics::units::Second>::get(),
1244 "Per-requestor bytes write to memory rate"),
1245 ADD_STAT(requestorReadAccesses, statistics::units::
Count::get(),
1246 "Per-requestor read serviced memory accesses"),
1247 ADD_STAT(requestorWriteAccesses, statistics::units::
Count::get(),
1248 "Per-requestor write serviced memory accesses"),
1249 ADD_STAT(requestorReadTotalLat, statistics::units::
Tick::get(),
1250 "Per-requestor read total memory access latency"),
1251 ADD_STAT(requestorWriteTotalLat, statistics::units::
Tick::get(),
1252 "Per-requestor write total memory access latency"),
1253 ADD_STAT(requestorReadAvgLat, statistics::units::Rate<
1254 statistics::units::
Tick, statistics::units::
Count>::get(),
1255 "Per-requestor read average memory access latency"),
1256 ADD_STAT(requestorWriteAvgLat, statistics::units::Rate<
1257 statistics::units::
Tick, statistics::units::
Count>::get(),
1258 "Per-requestor write average memory access latency")
1265 using namespace statistics;
1267 assert(ctrl.system());
1268 const auto max_requestors = ctrl.system()->maxRequestors();
1270 avgRdQLen.precision(2);
1271 avgWrQLen.precision(2);
1273 readPktSize.init(
ceilLog2(ctrl.system()->cacheLineSize()) + 1);
1274 writePktSize.init(
ceilLog2(ctrl.system()->cacheLineSize()) + 1);
1276 rdQLenPdf.init(ctrl.readBufferSize);
1277 wrQLenPdf.init(ctrl.writeBufferSize);
1280 .init(ctrl.readBufferSize)
1283 .init(ctrl.writeBufferSize)
1286 avgRdBWSys.precision(8);
1287 avgWrBWSys.precision(8);
1288 avgGap.precision(2);
1292 .init(max_requestors)
1296 .init(max_requestors)
1304 requestorReadAccesses
1305 .init(max_requestors)
1308 requestorWriteAccesses
1309 .init(max_requestors)
1312 requestorReadTotalLat
1313 .init(max_requestors)
1324 requestorWriteTotalLat
1325 .init(max_requestors)
1328 requestorWriteAvgLat
1332 for (
int i = 0;
i < max_requestors;
i++) {
1333 const std::string requestor = ctrl.system()->getRequestorName(
i);
1334 requestorReadBytes.subname(
i, requestor);
1335 requestorReadRate.subname(
i, requestor);
1336 requestorWriteBytes.subname(
i, requestor);
1337 requestorWriteRate.subname(
i, requestor);
1338 requestorReadAccesses.subname(
i, requestor);
1339 requestorWriteAccesses.subname(
i, requestor);
1340 requestorReadTotalLat.subname(
i, requestor);
1341 requestorReadAvgLat.subname(
i, requestor);
1342 requestorWriteTotalLat.subname(
i, requestor);
1343 requestorWriteAvgLat.subname(
i, requestor);
1350 avgGap = totGap / (readReqs + writeReqs);
1352 requestorReadRate = requestorReadBytes /
simSeconds;
1353 requestorWriteRate = requestorWriteBytes /
simSeconds;
1354 requestorReadAvgLat = requestorReadTotalLat / requestorReadAccesses;
1355 requestorWriteAvgLat = requestorWriteTotalLat / requestorWriteAccesses;
1363 panic_if(!found,
"Can't handle address range for packet %s\n",
1382 if (if_name !=
"port") {
1406 DPRINTF(Drain,
"Memory controller not drained, write: %d, read: %d,"
1459 return ctrl.getAddrRanges();
1467 if (!queue.trySatisfyFunctional(pkt)) {
1471 ctrl.recvFunctional(pkt);
1480 return ctrl.recvAtomic(pkt);
1487 return ctrl.recvAtomicBackdoor(pkt, backdoor);
1494 return ctrl.recvTimingReq(pkt);
1500 queue.disableSanityCheck();
virtual std::string name() const
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
void pushLabel(const std::string &lbl)
Push label for PrintReq (safe to call unconditionally).
void print(std::ostream &o, int verbosity=0, const std::string &prefix="") const
bool needsResponse() const
uint32_t payloadDelay
The extra pipelining delay from seeing the packet until the end of payload is transmitted by the comp...
RequestorID requestorId() const
uint32_t headerDelay
The extra delay from seeing the packet until the header is transmitted.
uint8_t qosValue() const
QoS Value getter Returns 0 if QoS value was never set (constructor default).
const std::string & cmdString() const
Return the string name of the cmd field (for debugging and tracing).
void popLabel()
Pop label for PrintReq (safe to call unconditionally).
bool cacheResponding() const
Ports are used to interface objects to each other.
bool isConnected() const
Is this port currently connected to a peer?
A queued port is a port that has an infinite queue for outgoing packets and thus decouples the module...
void schedTimingResp(PacketPtr pkt, Tick when)
Schedule the sending of a timing response.
void sendRangeChange() const
Called by the owner to send a range change.
void sendRetryReq()
Send a retry to the request port that previously attempted a sendTimingReq to this response port and ...
bool isTimingMode() const
Is the system in timing mode?
void access(PacketPtr pkt)
Perform an untimed memory access and update all the state (e.g.
void functionalAccess(PacketPtr pkt)
Perform an untimed memory read or write without changing anything but the memory itself.
void getBackdoor(MemBackdoorPtr &bd_ptr)
AddrRange getAddrRange() const
Get the address range.
A burst helper helps organize and manage a packet that is larger than the memory burst size.
unsigned int burstsServiced
Number of bursts serviced so far for a system packet.
const unsigned int burstCount
Number of bursts requred for a system packet.
void recvFunctional(PacketPtr pkt) override
Receive a functional request packet from the peer.
MemoryPort(const std::string &name, MemCtrl &_ctrl)
bool recvTimingReq(PacketPtr) override
Receive a timing request from the peer.
AddrRangeList getAddrRanges() const override
Get a list of the non-overlapping address ranges the owner is responsible for.
Tick recvAtomic(PacketPtr pkt) override
Receive an atomic request packet from the peer.
void disableSanityCheck()
Tick recvAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr &backdoor) override
Receive an atomic request packet from the peer, and optionally provide a backdoor to the data being a...
The memory controller is a single-channel memory controller capturing the most important timing const...
virtual void recvFunctional(PacketPtr pkt)
virtual void pruneBurstTick()
Remove commands that have already issued from burstTicks.
uint32_t writeLowThreshold
enums::MemSched memSchedPolicy
Memory controller configuration initialized based on parameter values.
bool recvFunctionalLogic(PacketPtr pkt, MemInterface *mem_intr)
bool retryRdReq
Remember if we have to retry a request when available.
void printQs() const
Used for debugging to observe the contents of the queues.
const uint32_t minReadsPerSwitch
virtual void startup() override
startup() is the final initialization call before simulation.
void addToWriteQueue(PacketPtr pkt, unsigned int pkt_count, MemInterface *mem_intr)
Decode the incoming pkt, create a mem_pkt and push to the back of the write queue.
Tick recvAtomicLogic(PacketPtr pkt, MemInterface *mem_intr)
std::deque< MemPacket * > respQueue
Response queue where read packets wait after we're done working with them, but it's not time to send ...
MemoryPort port
Our incoming port, for a multi-ported controller add a crossbar in front of it.
uint32_t writeHighThreshold
std::unique_ptr< Packet > pendingDelete
Upstream caches need this packet until true is returned, so hold it for deletion until a subsequent c...
std::vector< MemPacketQueue > writeQueue
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.
EventFunctionWrapper respondEvent
virtual MemPacketQueue::iterator chooseNext(MemPacketQueue &queue, Tick extra_col_delay, MemInterface *mem_intr)
The memory schduler/arbiter - picks which request needs to go next, based on the specified policy suc...
virtual std::pair< MemPacketQueue::iterator, Tick > chooseNextFRFCFS(MemPacketQueue &queue, Tick extra_col_delay, MemInterface *mem_intr)
For FR-FCFS policy reorder the read/write queue depending on row buffer hits and earliest bursts avai...
bool readQueueFull(unsigned int pkt_count) const
Check if the read queue has room for more entries.
virtual Tick doBurstAccess(MemPacket *mem_pkt, MemInterface *mem_intr)
Actually do the burst based on media specific access function.
virtual void processNextReqEvent(MemInterface *mem_intr, MemPacketQueue &resp_queue, EventFunctionWrapper &resp_event, EventFunctionWrapper &next_req_event, bool &retry_wr_req)
Bunch of things requires to setup "events" in gem5 When event "respondEvent" occurs for example,...
bool addToReadQueue(PacketPtr pkt, unsigned int pkt_count, MemInterface *mem_intr)
When a new read comes in, first check if the write q has a pending request to the same address....
std::unordered_multiset< Tick > burstTicks
Holds count of commands issued in burst window starting at defined Tick.
virtual Addr burstAlign(Addr addr, MemInterface *mem_intr) const
Burst-align an address.
const uint32_t minWritesPerSwitch
bool writeQueueFull(unsigned int pkt_count) const
Check if the write queue has room for more entries.
virtual void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
const Tick backendLatency
Pipeline latency of the backend and PHY.
uint32_t readBufferSize
The following are basic design parameters of the memory controller, and are initialized based on para...
const Tick frontendLatency
Pipeline latency of the controller frontend.
virtual bool respQEmpty()
virtual bool allIntfDrained() const
Ensure that all interfaced have drained commands.
EventFunctionWrapper nextReqEvent
virtual bool packetReady(MemPacket *pkt, MemInterface *mem_intr)
Determine if there is a packet that can issue.
virtual Tick verifySingleCmd(Tick cmd_tick, Tick max_cmds_per_burst, bool row_cmd)
Check for command bus contention for single cycle command.
virtual bool nvmWriteBlock(MemInterface *mem_intr)
Will check if all writes are for nvm interface and nvm's write resp queue is full.
virtual void processRespondEvent(MemInterface *mem_intr, MemPacketQueue &queue, EventFunctionWrapper &resp_event, bool &retry_rd_req)
virtual void accessAndRespond(PacketPtr pkt, Tick static_latency, MemInterface *mem_intr)
When a packet reaches its "readyTime" in the response Q, use the "access()" method in AbstractMemory ...
virtual Tick minWriteToReadDataGap()
Calculate the minimum delay used when scheduling a write-to-read transision.
virtual bool recvTimingReq(PacketPtr pkt)
bool inReadBusState(bool next_state) const
Check the current direction of the memory channel.
virtual Tick minReadToWriteDataGap()
Calculate the minimum delay used when scheduling a read-to-write transision.
DrainState drain() override
Draining is the process of clearing out the states of SimObjects.These are the SimObjects that are pa...
std::vector< MemPacketQueue > readQueue
The controller's main read and write queues, with support for QoS reordering.
bool isTimingMode
Remember if the memory system is in timing mode.
virtual Tick recvAtomic(PacketPtr pkt)
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
virtual bool memBusy(MemInterface *mem_intr)
Checks if the memory interface is already busy.
virtual AddrRangeList getAddrRanges()
MemCtrl(const MemCtrlParams &p)
virtual Tick recvAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr &backdoor)
Tick getBurstWindow(Tick cmd_tick)
Calculate burst window aligned tick.
std::vector< MemPacketQueue > & selQueue(bool is_read)
Select either the read or write queue.
std::unordered_set< Addr > isInWriteQueue
To avoid iterating over the write queue to check for overlapping transactions, maintain a set of burs...
virtual bool pktSizeCheck(MemPacket *mem_pkt, MemInterface *mem_intr) const
Check if mem pkt's size is sane.
virtual void drainResume() override
Resume execution after a successful drain.
bool inWriteBusState(bool next_state) const
Check the current direction of the memory channel.
const Tick commandWindow
Length of a command window, used to check command bandwidth.
virtual void nonDetermReads(MemInterface *mem_intr)
Will access memory interface and select non-deterministic reads to issue.
General interface to memory device Includes functions and parameters shared across media types.
virtual void setupRank(const uint8_t rank, const bool is_read)=0
Setup the rank based on packet received.
virtual std::pair< MemPacketQueue::iterator, Tick > chooseNextFRFCFS(MemPacketQueue &queue, Tick min_col_at) const =0
For FR-FCFS policy, find first command that can issue Function will be overriden by interface to sele...
virtual void suspend()
This function is DRAM specific.
virtual Tick commandOffset() const =0
uint8_t pseudoChannel
pseudo channel number used for HBM modeling
virtual bool burstReady(MemPacket *pkt) const =0
Check if a burst operation can be issued to the interface.
virtual void checkRefreshState(uint8_t rank)
This function is DRAM specific.
virtual bool isBusy(bool read_queue_empty, bool all_writes_nvm)=0
This function checks if ranks are busy.
virtual void respondEvent(uint8_t rank)
This function is DRAM specific.
virtual std::pair< Tick, Tick > doBurstAccess(MemPacket *mem_pkt, Tick next_burst_at, const std::vector< MemPacketQueue > &queue)=0
This function performs the burst and update stats.
virtual MemPacket * decodePacket(const PacketPtr pkt, Addr pkt_addr, unsigned int size, bool is_read, uint8_t pseudo_channel=0)
Address decoder to figure out physical mapping onto ranks, banks, and rows.
virtual Tick accessLatency() const =0
virtual bool writeRespQueueFull() const
This function is NVM specific.
virtual void chooseRead(MemPacketQueue &queue)
This function is NVM specific.
Tick nextBurstAt
Till when the controller must wait before issuing next RD/WR burst?
Tick minWriteToReadDataGap() const
virtual bool readsWaitingToIssue() const
This function is NVM specific.
uint32_t numWritesQueued
NVM specific variable, but declaring it here allows treating different interfaces in a more genral wa...
Tick minReadToWriteDataGap() const
virtual bool allRanksDrained() const =0
Check drain state of interface.
virtual void drainRanks()
This function is DRAM specific.
uint32_t bytesPerBurst() const
A memory packet stores packets along with the timestamp of when the packet entered the queue,...
Tick readyTime
When will request leave the controller.
void qosValue(const uint8_t qv)
Set the packet QoS value (interface compatibility with Packet)
const uint8_t pseudoChannel
pseudo channel num
BurstHelper * burstHelper
A pointer to the BurstHelper if this MemPacket is a split packet If not a split packet (common case),...
unsigned int size
The size of this dram packet in bytes It is always equal or smaller than the burst size.
Addr addr
The starting address of the packet.
bool isRead() const
Return true if its a read packet (interface compatibility with Packet)
const Tick entryTime
When did request enter the controller.
const PacketPtr pkt
This comes from the outside world.
RequestorID requestorId() const
Get the packet RequestorID (interface compatibility with Packet)
const uint8_t rank
Will be populated by address decoder.
void logResponse(BusState dir, RequestorID id, uint8_t _qos, Addr addr, uint64_t entries, double delay)
Called upon receiving a response, updates statistics and updates queues status.
uint8_t qosSchedule(std::initializer_list< Queues * > queues_ptr, uint64_t queue_entry_size, const PacketPtr pkt)
Assign priority to a packet by executing the configured QoS policy.
uint64_t totalWriteQueueSize
Total write request packets queue length in #packets.
void recordTurnaroundStats()
Record statistics on turnarounds based on busStateNext and busState values.
BusState selectNextBusState()
Returns next bus direction (READ or WRITE) based on configured policy.
const std::unique_ptr< TurnaroundPolicy > turnPolicy
QoS Bus Turnaround Policy: selects the bus direction (READ/WRITE)
System * system() const
read the system pointer
uint8_t numPriorities() const
Gets the total number of priority levels in the QoS memory controller.
BusState busState
Bus state used to control the read/write switching and drive the scheduling of the next request.
uint64_t totalReadQueueSize
Total read request packets queue length in #packets.
BusState busStateNext
bus state for next request event triggered
uint8_t schedule(RequestorID id, uint64_t data)
void logRequest(BusState dir, RequestorID id, uint8_t _qos, Addr addr, uint64_t entries)
Called upon receiving a request or updates statistics and updates queues status.
void sample(const U &v, int n=1)
Add a value to the distribtion n times.
DRAMInterface declaration.
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
bool contains(const Addr &a) const
Determine if the range contains an address.
static constexpr int ceilLog2(const T &n)
static constexpr T divCeil(const T &a, const U &b)
void signalDrainDone() const
Signal that an object is drained.
DrainState drainState() const
Return the current drain state of an object.
DrainState
Object drain/handover states.
@ Draining
Draining buffers pending serialization/handover.
@ Drained
Buffers drained, ready for serialization/handover.
bool scheduled() const
Determine if the current event is scheduled.
#define panic(...)
This implements a cprintf based panic() function.
#define fatal(...)
This implements a cprintf based fatal() function.
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
virtual void startup()
startup() is the final initialization call before simulation.
virtual Port & getPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a port with a given name and index.
MemInterface declaration.
const FlagsType nonan
Don't print if this is NAN.
const FlagsType nozero
Don't print if this is zero.
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Tick curTick()
The universal simulation clock.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
uint64_t Tick
Tick count type.
statistics::Formula & simSeconds
NVMInterface declaration.
statistics::Scalar writeReqs
statistics::Scalar mergedWrBursts
statistics::Scalar readReqs
statistics::Scalar servicedByWrQ
statistics::Histogram rdPerTurnAround
statistics::Vector readPktSize
statistics::Scalar numWrRetry
statistics::Scalar totGap
statistics::Scalar numRdRetry
statistics::Scalar readBursts
void regStats() override
Callback to set stat parameters.
statistics::Vector requestorReadTotalLat
statistics::Vector requestorWriteTotalLat
statistics::Vector requestorWriteBytes
statistics::Scalar writeBursts
statistics::Vector writePktSize
statistics::Histogram wrPerTurnAround
statistics::Vector requestorWriteAccesses
statistics::Scalar bytesReadSys
statistics::Average avgRdQLen
statistics::Vector requestorReadAccesses
statistics::Scalar bytesWrittenSys
statistics::Average avgWrQLen
statistics::Vector wrQLenPdf
statistics::Scalar bytesReadWrQ
statistics::Vector requestorReadBytes
statistics::Vector rdQLenPdf
const std::string & name()