Go to the documentation of this file.
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"
56 port(
name() +
".port", *this), isTimingMode(false),
57 retryRdReq(false), retryWrReq(false),
59 respondEvent([
this]{ processRespondEvent(); },
name()),
60 dram(
p->dram), nvm(
p->nvm),
61 readBufferSize((dram ? dram->readBufferSize : 0) +
62 (nvm ? nvm->readBufferSize : 0)),
63 writeBufferSize((dram ? dram->writeBufferSize : 0) +
64 (nvm ? nvm->writeBufferSize : 0)),
65 writeHighThreshold(writeBufferSize *
p->write_high_thresh_perc / 100.0),
66 writeLowThreshold(writeBufferSize *
p->write_low_thresh_perc / 100.0),
67 minWritesPerSwitch(
p->min_writes_per_switch),
68 writesThisTime(0), readsThisTime(0),
69 memSchedPolicy(
p->mem_sched_policy),
70 frontendLatency(
p->static_frontend_latency),
71 backendLatency(
p->static_backend_latency),
72 commandWindow(
p->command_window),
73 nextBurstAt(0), prevArrival(0),
78 readQueue.resize(
p->qos_priorities);
79 writeQueue.resize(
p->qos_priorities);
83 dram->setCtrl(
this, commandWindow);
85 nvm->setCtrl(
this, commandWindow);
87 fatal_if(!dram && !nvm,
"Memory controller must have an interface");
90 if (
p->write_low_thresh_perc >=
p->write_high_thresh_perc)
91 fatal(
"Write buffer low threshold %d must be smaller than the "
92 "high threshold %d\n",
p->write_low_thresh_perc,
93 p->write_high_thresh_perc);
100 fatal(
"MemCtrl %s is unconnected!\n",
name());
150 panic(
"Can't handle address range for packet %s\n",
161 "Read queue limit %d, current size %d, entries needed %d\n",
173 "Write queue limit %d, current size %d, entries needed %d\n",
187 assert(pkt_count != 0);
197 unsigned pktsServicedByWrQ = 0;
202 for (
int cnt = 0; cnt < pkt_count; ++cnt) {
203 unsigned size = std::min((
addr | (burst_size - 1)) + 1,
211 bool foundInWrQ =
false;
217 for (
const auto&
p : vec) {
220 if (
p->addr <=
addr &&
221 ((
addr + size) <= (
p->addr +
p->size))) {
227 "Read to addr %lld with size %d serviced by "
242 if (pkt_count > 1 && burst_helper == NULL) {
244 "memory requests\n", pkt->
getAddr(), pkt_count);
278 addr = (
addr | (burst_size - 1)) + 1;
282 if (pktsServicedByWrQ == pkt_count) {
288 if (burst_helper != NULL)
312 for (
int cnt = 0; cnt < pkt_count; ++cnt) {
313 unsigned size = std::min((
addr | (burst_size - 1)) + 1,
354 "Merging write burst with existing queue entry\n");
362 addr = (
addr | (burst_size - 1)) + 1;
386 for (
const auto& packet : queue) {
398 for (
const auto& packet : queue) {
416 "Should only see read and writes at memory controller\n");
431 panic(
"Can't handle address range for packet %s\n",
440 unsigned size = pkt->
getSize();
486 "processRespondEvent(): Some req has reached its readyTime\n");
526 DPRINTF(Drain,
"Controller done draining\n");
528 }
else if (mem_pkt->
isDram()) {
544 MemPacketQueue::iterator
549 MemPacketQueue::iterator ret = queue.end();
551 if (!queue.empty()) {
552 if (queue.size() == 1) {
563 for (
auto i = queue.begin();
i != queue.end(); ++
i) {
573 panic(
"No scheduling policy chosen\n");
579 MemPacketQueue::iterator
582 auto selected_pkt_it = queue.end();
591 auto nvm_pkt_it = queue.end();
596 std::tie(selected_pkt_it, col_allowed_at) =
598 std::tie(nvm_pkt_it, nvm_col_at) =
603 if (col_allowed_at > nvm_col_at) {
604 selected_pkt_it = nvm_pkt_it;
607 std::tie(selected_pkt_it, col_allowed_at) =
610 std::tie(selected_pkt_it, col_allowed_at) =
614 if (selected_pkt_it == queue.end()) {
618 return selected_pkt_it;
634 panic(
"Can't handle address range for packet %s\n",
670 auto current_it = it++;
683 return (cmd_tick - burst_offset);
690 Tick cmd_at = cmd_tick;
697 while (
burstTicks.count(burst_tick) >= max_cmds_per_burst) {
711 Tick max_multi_cmd_split)
714 Tick cmd_at = cmd_tick;
724 Tick burst_offset = 0;
726 while (max_multi_cmd_split > (first_cmd_offset + burst_offset)) {
731 Tick first_cmd_tick = burst_tick - std::min(burst_offset, burst_tick);
734 bool first_can_issue =
false;
735 bool second_can_issue =
false;
737 while (!first_can_issue || !second_can_issue) {
738 bool same_burst = (burst_tick == first_cmd_tick);
739 auto first_cmd_count =
burstTicks.count(first_cmd_tick);
740 auto second_cmd_count = same_burst ? first_cmd_count + 1 :
743 first_can_issue = first_cmd_count < max_cmds_per_burst;
744 second_can_issue = second_cmd_count < max_cmds_per_burst;
746 if (!second_can_issue) {
747 DPRINTF(
MemCtrl,
"Contention (cmd2) found on command bus at %d\n",
756 bool gap_violated = !same_burst &&
757 ((burst_tick - first_cmd_tick) > max_multi_cmd_split);
759 if (!first_can_issue || (!second_can_issue && gap_violated)) {
760 DPRINTF(
MemCtrl,
"Contention (cmd1) found on command bus at %d\n",
830 DPRINTF(
MemCtrl,
"Access to %lld, ready at %lld next burst at %lld.\n",
872 switched_cmd_type?
"[turnaround triggered]":
"");
874 if (switched_cmd_type) {
877 "Switching to writes after %d reads with %d reads "
883 "Switching to reads after %d writes with %d writes "
910 bool nvm_busy =
true;
911 bool all_writes_nvm =
false;
915 nvm_busy =
nvm->
isBusy(read_queue_empty, all_writes_nvm);
919 if (dram_busy && nvm_busy) {
930 bool switch_to_writes =
false;
941 "Switching to writes due to read queue empty\n");
942 switch_to_writes =
true;
951 DPRINTF(Drain,
"MemCtrl controller done draining\n");
961 bool read_found =
false;
962 MemPacketQueue::iterator to_read;
971 "Checking READ queue [%d] priority [%d elements]\n",
972 prio, queue->size());
977 to_read =
chooseNext((*queue), switched_cmd_type ?
980 if (to_read != queue->end()) {
997 auto mem_pkt = *to_read;
1002 assert(mem_pkt->size <= (mem_pkt->isDram() ?
1005 assert(mem_pkt->readyTime >=
curTick());
1009 mem_pkt->qosValue(), mem_pkt->getAddr(), 1,
1010 mem_pkt->readyTime - mem_pkt->entryTime);
1019 assert(
respQueue.back()->readyTime <= mem_pkt->readyTime);
1030 switch_to_writes =
true;
1035 readQueue[mem_pkt->qosValue()].erase(to_read);
1041 if (switch_to_writes) {
1047 bool write_found =
false;
1048 MemPacketQueue::iterator to_write;
1057 "Checking WRITE queue [%d] priority [%d elements]\n",
1058 prio, queue->size());
1065 if (to_write != queue->end()) {
1081 auto mem_pkt = *to_write;
1084 assert(mem_pkt->size <= (mem_pkt->isDram() ?
1094 mem_pkt->qosValue(), mem_pkt->getAddr(), 1,
1095 mem_pkt->readyTime - mem_pkt->entryTime);
1099 writeQueue[mem_pkt->qosValue()].erase(to_write);
1109 bool below_threshold =
1154 return std::min(dram_min, nvm_min);
1162 return std::min(dram_min, nvm_min);
1175 :
Stats::Group(&_ctrl),
1178 ADD_STAT(readReqs,
"Number of read requests accepted"),
1179 ADD_STAT(writeReqs,
"Number of write requests accepted"),
1182 "Number of controller read bursts, "
1183 "including those serviced by the write queue"),
1185 "Number of controller write bursts, "
1186 "including those merged in the write queue"),
1188 "Number of controller read bursts serviced by the write queue"),
1190 "Number of controller write bursts merged with an existing one"),
1193 "Number of requests that are neither read nor write"),
1195 ADD_STAT(avgRdQLen,
"Average read queue length when enqueuing"),
1196 ADD_STAT(avgWrQLen,
"Average write queue length when enqueuing"),
1198 ADD_STAT(numRdRetry,
"Number of times read queue was full causing retry"),
1199 ADD_STAT(numWrRetry,
"Number of times write queue was full causing retry"),
1201 ADD_STAT(readPktSize,
"Read request sizes (log2)"),
1202 ADD_STAT(writePktSize,
"Write request sizes (log2)"),
1204 ADD_STAT(rdQLenPdf,
"What read queue length does an incoming req see"),
1205 ADD_STAT(wrQLenPdf,
"What write queue length does an incoming req see"),
1208 "Reads before turning the bus around for writes"),
1210 "Writes before turning the bus around for reads"),
1212 ADD_STAT(bytesReadWrQ,
"Total number of bytes read from write queue"),
1213 ADD_STAT(bytesReadSys,
"Total read bytes from the system interface side"),
1215 "Total written bytes from the system interface side"),
1217 ADD_STAT(avgRdBWSys,
"Average system read bandwidth in MiByte/s"),
1218 ADD_STAT(avgWrBWSys,
"Average system write bandwidth in MiByte/s"),
1220 ADD_STAT(totGap,
"Total gap between requests"),
1221 ADD_STAT(avgGap,
"Average gap between requests"),
1223 ADD_STAT(requestorReadBytes,
"Per-requestor bytes read from memory"),
1224 ADD_STAT(requestorWriteBytes,
"Per-requestor bytes write to memory"),
1226 "Per-requestor bytes read from memory rate (Bytes/sec)"),
1228 "Per-requestor bytes write to memory rate (Bytes/sec)"),
1230 "Per-requestor read serviced memory accesses"),
1232 "Per-requestor write serviced memory accesses"),
1234 "Per-requestor read total memory access latency"),
1236 "Per-requestor write total memory access latency"),
1238 "Per-requestor read average memory access latency"),
1240 "Per-requestor write average memory access latency")
1248 using namespace Stats;
1250 assert(ctrl.system());
1251 const auto max_requestors = ctrl.system()->maxRequestors();
1253 avgRdQLen.precision(2);
1254 avgWrQLen.precision(2);
1256 readPktSize.init(
ceilLog2(ctrl.system()->cacheLineSize()) + 1);
1257 writePktSize.init(
ceilLog2(ctrl.system()->cacheLineSize()) + 1);
1259 rdQLenPdf.init(ctrl.readBufferSize);
1260 wrQLenPdf.init(ctrl.writeBufferSize);
1263 .init(ctrl.readBufferSize)
1266 .init(ctrl.writeBufferSize)
1269 avgRdBWSys.precision(2);
1270 avgWrBWSys.precision(2);
1271 avgGap.precision(2);
1275 .init(max_requestors)
1279 .init(max_requestors)
1287 requestorReadAccesses
1288 .init(max_requestors)
1291 requestorWriteAccesses
1292 .init(max_requestors)
1295 requestorReadTotalLat
1296 .init(max_requestors)
1307 requestorWriteTotalLat
1308 .init(max_requestors)
1311 requestorWriteAvgLat
1315 for (
int i = 0;
i < max_requestors;
i++) {
1316 const std::string requestor = ctrl.system()->getRequestorName(
i);
1317 requestorReadBytes.subname(
i, requestor);
1318 requestorReadRate.subname(
i, requestor);
1319 requestorWriteBytes.subname(
i, requestor);
1320 requestorWriteRate.subname(
i, requestor);
1321 requestorReadAccesses.subname(
i, requestor);
1322 requestorWriteAccesses.subname(
i, requestor);
1323 requestorReadTotalLat.subname(
i, requestor);
1324 requestorReadAvgLat.subname(
i, requestor);
1325 requestorWriteTotalLat.subname(
i, requestor);
1326 requestorWriteAvgLat.subname(
i, requestor);
1330 avgRdBWSys = (bytesReadSys / 1000000) /
simSeconds;
1331 avgWrBWSys = (bytesWrittenSys / 1000000) /
simSeconds;
1333 avgGap = totGap / (readReqs + writeReqs);
1335 requestorReadRate = requestorReadBytes /
simSeconds;
1336 requestorWriteRate = requestorWriteBytes /
simSeconds;
1337 requestorReadAvgLat = requestorReadTotalLat / requestorReadAccesses;
1338 requestorWriteAvgLat = requestorWriteTotalLat / requestorWriteAccesses;
1351 panic(
"Can't handle address range for packet %s\n",
1359 if (if_name !=
"port") {
1374 return (dram_drained && nvm_drained);
1385 DPRINTF(Drain,
"Memory controller not drained, write: %d, read: %d,"
1433 DPRINTF(DRAM,
"Pushing DRAM ranges to port\n");
1434 ranges.push_back(ctrl.dram->getAddrRange());
1437 DPRINTF(NVM,
"Pushing NVM ranges to port\n");
1438 ranges.push_back(ctrl.nvm->getAddrRange());
1448 if (!queue.trySatisfyFunctional(pkt)) {
1452 ctrl.recvFunctional(pkt);
1461 return ctrl.recvAtomic(pkt);
1468 return ctrl.recvTimingReq(pkt);
1472 MemCtrlParams::create()
const unsigned int burstCount
Number of bursts requred for a system packet.
const uint8_t rank
Will be populated by address decoder.
#define fatal(...)
This implements a cprintf based fatal() function.
unsigned int burstsServiced
Number of bursts serviced so far for a system packet.
RequestorID requestorId() const
Get the packet RequestorID (interface compatibility with Packet)
void processNextReqEvent()
Bunch of things requires to setup "events" in gem5 When event "respondEvent" occurs for example,...
bool scheduled() const
Determine if the current event is scheduled.
EventFunctionWrapper nextReqEvent
BurstHelper * burstHelper
A pointer to the BurstHelper if this MemPacket is a split packet If not a split packet (common case),...
AddrRange getAddrRange() const
Get the address range.
Stats::Vector writePktSize
Tick minWriteToReadDataGap() const
std::pair< Tick, Tick > doBurstAccess(MemPacket *mem_pkt, Tick next_burst_at, const std::vector< MemPacketQueue > &queue)
Actually do the burst - figure out the latency it will take to service the req based on bank state,...
bool cacheResponding() const
virtual void startup() override
startup() is the final initialization call before simulation.
bool writeQueueFull(unsigned int pkt_count) const
Check if the write queue has room for more entries.
bool isTimingMode() const
Is the system in timing mode?
const uint32_t writeLowThreshold
bool isDram() const
Return true if its a DRAM access.
Stats::Vector requestorWriteBytes
uint8_t schedule(RequestorID id, uint64_t data)
Tick readyTime
When will request leave the controller.
void recordTurnaroundStats()
Record statistics on turnarounds based on busStateNext and busState values.
uint32_t payloadDelay
The extra pipelining delay from seeing the packet until the end of payload is transmitted by the comp...
Stats::Scalar bytesReadSys
Stats::Vector requestorReadAccesses
void doBurstAccess(MemPacket *mem_pkt)
Actually do the burst based on media specific access function.
Stats::Scalar writeBursts
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::vector< MemPacketQueue > writeQueue
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
uint8_t numPriorities() const
Gets the total number of priority levels in the QoS memory controller.
DrainState drain() override
Draining is the process of clearing out the states of SimObjects.These are the SimObjects that are pa...
void respondEvent(uint8_t rank)
Complete response process for DRAM when read burst is complete This will update the counters and chec...
uint64_t Tick
Tick count type.
bool isBusy()
This function checks if ranks are actively refreshing and therefore busy.
void setupRank(const uint8_t rank, const bool is_read) override
Setup the rank based on packet received.
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
void pushLabel(const std::string &lbl)
Push label for PrintReq (safe to call unconditionally).
bool contains(const Addr &a) const
Determine if the range contains an address.
RequestorID requestorId() const
std::unordered_set< Addr > isInWriteQueue
To avoid iterating over the write queue to check for overlapping transactions, maintain a set of burs...
virtual void drainResume() override
Resume execution after a successful drain.
Addr burstAlign(Addr addr, bool is_dram) const
Burst-align an address.
Stats::Scalar servicedByWrQ
void schedTimingResp(PacketPtr pkt, Tick when)
Schedule the sending of a timing response.
Stats::Vector readPktSize
void regStats() override
Callback to set stat parameters.
const uint32_t readBufferSize
The following are basic design parameters of the memory controller, and are initialized based on para...
Tick accessLatency() const override
uint32_t headerDelay
The extra delay from seeing the packet until the header is transmitted.
void print(std::ostream &o, int verbosity=0, const std::string &prefix="") const
void functionalAccess(PacketPtr pkt)
Perform an untimed memory read or write without changing anything but the memory itself.
std::vector< MemPacketQueue > & selQueue(bool is_read)
Select either the read or write queue.
const Tick entryTime
When did request enter the controller.
@ Drained
Buffers drained, ready for serialization/handover.
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.
bool allIntfDrained() const
Ensure that all interfaced have drained commands.
void setupRank(const uint8_t rank, const bool is_read) override
Setup the rank based on packet received.
Stats::Vector requestorWriteAccesses
DrainState
Object drain/handover states.
bool allRanksDrained() const override
Check drain state of NVM interface.
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.
bool writeRespQueueFull() const
Check if the write response queue has reached defined threshold.
void recvFunctional(PacketPtr pkt)
Receive a functional request packet from the peer.
uint64_t totalWriteQueueSize
Total write request packets queue length in #packets.
Stats::Scalar bytesWrittenSys
Stats::Scalar mergedWrBursts
uint8_t qosValue() const
QoS Value getter Returns 0 if QoS value was never set (constructor default).
T divCeil(const T &a, const U &b)
void access(PacketPtr pkt)
Perform an untimed memory access and update all the state (e.g.
Tick minReadToWriteDataGap()
Calculate the minimum delay used when scheduling a read-to-write transision.
bool burstReady(MemPacket *pkt) const override
Check if a burst operation can be issued to the DRAM.
Stats::Vector requestorReadTotalLat
Tick minWriteToReadDataGap()
Calculate the minimum delay used when scheduling a write-to-read transision.
void checkRefreshState(uint8_t rank)
Check the refresh state to determine if refresh needs to be kicked back into action after a read resp...
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.
BusState busStateNext
bus state for next request event triggered
virtual Port & getPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a port with a given name and index.
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
const Tick frontendLatency
Pipeline latency of the controller frontend.
Stats::Formula simSeconds
bool inWriteBusState(bool next_state) const
Check the current direction of the memory channel.
EventFunctionWrapper respondEvent
const std::string & cmdString() const
Return the string name of the cmd field (for debugging and tracing).
Enums::MemSched memSchedPolicy
Memory controller configuration initialized based on parameter values.
Tick nextBurstAt
Till when must we wait before issuing next RD/WR burst?
Ports are used to interface objects to each other.
bool needsResponse() const
uint64_t totalReadQueueSize
Total read request packets queue length in #packets.
Tick commandOffset() const override
void pruneBurstTick()
Remove commands that have already issued from burstTicks.
unsigned int size
The size of this dram packet in bytes It is always equal or smaller than the burst size.
Stats::Histogram rdPerTurnAround
Tick commandOffset() const override
virtual AddrRangeList getAddrRanges() const
Get a list of the non-overlapping address ranges the owner is responsible for.
void signalDrainDone() const
Signal that an object is drained.
void printQs() const
Used for debugging to observe the contents of the queues.
DRAMInterface *const dram
Create pointer to interface of the actual dram media when connected.
void processRespondEvent()
A memory packet stores packets along with the timestamp of when the packet entered the queue,...
A queued port is a port that has an infinite queue for outgoing packets and thus decouples the module...
bool isBusy(bool read_queue_empty, bool all_writes_nvm)
This function checks if ranks are busy.
bool recvTimingReq(PacketPtr)
Receive a timing request from the peer.
const uint32_t writeHighThreshold
void startup() override
Iterate through dram ranks and instantiate per rank startup routine.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
NVMInterface *const nvm
Create pointer to interface of the actual nvm media when connected.
bool allRanksDrained() const override
Return true once refresh is complete for all ranks and there are no additional commands enqueued.
const std::string & name()
bool packetReady(MemPacket *pkt)
Determine if there is a packet that can issue.
const FlagsType nozero
Don't print if this is zero.
virtual void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
DrainState drainState() const
Return the current drain state of an object.
bool retryRdReq
Remember if we have to retry a request when available.
const Tick commandWindow
Length of a command window, used to check command bandwidth.
bool isTimingMode
Remember if the memory system is in timing mode.
virtual const std::string name() const
std::deque< MemPacket * > respQueue
Response queue where read packets wait after we're done working with them, but it's not time to send ...
Tick verifySingleCmd(Tick cmd_tick, Tick max_cmds_per_burst)
Check for command bus contention for single cycle command.
const std::unique_ptr< TurnaroundPolicy > turnPolicy
QoS Bus Turnaround Policy: selects the bus direction (READ/WRITE)
const uint32_t writeBufferSize
std::unique_ptr< Packet > pendingDelete
Upstream caches need this packet until true is returned, so hold it for deletion until a subsequent c...
void addRankToRankDelay(Tick cmd_at) override
Add rank to rank delay to bus timing to all DRAM banks in alli ranks when access to an alternate inte...
Stats::Scalar bytesReadWrQ
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
void addToWriteQueue(PacketPtr pkt, unsigned int pkt_count, bool is_dram)
Decode the incoming pkt, create a mem_pkt and push to the back of the write queue.
void accessAndRespond(PacketPtr pkt, Tick static_latency)
When a packet reaches its "readyTime" in the response Q, use the "access()" method in AbstractMemory ...
const PacketPtr pkt
This comes from the outside world.
The memory controller is a single-channel memory controller capturing the most important timing const...
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.
uint32_t bytesPerBurst() const
const uint32_t minWritesPerSwitch
Overload hash function for BasicBlockRange type.
void qosValue(const uint8_t qv)
Set the packet QoS value (interface compatibility with Packet)
bool recvTimingReq(PacketPtr pkt)
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...
MemoryPort port
Our incoming port, for a multi-ported controller add a crossbar in front of it.
MemCtrl(const MemCtrlParams *p)
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Tick minReadToWriteDataGap() const
bool inReadBusState(bool next_state) const
Check the current direction of the memory channel.
void addToReadQueue(PacketPtr pkt, unsigned int pkt_count, bool is_dram)
When a new read comes in, first check if the write q has a pending request to the same address....
std::vector< MemPacketQueue > readQueue
The controller's main read and write queues, with support for QoS reordering.
std::pair< MemPacketQueue::iterator, Tick > chooseNextFRFCFS(MemPacketQueue &queue, Tick min_col_at) const override
For FR-FCFS policy, find first DRAM command that can issue.
bool isConnected() const
Is this port currently connected to a peer?
void sample(const U &v, int n=1)
Add a value to the distribtion n times.
Addr addr
The starting address of the packet.
Stats::Vector requestorReadBytes
Stats::Histogram wrPerTurnAround
std::unordered_multiset< Tick > burstTicks
Holds count of commands issued in burst window starting at defined Tick.
System * system() const
read the system pointer
Tick getBurstWindow(Tick cmd_tick)
Calculate burst window aligned tick.
void recvFunctional(PacketPtr pkt)
void sendRetryReq()
Send a retry to the request port that previously attempted a sendTimingReq to this response port and ...
void drainRanks()
Iterate through dram ranks to exit self-refresh in order to drain.
MemPacketQueue::iterator chooseNextFRFCFS(MemPacketQueue &queue, Tick extra_col_delay)
For FR-FCFS policy reorder the read/write queue depending on row buffer hits and earliest bursts avai...
MemoryPort(const std::string &name, MemCtrl &_ctrl)
const Tick backendLatency
Pipeline latency of the backend and PHY.
Stats::Vector requestorWriteTotalLat
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
void chooseRead(MemPacketQueue &queue)
Select read command to issue asynchronously.
MemPacketQueue::iterator chooseNext(MemPacketQueue &queue, Tick extra_col_delay)
The memory schduler/arbiter - picks which request needs to go next, based on the specified policy suc...
Tick accessLatency() const override
void sendRangeChange() const
Called by the owner to send a range change.
Tick recvAtomic(PacketPtr pkt)
BusState busState
Bus state used to control the read/write switching and drive the scheduling of the next request.
BusState selectNextBusState()
Returns next bus direction (READ or WRITE) based on configured policy.
MemPacket * decodePacket(const PacketPtr pkt, Addr pkt_addr, unsigned int size, bool is_read, bool is_dram)
Address decoder to figure out physical mapping onto ranks, banks, and rows.
void suspend()
Iterate through DRAM ranks and suspend them.
bool readsWaitingToIssue() const
Tick recvAtomic(PacketPtr pkt)
Receive an atomic request packet from the peer.
bool isRead() const
Return true if its a read packet (interface compatibility with Packet)
const FlagsType nonan
Don't print if this is NAN.
std::pair< Tick, Tick > doBurstAccess(MemPacket *pkt, Tick next_burst_at)
Actually do the burst and update stats.
void popLabel()
Pop label for PrintReq (safe to call unconditionally).
@ Draining
Draining buffers pending serialization/handover.
bool readQueueFull(unsigned int pkt_count) const
Check if the read queue has room for more entries.
Tick nextReqTime
The soonest you have to start thinking about the next request is the longest access time that can occ...
#define panic(...)
This implements a cprintf based panic() function.
bool burstReady(MemPacket *pkt) const override
Check if a burst operation can be issued to the NVM.
A burst helper helps organize and manage a packet that is larger than the memory burst size.
Tick curTick()
The current simulated tick.
Generated on Wed Sep 30 2020 14:02:13 for gem5 by doxygen 1.8.17