-
Notifications
You must be signed in to change notification settings - Fork 0
Adds SimpleMemCtrl and MemCtrl #23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
aakahlow
wants to merge
26
commits into
develop
Choose a base branch
from
memctrl-restr
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 1 commit
Commits
Show all changes
26 commits
Select commit
Hold shift + click to select a range
c63c554
mem: splitting dram and nvm interfaces into separate files
aakahlow 3596acf
mem: updates in mem interface to help implement a simple mem ctrl
aakahlow 8cb47dc
mem: Add a simple mem controller
aakahlow 7a25b4f
mem: Add mem ctrl
aakahlow 37af282
mem: Update simple ctrl and mem ctrl
aakahlow d584159
mem: Some updates based on comments
aakahlow b32d20b
mem: added the remaining of the fixes discussed in comments
mbabaie e90cff1
mem: applied the fixes asked for in the comments
mbabaie 6fba673
mem: update the event handlers
aakahlow 9cdbf5f
mem: revert back the port's ctrl to a reference
aakahlow 29208f2
mem: more updates based on PR comments
aakahlow 35e98b6
mem: all changes before renaming old MemCtrl() to the new naming
mbabaie c4df59a
mem: fixed most of renamings and passed all the tests
mbabaie 8705d3c
mem: resolve pr comments
aakahlow 2804add
mem: make SimpleMemCtrl dram not have a deault
aakahlow 4a0d404
mem: fix indendation issues in mem_interface.hh
aakahlow 1adc731
mem: updating readsWaitingToIssue signature
aakahlow b924e9b
mem: fixes in mem_ctrl.cc
aakahlow bb2b1c9
mem: remove unwanted import form SimpleMemCtrl.py
aakahlow dfe3eb5
mem: remove processNextReq from memctrl
aakahlow db63462
mem: some fixes in simpleMemCtrl processNextReqEvent
aakahlow 8121ed0
mem: remove dram check from SimpleMemCtrl
aakahlow fac8020
mem: removing nvm default
aakahlow c7260e7
mem: rename MemCtrl to HeteroMemCtrl
aakahlow 4574d8d
mem: rename SimpleMemCtrl as MemCtrl
aakahlow 3cfe2c5
mem: small fix
aakahlow File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -70,6 +70,8 @@ MemCtrl::MemCtrl(const MemCtrlParams &p) : | |
| dram->setCtrl(this, commandWindow); | ||
| nvm->setCtrl(this, commandWindow); | ||
|
|
||
| port.ctrl = this; | ||
|
|
||
| readBufferSize = dram->readBufferSize + nvm->readBufferSize; | ||
| writeBufferSize = dram->writeBufferSize + nvm->writeBufferSize; | ||
|
|
||
|
|
@@ -89,33 +91,14 @@ MemCtrl::MemCtrl(const MemCtrlParams &p) : | |
| Tick | ||
| MemCtrl::recvAtomic(PacketPtr pkt) | ||
| { | ||
| DPRINTF(MemCtrl, "recvAtomic: %s 0x%x\n", | ||
| pkt->cmdString(), pkt->getAddr()); | ||
|
|
||
| panic_if(pkt->cacheResponding(), "Should not see packets where cache " | ||
| "is responding"); | ||
|
|
||
| Tick latency = 0; | ||
| // do the actual memory access and turn the packet into a response | ||
| if (dram->getAddrRange().contains(pkt->getAddr())) { | ||
| dram->access(pkt); | ||
|
|
||
| if (pkt->hasData()) { | ||
| // this value is not supposed to be accurate, just enough to | ||
| // keep things going, mimic a closed page | ||
| latency = dram->accessLatency(); | ||
| } | ||
| if (dram->getAddrRange().contains(pkt->getAddr())) { | ||
| latency = SimpleMemCtrl::recvAtomicLogic(pkt, dram); | ||
| } else if (nvm->getAddrRange().contains(pkt->getAddr())) { | ||
| nvm->access(pkt); | ||
|
|
||
| if (pkt->hasData()) { | ||
| // this value is not supposed to be accurate, just enough to | ||
| // keep things going, mimic a closed page | ||
| latency = nvm->accessLatency(); | ||
| } | ||
| latency = SimpleMemCtrl::recvAtomicLogic(pkt, nvm); | ||
| } else { | ||
| panic("Can't handle address range for packet %s\n", | ||
| pkt->print()); | ||
| panic("Can't handle address range for packet %s\n", pkt->print()); | ||
| } | ||
|
|
||
| return latency; | ||
|
|
@@ -175,6 +158,12 @@ MemCtrl::recvTimingReq(PacketPtr pkt) | |
| return false; | ||
| } else { | ||
| addToWriteQueue(pkt, pkt_count, is_dram ? dram : nvm); | ||
| // If we are not already scheduled to get a request out of the | ||
| // queue, do so now | ||
| if (!nextReqEvent.scheduled()) { | ||
| DPRINTF(MemCtrl, "Request scheduled immediately\n"); | ||
| schedule(nextReqEvent, curTick()); | ||
| } | ||
| stats.writeReqs++; | ||
| stats.bytesWrittenSys += size; | ||
| } | ||
|
|
@@ -188,7 +177,14 @@ MemCtrl::recvTimingReq(PacketPtr pkt) | |
| stats.numRdRetry++; | ||
| return false; | ||
| } else { | ||
| addToReadQueue(pkt, pkt_count, is_dram ? dram : nvm); | ||
| if (!addToReadQueue(pkt, pkt_count, is_dram ? dram : nvm)) { | ||
| // If we are not already scheduled to get a request out of the | ||
| // queue, do so now | ||
| if (!nextReqEvent.scheduled()) { | ||
| DPRINTF(MemCtrl, "Request scheduled immediately\n"); | ||
| schedule(nextReqEvent, curTick()); | ||
| } | ||
| } | ||
| stats.readReqs++; | ||
| stats.bytesReadSys += size; | ||
| } | ||
|
|
@@ -203,56 +199,13 @@ MemCtrl::processRespondEvent() | |
| DPRINTF(MemCtrl, | ||
| "processRespondEvent(): Some req has reached its readyTime\n"); | ||
|
|
||
| MemPacket* mem_pkt = respQueue.front(); | ||
|
|
||
| if (mem_pkt->isDram()) { | ||
| // media specific checks and functions when read response is complete | ||
| dram->respondEvent(mem_pkt->rank); | ||
| } | ||
|
|
||
| if (mem_pkt->burstHelper) { | ||
| // it is a split packet | ||
| mem_pkt->burstHelper->burstsServiced++; | ||
| if (mem_pkt->burstHelper->burstsServiced == | ||
| mem_pkt->burstHelper->burstCount) { | ||
| // we have now serviced all children packets of a system packet | ||
| // so we can now respond to the requestor | ||
| // @todo we probably want to have a different front end and back | ||
| // end latency for split packets | ||
| accessAndRespond(mem_pkt->pkt, frontendLatency + backendLatency); | ||
| delete mem_pkt->burstHelper; | ||
| mem_pkt->burstHelper = NULL; | ||
| } | ||
| if (respQueue.front()->isDram()) { | ||
| respondEventLogic(dram, respQueue, respondEvent); | ||
| } else { | ||
| // it is not a split packet | ||
| accessAndRespond(mem_pkt->pkt, frontendLatency + backendLatency); | ||
| respondEventLogic(nvm, respQueue, respondEvent); | ||
| } | ||
|
|
||
| respQueue.pop_front(); | ||
|
|
||
| if (!respQueue.empty()) { | ||
| assert(respQueue.front()->readyTime >= curTick()); | ||
| assert(!respondEvent.scheduled()); | ||
| schedule(respondEvent, respQueue.front()->readyTime); | ||
| } else { | ||
| // if there is nothing left in any queue, signal a drain | ||
| if (drainState() == DrainState::Draining && | ||
| !totalWriteQueueSize && !totalReadQueueSize && | ||
| allIntfDrained()) { | ||
|
|
||
| DPRINTF(Drain, "Controller done draining\n"); | ||
| signalDrainDone(); | ||
| } else if (mem_pkt->isDram()) { | ||
| // check the refresh state and kick the refresh event loop | ||
| // into action again if banks already closed and just waiting | ||
| // for read to complete | ||
| dram->checkRefreshState(mem_pkt->rank); | ||
| } | ||
| } | ||
|
|
||
| delete mem_pkt; | ||
|
|
||
| // We have made a location in the queue available at this point, | ||
| // We have made a location in the read queue available at this point, | ||
| // so if there is a read that was forced to wait, retry now | ||
| if (retryRdReq) { | ||
| retryRdReq = false; | ||
|
|
@@ -261,7 +214,8 @@ MemCtrl::processRespondEvent() | |
| } | ||
|
|
||
| MemPacketQueue::iterator | ||
| MemCtrl::chooseNext(MemPacketQueue& queue, Tick extra_col_delay) | ||
| MemCtrl::chooseNext(MemPacketQueue& queue, Tick extra_col_delay, | ||
powerjg marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| MemInterface* mem_int) | ||
| { | ||
| // This method does the arbitration between requests. | ||
|
|
||
|
|
@@ -289,7 +243,7 @@ MemCtrl::chooseNext(MemPacketQueue& queue, Tick extra_col_delay) | |
| } | ||
| } | ||
| } else if (memSchedPolicy == enums::frfcfs) { | ||
| ret = chooseNextFRFCFS(queue, extra_col_delay); | ||
| ret = nextFRFCFS(queue, extra_col_delay); | ||
| } else { | ||
| panic("No scheduling policy chosen\n"); | ||
| } | ||
|
|
@@ -298,136 +252,48 @@ MemCtrl::chooseNext(MemPacketQueue& queue, Tick extra_col_delay) | |
| } | ||
|
|
||
| MemPacketQueue::iterator | ||
| MemCtrl::chooseNextFRFCFS(MemPacketQueue& queue, Tick extra_col_delay) | ||
| MemCtrl::nextFRFCFS(MemPacketQueue& queue, Tick extra_col_delay) | ||
| { | ||
|
|
||
| auto selected_pkt_it = queue.end(); | ||
| auto nvm_pkt_it = queue.end(); | ||
| Tick col_allowed_at = MaxTick; | ||
| Tick nvm_col_allowed_at = MaxTick; | ||
|
|
||
| // time we need to issue a column command to be seamless | ||
| const Tick min_col_at = std::max(nextBurstAt + extra_col_delay, curTick()); | ||
|
|
||
| assert (dram && nvm); | ||
|
|
||
| // find optimal packet for each interface | ||
| // Select packet by default to give priority if both | ||
| // can issue at the same time or seamlessly | ||
| std::tie(selected_pkt_it, col_allowed_at) = | ||
| dram->chooseNextFRFCFS(queue, min_col_at); | ||
| chooseNextFRFCFS(queue, extra_col_delay, dram); | ||
|
|
||
| std::tie(nvm_pkt_it, nvm_col_allowed_at) = | ||
| nvm->chooseNextFRFCFS(queue, min_col_at); | ||
| chooseNextFRFCFS(queue, extra_col_delay, nvm); | ||
|
|
||
|
|
||
| // Compare DRAM and NVM and select NVM if it can issue | ||
| // earlier than the DRAM packet | ||
| if (col_allowed_at > nvm_col_allowed_at) { | ||
| selected_pkt_it = nvm_pkt_it; | ||
| } | ||
|
|
||
| if (selected_pkt_it == queue.end()) { | ||
| DPRINTF(MemCtrl, "%s no available packets found\n", __func__); | ||
| } | ||
|
|
||
| return selected_pkt_it; | ||
| } | ||
|
|
||
| void | ||
| MemCtrl::accessAndRespond(PacketPtr pkt, Tick static_latency) | ||
| { | ||
| DPRINTF(MemCtrl, "Responding to Address %#x.. \n", pkt->getAddr()); | ||
|
|
||
| bool needsResponse = pkt->needsResponse(); | ||
| // do the actual memory access which also turns the packet into a | ||
| // response | ||
| if (dram && dram->getAddrRange().contains(pkt->getAddr())) { | ||
| dram->access(pkt); | ||
| } else if (nvm && nvm->getAddrRange().contains(pkt->getAddr())) { | ||
| nvm->access(pkt); | ||
| } else { | ||
| panic("Can't handle address range for packet %s\n", | ||
| pkt->print()); | ||
| } | ||
|
|
||
| // turn packet around to go back to requestor if response expected | ||
| if (needsResponse) { | ||
| // access already turned the packet into a response | ||
| assert(pkt->isResponse()); | ||
| // response_time consumes the static latency and is charged also | ||
| // with headerDelay that takes into account the delay provided by | ||
| // the xbar and also the payloadDelay that takes into account the | ||
| // number of data beats. | ||
| Tick response_time = curTick() + static_latency + pkt->headerDelay + | ||
| pkt->payloadDelay; | ||
| // Here we reset the timing of the packet before sending it out. | ||
| pkt->headerDelay = pkt->payloadDelay = 0; | ||
|
|
||
| // queue the packet in the response queue to be sent out after | ||
| // the static latency has passed | ||
| port.schedTimingResp(pkt, response_time); | ||
| } else { | ||
| // @todo the packet is going to be deleted, and the MemPacket | ||
| // is still having a pointer to it | ||
| pendingDelete.reset(pkt); | ||
| } | ||
|
|
||
| DPRINTF(MemCtrl, "Done\n"); | ||
|
|
||
| return; | ||
| } | ||
|
|
||
| void | ||
| MemCtrl::doBurstAccess(MemPacket* mem_pkt) | ||
| Tick | ||
| MemCtrl::doBurstAccess(MemPacket* mem_pkt, MemInterface* mem_int) | ||
| { | ||
| // first clean up the burstTick set, removing old entries | ||
| // before adding new entries for next burst | ||
| pruneBurstTick(); | ||
|
|
||
| // When was command issued? | ||
| Tick cmd_at; | ||
| Tick cmd_at = SimpleMemCtrl::doBurstAccess(mem_pkt, mem_int); | ||
|
|
||
| std::vector<MemPacketQueue>& queue = selQueue(mem_pkt->isRead()); | ||
|
|
||
| // Issue the next burst and update bus state to reflect | ||
| // when previous command was issued | ||
| if (mem_pkt->isDram()) { | ||
| std::tie(cmd_at, nextBurstAt) = | ||
| dram->doBurstAccess(mem_pkt, nextBurstAt, queue); | ||
|
|
||
| // Update timing for NVM ranks if NVM is configured on this channel | ||
| nvm->addRankToRankDelay(cmd_at); | ||
|
|
||
| } else { | ||
| std::tie(cmd_at, nextBurstAt) = | ||
| nvm->doBurstAccess(mem_pkt, nextBurstAt, queue); | ||
|
|
||
| // Update timing for NVM ranks if NVM is configured on this channel | ||
| dram->addRankToRankDelay(cmd_at); | ||
|
|
||
| } | ||
|
|
||
| DPRINTF(MemCtrl, "Access to %#x, ready at %lld next burst at %lld.\n", | ||
| mem_pkt->addr, mem_pkt->readyTime, nextBurstAt); | ||
|
|
||
| // Update the minimum timing between the requests, this is a | ||
| // conservative estimate of when we have to schedule the next | ||
| // request to not introduce any unecessary bubbles. In most cases | ||
| // we will wake up sooner than we have to. | ||
| nextReqTime = nextBurstAt - dram->commandOffset(); | ||
|
|
||
|
|
||
| // Update the common bus stats | ||
| if (mem_pkt->isRead()) { | ||
| ++readsThisTime; | ||
| // Update latency stats | ||
| stats.requestorReadTotalLat[mem_pkt->requestorId()] += | ||
| mem_pkt->readyTime - mem_pkt->entryTime; | ||
| stats.requestorReadBytes[mem_pkt->requestorId()] += mem_pkt->size; | ||
| } else { | ||
| ++writesThisTime; | ||
| stats.requestorWriteBytes[mem_pkt->requestorId()] += mem_pkt->size; | ||
| stats.requestorWriteTotalLat[mem_pkt->requestorId()] += | ||
| mem_pkt->readyTime - mem_pkt->entryTime; | ||
| } | ||
| return cmd_at; | ||
| } | ||
|
|
||
| void | ||
|
|
@@ -550,7 +416,8 @@ MemCtrl::processNextReqEvent() | |
| // If we are changing command type, incorporate the minimum | ||
| // bus turnaround delay which will be rank to rank delay | ||
| to_read = chooseNext((*queue), switched_cmd_type ? | ||
| minWriteToReadDataGap() : 0); | ||
| minWriteToReadDataGap() : 0, | ||
| dram); | ||
powerjg marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| if (to_read != queue->end()) { | ||
| // candidate read found | ||
|
|
@@ -570,8 +437,15 @@ MemCtrl::processNextReqEvent() | |
| } | ||
|
|
||
| auto mem_pkt = *to_read; | ||
| Tick cmd_at; | ||
| if (mem_pkt->isDram()) { | ||
| cmd_at = doBurstAccess(mem_pkt, dram); | ||
| } else { | ||
| cmd_at = doBurstAccess(mem_pkt, nvm); | ||
| } | ||
|
|
||
| doBurstAccess(mem_pkt); | ||
| DPRINTF(MemCtrl, | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. New DPRINTF? |
||
| "Command for %#x, issued at %lld.\n", mem_pkt->addr, cmd_at); | ||
|
|
||
| // sanity check | ||
| assert(mem_pkt->size <= (mem_pkt->isDram() ? | ||
|
|
@@ -635,7 +509,8 @@ MemCtrl::processNextReqEvent() | |
| // If we are changing command type, incorporate the minimum | ||
| // bus turnaround delay | ||
| to_write = chooseNext((*queue), | ||
| switched_cmd_type ? minReadToWriteDataGap() : 0); | ||
| switched_cmd_type ? minReadToWriteDataGap() : 0, | ||
| dram); | ||
powerjg marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| if (to_write != queue->end()) { | ||
| write_found = true; | ||
|
|
@@ -659,8 +534,15 @@ MemCtrl::processNextReqEvent() | |
| assert(mem_pkt->size <= (mem_pkt->isDram() ? | ||
| dram->bytesPerBurst() : | ||
| nvm->bytesPerBurst())); | ||
| Tick cmd_at; | ||
| if (mem_pkt->isDram()) { | ||
| cmd_at = doBurstAccess(mem_pkt, dram); | ||
| } else { | ||
| cmd_at = doBurstAccess(mem_pkt, nvm); | ||
| } | ||
|
|
||
| doBurstAccess(mem_pkt); | ||
| DPRINTF(MemCtrl, | ||
| "Command for %#x, issued at %lld.\n", mem_pkt->addr, cmd_at); | ||
|
|
||
| isInWriteQueue.erase(burstAlign(mem_pkt->addr, | ||
| mem_pkt->isDram() ? dram : nvm)); | ||
|
|
@@ -732,16 +614,17 @@ MemCtrl::minWriteToReadDataGap() | |
| void | ||
| MemCtrl::recvFunctional(PacketPtr pkt) | ||
| { | ||
| if (dram->getAddrRange().contains(pkt->getAddr())) { | ||
| // rely on the abstract memory | ||
| dram->functionalAccess(pkt); | ||
| } else if (nvm->getAddrRange().contains(pkt->getAddr())) { | ||
| // rely on the abstract memory | ||
| nvm->functionalAccess(pkt); | ||
| } else { | ||
| panic("Can't handle address range for packet %s\n", | ||
| pkt->print()); | ||
| } | ||
| bool found; | ||
|
|
||
| found = SimpleMemCtrl::recvFunctionalLogic(pkt, dram); | ||
|
|
||
| if (!found) { | ||
| found = SimpleMemCtrl::recvFunctionalLogic(pkt, nvm); | ||
| } | ||
|
|
||
| if (!found) { | ||
| panic("Can't handle address range for packet %s\n", pkt->print()); | ||
| } | ||
| } | ||
|
|
||
| bool | ||
|
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.