summaryrefslogtreecommitdiff
path: root/src/mem/protocol/MOESI_hammer-dir.sm
diff options
context:
space:
mode:
authorBrad Beckmann <Brad.Beckmann@amd.com>2009-11-18 16:34:31 -0800
committerBrad Beckmann <Brad.Beckmann@amd.com>2009-11-18 16:34:31 -0800
commitb0973035b4db86052c1d5d67e8695bdaa27130c2 (patch)
treecc6a6d38036c8584119f2ffc0b1f506361df27d9 /src/mem/protocol/MOESI_hammer-dir.sm
parent2783a7b9ad90d04d74418d7463c255c29ffd8046 (diff)
downloadgem5-b0973035b4db86052c1d5d67e8695bdaa27130c2.tar.xz
ruby: added the original hammer protocols from old ruby
Diffstat (limited to 'src/mem/protocol/MOESI_hammer-dir.sm')
-rw-r--r--src/mem/protocol/MOESI_hammer-dir.sm317
1 files changed, 317 insertions, 0 deletions
diff --git a/src/mem/protocol/MOESI_hammer-dir.sm b/src/mem/protocol/MOESI_hammer-dir.sm
new file mode 100644
index 000000000..836fa9787
--- /dev/null
+++ b/src/mem/protocol/MOESI_hammer-dir.sm
@@ -0,0 +1,317 @@
+/*
+ * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+machine(Directory, "AMD Hammer-like protocol") {
+
+ // STATES
+ enumeration(State, desc="Directory states", default="Directory_State_E") {
+ // Base states
+ NO, desc="Not Owner";
+ O, desc="Owner";
+ E, desc="Exclusive Owner (we can provide the data in exclusive)";
+ NO_B, "NO^B", desc="Not Owner, Blocked";
+ O_B, "O^B", desc="Owner, Blocked";
+ WB, desc="Blocked on a writeback";
+ }
+
+ // Events
+ enumeration(Event, desc="Directory events") {
+ GETX, desc="A GETX arrives";
+ GETS, desc="A GETS arrives";
+ PUT, desc="A PUT arrives";
+ Unblock, desc="An unblock message arrives";
+ Writeback_Clean, desc="The final part of a PutX (no data)";
+ Writeback_Dirty, desc="The final part of a PutX (data)";
+ Writeback_Exclusive_Clean, desc="The final part of a PutX (no data, exclusive)";
+ Writeback_Exclusive_Dirty, desc="The final part of a PutX (data, exclusive)";
+ }
+
+ // TYPES
+
+ // DirectoryEntry
+ structure(Entry, desc="...") {
+ State DirectoryState, desc="Directory state";
+ DataBlock DataBlk, desc="data for the block";
+ }
+
+ external_type(DirectoryMemory) {
+ Entry lookup(Address);
+ bool isPresent(Address);
+ }
+
+ // ** OBJECTS **
+
+ DirectoryMemory directory;
+
+ State getState(Address addr) {
+ return directory[addr].DirectoryState;
+ }
+
+ void setState(Address addr, State state) {
+ directory[addr].DirectoryState := state;
+ }
+
+ // ** OUT_PORTS **
+ out_port(forwardNetwork_out, RequestMsg, forwardFromDir);
+ out_port(responseNetwork_out, ResponseMsg, responseFromDir);
+ out_port(requestQueue_out, ResponseMsg, requestToDir); // For recycling requests
+
+ // ** IN_PORTS **
+
+ in_port(unblockNetwork_in, ResponseMsg, unblockToDir) {
+ if (unblockNetwork_in.isReady()) {
+ peek(unblockNetwork_in, ResponseMsg) {
+ if (in_msg.Type == CoherenceResponseType:UNBLOCK) {
+ trigger(Event:Unblock, in_msg.Address);
+ } else if (in_msg.Type == CoherenceResponseType:WB_CLEAN) {
+ trigger(Event:Writeback_Clean, in_msg.Address);
+ } else if (in_msg.Type == CoherenceResponseType:WB_DIRTY) {
+ trigger(Event:Writeback_Dirty, in_msg.Address);
+ } else if (in_msg.Type == CoherenceResponseType:WB_EXCLUSIVE_CLEAN) {
+ trigger(Event:Writeback_Exclusive_Clean, in_msg.Address);
+ } else if (in_msg.Type == CoherenceResponseType:WB_EXCLUSIVE_DIRTY) {
+ trigger(Event:Writeback_Exclusive_Dirty, in_msg.Address);
+ } else {
+ error("Invalid message");
+ }
+ }
+ }
+ }
+
+ in_port(requestQueue_in, RequestMsg, requestToDir) {
+ if (requestQueue_in.isReady()) {
+ peek(requestQueue_in, RequestMsg) {
+ if (in_msg.Type == CoherenceRequestType:GETS) {
+ trigger(Event:GETS, in_msg.Address);
+ } else if (in_msg.Type == CoherenceRequestType:GETX) {
+ trigger(Event:GETX, in_msg.Address);
+ } else if (in_msg.Type == CoherenceRequestType:PUT) {
+ trigger(Event:PUT, in_msg.Address);
+ } else {
+ error("Invalid message");
+ }
+ }
+ }
+ }
+
+ // Actions
+
+ action(a_sendWriteBackAck, "a", desc="Send writeback ack to requestor") {
+ peek(requestQueue_in, RequestMsg) {
+ enqueue(forwardNetwork_out, RequestMsg, latency="DIRECTORY_LATENCY") {
+ out_msg.Address := address;
+ out_msg.Type := CoherenceRequestType:WB_ACK;
+ out_msg.Requestor := in_msg.Requestor;
+ out_msg.Destination.add(in_msg.Requestor);
+ out_msg.MessageSize := MessageSizeType:Writeback_Control;
+ }
+ }
+ }
+
+ action(b_sendWriteBackNack, "b", desc="Send writeback nack to requestor") {
+ peek(requestQueue_in, RequestMsg) {
+ enqueue(forwardNetwork_out, RequestMsg, latency="DIRECTORY_LATENCY") {
+ out_msg.Address := address;
+ out_msg.Type := CoherenceRequestType:WB_NACK;
+ out_msg.Requestor := in_msg.Requestor;
+ out_msg.Destination.add(in_msg.Requestor);
+ out_msg.MessageSize := MessageSizeType:Writeback_Control;
+ }
+ }
+ }
+
+ action(d_sendData, "d", desc="Send data to requestor") {
+ peek(requestQueue_in, RequestMsg) {
+ enqueue(responseNetwork_out, ResponseMsg, latency="MEMORY_LATENCY") {
+ out_msg.Address := address;
+ out_msg.Type := CoherenceResponseType:DATA;
+ out_msg.Sender := id;
+ out_msg.Destination.add(in_msg.Requestor);
+ out_msg.DataBlk := directory[in_msg.Address].DataBlk;
+ out_msg.Dirty := false; // By definition, the block is now clean
+ out_msg.Acks := 1;
+ out_msg.MessageSize := MessageSizeType:Response_Data;
+ }
+ }
+ }
+
+ action(dd_sendExclusiveData, "\d", desc="Send exclusive data to requestor") {
+ peek(requestQueue_in, RequestMsg) {
+ enqueue(responseNetwork_out, ResponseMsg, latency="MEMORY_LATENCY") {
+ out_msg.Address := address;
+ out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE;
+ out_msg.Sender := id;
+ out_msg.Destination.add(in_msg.Requestor);
+ out_msg.DataBlk := directory[in_msg.Address].DataBlk;
+ out_msg.Dirty := false; // By definition, the block is now clean
+ out_msg.Acks := 1;
+ out_msg.MessageSize := MessageSizeType:Response_Data;
+ }
+ }
+ }
+
+ action(f_forwardRequest, "f", desc="Forward requests") {
+ if (numberOfNodes() > 1) {
+ peek(requestQueue_in, RequestMsg) {
+ enqueue(forwardNetwork_out, RequestMsg, latency="DIRECTORY_LATENCY") {
+ out_msg.Address := address;
+ out_msg.Type := in_msg.Type;
+ out_msg.Requestor := in_msg.Requestor;
+ out_msg.Destination.broadcast(); // Send to everyone, but...
+ out_msg.Destination.remove(in_msg.Requestor); // Don't include the original requestor
+ out_msg.MessageSize := MessageSizeType:Forwarded_Control;
+ }
+ }
+ }
+ }
+
+ action(i_popIncomingRequestQueue, "i", desc="Pop incoming request queue") {
+ requestQueue_in.dequeue();
+ }
+
+ action(j_popIncomingUnblockQueue, "j", desc="Pop incoming unblock queue") {
+ unblockNetwork_in.dequeue();
+ }
+
+ action(l_writeDataToMemory, "l", desc="Write PUTX/PUTO data to memory") {
+ peek(unblockNetwork_in, ResponseMsg) {
+ assert(in_msg.Dirty);
+ assert(in_msg.MessageSize == MessageSizeType:Writeback_Data);
+ directory[in_msg.Address].DataBlk := in_msg.DataBlk;
+ DEBUG_EXPR(in_msg.Address);
+ DEBUG_EXPR(in_msg.DataBlk);
+ }
+ }
+
+ action(ll_checkIncomingWriteback, "\l", desc="Check PUTX/PUTO response message") {
+ peek(unblockNetwork_in, ResponseMsg) {
+ assert(in_msg.Dirty == false);
+ assert(in_msg.MessageSize == MessageSizeType:Writeback_Control);
+
+ // NOTE: The following check would not be valid in a real
+ // implementation. We include the data in the "dataless"
+ // message so we can assert the clean data matches the datablock
+ // in memory
+ assert(directory[in_msg.Address].DataBlk == in_msg.DataBlk);
+ }
+ }
+
+ // action(z_stall, "z", desc="Cannot be handled right now.") {
+ // Special name recognized as do nothing case
+ // }
+
+ action(zz_recycleRequest, "\z", desc="Recycle the request queue") {
+ requestQueue_in.recycle();
+ }
+
+ // TRANSITIONS
+
+ transition(E, GETX, NO_B) {
+ dd_sendExclusiveData;
+ f_forwardRequest;
+ i_popIncomingRequestQueue;
+ }
+
+ transition(E, GETS, NO_B) {
+ dd_sendExclusiveData;
+ f_forwardRequest;
+ i_popIncomingRequestQueue;
+ }
+
+ //
+ transition(O, GETX, NO_B) {
+ d_sendData;
+ f_forwardRequest;
+ i_popIncomingRequestQueue;
+ }
+
+ transition(O, GETS, O_B) {
+ d_sendData;
+ f_forwardRequest;
+ i_popIncomingRequestQueue;
+ }
+
+ //
+ transition(NO, GETX, NO_B) {
+ f_forwardRequest;
+ i_popIncomingRequestQueue;
+ }
+
+ transition(NO, GETS, NO_B) {
+ f_forwardRequest;
+ i_popIncomingRequestQueue;
+ }
+
+ transition(NO, PUT, WB) {
+ a_sendWriteBackAck;
+ i_popIncomingRequestQueue;
+ }
+
+ transition({O, E}, PUT) {
+ b_sendWriteBackNack;
+ i_popIncomingRequestQueue;
+ }
+
+ // Blocked states
+ transition({NO_B, O_B, WB}, {GETS, GETX, PUT}) {
+ zz_recycleRequest;
+ }
+
+ transition(NO_B, Unblock, NO) {
+ j_popIncomingUnblockQueue;
+ }
+
+ transition(O_B, Unblock, O) {
+ j_popIncomingUnblockQueue;
+ }
+
+ // WB
+ transition(WB, Writeback_Dirty, O) {
+ l_writeDataToMemory;
+ j_popIncomingUnblockQueue;
+ }
+
+ transition(WB, Writeback_Exclusive_Dirty, E) {
+ l_writeDataToMemory;
+ j_popIncomingUnblockQueue;
+ }
+
+ transition(WB, Writeback_Clean, O) {
+ ll_checkIncomingWriteback;
+ j_popIncomingUnblockQueue;
+ }
+
+ transition(WB, Writeback_Exclusive_Clean, E) {
+ ll_checkIncomingWriteback;
+ j_popIncomingUnblockQueue;
+ }
+
+ transition(WB, Unblock, NO) {
+ j_popIncomingUnblockQueue;
+ }
+}