mem: DRAM controller tidying up
Minor tidying up and removing of redundant code, including the printing of queue state every million accesses.
This commit is contained in:
parent
bc83eb2197
commit
03a1aed803
2 changed files with 27 additions and 34 deletions
|
@ -80,8 +80,7 @@ SimpleDRAM::SimpleDRAM(const SimpleDRAMParams* p) :
|
||||||
maxAccessesPerRow(p->max_accesses_per_row),
|
maxAccessesPerRow(p->max_accesses_per_row),
|
||||||
frontendLatency(p->static_frontend_latency),
|
frontendLatency(p->static_frontend_latency),
|
||||||
backendLatency(p->static_backend_latency),
|
backendLatency(p->static_backend_latency),
|
||||||
busBusyUntil(0), writeStartTime(0),
|
busBusyUntil(0), prevArrival(0),
|
||||||
prevArrival(0), numReqs(0),
|
|
||||||
newTime(0), startTickPrechargeAll(0), numBanksActive(0)
|
newTime(0), startTickPrechargeAll(0), numBanksActive(0)
|
||||||
{
|
{
|
||||||
// create the bank states based on the dimensions of the ranks and
|
// create the bank states based on the dimensions of the ranks and
|
||||||
|
@ -112,22 +111,22 @@ SimpleDRAM::SimpleDRAM(const SimpleDRAMParams* p) :
|
||||||
|
|
||||||
if (range.interleaved()) {
|
if (range.interleaved()) {
|
||||||
if (channels != range.stripes())
|
if (channels != range.stripes())
|
||||||
panic("%s has %d interleaved address stripes but %d channel(s)\n",
|
fatal("%s has %d interleaved address stripes but %d channel(s)\n",
|
||||||
name(), range.stripes(), channels);
|
name(), range.stripes(), channels);
|
||||||
|
|
||||||
if (addrMapping == Enums::RoRaBaChCo) {
|
if (addrMapping == Enums::RoRaBaChCo) {
|
||||||
if (rowBufferSize != range.granularity()) {
|
if (rowBufferSize != range.granularity()) {
|
||||||
panic("Interleaving of %s doesn't match RoRaBaChCo "
|
fatal("Interleaving of %s doesn't match RoRaBaChCo "
|
||||||
"address map\n", name());
|
"address map\n", name());
|
||||||
}
|
}
|
||||||
} else if (addrMapping == Enums::RoRaBaCoCh) {
|
} else if (addrMapping == Enums::RoRaBaCoCh) {
|
||||||
if (system()->cacheLineSize() != range.granularity()) {
|
if (system()->cacheLineSize() != range.granularity()) {
|
||||||
panic("Interleaving of %s doesn't match RoRaBaCoCh "
|
fatal("Interleaving of %s doesn't match RoRaBaCoCh "
|
||||||
"address map\n", name());
|
"address map\n", name());
|
||||||
}
|
}
|
||||||
} else if (addrMapping == Enums::RoCoRaBaCh) {
|
} else if (addrMapping == Enums::RoCoRaBaCh) {
|
||||||
if (system()->cacheLineSize() != range.granularity())
|
if (system()->cacheLineSize() != range.granularity())
|
||||||
panic("Interleaving of %s doesn't match RoCoRaBaCh "
|
fatal("Interleaving of %s doesn't match RoCoRaBaCh "
|
||||||
"address map\n", name());
|
"address map\n", name());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -146,6 +145,10 @@ SimpleDRAM::init()
|
||||||
void
|
void
|
||||||
SimpleDRAM::startup()
|
SimpleDRAM::startup()
|
||||||
{
|
{
|
||||||
|
// update the start tick for the precharge accounting to the
|
||||||
|
// current tick
|
||||||
|
startTickPrechargeAll = curTick();
|
||||||
|
|
||||||
// print the configuration of the controller
|
// print the configuration of the controller
|
||||||
printParams();
|
printParams();
|
||||||
|
|
||||||
|
@ -190,7 +193,8 @@ SimpleDRAM::writeQueueFull(unsigned int neededEntries) const
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleDRAM::DRAMPacket*
|
SimpleDRAM::DRAMPacket*
|
||||||
SimpleDRAM::decodeAddr(PacketPtr pkt, Addr dramPktAddr, unsigned size, bool isRead)
|
SimpleDRAM::decodeAddr(PacketPtr pkt, Addr dramPktAddr, unsigned size,
|
||||||
|
bool isRead)
|
||||||
{
|
{
|
||||||
// decode the address based on the address mapping scheme, with
|
// decode the address based on the address mapping scheme, with
|
||||||
// Ro, Ra, Co, Ba and Ch denoting row, rank, column, bank and
|
// Ro, Ra, Co, Ba and Ch denoting row, rank, column, bank and
|
||||||
|
@ -400,9 +404,6 @@ SimpleDRAM::processWriteEvent()
|
||||||
DPRINTF(DRAM, "Writing, bus busy for %lld ticks, banks busy "
|
DPRINTF(DRAM, "Writing, bus busy for %lld ticks, banks busy "
|
||||||
"for %lld ticks\n", busBusyUntil - temp1, maxBankFreeAt() - temp2);
|
"for %lld ticks\n", busBusyUntil - temp1, maxBankFreeAt() - temp2);
|
||||||
|
|
||||||
// Update stats
|
|
||||||
avgWrQLen = writeQueue.size();
|
|
||||||
|
|
||||||
// If we emptied the write queue, or got below the threshold and
|
// If we emptied the write queue, or got below the threshold and
|
||||||
// are not draining, or we have reads waiting and have done enough
|
// are not draining, or we have reads waiting and have done enough
|
||||||
// writes, then switch to reads. The retry above could already
|
// writes, then switch to reads. The retry above could already
|
||||||
|
@ -444,13 +445,13 @@ SimpleDRAM::triggerWrites()
|
||||||
// Flag variable to stop any more read scheduling
|
// Flag variable to stop any more read scheduling
|
||||||
stopReads = true;
|
stopReads = true;
|
||||||
|
|
||||||
writeStartTime = std::max(busBusyUntil, curTick()) + tWTR;
|
Tick write_start_time = std::max(busBusyUntil, curTick()) + tWTR;
|
||||||
|
|
||||||
DPRINTF(DRAM, "Writes scheduled at %lld\n", writeStartTime);
|
DPRINTF(DRAM, "Writes scheduled at %lld\n", write_start_time);
|
||||||
|
|
||||||
assert(writeStartTime >= curTick());
|
assert(write_start_time >= curTick());
|
||||||
assert(!writeEvent.scheduled());
|
assert(!writeEvent.scheduled());
|
||||||
schedule(writeEvent, writeStartTime);
|
schedule(writeEvent, write_start_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -573,13 +574,13 @@ SimpleDRAM::printParams() const
|
||||||
"Memory controller %s physical organization\n" \
|
"Memory controller %s physical organization\n" \
|
||||||
"Number of devices per rank %d\n" \
|
"Number of devices per rank %d\n" \
|
||||||
"Device bus width (in bits) %d\n" \
|
"Device bus width (in bits) %d\n" \
|
||||||
"DRAM data bus burst %d\n" \
|
"DRAM data bus burst (bytes) %d\n" \
|
||||||
"Row buffer size %d\n" \
|
"Row buffer size (bytes) %d\n" \
|
||||||
"Columns per row buffer %d\n" \
|
"Columns per row buffer %d\n" \
|
||||||
"Rows per bank %d\n" \
|
"Rows per bank %d\n" \
|
||||||
"Banks per rank %d\n" \
|
"Banks per rank %d\n" \
|
||||||
"Ranks per channel %d\n" \
|
"Ranks per channel %d\n" \
|
||||||
"Total mem capacity %u\n",
|
"Total mem capacity (bytes) %u\n",
|
||||||
name(), devicesPerRank, deviceBusWidth, burstSize, rowBufferSize,
|
name(), devicesPerRank, deviceBusWidth, burstSize, rowBufferSize,
|
||||||
columnsPerRowBuffer, rowsPerBank, banksPerRank, ranksPerChannel,
|
columnsPerRowBuffer, rowsPerBank, banksPerRank, ranksPerChannel,
|
||||||
rowBufferSize * rowsPerBank * banksPerRank * ranksPerChannel);
|
rowBufferSize * rowsPerBank * banksPerRank * ranksPerChannel);
|
||||||
|
@ -646,15 +647,11 @@ SimpleDRAM::recvTimingReq(PacketPtr pkt)
|
||||||
|
|
||||||
// simply drop inhibited packets for now
|
// simply drop inhibited packets for now
|
||||||
if (pkt->memInhibitAsserted()) {
|
if (pkt->memInhibitAsserted()) {
|
||||||
DPRINTF(DRAM,"Inhibited packet -- Dropping it now\n");
|
DPRINTF(DRAM, "Inhibited packet -- Dropping it now\n");
|
||||||
pendingDelete.push_back(pkt);
|
pendingDelete.push_back(pkt);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Every million accesses, print the state of the queues
|
|
||||||
if (numReqs % 1000000 == 0)
|
|
||||||
printQs();
|
|
||||||
|
|
||||||
// Calc avg gap between requests
|
// Calc avg gap between requests
|
||||||
if (prevArrival != 0) {
|
if (prevArrival != 0) {
|
||||||
totGap += curTick() - prevArrival;
|
totGap += curTick() - prevArrival;
|
||||||
|
@ -682,7 +679,6 @@ SimpleDRAM::recvTimingReq(PacketPtr pkt)
|
||||||
} else {
|
} else {
|
||||||
addToReadQueue(pkt, dram_pkt_count);
|
addToReadQueue(pkt, dram_pkt_count);
|
||||||
readReqs++;
|
readReqs++;
|
||||||
numReqs++;
|
|
||||||
bytesReadSys += size;
|
bytesReadSys += size;
|
||||||
}
|
}
|
||||||
} else if (pkt->isWrite()) {
|
} else if (pkt->isWrite()) {
|
||||||
|
@ -696,7 +692,6 @@ SimpleDRAM::recvTimingReq(PacketPtr pkt)
|
||||||
} else {
|
} else {
|
||||||
addToWriteQueue(pkt, dram_pkt_count);
|
addToWriteQueue(pkt, dram_pkt_count);
|
||||||
writeReqs++;
|
writeReqs++;
|
||||||
numReqs++;
|
|
||||||
bytesWrittenSys += size;
|
bytesWrittenSys += size;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -705,8 +700,6 @@ SimpleDRAM::recvTimingReq(PacketPtr pkt)
|
||||||
accessAndRespond(pkt, 1);
|
accessAndRespond(pkt, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
retryRdReq = false;
|
|
||||||
retryWrReq = false;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -722,7 +715,7 @@ SimpleDRAM::processRespondEvent()
|
||||||
// it is a split packet
|
// it is a split packet
|
||||||
dram_pkt->burstHelper->burstsServiced++;
|
dram_pkt->burstHelper->burstsServiced++;
|
||||||
if (dram_pkt->burstHelper->burstsServiced ==
|
if (dram_pkt->burstHelper->burstsServiced ==
|
||||||
dram_pkt->burstHelper->burstCount) {
|
dram_pkt->burstHelper->burstCount) {
|
||||||
// we have now serviced all children packets of a system packet
|
// we have now serviced all children packets of a system packet
|
||||||
// so we can now respond to the requester
|
// so we can now respond to the requester
|
||||||
// @todo we probably want to have a different front end and back
|
// @todo we probably want to have a different front end and back
|
||||||
|
@ -739,9 +732,6 @@ SimpleDRAM::processRespondEvent()
|
||||||
delete respQueue.front();
|
delete respQueue.front();
|
||||||
respQueue.pop_front();
|
respQueue.pop_front();
|
||||||
|
|
||||||
// Update stats
|
|
||||||
avgRdQLen = readQueue.size() + respQueue.size();
|
|
||||||
|
|
||||||
if (!respQueue.empty()) {
|
if (!respQueue.empty()) {
|
||||||
assert(respQueue.front()->readyTime >= curTick());
|
assert(respQueue.front()->readyTime >= curTick());
|
||||||
assert(!respondEvent.scheduled());
|
assert(!respondEvent.scheduled());
|
||||||
|
@ -1223,7 +1213,7 @@ SimpleDRAM::doDRAMAccess(DRAMPacket* dram_pkt)
|
||||||
moveToRespQ();
|
moveToRespQ();
|
||||||
|
|
||||||
// Schedule the next read event
|
// Schedule the next read event
|
||||||
if (!nextReqEvent.scheduled() && !stopReads){
|
if (!nextReqEvent.scheduled() && !stopReads) {
|
||||||
schedule(nextReqEvent, newTime);
|
schedule(nextReqEvent, newTime);
|
||||||
} else {
|
} else {
|
||||||
if (newTime < nextReqEvent.when())
|
if (newTime < nextReqEvent.when())
|
||||||
|
|
|
@ -353,7 +353,8 @@ class SimpleDRAM : public AbstractMemory
|
||||||
* @param isRead Is the request for a read or a write to DRAM
|
* @param isRead Is the request for a read or a write to DRAM
|
||||||
* @return A DRAMPacket pointer with the decoded information
|
* @return A DRAMPacket pointer with the decoded information
|
||||||
*/
|
*/
|
||||||
DRAMPacket* decodeAddr(PacketPtr pkt, Addr dramPktAddr, unsigned int size, bool isRead);
|
DRAMPacket* decodeAddr(PacketPtr pkt, Addr dramPktAddr, unsigned int size,
|
||||||
|
bool isRead);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The memory schduler/arbiter - picks which read request needs to
|
* The memory schduler/arbiter - picks which read request needs to
|
||||||
|
@ -430,6 +431,10 @@ class SimpleDRAM : public AbstractMemory
|
||||||
void recordActivate(Tick act_tick, uint8_t rank, uint8_t bank);
|
void recordActivate(Tick act_tick, uint8_t rank, uint8_t bank);
|
||||||
|
|
||||||
void printParams() const;
|
void printParams() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used for debugging to observe the contents of the queues.
|
||||||
|
*/
|
||||||
void printQs() const;
|
void printQs() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -533,9 +538,7 @@ class SimpleDRAM : public AbstractMemory
|
||||||
*/
|
*/
|
||||||
Tick busBusyUntil;
|
Tick busBusyUntil;
|
||||||
|
|
||||||
Tick writeStartTime;
|
|
||||||
Tick prevArrival;
|
Tick prevArrival;
|
||||||
int numReqs;
|
|
||||||
|
|
||||||
// The absolute soonest you have to start thinking about the
|
// The absolute soonest you have to start thinking about the
|
||||||
// next request is the longest access time that can occur before
|
// next request is the longest access time that can occur before
|
||||||
|
|
Loading…
Reference in a new issue