Go to the documentation of this file.
32 #include "debug/DRAM.hh"
33 #include "debug/Drain.hh"
34 #include "debug/MemCtrl.hh"
35 #include "debug/QOS.hh"
48 retryRdReqPC1(false), retryWrReqPC1(false),
52 respondEventPC1([
this] {processRespondEvent(pc1Int, respQueuePC1,
53 respondEventPC1, retryRdReqPC1); },
name()),
55 partitionedQ(
p.partitioned_q)
57 DPRINTF(MemCtrl,
"Setting up HBM controller\n");
59 pc0Int =
dynamic_cast<DRAMInterface*
>(dram);
61 assert(
dynamic_cast<DRAMInterface*
>(
p.dram_2) !=
nullptr);
63 readBufferSize = pc0Int->readBufferSize + pc1Int->readBufferSize;
64 writeBufferSize = pc0Int->writeBufferSize + pc1Int->writeBufferSize;
66 fatal_if(!pc0Int,
"Memory controller must have pc0 interface");
67 fatal_if(!pc1Int,
"Memory controller must have pc1 interface");
69 pc0Int->setCtrl(
this, commandWindow, 0);
70 pc1Int->setCtrl(
this, commandWindow, 1);
73 writeHighThreshold = (writeBufferSize * (
p.write_high_thresh_perc/2)
75 writeLowThreshold = (writeBufferSize * (
p.write_low_thresh_perc/2)
78 writeHighThreshold = (writeBufferSize *
p.write_high_thresh_perc
80 writeLowThreshold = (writeBufferSize *
p.write_low_thresh_perc
116 panic(
"Can't handle address range for packet %s\n", pkt->
print());
132 panic(
"Can't handle address range for packet %s\n", pkt->
print());
147 panic(
"Can't handle address range for packet %s\n",
157 "Write queue limit %d, PC0 size %d, entries needed %d\n",
168 "Write queue limit %d, PC1 size %d, entries needed %d\n",
179 "Read queue limit %d, PC0 size %d, entries needed %d\n",
192 "Read queue limit %d, PC1 size %d, entries needed %d\n",
205 "HBMCtrl: Read queue limit %d, entries needed %d\n",
224 "Should only see read and writes at memory controller\n");
246 unsigned size = pkt->
getSize();
338 auto current_it = it++;
351 auto current_it = it++;
370 Tick cmd_at = cmd_tick;
379 while (
rowBurstTicks.count(burst_tick) >= max_cmds_per_burst) {
390 while (
colBurstTicks.count(burst_tick) >= max_cmds_per_burst) {
405 Tick max_multi_cmd_split)
409 Tick cmd_at = cmd_tick;
419 Tick burst_offset = 0;
421 while (max_multi_cmd_split > (first_cmd_offset + burst_offset)) {
426 Tick first_cmd_tick = burst_tick - std::min(burst_offset, burst_tick);
429 bool first_can_issue =
false;
430 bool second_can_issue =
false;
432 while (!first_can_issue || !second_can_issue) {
433 bool same_burst = (burst_tick == first_cmd_tick);
435 auto second_cmd_count = same_burst ?
438 first_can_issue = first_cmd_count < max_cmds_per_burst;
439 second_can_issue = second_cmd_count < max_cmds_per_burst;
441 if (!second_can_issue) {
442 DPRINTF(
MemCtrl,
"Contention (cmd2) found on command bus at %d\n",
451 bool gap_violated = !same_burst &&
452 ((burst_tick - first_cmd_tick) > max_multi_cmd_split);
454 if (!first_can_issue || (!second_can_issue && gap_violated)) {
455 DPRINTF(
MemCtrl,
"Contention (cmd1) found on command bus at %d\n",
bool recvTimingReq(PacketPtr pkt) override
Tick curTick()
The universal simulation clock.
const std::string & cmdString() const
Return the string name of the cmd field (for debugging and tracing).
uint64_t totalReadQueueSize
Total read request packets queue length in #packets.
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....
EventFunctionWrapper nextReqEvent
AddrRange getAddrRange() const
Get the address range.
bool contains(const Addr &a) const
Determine if the range contains an address.
HBMCtrl(const HBMCtrlParams &p)
The memory controller is a single-channel memory controller capturing the most important timing const...
Tick verifySingleCmd(Tick cmd_tick, Tick max_cmds_per_burst, bool row_cmd) override
Check for command bus contention for single cycle command.
bool cacheResponding() const
std::unordered_multiset< Tick > colBurstTicks
This is used to ensure that the column command bandwidth does not exceed the allowable media constrai...
void drainRanks() override
Iterate through dram ranks to exit self-refresh in order to drain.
virtual void startup() override
startup() is the final initialization call before simulation.
void recvFunctional(PacketPtr pkt) override
EventFunctionWrapper nextReqEventPC1
NextReq and Respond events for second pseudo channel.
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.
uint32_t readBufferSize
The following are basic design parameters of the memory controller, and are initialized based on para...
statistics::Scalar bytesReadSys
uint64_t readQueueSizePC1
std::vector< MemPacketQueue > writeQueue
uint8_t schedule(RequestorID id, uint64_t data)
Tick recvAtomic(PacketPtr pkt) override
statistics::Scalar numWrRetry
void print(std::ostream &o, int verbosity=0, const std::string &prefix="") const
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
uint64_t Tick
Tick count type.
Tick commandOffset() const override
DRAMInterface * pc0Int
Pointers to interfaces of the two pseudo channels pc0Int is same as MemCtrl::dram (it will be pointin...
EventFunctionWrapper respondEventPC1
System * system() const
read the system pointer
virtual void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Tick verifyMultiCmd(Tick cmd_tick, Tick max_cmds_per_burst, Tick max_multi_cmd_split=0) override
Check for command bus contention for multi-cycle (2 currently) command.
bool writeQueueFullPC1(unsigned int pkt_count) const
bool recvFunctionalLogic(PacketPtr pkt, MemInterface *mem_intr)
statistics::Scalar bytesWrittenSys
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
virtual void startup() override
startup() is the final initialization call before simulation.
statistics::Scalar writeReqs
bool isTimingMode() const
Is the system in timing mode?
bool isTimingMode
Remember if the memory system is in timing mode.
statistics::Scalar numRdRetry
std::deque< MemPacket * > respQueue
Response queue where read packets wait after we're done working with them, but it's not time to send ...
std::deque< MemPacket * > respQueuePC1
Response queue for pkts sent to second pseudo channel The first pseudo channel uses MemCtrl::respQueu...
virtual void drainResume() override
Resume execution after a successful drain.
const std::string & name()
statistics::Scalar totGap
Tick nextBurstAt
Till when the controller must wait before issuing next RD/WR burst?
void getBackdoor(MemBackdoorPtr &bd_ptr)
std::vector< MemPacketQueue > readQueue
The controller's main read and write queues, with support for QoS reordering.
static constexpr T divCeil(const T &a, const U &b)
bool partitionedQ
This indicates if the R/W queues will be partitioned among pseudo channels.
void pruneBurstTick() override
Remove commands that have already issued from rowBurstTicks and colBurstTicks.
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
statistics::Scalar readReqs
Tick recvAtomicLogic(PacketPtr pkt, MemInterface *mem_intr)
bool readQueueFullPC0(unsigned int pkt_count) const
Check if the read queue partition of both pseudo channels has room for more entries.
bool readQueueFullPC1(unsigned int pkt_count) const
bool writeQueueFull(unsigned int pkt_count) const
Check if the write queue has room for more entries.
bool readQueueFull(unsigned int pkt_count) const
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,...
Tick getBurstWindow(Tick cmd_tick)
Calculate burst window aligned tick.
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 recvAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr &backdoor) override
uint32_t bytesPerBurst() const
virtual void drainResume() override
Resume execution after a successful drain.
uint64_t readQueueSizePC0
Following counters are used to keep track of the entries in read/write queue for each pseudo channel ...
const Tick commandWindow
Length of a command window, used to check command bandwidth.
uint64_t writeQueueSizePC0
#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....
std::unordered_multiset< Tick > rowBurstTicks
Holds count of row commands issued in burst window starting at defined Tick.
virtual void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
uint64_t writeQueueSizePC1
bool writeQueueFullPC0(unsigned int pkt_count) const
Check if the write queue partition of both pseudo channels has room for more entries.
bool scheduled() const
Determine if the current event is scheduled.
void startup() override
Iterate through dram ranks and instantiate per rank startup routine.
bool retryRdReqPC1
Remember if we have to retry a request for second pseudo channel.
#define panic(...)
This implements a cprintf based panic() function.
Generated on Thu Jun 16 2022 10:41:56 for gem5 by doxygen 1.8.17