mem: Create a separate class for the cache write buffer
Review Request #3346 - Created Feb. 24, 2016 and submitted
Information | |
---|---|
Andreas Hansson | |
gem5 | |
default | |
Reviewers | |
Default | |
Changeset 11369:5164e22ac2fb --------------------------- mem: Create a separate class for the cache write buffer This patch breaks out the cache write buffer into a separate class, without affecting any stats. The goal of the patch is to avoid encumbering the much-simpler write queue with the complex MSHR handling. In a follow on patch this simplification allows us to implement write combining. The WriteQueue gets its own class, but shares a common ancestor, the generic Queue, with the MSHRQueue.
Overall I think this specialization is good. I think the tuple return thing is very clunky though. It looks like getNextQueueEntry() is only called from getTimingPacket(), which in turn is only called from sendDeferredPacket(). Also a lot of getTimingPacket() is basically
if (mshr) {
// do a bunch of stuff
} else {
assert(wq_entry);
// do a bunch of other stuff
}So I think this whole call stack structure really only made sense because of the unification of the write buffer and MSHR objects, and now it no longer makes sense, and the tuple return values are a symptom of that.
I think if we're going to bother to do this specialization, we really need to refactor this piece of code avoid this pointless merging and forking of the MSHR vs write buffer code paths that leads to these tuple return values. In cases where the code paths are merged and we still want to do something different between the two cases, we should try and do that by defining appropriate virtual functions on QueueEntry, and perhaps (if necessary) creating a common base class for the Queue<> classes and defining some virtual functions on that.
Description: |
|
|||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Diff: |
Revision 2 (+1265 -558) |
Thanks for all the changes\\\! This is very close to what I was picturing, just one turn of the crank away (assuming you agree with the destination). All it would take would be to: \- Move the calls to checkConflictingSnoop() into sendMSHRQueuePacket()/sendWriteQueuePacket() \- Replace the returns in getNextQueueEntry() with calls to send*QueuePacket() Looking more closely I think I see why you didn't do this, which is that checkConflictingSnoop is a method on CacheReqPacketQueue which is maybe a pointer you don't have once you're in send*QueuePacket(). Can we get back to that structure via memSidePort, or if not, just pass it in as an argument through getNextQueueEntry() to send*QueuePacket()?
-
src/mem/cache/cache.cc (Diff revision 2) -
e.g., just change this line to
return sendMSHRQueuePacket(conflict_mshr);
-
src/mem/cache/cache.cc (Diff revision 2) -
similarly this would be
return sendWriteQueuePacket(write_mshr);
and so on for the remaining return statements...
-
src/mem/cache/cache.cc (Diff revision 2) -
I believe this would just be
return false;
-
src/mem/cache/cache.cc (Diff revision 2) -
this would become
waitingOnRetry = cache.sendNextPacket();
(or whatever else you may choose to rename getNextQueueEntry() once it incorporates the send*QueuePacket() methods)
or maybe based on the discussion at the end above, if we need to pass in the queue pointer for the checkConflictingSnoop() call, it would bewaitingonRetry = cache.sendNextPacket(this);
-
src/mem/cache/cache.cc (Diff revision 2) -
then this whole if/else if/else block goes away
Description: |
|
||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Diff: |
Revision 3 (+1303 -563) |
Thanks a bunch for all your patience and flexibility!!!