changeset a8d64545cda6 in /z/repo/m5
details: http://repo.m5sim.org/m5?cmd=changeset;node=a8d64545cda6
description:
This patch supports cache flushing in MOESI_hammer
diffstat:
configs/example/ruby_random_test.py | 9 +-
src/cpu/testers/rubytest/Check.cc | 35 +++
src/cpu/testers/rubytest/Check.hh | 1 +
src/cpu/testers/rubytest/RubyTester.cc | 3 +-
src/cpu/testers/rubytest/RubyTester.hh | 2 +
src/cpu/testers/rubytest/RubyTester.py | 1 +
src/mem/packet.cc | 4 +-
src/mem/packet.hh | 4 +
src/mem/protocol/MOESI_hammer-cache.sm | 312 +++++++++++++++++++++++++++++++-
src/mem/protocol/MOESI_hammer-dir.sm | 135 +++++++++++++-
src/mem/protocol/MOESI_hammer-msg.sm | 3 +
src/mem/protocol/RubySlicc_Exports.sm | 1 +
src/mem/ruby/system/RubyPort.cc | 14 +-
src/mem/ruby/system/Sequencer.cc | 12 +-
14 files changed, 508 insertions(+), 28 deletions(-)
diffs (truncated from 1084 to 300 lines):
diff -r 1333bd6cc2eb -r a8d64545cda6 configs/example/ruby_random_test.py
--- a/configs/example/ruby_random_test.py Mon Mar 28 10:49:36 2011 -0500
+++ b/configs/example/ruby_random_test.py Mon Mar 28 10:49:45 2011 -0500
@@ -82,7 +82,14 @@
#
# Create the ruby random tester
#
-tester = RubyTester(checks_to_complete = options.checks,
+
+# Check the protocol
+check_flush = False
+if buildEnv['PROTOCOL'] == 'MOESI_hammer':
+ check_flush = True
+
+tester = RubyTester(check_flush = check_flush,
+ checks_to_complete = options.checks,
wakeup_frequency = options.wakeup_freq)
#
diff -r 1333bd6cc2eb -r a8d64545cda6 src/cpu/testers/rubytest/Check.cc
--- a/src/cpu/testers/rubytest/Check.cc Mon Mar 28 10:49:36 2011 -0500
+++ b/src/cpu/testers/rubytest/Check.cc Mon Mar 28 10:49:45 2011 -0500
@@ -59,6 +59,10 @@
initiatePrefetch(); // Prefetch from random processor
}
+ if (m_tester_ptr->getCheckFlush() && (random() & 0xff) == 0) {
+ initiateFlush(); // issue a Flush request from random processor
+ }
+
if (m_status == TesterStatus_Idle) {
initiateAction();
} else if (m_status == TesterStatus_Ready) {
@@ -124,6 +128,37 @@
}
void
+Check::initiateFlush()
+{
+
+ DPRINTF(RubyTest, "initiating Flush\n");
+
+ int index = random() % m_num_cpu_sequencers;
+ RubyTester::CpuPort* port =
+ safe_cast<RubyTester::CpuPort*>(m_tester_ptr->getCpuPort(index));
+
+ Request::Flags flags;
+
+ Request *req = new Request(m_address.getAddress(), CHECK_SIZE, flags,
curTick(),
+ m_pc.getAddress());
+
+ Packet::Command cmd;
+
+ cmd = MemCmd::FlushReq;
+
+ PacketPtr pkt = new Packet(req, cmd, port->idx);
+
+ // push the subblock onto the sender state. The sequencer will
+ // update the subblock on the return
+ pkt->senderState =
+ new SenderState(m_address, req->getSize(), pkt->senderState);
+
+ if (port->sendTiming(pkt)) {
+ DPRINTF(RubyTest, "initiating Flush - successful\n");
+ }
+}
+
+void
Check::initiateAction()
{
DPRINTF(RubyTest, "initiating Action\n");
diff -r 1333bd6cc2eb -r a8d64545cda6 src/cpu/testers/rubytest/Check.hh
--- a/src/cpu/testers/rubytest/Check.hh Mon Mar 28 10:49:36 2011 -0500
+++ b/src/cpu/testers/rubytest/Check.hh Mon Mar 28 10:49:45 2011 -0500
@@ -58,6 +58,7 @@
void print(std::ostream& out) const;
private:
+ void initiateFlush();
void initiatePrefetch();
void initiateAction();
void initiateCheck();
diff -r 1333bd6cc2eb -r a8d64545cda6 src/cpu/testers/rubytest/RubyTester.cc
--- a/src/cpu/testers/rubytest/RubyTester.cc Mon Mar 28 10:49:36 2011 -0500
+++ b/src/cpu/testers/rubytest/RubyTester.cc Mon Mar 28 10:49:45 2011 -0500
@@ -40,7 +40,8 @@
: MemObject(p), checkStartEvent(this),
m_checks_to_complete(p->checks_to_complete),
m_deadlock_threshold(p->deadlock_threshold),
- m_wakeup_frequency(p->wakeup_frequency)
+ m_wakeup_frequency(p->wakeup_frequency),
+ m_check_flush(p->check_flush)
{
m_checks_completed = 0;
diff -r 1333bd6cc2eb -r a8d64545cda6 src/cpu/testers/rubytest/RubyTester.hh
--- a/src/cpu/testers/rubytest/RubyTester.hh Mon Mar 28 10:49:36 2011 -0500
+++ b/src/cpu/testers/rubytest/RubyTester.hh Mon Mar 28 10:49:45 2011 -0500
@@ -99,6 +99,7 @@
void printConfig(std::ostream& out) const {}
void print(std::ostream& out) const;
+ bool getCheckFlush() { return m_check_flush; }
protected:
class CheckStartEvent : public Event
@@ -134,6 +135,7 @@
int m_deadlock_threshold;
int m_num_cpu_sequencers;
int m_wakeup_frequency;
+ bool m_check_flush;
};
inline std::ostream&
diff -r 1333bd6cc2eb -r a8d64545cda6 src/cpu/testers/rubytest/RubyTester.py
--- a/src/cpu/testers/rubytest/RubyTester.py Mon Mar 28 10:49:36 2011 -0500
+++ b/src/cpu/testers/rubytest/RubyTester.py Mon Mar 28 10:49:45 2011 -0500
@@ -36,3 +36,4 @@
checks_to_complete = Param.Int(100, "checks to complete")
deadlock_threshold = Param.Int(50000, "how often to check for deadlock")
wakeup_frequency = Param.Int(10, "number of cycles between wakeups")
+ check_flush = Param.Bool(False, "check cache flushing")
diff -r 1333bd6cc2eb -r a8d64545cda6 src/mem/packet.cc
--- a/src/mem/packet.cc Mon Mar 28 10:49:36 2011 -0500
+++ b/src/mem/packet.cc Mon Mar 28 10:49:45 2011 -0500
@@ -148,7 +148,9 @@
/* BadAddressError -- memory address invalid */
{ SET2(IsResponse, IsError), InvalidCmd, "BadAddressError" },
/* PrintReq */
- { SET2(IsRequest, IsPrint), InvalidCmd, "PrintReq" }
+ { SET2(IsRequest, IsPrint), InvalidCmd, "PrintReq" },
+ /* Flush Request */
+ { SET3(IsRequest, IsFlush, NeedsExclusive), InvalidCmd, "FlushReq" }
};
bool
diff -r 1333bd6cc2eb -r a8d64545cda6 src/mem/packet.hh
--- a/src/mem/packet.hh Mon Mar 28 10:49:36 2011 -0500
+++ b/src/mem/packet.hh Mon Mar 28 10:49:45 2011 -0500
@@ -105,6 +105,7 @@
BadAddressError, // memory address invalid
// Fake simulator-only commands
PrintReq, // Print state matching address
+ FlushReq, //request for a cache flush
NUM_MEM_CMDS
};
@@ -129,6 +130,7 @@
HasData, //!< There is an associated payload
IsError, //!< Error response
IsPrint, //!< Print state matching address (for debugging)
+ IsFlush, //!< Flush the address from caches
NUM_COMMAND_ATTRIBUTES
};
@@ -175,6 +177,7 @@
bool isLLSC() const { return testCmdAttrib(IsLlsc); }
bool isError() const { return testCmdAttrib(IsError); }
bool isPrint() const { return testCmdAttrib(IsPrint); }
+ bool isFlush() const { return testCmdAttrib(IsFlush); }
const Command
responseCommand() const
@@ -411,6 +414,7 @@
bool isLLSC() const { return cmd.isLLSC(); }
bool isError() const { return cmd.isError(); }
bool isPrint() const { return cmd.isPrint(); }
+ bool isFlush() const { return cmd.isFlush(); }
// Snoop flags
void assertMemInhibit() { flags.set(MEM_INHIBIT); }
diff -r 1333bd6cc2eb -r a8d64545cda6 src/mem/protocol/MOESI_hammer-cache.sm
--- a/src/mem/protocol/MOESI_hammer-cache.sm Mon Mar 28 10:49:36 2011 -0500
+++ b/src/mem/protocol/MOESI_hammer-cache.sm Mon Mar 28 10:49:45 2011 -0500
@@ -78,7 +78,16 @@
ST, AccessPermission:Busy, "ST", desc="S block transferring to L1";
OT, AccessPermission:Busy, "OT", desc="O block transferring to L1";
MT, AccessPermission:Busy, "MT", desc="M block transferring to L1";
- MMT, AccessPermission:Busy, "MMT", desc="MM block transferring to L1";
+ MMT, AccessPermission:Busy, "MMT", desc="MM block transferring to L0";
+
+ //Transition States Related to Flushing
+ MI_F, AccessPermission:Busy, "MI_F", desc="Issued PutX due to a Flush,
waiting for ack";
+ MM_F, AccessPermission:Busy, "MM_F", desc="Issued GETF due to a Flush,
waiting for ack";
+ IM_F, AccessPermission:Busy, "IM_F", desc="Issued GetX due to a Flush";
+ ISM_F, AccessPermission:Read_Only, "ISM_F", desc="Issued GetX, received
data, waiting for all acks";
+ SM_F, AccessPermission:Read_Only, "SM_F", desc="Issued GetX, we still have
an old copy of the line";
+ OM_F, AccessPermission:Read_Only, "OM_F", desc="Issued GetX, received
data";
+ MM_WF, AccessPermission:Busy, "MM_WF", desc="Issued GetX, received
exclusive data";
}
// EVENTS
@@ -113,6 +122,10 @@
// Triggers
All_acks, desc="Received all required data and message
acks";
All_acks_no_sharers, desc="Received all acks and no other processor
has a shared copy";
+
+ // For Flush
+ Flush_line, desc="flush the cache line from all caches";
+ Block_Ack, desc="the directory is blocked and ready for
the flush";
}
// TYPES
@@ -221,6 +234,8 @@
return Event:Ifetch;
} else if ((type == RubyRequestType:ST) || (type ==
RubyRequestType:ATOMIC)) {
return Event:Store;
+ } else if ((type == RubyRequestType:FLUSH)) {
+ return Event:Flush_line;
} else {
error("Invalid RubyRequestType");
}
@@ -318,7 +333,7 @@
Entry cache_entry := getCacheEntry(in_msg.Address);
TBE tbe := TBEs[in_msg.Address];
- if (in_msg.Type == CoherenceRequestType:GETX) {
+ if ((in_msg.Type == CoherenceRequestType:GETX) || (in_msg.Type ==
CoherenceRequestType:GETF)) {
trigger(Event:Other_GETX, in_msg.Address, cache_entry, tbe);
} else if (in_msg.Type == CoherenceRequestType:MERGED_GETS) {
trigger(Event:Merged_GETS, in_msg.Address, cache_entry, tbe);
@@ -342,6 +357,8 @@
trigger(Event:Writeback_Ack, in_msg.Address, cache_entry, tbe);
} else if (in_msg.Type == CoherenceRequestType:WB_NACK) {
trigger(Event:Writeback_Nack, in_msg.Address, cache_entry, tbe);
+ } else if (in_msg.Type == CoherenceRequestType:BLOCK_ACK) {
+ trigger(Event:Block_Ack, in_msg.Address, cache_entry, tbe);
} else {
error("Unexpected message");
}
@@ -504,6 +521,19 @@
}
}
+ action(bf_issueGETF, "bf", desc="Issue GETF") {
+ enqueue(requestNetwork_out, RequestMsg, latency=issue_latency) {
+ assert(is_valid(tbe));
+ out_msg.Address := address;
+ out_msg.Type := CoherenceRequestType:GETF;
+ out_msg.Requestor := machineID;
+ out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.MessageSize := MessageSizeType:Request_Control;
+ out_msg.InitialRequestTime := get_time();
+ tbe.NumPendingMsgs := machineCount(MachineType:L1Cache); // One from
each other cache (n-1) plus the memory (+1)
+ }
+ }
+
action(c_sendExclusiveData, "c", desc="Send exclusive data from cache to
requestor") {
peek(forwardToCache_in, RequestMsg) {
enqueue(responseNetwork_out, ResponseMsg,
latency=cache_response_latency) {
@@ -527,6 +557,29 @@
}
}
+ action(ct_sendExclusiveDataFromTBE, "ct", desc="Send exclusive data from tbe
to requestor") {
+ peek(forwardToCache_in, RequestMsg) {
+ enqueue(responseNetwork_out, ResponseMsg,
latency=cache_response_latency) {
+ assert(is_valid(tbe));
+ out_msg.Address := address;
+ out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
+ out_msg.Sender := machineID;
+ out_msg.Destination.add(in_msg.Requestor);
+ out_msg.DataBlk := tbe.DataBlk;
+ out_msg.Dirty := tbe.Dirty;
+ if (in_msg.DirectedProbe) {
+ out_msg.Acks := machineCount(MachineType:L1Cache);
+ } else {
+ out_msg.Acks := 2;
+ }
+ out_msg.SilentAcks := in_msg.SilentAcks;
+ out_msg.MessageSize := MessageSizeType:Response_Data;
+ out_msg.InitialRequestTime := in_msg.InitialRequestTime;
+ out_msg.ForwardRequestTime := in_msg.ForwardRequestTime;
+ }
+ }
+ }
+
action(d_issuePUT, "d", desc="Issue PUT") {
enqueue(requestNetwork_out, RequestMsg, latency=issue_latency) {
out_msg.Address := address;
@@ -537,6 +590,16 @@
}
}
+ action(df_issuePUTF, "df", desc="Issue PUTF") {
+ enqueue(requestNetwork_out, RequestMsg, latency=issue_latency) {
+ out_msg.Address := address;
+ out_msg.Type := CoherenceRequestType:PUTF;
+ out_msg.Requestor := machineID;
+ out_msg.Destination.add(map_Address_to_Directory(address));
+ out_msg.MessageSize := MessageSizeType:Writeback_Control;
+ }
+ }
+
action(e_sendData, "e", desc="Send data from cache to requestor") {
peek(forwardToCache_in, RequestMsg) {
enqueue(responseNetwork_out, ResponseMsg,
latency=cache_response_latency) {
@@ -583,7 +646,31 @@
}
}
_______________________________________________
m5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/m5-dev