* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+/*
+ * $Id: std-includes.hh,v 3.7 2003/02/24 21:05:24 xu Exp $
+ */
+
 #ifndef INCLUDES_H
 #define INCLUDES_H
 
 
  * $Id$
  */
 
-#include <cassert>
-
+#include "assert.hh"
 #include "mem/gems_common/util.hh"
 
 // Split a string into a head and tail strings on the specified
   string head = "";
   string tail = "";
 
-  unsigned counter = 0;
+  uint counter = 0;
   while(counter < str.size()) {
     if (str[counter] == split_character) {
       counter++;
   return ret;
 }
 
+bool string_to_bool(const string & str)
+{
+  string lower(str);
+  for (size_t i=0;i<str.length();i++)
+    lower[i] = tolower(str[i]);
+  if (lower == "true")
+    return true;
+  else if (lower == "false")
+    return false;
+  else
+    assert(0);
+}
+
 // Log functions
 int log_int(long long n)
 {
 
 string bool_to_string(bool value);
 string int_to_string(int n, bool zero_fill = false, int width = 0);
 float string_to_float(string& str);
+bool string_to_bool(const string & str);
 int log_int(long long n);
 bool is_power_of_2(long long n);
 
 
  */
 
 
-machine(L1Cache, "MSI Directory L1 Cache CMP") {
+machine(L1Cache, "MSI Directory L1 Cache CMP") : LATENCY_L1_REQUEST_LATENCY LATENCY_L1_RESPONSE_LATENCY LATENCY_TO_L2_LATENCY {
 
   // NODE L1 CACHE
   // From this node's L1 cache TO the network
 
   TBETable L1_TBEs, template_hack="<L1Cache_TBE>";
 
-  CacheMemory L1IcacheMemory, template_hack="<L1Cache_Entry>", constructor_hack='L1_CACHE_NUM_SETS_BITS,L1_CACHE_ASSOC,MachineType_L1Cache,int_to_string(i)+"_L1I"', abstract_chip_ptr="true";
-  CacheMemory L1DcacheMemory, template_hack="<L1Cache_Entry>", constructor_hack='L1_CACHE_NUM_SETS_BITS,L1_CACHE_ASSOC,MachineType_L1Cache,int_to_string(i)+"_L1D"', abstract_chip_ptr="true";
+//  CacheMemory L1IcacheMemory, template_hack="<L1Cache_Entry>", constructor_hack='L1_CACHE_NUM_SETS_BITS,L1_CACHE_ASSOC,MachineType_L1Cache,int_to_string(i)+"_L1I"', abstract_chip_ptr="true";
+//  CacheMemory L1DcacheMemory, template_hack="<L1Cache_Entry>", constructor_hack='L1_CACHE_NUM_SETS_BITS,L1_CACHE_ASSOC,MachineType_L1Cache,int_to_string(i)+"_L1D"', abstract_chip_ptr="true";
 
-  MessageBuffer mandatoryQueue, ordered="false", rank="100", abstract_chip_ptr="true";
+  CacheMemory L1IcacheMemory, factory='RubySystem::getCache(m_cfg["L1Icache"])';
+
+  CacheMemory L1DcacheMemory, factory='RubySystem::getCache(m_cfg["L1Dcache"])';
+
+
+//  MessageBuffer mandatoryQueue, ordered="false", rank="100", abstract_chip_ptr="true";
+
+//  Sequencer sequencer, abstract_chip_ptr="true", constructor_hack="i";
+
+  MessageBuffer mandatoryQueue, ordered="false";
+  Sequencer sequencer, factory='RubySystem::getSequencer(m_cfg["sequencer"])';
 
-  Sequencer sequencer, abstract_chip_ptr="true", constructor_hack="i";
 
   int cache_state_to_int(State state);
 
           // ** INSTRUCTION ACCESS ***
 
           // Check to see if it is in the OTHER L1
-          if (L1DcacheMemory.isTagPresent(in_msg.Address)) {
+          if (L1DcacheMemory.isTagPresent(in_msg.LineAddress)) {
             // The block is in the wrong L1, put the request on the queue to the shared L2
-            trigger(Event:L1_Replacement, in_msg.Address);
+            trigger(Event:L1_Replacement, in_msg.LineAddress);
           }
-          if (L1IcacheMemory.isTagPresent(in_msg.Address)) {
+          if (L1IcacheMemory.isTagPresent(in_msg.LineAddress)) {
             // The tag matches for the L1, so the L1 asks the L2 for it.
-            trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.Address);
+            trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress);
           } else {
-            if (L1IcacheMemory.cacheAvail(in_msg.Address)) {
+            if (L1IcacheMemory.cacheAvail(in_msg.LineAddress)) {
               // L1 does't have the line, but we have space for it in the L1 so let's see if the L2 has it
-              trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.Address);
+              trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress);
             } else {
               // No room in the L1, so we need to make room in the L1
-              trigger(Event:L1_Replacement, L1IcacheMemory.cacheProbe(in_msg.Address));
+              trigger(Event:L1_Replacement, L1IcacheMemory.cacheProbe(in_msg.LineAddress));
             }
           }
         } else {
           // *** DATA ACCESS ***
 
           // Check to see if it is in the OTHER L1
-          if (L1IcacheMemory.isTagPresent(in_msg.Address)) {
+          if (L1IcacheMemory.isTagPresent(in_msg.LineAddress)) {
             // The block is in the wrong L1, put the request on the queue to the shared L2
-            trigger(Event:L1_Replacement, in_msg.Address);
+            trigger(Event:L1_Replacement, in_msg.LineAddress);
           }
-          if (L1DcacheMemory.isTagPresent(in_msg.Address)) {
+          if (L1DcacheMemory.isTagPresent(in_msg.LineAddress)) {
             // The tag matches for the L1, so the L1 ask the L2 for it
-            trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.Address);
+            trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress);
           } else {
-            if (L1DcacheMemory.cacheAvail(in_msg.Address)) {
+            if (L1DcacheMemory.cacheAvail(in_msg.LineAddress)) {
               // L1 does't have the line, but we have space for it in the L1 let's see if the L2 has it
-              trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.Address);
+              trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress);
             } else {
               // No room in the L1, so we need to make room in the L1
-              trigger(Event:L1_Replacement, L1DcacheMemory.cacheProbe(in_msg.Address));
+              trigger(Event:L1_Replacement, L1DcacheMemory.cacheProbe(in_msg.LineAddress));
             }
           }
         }
   }
 
   action(j_sendUnblock, "j", desc="send unblock to the L2 cache") {
-    enqueue(unblockNetwork_out, ResponseMsg, latency="1") {
+    enqueue(unblockNetwork_out, ResponseMsg, latency="TO_L2_LATENCY") {
       out_msg.Address := address;
       out_msg.Type := CoherenceResponseType:UNBLOCK;
       out_msg.Sender := machineID;
   }
 
   action(jj_sendExclusiveUnblock, "\j", desc="send unblock to the L2 cache") {
-    enqueue(unblockNetwork_out, ResponseMsg, latency="1") {
+    enqueue(unblockNetwork_out, ResponseMsg, latency="TO_L2_LATENCY") {
       out_msg.Address := address;
       out_msg.Type := CoherenceResponseType:EXCLUSIVE_UNBLOCK;
       out_msg.Sender := machineID;
 
     bool isPresent(Address);
   }
 
-  TBETable L2_TBEs, template_hack="<L2Cache_TBE>";
+  TBETable L2_TBEs, template_hack="<L2Cache_TBE>", no_vector="true";
 
-  CacheMemory L2cacheMemory, template_hack="<L2Cache_Entry>", constructor_hack='L2_CACHE_NUM_SETS_BITS,L2_CACHE_ASSOC,MachineType_L2Cache,int_to_string(i)';
+//  CacheMemory L2cacheMemory, template_hack="<L2Cache_Entry>", constructor_hack='L2_CACHE_NUM_SETS_BITS,L2_CACHE_ASSOC,MachineType_L2Cache,int_to_string(i)';
+
+
+  CacheMemory L2cacheMemory, factory='RubySystem::getCache(m_cfg["cache"])', no_vector="true";
 
   // inclusive cache, returns L2 entries only
   Entry getL2CacheEntry(Address addr), return_by_ref="yes" {
 
  * $Id: MOESI_CMP_token-dir.sm 1.6 05/01/19 15:48:35-06:00 mikem@royal16.cs.wisc.edu $
  */
 
+// This file is copied from Yasuko Watanabe's prefetch / memory protocol
+// Copied here by aep 12/14/07
 
-machine(Directory, "Token protocol") {
+
+machine(Directory, "MESI_CMP_filter_directory protocol")  : LATENCY_MEMORY_LATENCY LATENCY_TO_MEM_CTRL_LATENCY {
 
   MessageBuffer requestToDir, network="From", virtual_network="2", ordered="false";
   MessageBuffer responseToDir, network="From", virtual_network="3", ordered="false";
   MessageBuffer responseFromDir, network="To", virtual_network="3", ordered="false";
 
+  MessageBuffer dmaRequestFromDir, network="To", virtual_network="4", ordered="true", no_vector="true";
+  MessageBuffer dmaRequestToDir, network="From", virtual_network="5", ordered="true", no_vector="true";
+
+
   // STATES
   enumeration(State, desc="Directory states", default="Directory_State_I") {
     // Base states
     I, desc="Owner";
+    ID, desc="Intermediate state for DMA_READ when in I";
+    ID_W, desc="Intermediate state for DMA_WRITE when in I";
   }
 
   // Events
   enumeration(Event, desc="Directory events") {
-    Fetch, desc="A GETX arrives";
-    Data, desc="A GETS arrives";
+    Fetch, desc="A memory fetch arrives";
+    Data, desc="writeback data arrives";
+    Memory_Data, desc="Fetched data from memory arrives";
+    Memory_Ack, desc="Writeback Ack from memory arrives";
+//added by SS for dma
+    DMA_READ, desc="A DMA Read memory request";
+    DMA_WRITE, desc="A DMA Write memory request";
+
+
   }
 
   // TYPES
     bool isPresent(Address);
   }
 
+  // to simulate detailed DRAM
+  external_type(MemoryControl, inport="yes", outport="yes") {
+
+  }
+
 
   // ** OBJECTS **
 
-  DirectoryMemory directory, constructor_hack="i";
+//  DirectoryMemory directory, constructor_hack="i";
+//  MemoryControl memBuffer, constructor_hack="i";
+
+  DirectoryMemory directory, factory='RubySystem::getDirectory(m_cfg["directory_name"])';
+
+  MemoryControl memBuffer, factory='RubySystem::getMemoryControl(m_cfg["memory_controller_name"])';
+
 
   State getState(Address addr) {
     return State:I;
   void setState(Address addr, State state) {
   }
 
+  bool isGETRequest(CoherenceRequestType type) {
+    return (type == CoherenceRequestType:GETS) ||
+      (type == CoherenceRequestType:GET_INSTR) ||
+      (type == CoherenceRequestType:GETX);
+  }
+
+
   // ** OUT_PORTS **
   out_port(responseNetwork_out, ResponseMsg, responseFromDir);
+  out_port(memQueue_out, MemoryMsg, memBuffer);
+  out_port(dmaResponseNetwork_out, DMAResponseMsg, dmaRequestFromDir);
 
   // ** IN_PORTS **
 
+//added by SS for dma
+  in_port(dmaRequestQueue_in, DMARequestMsg, dmaRequestToDir) {
+    if (dmaRequestQueue_in.isReady()) {
+      peek(dmaRequestQueue_in, DMARequestMsg) {
+        if (in_msg.Type == DMARequestType:READ) {
+          trigger(Event:DMA_READ, in_msg.PhysicalAddress);
+        } else if (in_msg.Type == DMARequestType:WRITE) {
+          trigger(Event:DMA_WRITE, in_msg.PhysicalAddress);
+        } else {
+          error("Invalid message");
+        }
+      }
+    }
+  }
+
+
   in_port(requestNetwork_in, RequestMsg, requestToDir) {
     if (requestNetwork_in.isReady()) {
       peek(requestNetwork_in, RequestMsg) {
         assert(in_msg.Destination.isElement(machineID));
-        if (in_msg.Type == CoherenceRequestType:GETS) {
-          trigger(Event:Fetch, in_msg.Address);
-        } else if (in_msg.Type == CoherenceRequestType:GETX) {
+        if (isGETRequest(in_msg.Type)) {
           trigger(Event:Fetch, in_msg.Address);
         } else {
+          DEBUG_EXPR(in_msg);
           error("Invalid message");
         }
       }
     }
   }
 
+  // off-chip memory request/response is done
+  in_port(memQueue_in, MemoryMsg, memBuffer) {
+    if (memQueue_in.isReady()) {
+      peek(memQueue_in, MemoryMsg) {
+        if (in_msg.Type == MemoryRequestType:MEMORY_READ) {
+          trigger(Event:Memory_Data, in_msg.Address);
+        } else if (in_msg.Type == MemoryRequestType:MEMORY_WB) {
+          trigger(Event:Memory_Ack, in_msg.Address);
+        } else {
+          DEBUG_EXPR(in_msg.Type);
+          error("Invalid message");
+        }
+      }
+    }
+  }
+
+
+
   // Actions
   action(a_sendAck, "a", desc="Send ack to L2") {
-    peek(responseNetwork_in, ResponseMsg) {
-      enqueue(responseNetwork_out, ResponseMsg, latency="MEMORY_LATENCY") {
+    peek(memQueue_in, MemoryMsg) {
+      enqueue(responseNetwork_out, ResponseMsg, latency="TO_MEM_CTRL_LATENCY") {
         out_msg.Address := address;
         out_msg.Type := CoherenceResponseType:MEMORY_ACK;
         out_msg.Sender := machineID;
-        out_msg.Destination.add(in_msg.Sender);
+        out_msg.Destination.add(in_msg.OriginalRequestorMachId);
         out_msg.MessageSize := MessageSizeType:Response_Control;
       }
     }
   }
 
   action(d_sendData, "d", desc="Send data to requestor") {
-    peek(requestNetwork_in, RequestMsg) {
-      enqueue(responseNetwork_out, ResponseMsg, latency="MEMORY_LATENCY") {
+    peek(memQueue_in, MemoryMsg) {
+      enqueue(responseNetwork_out, ResponseMsg, latency="TO_MEM_CTRL_LATENCY") {
         out_msg.Address := address;
         out_msg.Type := CoherenceResponseType:MEMORY_DATA;
         out_msg.Sender := machineID;
-        out_msg.Destination.add(in_msg.Requestor);
-        out_msg.DataBlk := directory[in_msg.Address].DataBlk;
+        out_msg.Destination.add(in_msg.OriginalRequestorMachId);
+        out_msg.DataBlk := in_msg.DataBlk;
         out_msg.Dirty := false;
         out_msg.MessageSize := MessageSizeType:Response_Data;
       }
     responseNetwork_in.dequeue();
   }
 
+  action(l_popMemQueue, "q", desc="Pop off-chip request queue") {
+    memQueue_in.dequeue();
+  }
+
+  action(qf_queueMemoryFetchRequest, "qf", desc="Queue off-chip fetch request") {
+    peek(requestNetwork_in, RequestMsg) {
+      enqueue(memQueue_out, MemoryMsg, latency="TO_MEM_CTRL_LATENCY") {
+        out_msg.Address := address;
+        out_msg.Type := MemoryRequestType:MEMORY_READ;
+        out_msg.Sender := machineID;
+        out_msg.OriginalRequestorMachId := in_msg.Requestor;
+        out_msg.MessageSize := in_msg.MessageSize;
+        out_msg.Prefetch := in_msg.Prefetch;
+        out_msg.DataBlk := directory[in_msg.Address].DataBlk;
+
+        DEBUG_EXPR(out_msg);
+      }
+    }
+  }
+
+  action(qw_queueMemoryWBRequest, "qw", desc="Queue off-chip writeback request") {
+    peek(responseNetwork_in, ResponseMsg) {
+      enqueue(memQueue_out, MemoryMsg, latency="TO_MEM_CTRL_LATENCY") {
+        out_msg.Address := address;
+        out_msg.Type := MemoryRequestType:MEMORY_WB;
+        out_msg.Sender := machineID;
+        out_msg.OriginalRequestorMachId := in_msg.Sender;
+        out_msg.DataBlk := in_msg.DataBlk;
+        out_msg.MessageSize := in_msg.MessageSize;
+        //out_msg.Prefetch := in_msg.Prefetch;
+
+        DEBUG_EXPR(out_msg);
+      }
+    }
+  }
+
   action(m_writeDataToMemory, "m", desc="Write dirty writeback to memory") {
     peek(responseNetwork_in, ResponseMsg) {
       directory[in_msg.Address].DataBlk := in_msg.DataBlk;
       DEBUG_EXPR(in_msg.DataBlk);
     }
   }
+//added by SS for dma
+  action(qf_queueMemoryFetchRequestDMA, "qfd", desc="Queue off-chip fetch request") {
+    peek(dmaRequestQueue_in, DMARequestMsg) {
+      enqueue(memQueue_out, MemoryMsg, latency="TO_MEM_CTRL_LATENCY") {
+        out_msg.Address := address;
+        out_msg.Type := MemoryRequestType:MEMORY_READ;
+        out_msg.Sender := machineID;
+        out_msg.OriginalRequestorMachId := machineID;
+        out_msg.MessageSize := in_msg.MessageSize;
+        out_msg.DataBlk := directory[address].DataBlk;
+        DEBUG_EXPR(out_msg);
+      }
+    }
+  }
+
+  action(p_popIncomingDMARequestQueue, "p", desc="Pop incoming DMA queue") {
+    dmaRequestQueue_in.dequeue();
+  }
+
+  action(dr_sendDMAData, "dr", desc="Send Data to DMA controller from directory") {
+    peek(memQueue_in, MemoryMsg) {
+      enqueue(dmaResponseNetwork_out, DMAResponseMsg, latency="MEMORY_LATENCY") {
+        out_msg.PhysicalAddress := address;
+        out_msg.Type := DMAResponseType:DATA;
+        out_msg.DataBlk := in_msg.DataBlk;   // we send the entire data block and rely on the dma controller to split it up if need be
+        out_msg.Destination.add(map_Address_to_DMA(address));
+        out_msg.MessageSize := MessageSizeType:Response_Data;
+      }
+    }
+  }
+
+  action(dw_writeDMAData, "dw", desc="DMA Write data to memory") {
+    peek(dmaRequestQueue_in, DMARequestMsg) {
+      directory[in_msg.PhysicalAddress].DataBlk.copyPartial(in_msg.DataBlk, in_msg.Offset, in_msg.Len);
+    }
+  }
+
+  action(qw_queueMemoryWBRequest_partial, "qwp", desc="Queue off-chip writeback request") {
+     peek(dmaRequestQueue_in, DMARequestMsg) {
+      enqueue(memQueue_out, MemoryMsg, latency="TO_MEM_CTRL_LATENCY") {
+        out_msg.Address := address;
+        out_msg.Type := MemoryRequestType:MEMORY_WB;
+        out_msg.OriginalRequestorMachId := machineID;
+        //out_msg.DataBlk := in_msg.DataBlk;
+        out_msg.DataBlk.copyPartial(in_msg.DataBlk, in_msg.Offset, in_msg.Len);
+        out_msg.MessageSize := in_msg.MessageSize;
+        //out_msg.Prefetch := in_msg.Prefetch;
+
+        DEBUG_EXPR(out_msg);
+      }
+    }
+  }
+
+  action(da_sendDMAAck, "da", desc="Send Ack to DMA controller") {
+      enqueue(dmaResponseNetwork_out, DMAResponseMsg, latency="MEMORY_LATENCY") {
+        out_msg.PhysicalAddress := address;
+        out_msg.Type := DMAResponseType:ACK;
+        out_msg.Destination.add(map_Address_to_DMA(address));
+        out_msg.MessageSize := MessageSizeType:Writeback_Control;
+      }
+  }
+
+  action(z_recycleRequestQueue, "z", desc="recycle request queue") {
+    requestNetwork_in.dequeue();
+  }
 
   // TRANSITIONS
 
   transition(I, Fetch) {
-    d_sendData;
+    //d_sendData;
+    qf_queueMemoryFetchRequest;
     j_popIncomingRequestQueue;
   }
 
   transition(I, Data) {
     m_writeDataToMemory;
-    a_sendAck;
+    //a_sendAck;
+    qw_queueMemoryWBRequest;
     k_popIncomingResponseQueue;
   }
+
+  transition(I, Memory_Data) {
+    d_sendData;
+    l_popMemQueue;
+  }
+
+  transition(I, Memory_Ack) {
+    a_sendAck;
+    l_popMemQueue;
+  }
+
+//added by SS for dma support
+  transition(I, DMA_READ, ID) {
+    qf_queueMemoryFetchRequestDMA;
+    p_popIncomingDMARequestQueue;
+  }
+
+  transition(ID, Memory_Data, I) {
+    dr_sendDMAData;
+    l_popMemQueue;
+  }
+
+  transition(I, DMA_WRITE, ID_W) {
+    dw_writeDMAData;
+    qw_queueMemoryWBRequest_partial;
+    p_popIncomingDMARequestQueue;
+  }
+
+  transition(ID_W, Memory_Ack, I) {
+    da_sendDMAAck;
+    l_popMemQueue;
+  }
+
+  transition({ID, ID_W}, {Fetch, Data} ) {
+    z_recycleRequestQueue;
+  }
+
+
 }
 
   MessageSizeType MessageSize,  desc="size category of the message";
 }
 
+enumeration(DMARequestType, desc="...", default="DMARequestType_NULL") {
+  READ,          desc="Memory Read";
+  WRITE,         desc="Memory Write";
+  NULL,          desc="Invalid";
+}
+
+enumeration(DMAResponseType, desc="...", default="DMAResponseType_NULL") {
+  DATA,          desc="DATA read";
+  ACK,           desc="ACK write";
+  NULL,          desc="Invalid";
+}
+
+structure(DMARequestMsg, desc="...", interface="NetworkMessage") {
+  DMARequestType Type,       desc="Request type (read/write)";
+  Address PhysicalAddress,   desc="Physical address for this request";
+  NetDest Destination,       desc="Destination";
+  DataBlock DataBlk,         desc="DataBlk attached to this request";
+  int Offset,                desc="The offset into the datablock";
+  int Len,                   desc="The length of the request";
+  MessageSizeType MessageSize, desc="size category of the message";
+}
+
+structure(DMAResponseMsg, desc="...", interface="NetworkMessage") {
+  DMAResponseType Type,      desc="Response type (DATA/ACK)";
+  Address PhysicalAddress,   desc="Physical address for this request";
+  NetDest Destination,       desc="Destination";
+  DataBlock DataBlk,         desc="DataBlk attached to this request";
+  MessageSizeType MessageSize, desc="size category of the message";
+}
+
+
+
 /*
 GenericRequestType convertToGenericType(CoherenceRequestType type) {
   if(type == CoherenceRequestType:PUTX) {
 
 MESI_CMP_directory-L2cache.sm
 MESI_CMP_directory-L1cache.sm
 MESI_CMP_directory-mem.sm
+MESI_CMP_directory-dma.sm
 standard_CMP-protocol.sm
+
 
 
-machine(L1Cache, "MI Example") {
+machine(L1Cache, "MI Example L1 Cache"): LATENCY_CACHE_RESPONSE_LATENCY  LATENCY_ISSUE_LATENCY {
 
   // NETWORK BUFFERS
   MessageBuffer requestFromCache, network="To", virtual_network="0", ordered="true";
     M,  desc="Modified";
     MI,  desc="Modified, issued PUT";
 
-    IS,  desc="Issued request for IFETCH/GETX";
+    IS,  desc="Issued request for LOAD/IFETCH";
     IM,  desc="Issued request for STORE/ATOMIC";
   }
 
     Data,       desc="Data from network";
     Fwd_GETX,        desc="Forward from network";
 
+    Inv,        desc="Invalidate request from dir";
+
     Replacement,  desc="Replace a block";
     Writeback_Ack,   desc="Ack from the directory for a writeback";
     Writeback_Nack,   desc="Nack from the directory for a writeback";
 
   // STRUCTURE DEFINITIONS
 
-  MessageBuffer mandatoryQueue, ordered="false", abstract_chip_ptr="true";
-  Sequencer sequencer, abstract_chip_ptr="true", constructor_hack="i";
+  MessageBuffer mandatoryQueue, ordered="false";
+  Sequencer sequencer, factory='RubySystem::getSequencer(m_cfg["sequencer"])';
 
   // CacheEntry
   structure(Entry, desc="...", interface="AbstractCacheEntry") {
     State CacheState,        desc="cache state";
     bool Dirty,              desc="Is the data dirty (different than memory)?";
-    DataBlock DataBlk,       desc="data for the block";
+    DataBlock DataBlk,       desc="Data in the block";
   }
 
 
   external_type(CacheMemory) {
     bool cacheAvail(Address);
     Address cacheProbe(Address);
-    void allocate(Address);
+    void allocate(Address, Entry);
     void deallocate(Address);
     Entry lookup(Address);
     void changePermission(Address, AccessPermission);
   structure(TBE, desc="...") {
     State TBEState,          desc="Transient state";
     DataBlock DataBlk,       desc="data for the block, required for concurrent writebacks";
-    bool Trans,              desc="Is this block part of a the current transaction?";
-    bool Logged,             desc="Has this block been logged in the current transaction?";
   }
 
   external_type(TBETable) {
 
   // STRUCTURES
 
-  CacheMemory cacheMemory, template_hack="<L1Cache_Entry>", constructor_hack='L1_CACHE_NUM_SETS_BITS, L1_CACHE_ASSOC, MachineType_L1Cache, int_to_string(i)+"_L1"', abstract_chip_ptr="true";
+  CacheMemory cacheMemory, factory='RubySystem::getCache(m_cfg["cache"])';
 
   TBETable TBEs, template_hack="<L1Cache_TBE>";
 
 
     if (cacheMemory.isTagPresent(addr)) {
       cacheMemory[addr].CacheState := state;
+      if (state == State:M) {
+        cacheMemory.changePermission(addr, AccessPermission:Read_Write);
+      } else {
+        cacheMemory.changePermission(addr, AccessPermission:Invalid);
+      }
     }
   }
 
         else if (in_msg.Type == CoherenceRequestType:WB_NACK) {
           trigger(Event:Writeback_Nack, in_msg.Address);
         }
+        else if (in_msg.Type == CoherenceRequestType:INV) {
+          trigger(Event:Inv, in_msg.Address);
+        }
         else {
           error("Unexpected message");
         }
       peek(mandatoryQueue_in, CacheMsg) {
 
 
-        if (cacheMemory.isTagPresent(in_msg.Address) == false &&
-            cacheMemory.cacheAvail(in_msg.Address) == false ) {
+        if (cacheMemory.isTagPresent(in_msg.LineAddress) == false &&
+            cacheMemory.cacheAvail(in_msg.LineAddress) == false ) {
           // make room for the block
-          trigger(Event:Replacement, cacheMemory.cacheProbe(in_msg.Address));
+          trigger(Event:Replacement, cacheMemory.cacheProbe(in_msg.LineAddress));
         }
         else {
-          trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.Address);
+          trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress);
         }
       }
     }
 
   action(i_allocateL1CacheBlock, "i", desc="Allocate a cache block") {
     if (cacheMemory.isTagPresent(address) == false) {
-      cacheMemory.allocate(address);
+      cacheMemory.allocate(address, new Entry);
     }
   }
 
   }
 
   action(n_popResponseQueue, "n", desc="Pop the response queue") {
-    responseNetwork_in.dequeue();
+    profileMsgDelay(1, responseNetwork_in.dequeue_getDelayCycles());
   }
 
   action(o_popForwardedRequestQueue, "o", desc="Pop the forwarded request queue") {
-    forwardRequestNetwork_in.dequeue();
+    profileMsgDelay(2, forwardRequestNetwork_in.dequeue_getDelayCycles());
   }
 
   action(r_load_hit, "r", desc="Notify sequencer the load completed.") {
     z_stall;
   }
 
-  transition({IS, IM}, Fwd_GETX) {
+  transition({IS, IM}, {Fwd_GETX, Inv}) {
     z_stall;
   }
 
+  transition(MI, Inv) {
+    o_popForwardedRequestQueue;
+  }
+
   transition(M, Store) {
     s_store_hit;
     m_popMandatoryQueue;
     m_popMandatoryQueue;
   }
 
+  transition(I, Inv) {
+    o_popForwardedRequestQueue;
+  }
 
   transition(I, Store, IM) {
     v_allocateTBE;
      h_deallocateL1CacheBlock;
   }
 
-  transition(M, Replacement, MI) {
+  transition(M, {Replacement,Inv},  MI) {
      v_allocateTBE;
      b_issuePUT;
      x_copyDataFromCacheToTBE;
 
 
-machine(Directory, "Directory protocol") {
+machine(Directory, "Directory protocol") : LATENCY_TO_MEM_CTRL_LATENCY LATENCY_DIRECTORY_LATENCY LATENCY_MEMORY_LATENCY {
 
-  MessageBuffer forwardFromDir, network="To", virtual_network="2", ordered="true";
+  MessageBuffer forwardFromDir, network="To", virtual_network="2", ordered="false";
   MessageBuffer responseFromDir, network="To", virtual_network="1", ordered="false";
+  MessageBuffer dmaRequestFromDir, network="To", virtual_network="4", ordered="true";
 
   MessageBuffer requestToDir, network="From", virtual_network="0", ordered="true";
-  MessageBuffer unblockToDir, network="From", virtual_network="3", ordered="true";
+  MessageBuffer dmaRequestToDir, network="From", virtual_network="5", ordered="true";
 
   // STATES
   enumeration(State, desc="Directory states", default="Directory_State_I") {
     I, desc="Invalid";
     M, desc="Modified";
 
-    MI, desc="Blocked on a writeback";
+    M_DRD, desc="Blocked on an invalidation for a DMA read";
+    M_DWR, desc="Blocked on an invalidation for a DMA write";
+
+    M_DWRI, desc="Intermediate state M_DWR-->I";
+
+    IM, desc="Intermediate state I-->M";
+    MI, desc="Intermediate state M-->I";
+    ID, desc="Intermediate state for DMA_READ when in I";
+    ID_W, desc="Intermediate state for DMA_WRITE when in I";
   }
 
   // Events
   enumeration(Event, desc="Directory events") {
+    // processor requests
     GETX, desc="A GETX arrives";
     GETS, desc="A GETS arrives";
     PUTX, desc="A PUTX arrives";
     PUTX_NotOwner, desc="A PUTX arrives";
-    PUTO, desc="A PUTO arrives";
-    Unblock, desc="An unblock message arrives";
+
+    // DMA requests
+    DMA_READ, desc="A DMA Read memory request";
+    DMA_WRITE, desc="A DMA Write memory request";
+
+    // Memory Controller
+    Memory_Data, desc="Fetched data from memory arrives";
+    Memory_Ack, desc="Writeback Ack from memory arrives";
   }
 
   // TYPES
   external_type(DirectoryMemory) {
     Entry lookup(Address);
     bool isPresent(Address);
+    void invalidateBlock(Address);
+  }
+
+  external_type(MemoryControl, inport="yes", outport="yes") {
+
+  }
+
+
+  // TBE entries for DMA requests
+  structure(TBE, desc="TBE entries for outstanding DMA requests") {
+    State TBEState,        desc="Transient State";
+    DataBlock DataBlk,     desc="Data to be written (DMA write only)";
+    int Offset,            desc="...";
+    int Len,               desc="...";
   }
 
+  external_type(TBETable) {
+    TBE lookup(Address);
+    void allocate(Address);
+    void deallocate(Address);
+    bool isPresent(Address);
+  }
 
   // ** OBJECTS **
+  DirectoryMemory directory, factory='RubySystem::getDirectory(m_cfg["directory_name"])';
+
+  MemoryControl memBuffer, factory='RubySystem::getMemoryControl(m_cfg["memory_controller_name"])';
 
-  DirectoryMemory directory, constructor_hack="i";
+  TBETable TBEs, template_hack="<Directory_TBE>";
 
   State getState(Address addr) {
-    return directory[addr].DirectoryState;
+    if (TBEs.isPresent(addr)) {
+      return TBEs[addr].TBEState;
+    } else if (directory.isPresent(addr)) {
+      return directory[addr].DirectoryState;
+    } else {
+      return State:I;
+    }
   }
 
   void setState(Address addr, State state) {
+
+    if (TBEs.isPresent(addr)) {
+      TBEs[addr].TBEState := state;
+    }
+
     if (directory.isPresent(addr)) {
 
       if (state == State:I)  {
         assert(directory[addr].Owner.count() == 0);
         assert(directory[addr].Sharers.count() == 0);
-      }
-
-      if (state == State:M) {
+      } else if (state == State:M) {
         assert(directory[addr].Owner.count() == 1);
         assert(directory[addr].Sharers.count() == 0);
       }
   out_port(forwardNetwork_out, RequestMsg, forwardFromDir);
   out_port(responseNetwork_out, ResponseMsg, responseFromDir);
   out_port(requestQueue_out, ResponseMsg, requestToDir); // For recycling requests
+  out_port(dmaResponseNetwork_out, DMAResponseMsg, dmaRequestFromDir);
 
+//added by SS
+  out_port(memQueue_out, MemoryMsg, memBuffer);
   // ** IN_PORTS **
 
+  in_port(dmaRequestQueue_in, DMARequestMsg, dmaRequestToDir) {
+    if (dmaRequestQueue_in.isReady()) {
+      peek(dmaRequestQueue_in, DMARequestMsg) {
+        if (in_msg.Type == DMARequestType:READ) {
+          trigger(Event:DMA_READ, in_msg.PhysicalAddress);
+        } else if (in_msg.Type == DMARequestType:WRITE) {
+          trigger(Event:DMA_WRITE, in_msg.PhysicalAddress);
+        } else {
+          error("Invalid message");
+        }
+      }
+    }
+  }
 
   in_port(requestQueue_in, RequestMsg, requestToDir) {
     if (requestQueue_in.isReady()) {
           } else {
             trigger(Event:PUTX_NotOwner, in_msg.Address);
           }
-        } else if (in_msg.Type == CoherenceRequestType:PUTO) {
-          trigger(Event:PUTO, in_msg.Address);
         } else {
           error("Invalid message");
         }
     }
   }
 
-  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);
+//added by SS
+  // off-chip memory request/response is done
+  in_port(memQueue_in, MemoryMsg, memBuffer) {
+    if (memQueue_in.isReady()) {
+      peek(memQueue_in, MemoryMsg) {
+        if (in_msg.Type == MemoryRequestType:MEMORY_READ) {
+          trigger(Event:Memory_Data, in_msg.Address);
+        } else if (in_msg.Type == MemoryRequestType:MEMORY_WB) {
+          trigger(Event:Memory_Ack, in_msg.Address);
         } else {
+          DEBUG_EXPR(in_msg.Type);
           error("Invalid message");
         }
       }
     }
   }
 
-
-
   // Actions
 
   action(a_sendWriteBackAck, "a", desc="Send writeback ack to requestor") {
     }
   }
 
+  action(l_sendWriteBackAck, "la", desc="Send writeback ack to requestor") {
+    peek(memQueue_in, MemoryMsg) {
+      enqueue(forwardNetwork_out, RequestMsg, latency="TO_MEM_CTRL_LATENCY") {
+        out_msg.Address := address;
+        out_msg.Type := CoherenceRequestType:WB_ACK;
+        out_msg.Requestor := in_msg.OriginalRequestorMachId;
+        out_msg.Destination.add(in_msg.OriginalRequestorMachId);
+        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") {
     directory[address].Owner.clear();
   }
 
+//  action(d_sendData, "d", desc="Send data to requestor") {
+//    peek(requestQueue_in, RequestMsg) {
+//      enqueue(responseNetwork_out, ResponseMsg, latency="MEMORY_LATENCY") {
+//        out_msg.Address := address;
+//
+//        if (in_msg.Type == CoherenceRequestType:GETS && directory[address].Sharers.count() == 0) {
+//          // out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE_CLEAN;
+//          out_msg.Type := CoherenceResponseType:DATA;
+//        } else {
+//          out_msg.Type := CoherenceResponseType:DATA;
+//        }
+//
+//        out_msg.Sender := machineID;
+//        out_msg.Destination.add(in_msg.Requestor);
+//        out_msg.DataBlk := directory[in_msg.Address].DataBlk;
+//        out_msg.MessageSize := MessageSizeType:Response_Data;
+//      }
+//    }
+//  }
+
   action(d_sendData, "d", desc="Send data to requestor") {
-    peek(requestQueue_in, RequestMsg) {
-      enqueue(responseNetwork_out, ResponseMsg, latency="MEMORY_LATENCY") {
+    peek(memQueue_in, MemoryMsg) {
+      enqueue(responseNetwork_out, ResponseMsg, latency="TO_MEM_CTRL_LATENCY") {
         out_msg.Address := address;
+        out_msg.Type := CoherenceResponseType:DATA;
+        out_msg.Sender := machineID;
+        out_msg.Destination.add(in_msg.OriginalRequestorMachId);
+        out_msg.DataBlk := in_msg.DataBlk;
+        out_msg.MessageSize := MessageSizeType:Response_Data;
+      }
+    }
+  }
 
-        if (in_msg.Type == CoherenceRequestType:GETS && directory[address].Sharers.count() == 0) {
-          // out_msg.Type := CoherenceResponseType:DATA_EXCLUSIVE_CLEAN;
-          out_msg.Type := CoherenceResponseType:DATA;
-        } else {
-          out_msg.Type := CoherenceResponseType:DATA;
-        }
+//  action(dr_sendDMAData, "dr", desc="Send Data to DMA controller from directory") {
+//    peek(dmaRequestQueue_in, DMARequestMsg) {
+//      enqueue(dmaResponseNetwork_out, DMAResponseMsg, latency="MEMORY_LATENCY") {
+//        out_msg.PhysicalAddress := address;
+//        out_msg.Type := DMAResponseType:DATA;
+//        out_msg.DataBlk := directory[in_msg.PhysicalAddress].DataBlk;   // we send the entire data block and rely on the dma controller to split it up if need be
+//        out_msg.Destination.add(map_Address_to_DMA(address));
+//        out_msg.MessageSize := MessageSizeType:Response_Data;
+//      }
+//    }
+//  }
+
+  action(dr_sendDMAData, "dr", desc="Send Data to DMA controller from directory") {
+    peek(memQueue_in, MemoryMsg) {
+      enqueue(dmaResponseNetwork_out, DMAResponseMsg, latency="MEMORY_LATENCY") {
+        out_msg.PhysicalAddress := address;
+        out_msg.Type := DMAResponseType:DATA;
+        out_msg.DataBlk := in_msg.DataBlk;   // we send the entire data block and rely on the dma controller to split it up if need be
+        out_msg.Destination.add(map_Address_to_DMA(address));
+        out_msg.MessageSize := MessageSizeType:Response_Data;
+      }
+    }
+  }
 
-        out_msg.Sender := machineID;
-        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 := directory[address].Sharers.count();
-        if (directory[address].Sharers.isElement(in_msg.Requestor)) {
-          out_msg.Acks := out_msg.Acks - 1;
-        }
+
+
+  action(drp_sendDMAData, "drp", desc="Send Data to DMA controller from incoming PUTX") {
+    peek(requestQueue_in, RequestMsg) {
+      enqueue(dmaResponseNetwork_out, DMAResponseMsg, latency="MEMORY_LATENCY") {
+        out_msg.PhysicalAddress := address;
+        out_msg.Type := DMAResponseType:DATA;
+        out_msg.DataBlk := in_msg.DataBlk;   // we send the entire data block and rely on the dma controller to split it up if need be
+        out_msg.Destination.add(map_Address_to_DMA(address));
         out_msg.MessageSize := MessageSizeType:Response_Data;
       }
     }
   }
 
+  action(da_sendDMAAck, "da", desc="Send Ack to DMA controller") {
+      enqueue(dmaResponseNetwork_out, DMAResponseMsg, latency="MEMORY_LATENCY") {
+        out_msg.PhysicalAddress := address;
+        out_msg.Type := DMAResponseType:ACK;
+        out_msg.Destination.add(map_Address_to_DMA(address));
+        out_msg.MessageSize := MessageSizeType:Writeback_Control;
+      }
+  }
+
+  action(d_deallocateDirectory, "\d", desc="Deallocate Directory Entry") {
+      directory.invalidateBlock(address);
+  }
+
   action(e_ownerIsRequestor, "e", desc="The owner is now the requestor") {
     peek(requestQueue_in, RequestMsg) {
       directory[address].Owner.clear();
         out_msg.Type := in_msg.Type;
         out_msg.Requestor := in_msg.Requestor;
         out_msg.Destination := directory[in_msg.Address].Owner;
-        out_msg.Acks := directory[address].Sharers.count();
-        if (directory[address].Sharers.isElement(in_msg.Requestor)) {
-          out_msg.Acks := out_msg.Acks - 1;
-        }
-        out_msg.MessageSize := MessageSizeType:Forwarded_Control;
+        out_msg.MessageSize := MessageSizeType:Writeback_Control;
       }
     }
   }
 
+  action(inv_sendCacheInvalidate, "inv", desc="Invalidate a cache block") {
+    peek(dmaRequestQueue_in, DMARequestMsg) {
+      enqueue(forwardNetwork_out, RequestMsg, latency="DIRECTORY_LATENCY") {
+      out_msg.Address := address;
+      out_msg.Type := CoherenceRequestType:INV;
+      out_msg.Requestor := machineID;
+      out_msg.Destination := directory[in_msg.PhysicalAddress].Owner;
+      out_msg.MessageSize := MessageSizeType:Writeback_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(p_popIncomingDMARequestQueue, "p", desc="Pop incoming DMA queue") {
+    dmaRequestQueue_in.dequeue();
   }
 
-  action(l_writeDataToMemory, "l", desc="Write PUTX/PUTO data to memory") {
-    // peek(unblockNetwork_in, ResponseMsg) {
+  action(l_writeDataToMemory, "l", desc="Write PUTX data to memory") {
     peek(requestQueue_in, RequestMsg) {
       // assert(in_msg.Dirty);
       // assert(in_msg.MessageSize == MessageSizeType:Writeback_Data);
     }
   }
 
+  action(dw_writeDMAData, "dw", desc="DMA Write data to memory") {
+    peek(dmaRequestQueue_in, DMARequestMsg) {
+      directory[in_msg.PhysicalAddress].DataBlk.copyPartial(in_msg.DataBlk, in_msg.Offset, in_msg.Len);
+    }
+  }
+
+  action(dwt_writeDMADataFromTBE, "dwt", desc="DMA Write data to memory from TBE") {
+    directory[address].DataBlk.copyPartial(TBEs[address].DataBlk, TBEs[address].Offset, TBEs[address].Len);
+  }
+
+  action(v_allocateTBE, "v", desc="Allocate TBE") {
+    peek(dmaRequestQueue_in, DMARequestMsg) {
+      TBEs.allocate(address);
+      TBEs[address].DataBlk := in_msg.DataBlk;
+      TBEs[address].Offset := in_msg.Offset;
+      TBEs[address].Len := in_msg.Len;
+    }
+  }
+
+  action(w_deallocateTBE, "w", desc="Deallocate TBE") {
+    TBEs.deallocate(address);
+  }
+
+  action(z_recycleRequestQueue, "z", desc="recycle request queue") {
+    requestQueue_in.recycle();
+  }
 
 
+  action(qf_queueMemoryFetchRequest, "qf", desc="Queue off-chip fetch request") {
+    peek(requestQueue_in, RequestMsg) {
+      enqueue(memQueue_out, MemoryMsg, latency="TO_MEM_CTRL_LATENCY") {
+        out_msg.Address := address;
+        out_msg.Type := MemoryRequestType:MEMORY_READ;
+        out_msg.Sender := machineID;
+        out_msg.OriginalRequestorMachId := in_msg.Requestor;
+        out_msg.MessageSize := in_msg.MessageSize;
+        out_msg.DataBlk := directory[in_msg.Address].DataBlk;
+        DEBUG_EXPR(out_msg);
+      }
+    }
+  }
+
+  action(qf_queueMemoryFetchRequestDMA, "qfd", desc="Queue off-chip fetch request") {
+    peek(dmaRequestQueue_in, DMARequestMsg) {
+      enqueue(memQueue_out, MemoryMsg, latency="TO_MEM_CTRL_LATENCY") {
+        out_msg.Address := address;
+        out_msg.Type := MemoryRequestType:MEMORY_READ;
+        out_msg.Sender := machineID;
+        //out_msg.OriginalRequestorMachId := machineID;
+        out_msg.MessageSize := in_msg.MessageSize;
+        out_msg.DataBlk := directory[address].DataBlk;
+        DEBUG_EXPR(out_msg);
+      }
+    }
+  }
+//  action(qw_queueMemoryWBRequest, "qw", desc="Queue off-chip writeback request") {
+//     peek(dmaRequestQueue_in, DMARequestMsg) {
+//      enqueue(memQueue_out, MemoryMsg, latency="TO_MEM_CTRL_LATENCY") {
+//        out_msg.Address := address;
+//        out_msg.Type := MemoryRequestType:MEMORY_WB;
+//        out_msg.OriginalRequestorMachId := machineID;
+//        out_msg.DataBlk := in_msg.DataBlk;
+//        out_msg.MessageSize := in_msg.MessageSize;
+
+//        DEBUG_EXPR(out_msg);
+//      }
+//    }
+//  }
+
+
+  action(qw_queueMemoryWBRequest_partial, "qwp", desc="Queue off-chip writeback request") {
+     peek(dmaRequestQueue_in, DMARequestMsg) {
+      enqueue(memQueue_out, MemoryMsg, latency="TO_MEM_CTRL_LATENCY") {
+        out_msg.Address := address;
+        out_msg.Type := MemoryRequestType:MEMORY_WB;
+        //out_msg.OriginalRequestorMachId := machineID;
+        //out_msg.DataBlk := in_msg.DataBlk;
+        out_msg.DataBlk.copyPartial(in_msg.DataBlk, in_msg.Offset, in_msg.Len);
+        out_msg.MessageSize := in_msg.MessageSize;
+        //out_msg.Prefetch := in_msg.Prefetch;
+
+        DEBUG_EXPR(out_msg);
+      }
+    }
+  }
+
+  action(qw_queueMemoryWBRequest_partialTBE, "qwt", desc="Queue off-chip writeback request") {
+    peek(requestQueue_in, RequestMsg) {
+      enqueue(memQueue_out, MemoryMsg, latency="TO_MEM_CTRL_LATENCY") {
+        out_msg.Address := address;
+        out_msg.Type := MemoryRequestType:MEMORY_WB;
+        out_msg.OriginalRequestorMachId := in_msg.Requestor;
+        //out_msg.DataBlk := in_msg.DataBlk;
+        out_msg.DataBlk.copyPartial(TBEs[address].DataBlk, TBEs[address].Offset, TBEs[address].Len);
+        out_msg.MessageSize := in_msg.MessageSize;
+        //out_msg.Prefetch := in_msg.Prefetch;
+
+        DEBUG_EXPR(out_msg);
+      }
+    }
+  }
+
+
+
+  action(l_queueMemoryWBRequest, "lq", desc="Write PUTX data to memory") {
+    peek(requestQueue_in, RequestMsg) {
+      enqueue(memQueue_out, MemoryMsg, latency="TO_MEM_CTRL_LATENCY") {
+        out_msg.Address := address;
+        out_msg.Type := MemoryRequestType:MEMORY_WB;
+        out_msg.OriginalRequestorMachId := in_msg.Requestor;
+        out_msg.DataBlk := in_msg.DataBlk;
+        out_msg.MessageSize := in_msg.MessageSize;
+        //out_msg.Prefetch := in_msg.Prefetch;
+
+        DEBUG_EXPR(out_msg);
+      }
+    }
+  }
+
+  action(l_popMemQueue, "q", desc="Pop off-chip request queue") {
+    memQueue_in.dequeue();
+  }
+
   // TRANSITIONS
 
-  transition(I, GETX, M) {
-    d_sendData;
+  transition({M_DRD, M_DWR}, GETX) {
+    z_recycleRequestQueue;
+  }
+
+  transition({IM, MI, ID, ID_W}, {GETX, GETS, DMA_READ, DMA_WRITE, PUTX, PUTX_NotOwner} ) {
+    z_recycleRequestQueue;
+  }
+
+  transition(I, GETX, IM) {
+    //d_sendData;
+    qf_queueMemoryFetchRequest;
     e_ownerIsRequestor;
     i_popIncomingRequestQueue;
   }
 
+  transition(IM, Memory_Data, M) {
+    d_sendData;
+    //e_ownerIsRequestor;
+    l_popMemQueue;
+  }
+
+
+  transition(I, DMA_READ, ID) {
+    //dr_sendDMAData;
+    qf_queueMemoryFetchRequestDMA;
+    p_popIncomingDMARequestQueue;
+  }
+
+  transition(ID, Memory_Data, I) {
+    dr_sendDMAData;
+    //p_popIncomingDMARequestQueue;
+    l_popMemQueue;
+  }
+
+
+
+  transition(I, DMA_WRITE, ID_W) {
+    dw_writeDMAData;
+//    da_sendDMAAck;
+    qw_queueMemoryWBRequest_partial;
+    p_popIncomingDMARequestQueue;
+  }
+
+  transition(ID_W, Memory_Ack, I) {
+    da_sendDMAAck;
+    l_popMemQueue;
+  }
+
+  transition(M, DMA_READ, M_DRD) {
+    inv_sendCacheInvalidate;
+    p_popIncomingDMARequestQueue;
+  }
+
+  transition(M_DRD, PUTX, I) {
+    drp_sendDMAData;
+    c_clearOwner;
+    a_sendWriteBackAck;
+    //    d_deallocateDirectory;
+    i_popIncomingRequestQueue;
+  }
+
+  transition(M, DMA_WRITE, M_DWR) {
+    v_allocateTBE;
+    inv_sendCacheInvalidate;
+    p_popIncomingDMARequestQueue;
+  }
+
+  transition(M_DWR, PUTX, M_DWRI) {
+    dwt_writeDMADataFromTBE;
+    qw_queueMemoryWBRequest_partialTBE;
+    //a_sendWriteBackAck;
+    c_clearOwner;
+    //da_sendDMAAck;
+    w_deallocateTBE;
+    i_popIncomingRequestQueue;
+  }
+
+  transition(M_DWRI, Memory_Ack, I) {
+    //dwt_writeDMADataFromTBE;
+    l_sendWriteBackAck;
+    //c_clearOwner;
+    da_sendDMAAck;
+    //w_deallocateTBE;
+    l_popMemQueue;
+  }
+
+
 
 
   transition(M, GETX, M) {
     i_popIncomingRequestQueue;
   }
 
-  // transition(M, PUTX, MI) {
-  transition(M, PUTX, I) {
+  transition(M, PUTX, MI) {
     c_clearOwner;
-    l_writeDataToMemory;
-    a_sendWriteBackAck;
+//    l_writeDataToMemory;
+    l_queueMemoryWBRequest;
+//    a_sendWriteBackAck;
+    d_deallocateDirectory;
     i_popIncomingRequestQueue;
   }
 
+  transition(MI, Memory_Ack, I) {
+    l_sendWriteBackAck;
+    l_popMemQueue;
+  }
+
   transition(M, PUTX_NotOwner, M) {
     b_sendWriteBackNack;
     i_popIncomingRequestQueue;
 
   transition(I, PUTX_NotOwner, I) {
     b_sendWriteBackNack;
+    d_deallocateDirectory;
     i_popIncomingRequestQueue;
   }
 
-
-  transition(MI, Unblock, M) {
-    j_popIncomingUnblockQueue;
-  }
-
 }
 
--- /dev/null
+
+machine(DMA, "DMA Controller") {
+
+  MessageBuffer responseFromDir, network="From", virtual_network="4", ordered="true", no_vector="true";
+  MessageBuffer reqToDirectory, network="To", virtual_network="5", ordered="false", no_vector="true";
+
+  enumeration(State, desc="DMA states", default="DMA_State_READY") {
+    READY, desc="Ready to accept a new request";
+    BUSY_RD,  desc="Busy: currently processing a request";
+    BUSY_WR,  desc="Busy: currently processing a request";
+  }
+
+  enumeration(Event, desc="DMA events") {
+    ReadRequest,  desc="A new read request";
+    WriteRequest, desc="A new write request";
+    Data,         desc="Data from a DMA memory read";
+    Ack,          desc="DMA write to memory completed";
+  }
+
+  external_type(DMASequencer) {
+    void ackCallback();
+    void dataCallback(DataBlock);
+  }
+
+  MessageBuffer mandatoryQueue, ordered="false", no_vector="true";
+  DMASequencer dma_sequencer, factory='RubySystem::getDMASequencer(m_cfg["dma_sequencer"])', no_vector="true";
+  State cur_state, no_vector="true";
+
+  State getState(Address addr) {
+    return cur_state;
+  }
+  void setState(Address addr, State state) {
+  cur_state := state;
+  }
+
+  out_port(reqToDirectory_out, DMARequestMsg, reqToDirectory, desc="...");
+
+  in_port(dmaRequestQueue_in, DMARequestMsg, mandatoryQueue, desc="...") {
+    if (dmaRequestQueue_in.isReady()) {
+      peek(dmaRequestQueue_in, DMARequestMsg) {
+        if (in_msg.Type == DMARequestType:READ ) {
+          trigger(Event:ReadRequest, in_msg.PhysicalAddress);
+        } else if (in_msg.Type == DMARequestType:WRITE) {
+          trigger(Event:WriteRequest, in_msg.PhysicalAddress);
+        } else {
+          error("Invalid request type");
+        }
+      }
+    }
+  }
+
+  in_port(dmaResponseQueue_in, DMAResponseMsg, responseFromDir, desc="...") {
+    if (dmaResponseQueue_in.isReady()) {
+      peek( dmaResponseQueue_in, DMAResponseMsg) {
+        if (in_msg.Type == DMAResponseType:ACK) {
+          trigger(Event:Ack, in_msg.PhysicalAddress);
+        } else if (in_msg.Type == DMAResponseType:DATA) {
+          trigger(Event:Data, in_msg.PhysicalAddress);
+        } else {
+          error("Invalid response type");
+        }
+      }
+    }
+  }
+
+  action(s_sendReadRequest, "s", desc="Send a DMA read request to memory") {
+    peek(dmaRequestQueue_in, DMARequestMsg) {
+      enqueue(reqToDirectory_out, DMARequestMsg) {
+        out_msg.PhysicalAddress := address;
+        out_msg.Type := DMARequestType:READ;
+        out_msg.DataBlk := in_msg.DataBlk;
+        out_msg.Len := in_msg.Len;
+        out_msg.Destination.add(map_Address_to_Directory(address));
+        out_msg.MessageSize := MessageSizeType:Writeback_Control;
+      }
+    }
+  }
+
+  action(s_sendWriteRequest, "\s", desc="Send a DMA write request to memory") {
+    peek(dmaRequestQueue_in, DMARequestMsg) {
+        enqueue(reqToDirectory_out, DMARequestMsg) {
+          out_msg.PhysicalAddress := address;
+          out_msg.Type := DMARequestType:WRITE;
+          out_msg.DataBlk := in_msg.DataBlk;
+          out_msg.Len := in_msg.Len;
+          out_msg.Destination.add(map_Address_to_Directory(address));
+          out_msg.MessageSize := MessageSizeType:Writeback_Control;
+        }
+      }
+  }
+
+  action(a_ackCallback, "a", desc="Notify dma controller that write request completed") {
+    peek (dmaResponseQueue_in, DMAResponseMsg) {
+      dma_sequencer.ackCallback();
+    }
+  }
+
+  action(d_dataCallback, "d", desc="Write data to dma sequencer") {
+    peek (dmaResponseQueue_in, DMAResponseMsg) {
+      dma_sequencer.dataCallback(in_msg.DataBlk);
+    }
+  }
+
+  action(p_popRequestQueue, "p", desc="Pop request queue") {
+    dmaRequestQueue_in.dequeue();
+  }
+
+  action(p_popResponseQueue, "\p", desc="Pop request queue") {
+    dmaResponseQueue_in.dequeue();
+  }
+
+  action(z_stall, "z", desc="dma is busy..stall") {
+    // do nothing
+  }
+
+  transition(READY, ReadRequest, BUSY_RD) {
+    s_sendReadRequest;
+    p_popRequestQueue;
+  }
+
+  transition(READY, WriteRequest, BUSY_WR) {
+    s_sendWriteRequest;
+    p_popRequestQueue;
+  }
+
+  transition(BUSY_RD, Data, READY) {
+    d_dataCallback;
+    p_popResponseQueue;
+  }
+
+  transition(BUSY_WR, Ack, READY) {
+    a_ackCallback;
+    p_popResponseQueue;
+  }
+}
 
   CoherenceRequestType Type,   desc="Type of request (GetS, GetX, PutX, etc)";
   MachineID Requestor,            desc="Node who initiated the request";
   NetDest Destination,             desc="Multicast destination mask";
-  int Acks,                    desc="How many acks to expect";
   DataBlock DataBlk,           desc="data for the cache line";
   MessageSizeType MessageSize, desc="size category of the message";
 }
   NetDest Destination,             desc="Node to whom the data is sent";
   DataBlock DataBlk,           desc="data for the cache line";
   bool Dirty,                  desc="Is the data dirty (different than memory)?";
-  int Acks,                    desc="How many acks to expect";
+  MessageSizeType MessageSize, desc="size category of the message";
+}
+
+enumeration(DMARequestType, desc="...", default="DMARequestType_NULL") {
+  READ,          desc="Memory Read";
+  WRITE,         desc="Memory Write";
+  NULL,          desc="Invalid";
+}
+
+enumeration(DMAResponseType, desc="...", default="DMAResponseType_NULL") {
+  DATA,          desc="DATA read";
+  ACK,           desc="ACK write";
+  NULL,          desc="Invalid";
+}
+
+structure(DMARequestMsg, desc="...", interface="NetworkMessage") {
+  DMARequestType Type,       desc="Request type (read/write)";
+  Address PhysicalAddress,   desc="Physical address for this request";
+  NetDest Destination,       desc="Destination";
+  DataBlock DataBlk,         desc="DataBlk attached to this request";
+  int Offset,                desc="The offset into the datablock";
+  int Len,                   desc="The length of the request";
+  MessageSizeType MessageSize, desc="size category of the message";
+}
+
+structure(DMAResponseMsg, desc="...", interface="NetworkMessage") {
+  DMAResponseType Type,      desc="Response type (DATA/ACK)";
+  Address PhysicalAddress,   desc="Physical address for this request";
+  NetDest Destination,       desc="Destination";
+  DataBlock DataBlk,         desc="DataBlk attached to this request";
   MessageSizeType MessageSize, desc="size category of the message";
 }
 
 MI_example-msg.sm
 MI_example-cache.sm
 MI_example-dir.sm
-standard_1level_SMP-protocol.sm
+MI_example-dma.sm
+standard_1level_CMP-protocol.sm
 
 // Mapping functions
 
 // NodeID map_address_to_node(Address addr);
+MachineID map_Address_to_DMA(Address addr);
 MachineID map_Address_to_Directory(Address addr);
 NodeID map_Address_to_DirectoryNode(Address addr);
 MachineID map_Address_to_CentralArbiterNode(Address addr);
 
   IO,          desc="I/O";
   REPLACEMENT, desc="Replacement";
   COMMIT,      desc="Commit version";
+  LD_XACT,     desc="Transactional Load";
+  LDX_XACT,    desc="Transactional Load-Intend-To-Modify";
+  ST_XACT,     desc="Transactional Store";
+  BEGIN_XACT,  desc="Begin Transaction";
+  COMMIT_XACT, desc="Commit Transaction";
+  ABORT_XACT,  desc="Abort Transaction";
   NULL,        desc="Invalid request type";
 }
 
   WB_ACK,      desc="WriteBack ack";
   EXE_ACK,     desc="Execlusive ack";
   COMMIT,      desc="Commit version";
+  LD_XACT,     desc="Transactional Load";
+  LDX_XACT,     desc="Transactional Load-Intend-Modify";
+  ST_XACT,     desc="Transactional Store";
+  BEGIN_XACT,  desc="Begin Transaction";
+  COMMIT_XACT, desc="Commit Transaction";
+  ABORT_XACT,  desc="Abort Transaction";
   NULL,        desc="null request type";
 }
 
 
 // CacheMsg
 structure(CacheMsg, desc="...", interface="Message") {
-  Address Address,           desc="Line address for this request";
+  Address LineAddress,       desc="Line address for this request";
   Address PhysicalAddress,   desc="Physical address for this request";
   CacheRequestType Type,     desc="Type of request (LD, ST, etc)";
   Address ProgramCounter,    desc="Program counter of the instruction that caused the miss";
   AccessModeType AccessMode, desc="user/supervisor access type";
   int Size,                  desc="size in bytes of access";
   PrefetchBit Prefetch,      desc="Is this a prefetch request";
-  // following field only used for MVC
-  int Version,     desc="Version associated with this request";
-  // trans mem fields
-  //bool Aborted,              desc="This flag is set if the request is from an aborted xact.";
-  Address LogicalAddress,    desc="Virtual address for this request";
-  //int TransactionLevel,         desc="Transaction Level of this request";
-  //uint64 SequenceNumber,   desc="Sequence number of this request";
-  int ThreadID,            desc="The SMT thread that initiated this request";
-  //uint64 RequestTime,      desc="The cycle in which this request was issued";
 }
 
-
-
-
 // MaskPredictorType
 enumeration(MaskPredictorType, "MaskPredictorType_Undefined", desc="...") {
   Undefined, desc="Undefined";
 
 
 external_type(DataBlock, desc="..."){
   void clear();
+  void copyPartial(DataBlock, int, int);
 }
 
 external_type(MessageBuffer, buffer="yes", inport="yes", outport="yes");
 external_type(NodeID, default="0");
 external_type(MachineID);
 
-external_type(StoreBuffer);
-
+MessageBuffer getMandatoryQueue(int core_id);
 
 external_type(Set, non_obj="yes") {
   void setSize(int);
   MachineID smallestElement(MachineType);
 }
 
-external_type(PersistentTable) {
-  void persistentRequestLock(Address, MachineID, AccessType);
-  void persistentRequestUnlock(Address, MachineID);
-  bool okToIssueStarving(Address);
-  MachineID findSmallest(Address);
-  AccessType typeOfSmallest(Address);
-  void markEntries(Address);
-  bool isLocked(Address);
-  int countStarvingForAddress(Address);
-  int countReadStarvingForAddress(Address);
-}
-
-external_type(NodePersistentTable) {
-  void persistentRequestLock(Address, NodeID, AccessType);
-  void persistentRequestUnlock(Address, NodeID);
-  bool okToIssueStarving(Address);
-  NodeID findSmallest(Address);
-  AccessType typeOfSmallest(Address);
-  void markEntries(Address);
-  bool isLocked(Address);
-  int countStarvingForAddress(Address);
-  int countReadStarvingForAddress(Address);
-}
-
 external_type(Sequencer) {
-  void readCallback(Address, DataBlock, GenericMachineType, PrefetchBit, int);
-  void writeCallback(Address, DataBlock, GenericMachineType, PrefetchBit, int);
-  void readCallback(Address, DataBlock, GenericMachineType, PrefetchBit);
-  void writeCallback(Address, DataBlock, GenericMachineType, PrefetchBit);
   void readCallback(Address, DataBlock);
   void writeCallback(Address, DataBlock);
-  void readCallback(Address);
-  void writeCallback(Address);
-  void readCallbackAbort(Address, int);
-  void writeCallbackAbort(Address, int);
-  void readConflictCallback(Address);
-  void writeConflictCallback(Address);
-  void xactCallback(Address);
-  void updateCurrentVersion();
-  void updateLastCommittedVersion();
-  void systemRecovery();
-  void systemRestart();
   void checkCoherence(Address);
   void profileNack(Address, int, int, uint64);
-  void resetRequestTime(Address, int);
-  bool isReadAborted(Address, int);
-  bool isWriteAborted(Address, int);
 }
 
 external_type(TimerTable, inport="yes") {
   bool isSet(Address);
 }
 
+external_type(GenericBloomFilter) {
+
+  void clear(int);
+  void increment(Address, int);
+  void decrement(Address, int);
+  void set(Address, int);
+  void unset(Address, int);
+
+  bool isSet(Address, int);
+  int getCount(Address, int);
+}
+
 
 
--- /dev/null
+
+/*
+ * Copyright (c) 1999-2005 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.
+ */
+
+/*
+ * $Id$
+ */
+
+// global protocol features
+global(Protocol, desc="Global properties of this protocol",
+       interface = "AbstractProtocol") {
+  bool TwoLevelCache := false;
+  bool CMP := true;
+}
+
 
 
 #include "mem/ruby/buffers/MessageBuffer.hh"
 #include "mem/ruby/config/RubyConfig.hh"
+#include "mem/ruby/system/System.hh"
 
 MessageBuffer::MessageBuffer()
 {
   // the plus one is a kluge because of a SLICC issue
 
   if (!m_ordering_set) {
-    WARN_EXPR(*this);
+    //    WARN_EXPR(*this);
     WARN_EXPR(m_name);
     ERROR_MSG("Ordering property of this queue has not been set");
   }
 
   // Calculate the arrival time of the message, that is, the first
   // cycle the message can be dequeued.
+//  printf ("delta %i \n", delta);
   assert(delta>0);
   Time current_time = g_eventQueue_ptr->getTime();
   Time arrival_time = 0;
-  if (!RANDOMIZATION || (m_randomization == false)) {
+  if (!RubySystem::getRandomization() || (m_randomization == false)) {
     // No randomization
     arrival_time = current_time + delta;
 
 {
   DEBUG_MSG(QUEUE_COMP,MedPrio,"pop from " + m_name);
   assert(isReady());
-  m_prio_heap.extractMin();
+  Time ready_time = m_prio_heap.extractMin().m_time;
   // record previous size and time so the current buffer size isn't adjusted until next cycle
   if (m_time_last_time_pop < g_eventQueue_ptr->getTime()) {
     m_size_at_cycle_start = m_size;
 
 void MessageBuffer::recycle()
 {
-  //  const int RECYCLE_LATENCY = 3;
+  //  const int RubyConfig::getRecycleLatency() = 3;
   DEBUG_MSG(QUEUE_COMP,MedPrio,"recycling " + m_name);
   assert(isReady());
   MessageBufferNode node = m_prio_heap.extractMin();
-  node.m_time = g_eventQueue_ptr->getTime() + RECYCLE_LATENCY;
+  node.m_time = g_eventQueue_ptr->getTime() + m_recycle_latency;
   m_prio_heap.insert(node);
-  g_eventQueue_ptr->scheduleEventAbsolute(m_consumer_ptr, g_eventQueue_ptr->getTime() + RECYCLE_LATENCY);
+  g_eventQueue_ptr->scheduleEventAbsolute(m_consumer_ptr, g_eventQueue_ptr->getTime() + m_recycle_latency);
 }
 
 int MessageBuffer::setAndReturnDelayCycles(MsgPtr& message)
 
   // Public Methods
 
   static void printConfig(ostream& out) {}
+  void setRecycleLatency(int recycle_latency) { m_recycle_latency = recycle_latency; }
 
   // TRUE if head of queue timestamp <= SystemTime
   bool isReady() const {
   void clearStats() { m_not_avail_count = 0; m_msg_counter = 0; }
 
 private:
+  //added by SS
+  int m_recycle_latency;
+
   // Private Methods
   int setAndReturnDelayCycles(MsgPtr& message);
 
 
+
 /*
  * Copyright (c) 1999 Mark D. Hill and David A. Wood
  * All rights reserved.
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+/*
+ * $Id$
+ */
+
 #ifndef ADDRESS_H
 #define ADDRESS_H
 
 #include <iomanip>
 #include "mem/ruby/common/Global.hh"
-#include "mem/ruby/config/RubyConfig.hh"
+#include "mem/ruby/system/System.hh"
 #include "mem/ruby/system/NodeID.hh"
 #include "mem/ruby/system/MachineID.hh"
 
   physical_address_t maskHighOrderBits(int number) const;
   physical_address_t shiftLowOrderBits(int number) const;
   physical_address_t getLineAddress() const
-    { return bitSelect(RubyConfig::dataBlockBits(), ADDRESS_WIDTH); }
+    { return bitSelect(RubySystem::getBlockSizeBits(), ADDRESS_WIDTH); }
   physical_address_t getOffset() const
-    { return bitSelect(0, RubyConfig::dataBlockBits()-1); }
+    { return bitSelect(0, RubySystem::getBlockSizeBits()-1); }
 
-  void makeLineAddress() { m_address = maskLowOrderBits(RubyConfig::dataBlockBits()); }
+  void makeLineAddress() { m_address = maskLowOrderBits(RubySystem::getBlockSizeBits()); }
   // returns the next stride address based on line address
   void makeNextStrideAddress( int stride) {
-    m_address = maskLowOrderBits(RubyConfig::dataBlockBits())
-      + RubyConfig::dataBlockBytes()*stride;
+    m_address = maskLowOrderBits(RubySystem::getBlockSizeBits())
+      + RubySystem::getBlockSizeBytes()*stride;
   }
-  void makePageAddress() { m_address = maskLowOrderBits(RubyConfig::pageSizeBits()); }
   int getBankSetNum() const;
   int getBankSetDist() const;
 
 inline
 Address line_address(const Address& addr) { Address temp(addr); temp.makeLineAddress(); return temp; }
 
+/*
 inline
 Address next_stride_address(const Address& addr, int stride) {
   Address temp = addr;
   temp.setAddress(temp.maskHighOrderBits(ADDRESS_WIDTH-RubyConfig::memorySizeBits()));  // surpress wrap-around problem
   return temp;
 }
-
-inline
-Address page_address(const Address& addr) { Address temp(addr); temp.makePageAddress(); return temp; }
+*/
 
 // Output operator declaration
 ostream& operator<<(ostream& out, const Address& obj);
 inline
 integer_t Address::memoryModuleIndex() const
 {
-  integer_t index = bitSelect(RubyConfig::dataBlockBits()+RubyConfig::memoryBits(), ADDRESS_WIDTH);
+  integer_t index = bitSelect(RubySystem::getBlockSizeBits()+RubySystem::getMemorySizeBits(), ADDRESS_WIDTH);
   assert (index >= 0);
+  /*
   if (index >= RubyConfig::memoryModuleBlocks()) {
-    cerr << " memoryBits: " << RubyConfig::memoryBits() << " memorySizeBits: " << RubyConfig::memorySizeBits()
-         << " Address: " << "[" << hex << "0x" << m_address << "," << " line 0x" << maskLowOrderBits(RubyConfig::dataBlockBits()) << dec << "]" << flush
+    cerr << " memoryBits: " << RubySystem::getMemorySizeBits() << " memorySizeBits: " << RubySystem::getMemorySizeBits()
+         << " Address: " << "[" << hex << "0x" << m_address << "," << " line 0x" << maskLowOrderBits(RubySystem::getBlockSizeBits()) << dec << "]" << flush
          << "error: limit exceeded. " <<
-      " dataBlockBits: " << RubyConfig::dataBlockBits() <<
+      " getDataBlockBits: " << RubySystem::getBlockSizeBits() <<
       " memoryModuleBlocks: " << RubyConfig::memoryModuleBlocks() <<
       " index: " << index << endl;
   }
   assert (index < RubyConfig::memoryModuleBlocks());
+  */
   return index;
 
   //  Index indexHighPortion = address.bitSelect(MEMORY_SIZE_BITS-1, PAGE_SIZE_BITS+NUMBER_OF_MEMORY_MODULE_BITS);
 inline
 void Address::print(ostream& out) const
 {
-  out << "[" << hex << "0x" << m_address << "," << " line 0x" << maskLowOrderBits(RubyConfig::dataBlockBits()) << dec << "]" << flush;
+  out << "[" << hex << "0x" << m_address << "," << " line 0x" << maskLowOrderBits(RubySystem::getBlockSizeBits()) << dec << "]" << flush;
 }
 
 class Address;
 
   virtual ~Consumer() { }
 
   // Public Methods - pure virtual methods
-  void triggerWakeup() { Time time = g_eventQueue_ptr->getTime(); if (m_last_wakeup != time) { wakeup(); m_last_wakeup = time; }}
+  // void triggerWakeup() { Time time = g_eventQueue_ptr->getTime(); if (m_last_wakeup != time) { wakeup(); m_last_wakeup = time; }}
+  void triggerWakeup(RubyEventQueue * eventQueue) { Time time = eventQueue->getTime(); if (m_last_wakeup != time) { wakeup(); m_last_wakeup = time; }}
   virtual void wakeup() = 0;
   virtual void print(ostream& out) const = 0;
   const Time& getLastScheduledWakeup() const { return m_last_scheduled_wakeup; }
 
 
-/*
- * 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.
- */
-
-/*
- * $Id$
- */
-
 #include "mem/ruby/common/DataBlock.hh"
 
-DataBlock::DataBlock()
-{
-  if (DATA_BLOCK || XACT_MEMORY) {
-    m_data.setSize(RubyConfig::dataBlockBytes());
-  }
-  clear();
-}
-
-DataBlock::~DataBlock()
-{
-
-}
-
-void DataBlock::clear()
-{
-  int size = m_data.size();
-  for (int i = 0; i < size; i++) {
-    m_data[i] = 0;
-  }
-}
-
-bool DataBlock::equal(const DataBlock& obj) const
+DataBlock &
+DataBlock::operator=(const DataBlock & obj)
 {
-  bool value = true;
-  int size = m_data.size();
-  for (int i = 0; i < size; i++) {
-    value = value && (m_data[i] == obj.m_data[i]);
-  }
-  return value;
-}
-
-void DataBlock::print(ostream& out) const
-{
-  int size = m_data.size();
-  for (int i = 0; i < size; i+=4) {
-    out << hex << *((uint32*)(&(m_data[i]))) << " ";
-  }
-  out << dec << "]" << flush;
-}
-
-uint8 DataBlock::getByte(int whichByte) const
-{
-  if (DATA_BLOCK || XACT_MEMORY) {
-  return m_data[whichByte];
+  if (this == &obj) {
+    //    assert(false);
   } else {
-    return 0;
-  }
-}
-
-void DataBlock::setByte(int whichByte, uint8 data)
-{
-  if (DATA_BLOCK || XACT_MEMORY) {
-    m_data[whichByte] = data;
+    if (!m_alloc)
+      m_data = new uint8[RubySystem::getBlockSizeBytes()];
+    memcpy(m_data, obj.m_data, RubySystem::getBlockSizeBytes());
+    m_alloc = true;
   }
+  return *this;
 }
-
 
 #define DATABLOCK_H
 
 #include "mem/ruby/common/Global.hh"
-#include "mem/ruby/config/RubyConfig.hh"
+#include "mem/ruby/system/System.hh"
 #include "mem/gems_common/Vector.hh"
 
 class DataBlock {
-public:
+ public:
   // Constructors
-  DataBlock();
+  DataBlock() {alloc();}
+  DataBlock(const DataBlock & cp) {
+    m_data = new uint8[RubySystem::getBlockSizeBytes()];
+    memcpy(m_data, cp.m_data, RubySystem::getBlockSizeBytes());
+    m_alloc = true;
+  }
 
   // Destructor
-  ~DataBlock();
+  ~DataBlock() { if(m_alloc) delete [] m_data;}
+
+  DataBlock& operator=(const DataBlock& obj);
 
   // Public Methods
+  void assign(uint8* data);
+
   void clear();
   uint8 getByte(int whichByte) const;
+  const uint8* getData(int offset, int len) const;
   void setByte(int whichByte, uint8 data);
+  void setData(uint8* data, int offset, int len);
+  void copyPartial(const DataBlock & dblk, int offset, int len);
   bool equal(const DataBlock& obj) const;
   void print(ostream& out) const;
 
 private:
-  // Private Methods
-
+  void alloc();
   // Data Members (m_ prefix)
-  Vector<uint8> m_data;
+  uint8* m_data;
+  bool m_alloc;
 };
 
 // Output operator declaration
 
 bool operator==(const DataBlock& obj1, const DataBlock& obj2);
 
+// inline functions for speed
+
+inline
+void DataBlock::assign(uint8* data)
+{
+  delete [] m_data;
+  m_data = data;
+  m_alloc = false;
+}
+
+inline
+void DataBlock::alloc()
+{
+  m_data = new uint8[RubySystem::getBlockSizeBytes()];
+  m_alloc = true;
+  clear();
+}
+
+inline
+void DataBlock::clear()
+{
+  memset(m_data, 0, RubySystem::getBlockSizeBytes());
+}
+
+inline
+bool DataBlock::equal(const DataBlock& obj) const
+{
+  return !memcmp(m_data, obj.m_data, RubySystem::getBlockSizeBytes());
+}
+
+inline
+void DataBlock::print(ostream& out) const
+{
+  int size = RubySystem::getBlockSizeBytes();
+  out << "[ ";
+  for (int i = 0; i < size; i+=4) {
+    out << hex << *((uint32*)(&(m_data[i]))) << " ";
+  }
+  out << dec << "]" << flush;
+}
+
+inline
+uint8 DataBlock::getByte(int whichByte) const
+{
+  return m_data[whichByte];
+}
+
+inline
+const uint8* DataBlock::getData(int offset, int len) const
+{
+  assert(offset + len <= RubySystem::getBlockSizeBytes());
+  return &m_data[offset];
+}
+
+inline
+void DataBlock::setByte(int whichByte, uint8 data)
+{
+    m_data[whichByte] = data;
+}
+
+inline
+void DataBlock::setData(uint8* data, int offset, int len)
+{
+  assert(offset + len <= RubySystem::getBlockSizeBytes());
+  memcpy(&m_data[offset], data, len);
+}
+
+inline
+void DataBlock::copyPartial(const DataBlock & dblk, int offset, int len)
+{
+  setData(&dblk.m_data[offset], offset, len);
+}
 
 // ******************* Definitions *******************
 
 
 #include "mem/ruby/common/Global.hh"
 #include "mem/ruby/common/Debug.hh"
 #include "mem/ruby/eventqueue/RubyEventQueue.hh"
+#include "mem/gems_common/util.hh"
 
 class Debug;
 extern Debug* g_debug_ptr;
 std::ostream * debug_cout_ptr;
 
-struct DebugComponentData
+bool Debug::m_protocol_trace = false;
+
+// component character list
+const char DEFINE_COMP_CHAR[] =
 {
-    const char *desc;
-    const char ch;
+#undef DEFINE_COMP
+#define DEFINE_COMP(component, character, description) character,
+#include "Debug.def"
 };
 
-// component character list
-DebugComponentData debugComponents[] =
+// component description list
+const char* DEFINE_COMP_DESCRIPTION[] =
 {
-    {"System",            's' },
-    {"Node",              'N' },
-    {"Queue",             'q' },
-    {"Event Queue",       'e' },
-    {"Network",           'n' },
-    {"Sequencer",         'S' },
-    {"Tester",            't' },
-    {"Generated",         'g' },
-    {"SLICC",             'l' },
-    {"Network Queues",    'Q' },
-    {"Time",              'T' },
-    {"Network Internals", 'i' },
-    {"Store Buffer",      'b' },
-    {"Cache",             'c' },
-    {"Predictor",         'p' },
-    {"Allocator",         'a' },
+#undef DEFINE_COMP
+#define DEFINE_COMP(component, character, description) description,
+#include "Debug.def"
 };
 
 extern "C" void changeDebugVerbosity(VerbosityLevel vb);
   g_debug_ptr->setFilter(filter);
 }
 
+Debug::Debug()
+{
+  m_verbosityLevel = No_Verb;
+  m_starting_cycle = ~0;
+  clearFilter();
+  debug_cout_ptr = &cout;
+}
+
+Debug::Debug( const string & name, const vector<string> & argv )
+{
+  for (size_t i=0;i<argv.size();i+=2){
+    if (argv[i] == "filter_string")
+      setFilterString( argv[i+1].c_str() );
+    else if (argv[i] == "verbosity_string")
+      setVerbosityString( argv[i+1].c_str() );
+    else if (argv[i] == "start_time")
+      m_starting_cycle = atoi( argv[i+1].c_str() );
+    else if (argv[i] == "output_filename")
+      setDebugOutputFile( argv[i+1].c_str() );
+    else if (argv[i] == "protocol_trace")
+      m_protocol_trace = string_to_bool(argv[i+1]);
+    else
+      assert(0);
+  }
+}
+
 Debug::Debug( const char *filterString, const char *verboseString,
               Time filterStartTime, const char *filename )
 {
 {
   for (int i=0; i<NUMBER_OF_COMPS; i++) {
     // Look at all components to find a character match
-    if (debugComponents[i].ch == ch) {
+    if (DEFINE_COMP_CHAR[i] == ch) {
       // We found a match - return no error
       return false; // no error
     }
 {
   for (int i=0; i<NUMBER_OF_COMPS; i++) {
     // Look at all components to find a character match
-    if (debugComponents[i].ch == ch) {
+    if (DEFINE_COMP_CHAR[i] == ch) {
       // We found a match - update the filter bit mask
-      cout << "  Debug: Adding to filter: '" << ch << "' (" << debugComponents[i].desc << ")" << endl;
+      cout << "  Debug: Adding to filter: '" << ch << "' (" << DEFINE_COMP_DESCRIPTION[i] << ")" << endl;
       m_filter |= (1 << i);
       return false; // no error
     }
 {
   cerr << "Debug components: " << endl;
   for (int i=0; i<NUMBER_OF_COMPS; i++) {
-    cerr << "  " << debugComponents[i].ch << ": " << debugComponents[i].desc << endl;
+    cerr << "  " << DEFINE_COMP_CHAR[i] << ": " << DEFINE_COMP_DESCRIPTION[i] << endl;
   }
 }
 
 
  * $Id$
  */
 
-#ifndef __MEM_RUBY_DEBUG_HH__
-#define __MEM_RUBY_DEBUG_HH__
+#ifndef DEBUG_H
+#define DEBUG_H
 
 #include <unistd.h>
 #include <iostream>
 
-#include "config/ruby_debug.hh"
-#include "mem/ruby/common/Global.hh"
-
 extern std::ostream * debug_cout_ptr;
 
 // component enumeration
 enum DebugComponents
 {
-    SYSTEM_COMP,
-    NODE_COMP,
-    QUEUE_COMP,
-    EVENTQUEUE_COMP,
-    NETWORK_COMP,
-    SEQUENCER_COMP,
-    TESTER_COMP,
-    GENERATED_COMP,
-    SLICC_COMP,
-    NETWORKQUEUE_COMP,
-    TIME_COMP,
-    NETWORK_INTERNALS_COMP,
-    STOREBUFFER_COMP,
-    CACHE_COMP,
-    PREDICTOR_COMP,
-    ALLOCATOR_COMP,
-    NUMBER_OF_COMPS
+#undef DEFINE_COMP
+#define DEFINE_COMP(component, character, description) component,
+#include "Debug.def"
+  NUMBER_OF_COMPS
 };
 
 enum PriorityLevel {HighPrio, MedPrio, LowPrio};
 class Debug {
 public:
   // Constructors
+  Debug();
+  Debug( const string & name, const vector<string> & argv );
   Debug( const char *filterString, const char *verboseString,
          Time filterStartTime, const char *filename );
 
   ~Debug();
 
   // Public Methods
+  static bool getProtocolTrace() { return m_protocol_trace; }
   bool validDebug(int module, PriorityLevel priority);
   void printVerbosity(ostream& out) const;
   void setVerbosity(VerbosityLevel vb);
   Debug& operator=(const Debug& obj);
 
   // Data Members (m_ prefix)
+  static bool m_protocol_trace;
   VerbosityLevel m_verbosityLevel;
   int m_filter;
   Time m_starting_cycle;
            << __PRETTY_FUNCTION__ << " in "\
            << __FILE__ << ":"\
            << __LINE__ << endl << flush;\
-      if(isatty(STDERR_FILENO)) {\
+      if(isatty(STDIN_FILENO)) {\
         cerr << "At this point you might want to attach a debug to ";\
         cerr << "the running and get to the" << endl;\
         cerr << "crash site; otherwise press enter to continue" << endl;\
          << __PRETTY_FUNCTION__ << " in "\
          << __FILE__ << ":"\
          << __LINE__ << endl << flush;\
-    if(isatty(STDERR_FILENO)) {\
+    if(isatty(STDIN_FILENO)) {\
       cerr << "press enter to continue" << endl;\
       cerr << "PID: " << getpid();\
       cerr << endl << flush; \
   }\
 }
 
-#endif // __MEM_RUBY_DEBUG_HH__
+#endif //DEBUG_H
 
 
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+/*
+ * $Id$
+ *
+ * Description:
+ *
+ */
+
 #ifndef DRIVER_H
 #define DRIVER_H
 
 #include "mem/ruby/common/Consumer.hh"
 #include "mem/ruby/system/NodeID.hh"
 #include "mem/protocol/CacheRequestType.hh"
-#include "mem/packet.hh"
 
 class RubySystem;
 class SubBlock;
 
   // Public Methods
   virtual void get_network_config() {}
-  virtual void hitCallback(Packet* pkt) = 0;
+  virtual void dmaHitCallback() = 0;
+  virtual void hitCallback(NodeID proc, SubBlock& data, CacheRequestType type, int thread) = 0; // Called by sequencer
+  virtual void conflictCallback(NodeID proc, SubBlock& data, CacheRequestType type, int thread) { assert(0) }; // Called by sequencer
   virtual integer_t getInstructionCount(int procID) const { return 1; }
   virtual integer_t getCycleCount(int procID) const { return 1; }
-
+  virtual void addThreadDependency(int procID, int requestor_thread, int conflict_thread) const { assert(0);}
+  virtual int inTransaction(int procID, int thread ) const{
+    cout << "Driver.hh inTransaction " << endl;
+return false; } //called by Sequencer
   virtual void printDebug(){}  //called by Sequencer
 
   virtual void printStats(ostream& out) const = 0;
 
   virtual void printConfig(ostream& out) const = 0;
 
+  //virtual void abortCallback(NodeID proc){}
+
   virtual integer_t readPhysicalMemory(int procID, physical_address_t address,
                                        int len ){ ASSERT(0); return 0; }
 
 
  *
  * */
 
-#ifndef __MEM_RUBY_GLOBAL_HH__
-#define __MEM_RUBY_GLOBAL_HH__
+#ifndef GLOBAL_H
+#define GLOBAL_H
 
+/*
 #ifdef SINGLE_LEVEL_CACHE
 const bool TWO_LEVEL_CACHE = false;
 #define L1I_CACHE_MEMBER_VARIABLE m_L1Cache_cacheMemory_vec[m_version] // currently all protocols require L1s == nodes
 #define DIRECTORY_MEMBER_VARIABLE m_Directory_directory_vec[m_version]
 #define TBE_TABLE_MEMBER_VARIABLE m_L1Cache_TBEs_vec[m_version]
 
-typedef unsigned char uint8;
-typedef unsigned int uint32;
-typedef unsigned long long uint64;
-
-typedef signed char int8;
-typedef int int32;
-typedef long long int64;
-
-typedef long long integer_t;
-typedef unsigned long long uinteger_t;
+*/
 
-typedef int64 Time;
-typedef uint64 physical_address_t;
-typedef uint64 la_t;
-typedef uint64 pa_t;
-typedef integer_t simtime_t;
 
 // external includes for all classes
+#include "mem/ruby/common/TypeDefines.hh"
 #include "mem/gems_common/std-includes.hh"
 #include "mem/ruby/common/Debug.hh"
 
 typedef Time LogicalTime;
 typedef int64 Index;            // what the address bit ripper returns
 typedef int word;               // one word of a cache line
+typedef unsigned int uint;
 typedef int SwitchID;
 typedef int LinkID;
 
 }
 
 
-#endif // __MEM_RUBY_GLOBAL_HH__
+#endif //GLOBAL_H
 
 
 // set sizes
 
 #include "mem/ruby/common/Set.hh"
+#include "mem/ruby/system/System.hh"
 #include "mem/ruby/config/RubyConfig.hh"
 
 #if __amd64__ || __LP64__
 Set::Set()
 {
   m_p_nArray = NULL;
-  setSize(RubyConfig::numberOfProcessors());
+  setSize(RubySystem::getNumberOfSequencers());
 }
 
 // copy constructor
 #endif // __32BITS__
 
   // decide whether to use dynamic or static alloction
-  if(m_nArrayLen<=NUMBER_WORDS_PER_SET) { // constant defined in RubyConfig.h
+  if(m_nArrayLen<=NUMBER_WORDS_PER_SET) { // constant defined in RubyConfig.hh
     // its OK to use the static allocation, and it will
     // probably be faster (as m_nArrayLen is already in the
     // cache and they will probably share the same cache line)
     return;
   }
   char buff[24];
-  out << "[Set 0x ";
+  out << "[Set (" << m_nSize << ") 0x ";
   for (int i=m_nArrayLen-1; i>=0; i--) {
 #ifdef __32BITS__
     sprintf(buff,"%08X ",m_p_nArray[i]);
 
   }
 }
 
-SubBlock::SubBlock(const Address& addr, const Address& logicalAddress, int size)
-{
-  m_address = addr;
-  m_logicalAddress = logicalAddress;
-  setSize(size);
-  for(int i=0; i<size; i++) {
-    setByte(i, 0);
-  }
-}
-
 void SubBlock::internalMergeFrom(const DataBlock& data)
 {
   int size = getSize();
 
   // Constructors
   SubBlock() { }
   SubBlock(const Address& addr, int size);
-  SubBlock(const Address& addr, const Address& logicalAddress, int size);
 
   // Destructor
   ~SubBlock() { }
 
   // Public Methods
   const Address& getAddress() const { return m_address; }
-  const Address& getLogicalAddress() const { return m_logicalAddress; }
   void setAddress(const Address& addr) { m_address = addr; }
-  void setLogicalAddress(const Address& addr) { m_logicalAddress = addr; }
 
   int getSize() const { return m_data.size(); }
   void setSize(int size) {  m_data.setSize(size); }
 
   // Merging to and from DataBlocks - We only need to worry about
   // updates when we are using DataBlocks
-  void mergeTo(DataBlock& data) const { if (DATA_BLOCK) { internalMergeTo(data); } }
-  void mergeFrom(const DataBlock& data) { if (DATA_BLOCK) { internalMergeFrom(data); } }
+  void mergeTo(DataBlock& data) const { internalMergeTo(data); }
+  void mergeFrom(const DataBlock& data) { internalMergeFrom(data); }
 
   void print(ostream& out) const;
 private:
-  // Private Methods
-  //  SubBlock(const SubBlock& obj);
-  //  SubBlock& operator=(const SubBlock& obj);
-  //  bool bytePresent(const Address& addr) { return ((addr.getAddress() >= m_address.getAddress()) && (addr.getAddress() < (m_address.getAddress()+getSize()))); }
-  //  uint8 getByte(const Address& addr) { return m_data[addr.getAddress() - m_address.getAddress()]; }
 
   void internalMergeTo(DataBlock& data) const;
   void internalMergeFrom(const DataBlock& data);
 
   // Data Members (m_ prefix)
   Address m_address;
-  Address m_logicalAddress;
-  Vector<unsigned> m_data;
+  Vector<uint> m_data;
 };
 
 // Output operator declaration
 
--- /dev/null
+
+#ifndef TYPEDEFINES_H
+#define TYPEDEFINES_H
+
+
+typedef unsigned char uint8;
+typedef unsigned int uint32;
+typedef unsigned long long uint64;
+
+typedef signed char int8;
+typedef int int32;
+typedef long long int64;
+
+typedef long long integer_t;
+typedef unsigned long long uinteger_t;
+
+typedef int64 Time;
+typedef uint64 physical_address_t;
+typedef uint64 la_t;
+typedef uint64 pa_t;
+typedef integer_t simtime_t;
+
+#endif
 
--- /dev/null
+#!/usr/bin/ruby
+#
+#  Creates a homogeneous CMP system with a single unified cache per
+#  core and a crossbar network.  Uses the default parameters listed
+#  below, which can be overridden if a wrapper script sets the hash
+#  libruby_args.
+#
+
+require "cfg.rb"
+
+# default values
+
+num_cores = 16
+L1_CACHE_SIZE_KB = 32
+L1_CACHE_ASSOC = 8
+L1_CACHE_LATENCY = "auto"
+num_memories = 2
+memory_size_mb = 1024
+NUM_DMA = 1
+
+# check for overrides
+
+for i in 0..$*.size-1 do
+  if $*[i] == "-p"
+    num_cores = $*[i+1].to_i
+    i = i+1
+  elsif $*[i] == "-m"
+    num_memories = $*[i+1].to_i
+    i = i+1
+  elsif $*[i] == "-s"
+    memory_size_mb = $*[i+1].to_i
+    i = i + 1
+  end
+end
+
+net_ports = Array.new
+iface_ports = Array.new
+
+num_cores.times { |n|
+  cache = SetAssociativeCache.new("l1u_"+n.to_s, L1_CACHE_SIZE_KB, L1_CACHE_LATENCY, L1_CACHE_ASSOC, "PSEUDO_LRU")
+  sequencer = Sequencer.new("Sequencer_"+n.to_s, cache, cache)
+  iface_ports << sequencer
+  net_ports << MI_example_CacheController.new("L1CacheController_"+n.to_s,
+                                   "L1Cache",
+                                   [cache],
+                                   sequencer)
+}
+num_memories.times { |n|
+  directory = DirectoryMemory.new("DirectoryMemory_"+n.to_s, memory_size_mb/num_memories)
+  memory_control = MemoryControl.new("MemoryControl_"+n.to_s)
+  net_ports << MI_example_DirectoryController.new("DirectoryController_"+n.to_s,
+                                       "Directory",
+                                       directory, memory_control)
+}
+NUM_DMA.times { |n|
+  dma_sequencer = DMASequencer.new("DMASequencer_"+n.to_s)
+  iface_ports << dma_sequencer
+  net_ports << DMAController.new("DMAController_"+n.to_s, "DMA", dma_sequencer)
+}
+
+topology = CrossbarTopology.new("theTopology", net_ports)
+on_chip_net = Network.new("theNetwork", topology)
+
+RubySystem.init(iface_ports, on_chip_net)
 
  *
  */
 
-#include "config/ruby_debug.hh"
 #include "mem/ruby/config/RubyConfig.hh"
-#include "mem/protocol/protocol_name.hh"
+//#include "mem/protocol/protocol_name.hh"
 #include "mem/gems_common/util.hh"
-#include "mem/protocol/Protocol.hh"
+
+#define CONFIG_DEF_FILE "mem/ruby/config/config.hh"
+
+#define ERROR_MSG(MESSAGE)\
+{\
+    cerr << "Fatal Error: in fn "\
+         << __PRETTY_FUNCTION__ << " in "\
+         << __FILE__ << ":"\
+         << __LINE__ << ": "\
+         << (MESSAGE) << endl << flush;\
+    abort();\
+}
+
+// declare all configuration variables
+#define PARAM_BOOL( NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \
+  bool RubyConfig::m_##NAME = DEFAULT_VALUE;
+#define PARAM_STRING( NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \
+  const char* RubyConfig::m_##NAME = DEFAULT_VALUE;
+#define PARAM_ULONG( NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \
+  uint64 RubyConfig::m_##NAME = DEFAULT_VALUE;
+#define PARAM( NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \
+  int RubyConfig::m_##NAME = DEFAULT_VALUE;
+#define PARAM_ARRAY( NAME, TYPE, DEFAULT_ARRAY_SIZE, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \
+  TYPE* RubyConfig::m_##NAME = NULL;
+#define PARAM_ARRAY2D( NAME, TYPE, D1_DEFAULT_ARRAY_SIZE, D2_DEFAULT_ARRAY_SIZE, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \
+  TYPE** RubyConfig::m_##NAME = NULL;
+#define PARAM_ARRAY3D( NAME, TYPE, D1_DEFAULT_ARRAY_SIZE, D2_DEFAULT_ARRAY_SIZE, D3_DEFAULT_ARRAY_SIZE, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \
+  TYPE*** RubyConfig::m_##NAME = NULL;
+#include CONFIG_DEF_FILE
+#undef PARAM_BOOL
+#undef PARAM_STRING
+#undef PARAM_ULONG
+#undef PARAM
+#undef PARAM_ARRAY
+#undef PARAM_ARRAY2D
+#undef PARAM_ARRAY3D
 
 #define CHECK_POWER_OF_2(N) { if (!is_power_of_2(N)) { ERROR_MSG(#N " must be a power of 2."); }}
 #define CHECK_ZERO(N) { if (N != 0) { ERROR_MSG(#N " must be zero at initialization."); }}
 #define CHECK_NON_ZERO(N) { if (N == 0) { ERROR_MSG(#N " must be non-zero."); }}
 
+uint32 RubyConfig::m_data_block_mask;
+
+void RubyConfig::reset()
+{
+ #define PARAM_BOOL( NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \
+  m_##NAME = DEFAULT_VALUE;
+#define PARAM_STRING( NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \
+  m_##NAME = DEFAULT_VALUE;
+#define PARAM_ULONG( NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \
+  m_##NAME = DEFAULT_VALUE;
+#define PARAM( NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \
+  m_##NAME = DEFAULT_VALUE;
+#define PARAM_ARRAY( NAME, TYPE, DEFAULT_ARRAY_SIZE, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \
+  m_##NAME = new TYPE[DEFAULT_ARRAY_SIZE]; \
+  for (int i=0; i<DEFAULT_ARRAY_SIZE; i++) \
+    m_##NAME[i] = DEFAULT_VALUE;
+#define PARAM_ARRAY2D( NAME, TYPE, D1_DEFAULT_ARRAY_SIZE, D2_DEFAULT_ARRAY_SIZE, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \
+  m_##NAME = new TYPE*[D1_DEFAULT_ARRAY_SIZE]; \
+  for (int i=0; i<D1_DEFAULT_ARRAY_SIZE; i++) {       \
+    m_##NAME[i] = new TYPE[D2_DEFAULT_ARRAY_SIZE]; \
+    for (int j=0; j<D2_DEFAULT_ARRAY_SIZE; j++) \
+      m_##NAME[i][j] = DEFAULT_VALUE; \
+  }
+#define PARAM_ARRAY3D( NAME, TYPE, D1_DEFAULT_ARRAY_SIZE, D2_DEFAULT_ARRAY_SIZE, D3_DEFAULT_ARRAY_SIZE, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \
+  m_##NAME = new TYPE**[D1_DEFAULT_ARRAY_SIZE];                         \
+  for (int i=0; i<D1_DEFAULT_ARRAY_SIZE; i++) {                         \
+    m_##NAME[i] = new TYPE*[D2_DEFAULT_ARRAY_SIZE];                     \
+    for (int j=0; j<D2_DEFAULT_ARRAY_SIZE; j++) {                       \
+      m_##NAME[i][j] = new TYPE[D3_DEFAULT_ARRAY_SIZE];                 \
+      for (int k=0; k<D3_DEFAULT_ARRAY_SIZE; k++)                       \
+        m_##NAME[i][j][k] = DEFUALT_VALUE;                              \
+    }                                                                   \
+  }
+#include CONFIG_DEF_FILE
+#undef PARAM_BOOL
+#undef PARAM_STRING
+#undef PARAM_ULONG
+#undef PARAM
+#undef PARAM_ARRAY
+#undef PARAM_ARRAY2D
+#undef PARAM_ARRAY3D
+}
 
 void RubyConfig::init()
 {
+  /*
   // MemoryControl:
-  CHECK_NON_ZERO(MEM_BUS_CYCLE_MULTIPLIER);
-  CHECK_NON_ZERO(BANKS_PER_RANK);
-  CHECK_NON_ZERO(RANKS_PER_DIMM);
-  CHECK_NON_ZERO(DIMMS_PER_CHANNEL);
-  CHECK_NON_ZERO(BANK_QUEUE_SIZE);
-  CHECK_NON_ZERO(BANK_BUSY_TIME);
-  CHECK_NON_ZERO(MEM_CTL_LATENCY);
-  CHECK_NON_ZERO(REFRESH_PERIOD);
-  CHECK_NON_ZERO(BASIC_BUS_BUSY_TIME);
-
-  CHECK_POWER_OF_2(BANKS_PER_RANK);
-  CHECK_POWER_OF_2(RANKS_PER_DIMM);
-  CHECK_POWER_OF_2(DIMMS_PER_CHANNEL);
-
-  CHECK_NON_ZERO(g_MEMORY_SIZE_BYTES);
-  CHECK_NON_ZERO(g_DATA_BLOCK_BYTES);
-  CHECK_NON_ZERO(g_PAGE_SIZE_BYTES);
-  CHECK_NON_ZERO(g_NUM_PROCESSORS);
-  CHECK_NON_ZERO(g_PROCS_PER_CHIP);
-  if(g_NUM_SMT_THREADS == 0){ //defaults to single-threaded
-    g_NUM_SMT_THREADS = 1;
-  }
-  if (g_NUM_L2_BANKS == 0) {  // defaults to number of ruby nodes
-    g_NUM_L2_BANKS = g_NUM_PROCESSORS;
+  CHECK_NON_ZERO(m_MEM_BUS_CYCLE_MULTIPLIER);
+  CHECK_NON_ZERO(m_BANKS_PER_RANK);
+  CHECK_NON_ZERO(m_RANKS_PER_DIMM);
+  CHECK_NON_ZERO(m_DIMMS_PER_CHANNEL);
+  CHECK_NON_ZERO(m_BANK_QUEUE_SIZE);
+  CHECK_NON_ZERO(m_BankBusyTime);
+  CHECK_NON_ZERO(m_MEM_CTL_LATENCY);
+  CHECK_NON_ZERO(m_REFRESH_PERIOD);
+  CHECK_NON_ZERO(m_BASIC_BUS_BUSY_TIME);
+
+  CHECK_POWER_OF_2(m_BANKS_PER_RANK);
+  CHECK_POWER_OF_2(m_RANKS_PER_DIMM);
+  CHECK_POWER_OF_2(m_DIMMS_PER_CHANNEL);
+
+  CHECK_NON_ZERO(m_MemorySizeBytes);
+  //  CHECK_NON_ZERO(m_DATA_BLOCK_BYTES);
+  CHECK_NON_ZERO(m_NUM_PROCESSORS);
+  CHECK_NON_ZERO(m_ProcsPerChip);
+
+  if (m_NUM_L2_BANKS == 0) {  // defaults to number of ruby nodes
+    m_NUM_L2_BANKS = m_NUM_PROCESSORS;
   }
-  if (g_NUM_MEMORIES == 0) {  // defaults to number of ruby nodes
-    g_NUM_MEMORIES = g_NUM_PROCESSORS;
+  if (m_NUM_MEMORIES == 0) {  // defaults to number of ruby nodes
+    m_NUM_MEMORIES = m_NUM_PROCESSORS;
   }
 
-  CHECK_ZERO(g_MEMORY_SIZE_BITS);
-  CHECK_ZERO(g_DATA_BLOCK_BITS);
-  CHECK_ZERO(g_PAGE_SIZE_BITS);
-  CHECK_ZERO(g_NUM_PROCESSORS_BITS);
-  CHECK_ZERO(g_NUM_CHIP_BITS);
-  CHECK_ZERO(g_NUM_L2_BANKS_BITS);
-  CHECK_ZERO(g_NUM_MEMORIES_BITS);
-  CHECK_ZERO(g_PROCS_PER_CHIP_BITS);
-  CHECK_ZERO(g_NUM_L2_BANKS_PER_CHIP);
-  CHECK_ZERO(g_NUM_L2_BANKS_PER_CHIP_BITS);
-  CHECK_ZERO(g_NUM_MEMORIES_BITS);
-  CHECK_ZERO(g_MEMORY_MODULE_BLOCKS);
-  CHECK_ZERO(g_MEMORY_MODULE_BITS);
-  CHECK_ZERO(g_NUM_MEMORIES_PER_CHIP);
-
-  CHECK_POWER_OF_2(g_MEMORY_SIZE_BYTES);
-  CHECK_POWER_OF_2(g_DATA_BLOCK_BYTES);
-  CHECK_POWER_OF_2(g_NUM_PROCESSORS);
-  CHECK_POWER_OF_2(g_NUM_L2_BANKS);
-  CHECK_POWER_OF_2(g_NUM_MEMORIES);
-  CHECK_POWER_OF_2(g_PROCS_PER_CHIP);
-
-  ASSERT(g_NUM_PROCESSORS >= g_PROCS_PER_CHIP);  // obviously can't have less processors than procs/chip
-  g_NUM_CHIPS = g_NUM_PROCESSORS/g_PROCS_PER_CHIP;
-  ASSERT(g_NUM_L2_BANKS >= g_NUM_CHIPS);  // cannot have a single L2cache across multiple chips
-
-  g_NUM_L2_BANKS_PER_CHIP = g_NUM_L2_BANKS/g_NUM_CHIPS;
-
-  ASSERT(L2_CACHE_NUM_SETS_BITS > log_int(g_NUM_L2_BANKS_PER_CHIP));  // cannot have less than one set per bank
-  L2_CACHE_NUM_SETS_BITS = L2_CACHE_NUM_SETS_BITS - log_int(g_NUM_L2_BANKS_PER_CHIP);
-
-  if (g_NUM_CHIPS > g_NUM_MEMORIES) {
-    g_NUM_MEMORIES_PER_CHIP = 1;  // some chips have a memory, others don't
+  CHECK_ZERO(m_MEMORY_SIZE_BITS);
+  CHECK_ZERO(m_NUM_PROCESSORS_BITS);
+  CHECK_ZERO(m_NUM_CHIP_BITS);
+  CHECK_ZERO(m_NUM_L2_BANKS_BITS);
+  CHECK_ZERO(m_NUM_MEMORIES_BITS);
+  CHECK_ZERO(m_PROCS_PER_CHIP_BITS);
+  CHECK_ZERO(m_NUM_L2_BANKS_PER_CHIP);
+  CHECK_ZERO(m_NUM_L2_BANKS_PER_CHIP_BITS);
+  CHECK_ZERO(m_NUM_MEMORIES_BITS);
+  CHECK_ZERO(m_MEMORY_MODULE_BLOCKS);
+  CHECK_ZERO(m_MEMORY_MODULE_BITS);
+  CHECK_ZERO(m_NUM_MEMORIES_PER_CHIP);
+
+  CHECK_POWER_OF_2(m_MemorySizeBytes);
+  CHECK_POWER_OF_2(m_NUM_PROCESSORS);
+  CHECK_POWER_OF_2(m_NUM_L2_BANKS);
+  CHECK_POWER_OF_2(m_NUM_MEMORIES);
+  CHECK_POWER_OF_2(m_ProcsPerChip);
+
+  assert(m_NUM_PROCESSORS >= m_ProcsPerChip);  // obviously can't have less processors than procs/chip
+  m_NUM_CHIPS = m_NUM_PROCESSORS/m_ProcsPerChip;
+  assert(m_NUM_L2_BANKS >= m_NUM_CHIPS);  // cannot have a single L2cache across multiple chips
+
+  m_NUM_L2_BANKS_PER_CHIP = m_NUM_L2_BANKS/m_NUM_CHIPS;
+
+  if (m_NUM_CHIPS > m_NUM_MEMORIES) {
+    m_NUM_MEMORIES_PER_CHIP = 1;  // some chips have a memory, others don't
   } else {
-    g_NUM_MEMORIES_PER_CHIP = g_NUM_MEMORIES/g_NUM_CHIPS;
+    m_NUM_MEMORIES_PER_CHIP = m_NUM_MEMORIES/m_NUM_CHIPS;
   }
 
-  g_NUM_CHIP_BITS = log_int(g_NUM_CHIPS);
-  g_MEMORY_SIZE_BITS = log_int(g_MEMORY_SIZE_BYTES);
-  g_DATA_BLOCK_BITS = log_int(g_DATA_BLOCK_BYTES);
-  g_PAGE_SIZE_BITS = log_int(g_PAGE_SIZE_BYTES);
-  g_NUM_PROCESSORS_BITS = log_int(g_NUM_PROCESSORS);
-  g_NUM_L2_BANKS_BITS = log_int(g_NUM_L2_BANKS);
-  g_NUM_L2_BANKS_PER_CHIP_BITS = log_int(g_NUM_L2_BANKS_PER_CHIP);
-  g_NUM_MEMORIES_BITS = log_int(g_NUM_MEMORIES);
-  g_PROCS_PER_CHIP_BITS = log_int(g_PROCS_PER_CHIP);
-
-  g_MEMORY_MODULE_BITS = g_MEMORY_SIZE_BITS - g_DATA_BLOCK_BITS - g_NUM_MEMORIES_BITS;
-  g_MEMORY_MODULE_BLOCKS = (int64(1) << g_MEMORY_MODULE_BITS);
-
-  if ((!Protocol::m_CMP) && (g_PROCS_PER_CHIP > 1)) {
-    ERROR_MSG("Non-CMP protocol should set g_PROCS_PER_CHIP to 1");
-  }
+  m_NUM_CHIP_BITS = log_int(m_NUM_CHIPS);
+  m_MEMORY_SIZE_BITS = log_int(m_MemorySizeBytes);
 
-  // Randomize the execution
-  srandom(g_RANDOM_SEED);
-}
+  m_data_block_mask = ~ (~0 << m_DATA_BLOCK_BITS);
 
-int RubyConfig::L1CacheNumToL2Base(NodeID L1CacheNum)
-{
-  return L1CacheNum/g_PROCS_PER_CHIP;
+  m_NUM_PROCESSORS_BITS = log_int(m_NUM_PROCESSORS);
+  m_NUM_L2_BANKS_BITS = log_int(m_NUM_L2_BANKS);
+  m_NUM_L2_BANKS_PER_CHIP_BITS = log_int(m_NUM_L2_BANKS_PER_CHIP);
+  m_NUM_MEMORIES_BITS = log_int(m_NUM_MEMORIES);
+  m_PROCS_PER_CHIP_BITS = log_int(m_ProcsPerChip);
+
+  m_MEMORY_MODULE_BITS = m_MEMORY_SIZE_BITS - m_DATA_BLOCK_BITS - m_NUM_MEMORIES_BITS;
+  m_MEMORY_MODULE_BLOCKS = (int64(1) << m_MEMORY_MODULE_BITS);
+
+  */
+
+  // Randomize the execution
+  //  srandom(m_RandomSeed);
 }
 
 static void print_parameters(ostream& out)
 {
 
-#define PARAM(NAME) { out << #NAME << ": " << NAME << endl; }
-#define PARAM_UINT(NAME) { out << #NAME << ": " << NAME << endl; }
-#define PARAM_ULONG(NAME) { out << #NAME << ": " << NAME << endl; }
-#define PARAM_BOOL(NAME) { out << #NAME << ": " << bool_to_string(NAME) << endl; }
-#define PARAM_DOUBLE(NAME) { out << #NAME << ": " << NAME << endl; }
-#define PARAM_STRING(NAME) { assert(NAME != NULL); out << #NAME << ": " << string(NAME) << endl; }
-#define PARAM_ARRAY(PTYPE, NAME, ARRAY_SIZE)   \
-  {                                            \
-    out << #NAME << ": (";                     \
-    for (int i = 0; i < ARRAY_SIZE; i++) {     \
-      if (i != 0) {                            \
-        out << ", ";                           \
-      }                                        \
-      out << NAME[i];                          \
-    }                                          \
-    out << ")" << endl;                        \
-  }                                            \
-
-
-#include "mem/ruby/config/config.hh"
+#define print_true(NAME)
+#define print_false(NAME)                                         \
+  out << #NAME << ": " << RubyConfig::get##NAME () << endl
+
+#define PARAM(NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR) { print_##CUSTOM_ACCESSOR(NAME); }
+#define PARAM_UINT(NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR) { print_##CUSTOM_ACCESSOR(NAME); }
+#define PARAM_ULONG(NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR) { print_##CUSTOM_ACCESSOR(NAME); }
+#define PARAM_BOOL(NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR) { print_##CUSTOM_ACCESSOR(NAME); }
+#define PARAM_DOUBLE(NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR) { print_##CUSTOM_ACCESSOR(NAME); }
+#define PARAM_STRING(NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR) { print_##CUSTOM_ACCESSOR(NAME); }
+#define PARAM_ARRAY( NAME, TYPE, DEFAULT_ARRAY_SIZE, DEFAULT_VALUE, CUSTOM_ACCESSOR ) { out << #NAME << ": ARRAY" << endl; }
+#define PARAM_ARRAY2D( NAME, TYPE, D1_DEFAULT_ARRAY_SIZE, D2_DEFAULT_ARRAY_SIZE, DEFAULT_VALUE, CUSTOM_ACCESSOR ) { out << #NAME << ": ARRAY2D" << endl; }
+#define PARAM_ARRAY3D( NAME, TYPE, D1_DEFAULT_ARRAY_SIZE, D2_DEFAULT_ARRAY_SIZE, D3_DEFAULT_ARRAY_SIZE, DEFAULT_VALUE, CUSTOM_ACCESSOR ) { out << #NAME << ": ARRAY3D" << endl; }
+#include CONFIG_VAR_FILENAME
 #undef PARAM
 #undef PARAM_UINT
 #undef PARAM_ULONG
 #undef PARAM_DOUBLE
 #undef PARAM_STRING
 #undef PARAM_ARRAY
+#undef PARAM_ARRAY2D
+#undef PARAM_ARRAY3D
 }
 
 void RubyConfig::printConfiguration(ostream& out) {
   out << "Ruby Configuration" << endl;
   out << "------------------" << endl;
 
-  out << "protocol: " << CURRENT_PROTOCOL << endl;
+  //out << "protocol: " << CURRENT_PROTOCOL << endl;
   out << "compiled_at: " << __TIME__ << ", " << __DATE__ << endl;
-  out << "RUBY_DEBUG: " << bool_to_string(RUBY_DEBUG) << endl;
+  //  out << "RUBY_DEBUG: " << bool_to_string(RUBY_DEBUG) << endl;
 
   char buffer[100];
   gethostname(buffer, 50);
 
 #ifndef RUBYCONFIG_H
 #define RUBYCONFIG_H
 
-#include "mem/ruby/common/Global.hh"
-#include "mem/gems_common/ioutil/vardecl.hh"
-#include "mem/ruby/system/NodeID.hh"
+#include <cstdlib>
+#include <string>
+#include <ostream>
+#include <assert.h>
 
-#define   MEMORY_LATENCY  RubyConfig::memoryResponseLatency()
-#define   ABORT_DELAY  m_chip_ptr->getTransactionManager(m_version)->getAbortDelay()
+#include "mem/ruby/common/TypeDefines.hh"
+#define   CONFIG_VAR_FILENAME "mem/ruby/config/config.hh"
 
 // Set paramterization
 /*
  */
 const int NUMBER_WORDS_PER_SET = 4;
 
+using namespace std;
+
 class RubyConfig {
 public:
 
   // CACHE BLOCK CONFIG VARIBLES
-  static int dataBlockBits() { return g_DATA_BLOCK_BITS; }
-  static int dataBlockBytes() { return g_DATA_BLOCK_BYTES; }
+  static uint32 dataBlockMask() { return m_data_block_mask; }
+
+  static int numberOfDMA() { return 1; }
+  static int numberOfDMAPerChip() { return 1; }
+  static int DMATransitionsPerCycle() { return 1; }
 
   // SUPPORTED PHYSICAL MEMORY CONFIG VARIABLES
-  static int pageSizeBits() { return g_PAGE_SIZE_BITS; }
-  static int pageSizeBytes() { return g_PAGE_SIZE_BYTES; }
-  static int memorySizeBits() { return g_MEMORY_SIZE_BITS; }
-  static int64 memorySizeBytes() { return g_MEMORY_SIZE_BYTES; }
-  static int memoryModuleBits() { return g_MEMORY_MODULE_BITS; }
-  static int64 memoryModuleBlocks() { return g_MEMORY_MODULE_BLOCKS; }
-
-  // returns number of SMT threads per physical processor
-  static int numberofSMTThreads() { return g_NUM_SMT_THREADS; }
+  //  static int memoryModuleBits() { return m_MEMORY_MODULE_BITS; }
+  //  static int64 memoryModuleBlocks() { return m_MEMORY_MODULE_BLOCKS; }
+
   // defines the number of simics processors (power of 2)
-  static int numberOfProcessors() { return g_NUM_PROCESSORS; }
-  static int procsPerChipBits() { return g_PROCS_PER_CHIP_BITS; }
-  static int numberOfProcsPerChip() { return g_PROCS_PER_CHIP; }
-  static int numberOfChips() { return g_NUM_CHIPS; }
+  //  static int numberOfProcessors() { return m_NUM_PROCESSORS; }
+  //  static int procsPerChipBits() { return m_PROCS_PER_CHIP_BITS; }
+  //  static int numberOfProcsPerChip() { return m_ProcsPerChip; }
+  //  static int numberOfChips() { return m_NUM_CHIPS; }
 
   // MACHINE INSTANIATION CONFIG VARIABLES
   // -------------------------------------
   // L1 CACHE MACHINES
   // defines the number of L1banks - idependent of ruby chips (power of 2)
   // NOTE - no protocols currently supports L1s != processors, just a placeholder
-  static int L1CacheBits() { return g_NUM_PROCESSORS_BITS; }
-  static int numberOfL1Cache() { return g_NUM_PROCESSORS; }
-  static int L1CachePerChipBits() { return procsPerChipBits() ; } // L1s != processors not currently supported
-  static int numberOfL1CachePerChip() { return numberOfProcsPerChip(); } // L1s != processors not currently supported
-  static int numberOfL1CachePerChip(NodeID myNodeID) { return numberOfL1CachePerChip(); }
-  static int L1CacheTransitionsPerCycle() { return L1CACHE_TRANSITIONS_PER_RUBY_CYCLE; }
-
-  // L2 CACHE MACHINES
-  // defines the number of L2banks/L2Caches - idependent of ruby chips (power of 2)
-  static int L2CacheBits() { return g_NUM_L2_BANKS_BITS; }
-  static int numberOfL2Cache() { return g_NUM_L2_BANKS; }
-  static int L1CacheNumToL2Base(NodeID L1RubyNodeID);
-  static int L2CachePerChipBits() { return g_NUM_L2_BANKS_PER_CHIP_BITS; }
-  static int numberOfL2CachePerChip() { return g_NUM_L2_BANKS_PER_CHIP; }
-  static int numberOfL2CachePerChip(NodeID myNodeID) { return numberOfL2CachePerChip(); }
-  static int L2CacheTransitionsPerCycle() { return L2CACHE_TRANSITIONS_PER_RUBY_CYCLE; }
 
   // DIRECTORY/MEMORY MACHINES
   // defines the number of ruby memories - idependent of ruby chips (power of 2)
-  static int memoryBits() { return g_NUM_MEMORIES_BITS; }
-  static int numberOfDirectory() { return numberOfMemories(); }
-  static int numberOfMemories() { return g_NUM_MEMORIES; }
-  static int numberOfDirectoryPerChip() { return g_NUM_MEMORIES_PER_CHIP; }
-  static int numberOfDirectoryPerChip(NodeID myNodeID) { return g_NUM_MEMORIES_PER_CHIP; }
-  static int DirectoryTransitionsPerCycle() { return DIRECTORY_TRANSITIONS_PER_RUBY_CYCLE; }
-
-  // PERSISTENT ARBITER MACHINES
-  static int numberOfPersistentArbiter() { return numberOfMemories(); }
-  static int numberOfPersistentArbiterPerChip() {return numberOfDirectoryPerChip(); }
-  static int numberOfPersistentArbiterPerChip(NodeID myNodeID) {return numberOfDirectoryPerChip(myNodeID); }
-  static int PersistentArbiterTransitionsPerCycle() { return L2CACHE_TRANSITIONS_PER_RUBY_CYCLE; }
+  //  static int memoryBits() { return m_NUM_MEMORIES_BITS; }
+  //  static int numberOfDirectory() { return numberOfMemories(); }
+  //  static int numberOfMemories() { return m_NUM_MEMORIES; }
+  //  static int numberOfDirectoryPerChip() { return m_NUM_MEMORIES_PER_CHIP; }
+  //  static int DirectoryTransitionsPerCycle() { return m_DIRECTORY_TRANSITIONS_PER_RUBY_CYCLE; }
 
   // ---- END MACHINE SPECIFIC VARIABLES ----
 
   // VARIABLE MEMORY RESPONSE LATENCY
   // *** NOTE *** This is where variation is added to the simulation
   // see Alameldeen et al. HPCA 2003 for further details
-  static int memoryResponseLatency() { return MEMORY_RESPONSE_LATENCY_MINUS_2+(random() % 5); }
+//  static int getMemoryLatency() { return m_MEMORY_RESPONSE_LATENCY_MINUS_2+(random() % 5); }
 
+  static void reset();
   static void init();
-  static void printConfiguration(ostream& out);
+  static void printConfiguration(std::ostream& out);
 
   // Memory Controller
-  static int memBusCycleMultiplier () { return MEM_BUS_CYCLE_MULTIPLIER; }
-  static int banksPerRank () { return BANKS_PER_RANK; }
-  static int ranksPerDimm () { return RANKS_PER_DIMM; }
-  static int dimmsPerChannel () { return DIMMS_PER_CHANNEL; }
-  static int bankBit0 () { return BANK_BIT_0; }
-  static int rankBit0 () { return RANK_BIT_0; }
-  static int dimmBit0 () { return DIMM_BIT_0; }
-  static int bankQueueSize () { return BANK_QUEUE_SIZE; }
-  static int bankBusyTime () { return BANK_BUSY_TIME; }
-  static int rankRankDelay () { return RANK_RANK_DELAY; }
-  static int readWriteDelay () { return READ_WRITE_DELAY; }
-  static int basicBusBusyTime () { return BASIC_BUS_BUSY_TIME; }
-  static int memCtlLatency () { return MEM_CTL_LATENCY; }
-  static int refreshPeriod () { return REFRESH_PERIOD; }
-  static int tFaw () { return TFAW; }
-  static int memRandomArbitrate () { return MEM_RANDOM_ARBITRATE; }
-  static int memFixedDelay () { return MEM_FIXED_DELAY; }
+
+//  static int memBusCycleMultiplier () { return m_MEM_BUS_CYCLE_MULTIPLIER; }
+/*  static int banksPerRank () { return m_BANKS_PER_RANK; }
+  static int ranksPerDimm () { return m_RANKS_PER_DIMM; }
+  static int dimmsPerChannel () { return m_DIMMS_PER_CHANNEL; }
+  static int bankBit0 () { return m_BANK_BIT_0; }
+  static int rankBit0 () { return m_RANK_BIT_0; }
+  static int dimmBit0 () { return m_DIMM_BIT_0; }
+  static int bankQueueSize () { return m_BANK_QUEUE_SIZE; }
+  static int bankBusyTime () { return m_BankBusyTime; }
+  static int rankRankDelay () { return m_RANK_RANK_DELAY; }
+  static int readWriteDelay () { return m_READ_WRITE_DELAY; }
+  static int basicBusBusyTime () { return m_BASIC_BUS_BUSY_TIME; }
+  static int memCtlLatency () { return m_MEM_CTL_LATENCY; }
+  static int refreshPeriod () { return m_REFRESH_PERIOD; }
+  static int tFaw () { return m_TFAW; }
+  static int memRandomArbitrate () { return m_MEM_RANDOM_ARBITRATE; }
+  static int memFixedDelay () { return m_MEM_FIXED_DELAY; }
+*/
+  /* cache accessors */
+  static int getCacheIDFromParams(int level, int num, string split_type) {
+    // TODO:  this function
+    return 0;
+  }
+
+#define accessor_true( TYPE, NAME )
+#define accessor_false( TYPE, NAME )                    \
+  static TYPE get##NAME() { return m_##NAME; }          \
+  static void set##NAME(TYPE val) { m_##NAME = val; }
+
+#define array_accessor_true( TYPE, NAME, DEFAULT_ARRAY_SIZE )
+#define array_accessor_false( TYPE, NAME, DEFAULT_ARRAY_SIZE )          \
+  static TYPE get##NAME(int idx) {                                      \
+    assert(m_##NAME != NULL);                                           \
+    return m_##NAME[idx];                                               \
+  }                                                                     \
+  static void set##NAME(int idx, TYPE val) {                            \
+    if(m_##NAME == NULL) {                                              \
+      assert(DEFAULT_ARRAY_SIZE > 0);                                   \
+      m_##NAME = new TYPE[DEFAULT_ARRAY_SIZE];                          \
+    }                                                                   \
+    m_##NAME[idx] = val;                                                \
+  }
+
+#define array2d_accessor_true( TYPE, NAME )
+#define array2d_accessor_false( TYPE, NAME )                            \
+  static TYPE get##NAME(int idx1, int idx2) { return m_##NAME[idx1][idx2]; } \
+  static void set##NAME(int idx1, int idx2, TYPE val) { m_##NAME[idx1][idx2] = val; }
+
+#define array3d_accessor_true( TYPE, NAME )
+#define array3d_accessor_false( TYPE, NAME )                            \
+  static TYPE get##NAME(int idx1, int idx2, int idx3) { return m_##NAME[idx1][idx2][idx3]; } \
+  static void set##NAME(int idx1, int idx2, int idx3, TYPE val) { m_##NAME[idx1][idx2][idx3] = val; }
+
+#define PARAM( NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR )   \
+  accessor_##CUSTOM_ACCESSOR(int32,NAME)
+#define PARAM_UINT( NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR )      \
+  accessor_##CUSTOM_ACCESSOR(uint32,NAME)
+#define PARAM_ULONG( NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR )     \
+  accessor_##CUSTOM_ACCESSOR(uint64,NAME)
+#define PARAM_BOOL( NAME, DEFAULT_VALUE,CUSTOM_ACCESSOR )       \
+  accessor_##CUSTOM_ACCESSOR(bool,NAME)
+#define PARAM_DOUBLE( NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR )    \
+  accessor_##CUSTOM_ACCESSOR(double,NAME)
+#define PARAM_STRING( NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR )    \
+  accessor_##CUSTOM_ACCESSOR(const char*,NAME)
+#define PARAM_ARRAY( NAME, TYPE, DEFAULT_ARRAY_SIZE, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \
+  array_accessor_##CUSTOM_ACCESSOR(TYPE, NAME, DEFAULT_ARRAY_SIZE)
+#define PARAM_ARRAY2D( NAME, TYPE, D1_DEFAULT_ARRAY_SIZE, D2_DEFAULT_ARRAY_SIZE, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \
+  array2d_accessor_##CUSTOM_ACCESSOR(TYPE, NAME)
+#define PARAM_ARRAY3D( NAME, TYPE, D1_DEFAULT_ARRAY_SIZE, D2_DEFAULT_ARRAY_SIZE, D3_DEFAULT_ARRAY_SIZE, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \
+  array3d_accessor_##CUSTOM_ACCESSOR(TYPE, NAME)
+#include CONFIG_VAR_FILENAME
+#undef PARAM
+#undef PARAM_UINT
+#undef PARAM_ULONG
+#undef PARAM_BOOL
+#undef PARAM_DOUBLE
+#undef PARAM_STRING
+#undef PARAM_ARRAY
+#undef PARAM_ARRAY2D
+#undef PARAM_ARRAY3D
 
 private:
+  static uint32 m_data_block_mask;
+
+#define PARAM( NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR )   \
+  static int32  m_##NAME;
+#define PARAM_UINT( NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR )      \
+  static uint32 m_##NAME;
+#define PARAM_ULONG( NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR )     \
+  static uint64 m_##NAME;
+#define PARAM_BOOL( NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR )      \
+  static bool   m_##NAME;
+#define PARAM_DOUBLE( NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR )    \
+  static double m_##NAME;
+#define PARAM_STRING( NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR )    \
+  static const char  *m_##NAME;
+#define PARAM_ARRAY( NAME, TYPE, DEFAULT_ARRAY_SIZE, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \
+  static TYPE* m_##NAME;
+#define PARAM_ARRAY2D( NAME, TYPE, D1_DEFAULT_ARRAY_SIZE, D2_DEFAULT_ARRAY_SIZE, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \
+  static TYPE** m_##NAME;
+#define PARAM_ARRAY3D( NAME, TYPE, D1_DEFAULT_ARRAY_SIZE, D2_DEFAULT_ARRAY_SIZE, D3_DEFAULT_ARRAY_SIZE, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \
+  static TYPE*** m_##NAME;
+#include CONFIG_VAR_FILENAME
+#undef PARAM
+#undef PARAM_UINT
+#undef PARAM_ULONG
+#undef PARAM_BOOL
+#undef PARAM_DOUBLE
+#undef PARAM_STRING
+#undef PARAM_ARRAY
+#undef PARAM_ARRAY2D
+#undef PARAM_ARRAY3D
+
 };
 
 #endif //RUBYCONFIG_H
 
--- /dev/null
+#!/usr/bin/ruby
+
+class AssertionFailure < RuntimeError
+end
+
+class Boolean
+  def self.is_a?(obj)
+    return self.name == "Boolean"
+  end
+end
+
+def assert(condition,message)
+  unless condition
+    raise AssertionFailure, "Assertion failed: #{message}"
+  end
+end
+
+class LibRubyObject
+  @@all_objs = Array.new
+  attr_reader :obj_name
+  @@default_params = Hash.new
+
+  def initialize(obj_name)
+    assert obj_name.is_a?(String), "Obj_Name must be a string"
+    @obj_name = obj_name
+    @@all_objs << self
+    @params = Hash.new
+  end
+
+  def cppClassName()
+    raise NotImplementedException
+  end
+
+  def self.param(param_name, type)
+    idx = self.name.to_sym
+    @@default_params[idx] = Hash.new if ! @@default_params.key?(idx)
+    @@default_params[idx][param_name] = nil
+    send :define_method, param_name do
+      @params[param_name] = @@default_params[idx][param_name] if ! @params.key?(param_name)
+      @params[param_name]
+    end
+    method_name = (param_name.to_s + "=").to_sym
+    send :define_method, method_name do |val|
+      if val.is_a?(FalseClass) || val.is_a?(TrueClass)
+        assert type.is_a?(Boolean), "default value of param \"#{param_name}\" must be either true or false"
+      else
+        assert val.is_a?(type), "default value of param \"#{param_name}\" does not match type #{type}"
+      end
+#      assert val.is_a?(type), "#{param_name} must be of type #{type}"
+      @params[param_name] = val
+    end
+  end
+
+  def self.default_param(param_name, type, default)
+    idx = self.name.to_sym
+    @@default_params[idx] = Hash.new if ! @@default_params.key?(idx)
+    if default.is_a?(FalseClass) || default.is_a?(TrueClass)
+      assert type.is_a?(Boolean), "default value of param \"#{param_name}\" must be either true or false"
+    else
+      assert default.is_a?(type), "default value of param \"#{param_name}\" does not match type #{type}"
+    end
+    @@default_params[idx][param_name] = default
+    send :define_method, param_name do
+      @params[param_name] = @@default_params[idx][param_name] if ! @params.key?(param_name)
+      @params[param_name]
+    end
+    method_name = (param_name.to_s + "=").to_sym
+    send :define_method, method_name do |val|
+      assert val.is_a?(type), "#{param_name} must be of type #{type}"
+      @params[param_name] = val
+    end
+  end
+
+  def applyDefaults()
+    idx = self.class.name.to_sym
+    @@default_params[idx] = Hash.new if ! @@default_params.key?(idx)
+    @@default_params[idx].each { |key, val|
+      @params[key] = val if ! @params.key?(key)
+    }
+  end
+
+  def argv()
+    str = ""
+
+    applyDefaults
+
+    @params.each { |key, val|
+      str += key.id2name + " "
+      if val.is_a?(LibRubyObject)
+        str += val.obj_name + " "
+      else
+        if val.is_a?(String) and val == ""
+          str += "null "
+        else
+          str += val.to_s + " "
+        end
+      end
+    }
+    return str
+  end
+
+  def self.printConstructors()
+    @@all_objs.each { |obj|
+      print obj.cppClassName, " ", obj.obj_name, " ",obj.argv,"\n"
+    }
+  end
+  def self.all()
+    @@all_objs
+  end
+end
+
+class IfacePort < LibRubyObject
+  def initialize(obj_name)
+    super(obj_name)
+  end
+
+  def bochsConnType
+    raise NotImplementedException
+  end
+end
+
+class NetPort < LibRubyObject
+  attr :mach_type
+  attr_reader :version
+
+  @@type_cnt = Hash.new
+  @type_id
+  def initialize(obj_name, mach_type)
+    super(obj_name)
+    @mach_type = mach_type
+    @@type_cnt[mach_type] ||= 0
+    @type_id = @@type_cnt[mach_type]
+    @@type_cnt[mach_type] += 1
+
+    idx = "NetPort".to_sym
+    @@default_params[idx] = Hash.new if ! @@default_params.key?(idx)
+    @@default_params[idx].each { |key, val|
+      @params[key] = val if ! @params.key?(key)
+    }
+  end
+
+  def port_name
+    mach_type
+  end
+  def port_num
+    @type_id
+  end
+  def cppClassName
+    "NetPort"
+  end
+end
+
+class MemoryVector < LibRubyObject
+  def initialize(obj_name)
+    super(obj_name)
+  end
+
+  def cppClassName
+    "MemoryController"
+  end
+end
+
+class Debug < LibRubyObject
+  def initialize *args
+    case args.size
+      when 1
+      super(args[0])
+      when 6
+      init_params *args[1]
+    else
+      raise Exception
+    end
+  end
+
+  def init_params (protocol_trace, filter_string, verbosity_string, start_time, output_filename)
+    @params[:protocol_trace] = protocol_trace
+    @params[:filter_string] = filter_string
+    @params[:verbosity_string] = verbosity_string
+    @params[:start_time] = start_time
+    @params[:output_filename] = output_filename
+  end
+
+  def cppClassName
+    "Debug"
+  end
+end
+
+class RubySystem
+
+  @@params = Hash.new
+  @@network = nil
+
+  def self.init(iface_ports, network)
+    @@iface_ports = iface_ports
+    @@network = network
+  end
+
+  def self.default_param(param_name, type, default)
+    if default.is_a?(FalseClass) || default.is_a?(TrueClass)
+      assert type.is_a?(Boolean), "default value of param \"#{param_name}\" must be either true or false"
+    else
+      assert default.is_a?(type), "default value of param \"#{param_name}\" does not match type #{type}"
+    end
+    @@params[param_name] = default
+    method_name = (param_name.to_s).to_sym
+    instance_eval <<-EOS
+       def #{method_name.to_s}
+         @@params[:#{param_name.to_s}]
+       end
+    EOS
+    instance_eval <<-EOS
+       def #{method_name.to_s}=(val)
+         @@params[:#{param_name.to_s}] = val
+       end
+    EOS
+  end
+
+  def self.generateConfig()
+    # get current time for random seed if set to "rand"
+    if @@params[:random_seed] == "rand"
+      t = Time.now
+      @@params[:random_seed] = t.usec.to_i
+    end
+    if ! @@params[:random_seed].is_a?(Integer)
+      raise TypeException
+    end
+    print "System sys0 ",argv,"\n"
+    LibRubyObject.all.each { |obj|
+      if obj.is_a?(SetAssociativeCache)
+        obj.calculateLatency
+      end
+    }
+    LibRubyObject.printConstructors
+  end
+
+  def self.printIfacePorts()
+    @@iface_ports.each { |port|
+      print port.obj_name, " "
+    }
+    puts
+  end
+
+  def self.getBochsConnections()
+    ports = Hash.new
+    @@iface_ports.each { |port|
+      ports[port.obj_name] = port.bochsConnType
+    }
+    return ports
+  end
+
+  def self.getMemorySizeMB()
+    DirectoryMemory.memorySizeMB
+  end
+
+  # override the default accessors (generated by default_param) for random_seed
+  def self.random_seed=(seed)
+    assert (val.is_a?(Integer) or val == "rand"), "RubySystem.random_seed takes either an integer value or the string \"rand\""
+    @@params[:random_seed] = seed
+  end
+
+private
+
+  def self.argv()
+    str = ""
+    @@params.each { |key, val|
+      str += key.id2name + " "
+      str += val.to_s + " "
+    }
+    return str
+  end
+
+  def self.writeConfig()
+    @@network.printTopology
+  end
+
+end
+
+#require "defaults.rb"
+
+
+
+class CacheController < NetPort
+  @@total_cache_controllers = 0
+  attr :caches
+  attr :sequencer
+  def initialize(obj_name, mach_type, caches, sequencer)
+    super(obj_name, mach_type)
+    @caches = caches
+    @caches.each { |cache|
+      cache.controller = self
+    }
+
+    @sequencer = sequencer
+    @sequencer.controller = self
+
+    @version = @@total_cache_controllers
+    @@total_cache_controllers += 1
+    @sequencer.version = @version
+    buffer_size()
+  end
+
+  def argv()
+    vec = "version "+@version.to_s
+    @caches.each { |cache|
+      vec += " cache " + cache.obj_name
+    }
+    vec += " sequencer "+@sequencer.obj_name
+    vec += " transitions_per_cycle "+@params[:transitions_per_cycle].to_s
+    vec += " buffer_size "+@params[:buffer_size].to_s
+    vec += " number_of_TBEs "+@params[:number_of_TBEs].to_s
+
+  end
+
+  def cppClassName()
+    "generated:"+@mach_type
+  end
+end
+
+class DirectoryController < NetPort
+  @@total_directory_controllers = 0
+  attr :directory
+  attr :memory_control
+
+  def initialize(obj_name, mach_type, directory, memory_control)
+    super(obj_name, mach_type)
+
+    @directory = directory
+    directory.controller = self
+
+    @memory_control = memory_control
+
+    @version = @@total_directory_controllers
+    @@total_directory_controllers += 1
+    buffer_size()
+  end
+
+  def argv()
+    "version "+@version.to_s+" directory_name "+@directory.obj_name+" transitions_per_cycle "+@params[:transitions_per_cycle].to_s + " buffer_size "+@params[:buffer_size].to_s + " number_of_TBEs "+@params[:number_of_TBEs].to_s + " memory_controller_name "+@memory_control.obj_name + " recycle_latency "+@params[:recycle_latency].to_s
+  end
+
+  def cppClassName()
+    "generated:"+@mach_type
+  end
+
+end
+
+class DMAController < NetPort
+  @@total_dma_controllers = 0
+  attr :dma_sequencer
+  def initialize(obj_name, mach_type, dma_sequencer)
+    super(obj_name, mach_type)
+    @dma_sequencer = dma_sequencer
+    @version = @@total_dma_controllers
+    @@total_dma_controllers += 1
+    dma_sequencer.controller = self
+    buffer_size
+  end
+
+  def argv()
+    "version "+@version.to_s+" dma_sequencer "+@dma_sequencer.obj_name+" transitions_per_cycle "+@params[:transitions_per_cycle].to_s + " buffer_size "+@params[:buffer_size].to_s + " number_of_TBEs "+@params[:number_of_TBEs].to_s
+  end
+
+  def cppClassName()
+    "generated:"+@mach_type
+  end
+end
+
+class Cache < LibRubyObject
+  attr :size_kb, :latency
+  attr_writer :controller
+  def initialize(obj_name, size_kb, latency)
+    super(obj_name)
+    assert size_kb.is_a?(Integer), "Cache size must be an integer"
+    @size_kb = size_kb
+    @latency = latency
+  end
+
+  def args
+    "controller "+@controller.obj_name+" size_kb "+@size_kb.to_s+" latency "+@latency.to_s
+  end
+end
+
+class SetAssociativeCache < Cache
+  attr :assoc, :replacement_policy
+
+  # latency can be either an integer, a float, or the string "auto"
+  #  when an integer, it represents the number of cycles for a hit
+  #  when a float, it represents the cache access time in ns
+  #  when set to "auto", libruby will attempt to find a realistic latency by running CACTI
+  def initialize(obj_name, size_kb, latency, assoc, replacement_policy)
+    super(obj_name, size_kb, latency)
+    @assoc = assoc
+    @replacement_policy = replacement_policy
+  end
+
+  def calculateLatency()
+    if @latency == "auto"
+      cacti_args = Array.new()
+      cacti_args << (@size_kb*1024) <<  RubySystem.block_size_bytes << @assoc
+      cacti_args << 1 << 0 << 0 << 0 << 1
+      cacti_args << RubySystem.tech_nm << RubySystem.block_size_bytes*8
+      cacti_args << 0 << 0 << 0 << 1 << 0 << 0 << 0 << 0 << 1
+      cacti_args << 360 << 0 << 0 << 0 << 0 << 1 << 1 << 1 << 1 << 0 << 0
+      cacti_args << 50 << 10 << 10 << 0 << 1 << 1
+
+      cacti_cmd = File.dirname(__FILE__) + "/cacti/cacti " + cacti_args.join(" ")
+
+      IO.popen(cacti_cmd) { |pipe|
+        str1 = pipe.readline
+        str2 = pipe.readline
+        results = str2.split(", ")
+        if results.size != 61
+          print "CACTI ERROR: CACTI produced unexpected output.\n"
+          print "Are you using the version shipped with libruby?\n"
+          raise Exception
+        end
+        latency_ns = results[5].to_f
+        if (latency_ns == "1e+39")
+          print "CACTI ERROR:  CACTI was unable to realistically model the cache ",@obj_name,"\n"
+          print "Either change the cache parameters or manually set the latency values\n"
+          raise Exception
+        end
+        clk_period_ns = 1e9 * (1.0 / (RubySystem.freq_mhz * 1e6))
+        latency_cycles = (latency_ns / clk_period_ns).ceil
+        @latency = latency_cycles
+      }
+    elsif @latency.is_a?(Float)
+      clk_period_ns = 1e9 * (1.0 / (RubySystem.freq_mhz * 1e6))
+      latency_cycles = (@latency / clk_period_ns).ceil
+      @latency = latency_cycles
+    elsif ! @latency.is_a?(Integer)
+      raise Exception
+    end
+  end
+
+  def argv()
+    args+" assoc "+@assoc.to_s+" replacement_policy "+@replacement_policy
+  end
+
+  def cppClassName()
+    "SetAssociativeCache"
+  end
+end
+
+class DirectoryMemory < LibRubyObject
+  attr :size_mb
+  attr_writer :controller
+  @@total_size_mb = 0
+
+  def initialize(obj_name, size_mb)
+    super(obj_name)
+    @size_mb = size_mb
+    @@total_size_mb += size_mb
+  end
+
+  def argv()
+    "version "+@controller.version.to_s+" size_mb "+@size_mb.to_s+" controller "+@controller.obj_name
+  end
+
+  def cppClassName()
+    "DirectoryMemory"
+  end
+
+  def self.memorySizeMB()
+    @@total_size_mb
+  end
+end
+
+#added by SS
+class MemoryControl < LibRubyObject
+  attr :name
+  def initialize(obj_name)
+    super(obj_name)
+    @name = obj_name
+  end
+
+  def argv()
+    vec = super()
+    vec += " mem_bus_cycle_multiplier "+mem_bus_cycle_multiplier.to_s
+    vec += " banks_per_rank "+banks_per_rank.to_s
+    vec += " ranks_per_dimm "+ranks_per_dimm.to_s
+    vec += " dimms_per_channel "+dimms_per_channel.to_s
+    vec += " bank_bit_0 "+bank_bit_0.to_s
+    vec += " rank_bit_0 "+rank_bit_0.to_s
+    vec += " dimm_bit_0 "+dimm_bit_0.to_s
+    vec += " bank_queue_size "+bank_queue_size.to_s
+    vec += " bank_busy_time "+bank_busy_time.to_s
+    vec += " rank_rank_delay "+rank_rank_delay.to_s
+    vec += " read_write_delay "+read_write_delay.to_s
+    vec += " basic_bus_busy_time "+basic_bus_busy_time.to_s
+    vec += " mem_ctl_latency "+mem_ctl_latency.to_s
+    vec += " refresh_period "+refresh_period.to_s
+    vec += " tFaw "+tFaw.to_s
+    vec += " mem_random_arbitrate "+mem_random_arbitrate.to_s
+    vec += " mem_fixed_delay "+mem_fixed_delay.to_s
+    vec += " memory_controller_name "+@name
+
+  end
+
+
+  def cppClassName()
+    "MemoryControl"
+  end
+end
+
+
+
+class Sequencer < IfacePort
+
+  def cppClassName()
+    "Sequencer"
+  end
+
+  param :controller, NetPort  # must be set after initialization
+  param :icache, Cache
+  param :dcache, Cache
+  param :version, Integer
+
+  def initialize(obj_name, icache, dcache)
+    super(obj_name)
+    self.icache=icache
+    self.dcache=dcache
+  end
+
+  def bochsConnType()
+    return "cpu"+version.to_s
+  end
+
+end
+
+
+
+class DMASequencer < IfacePort
+  def initialize(obj_name)
+    super(obj_name)
+    @params = {
+      :controller => nil,
+      :version => nil
+    }
+  end
+
+  def controller=(controller)
+    @params[:controller] = controller.obj_name
+    @params[:version] = controller.version
+  end
+
+  def cppClassName()
+    "DMASequencer"
+  end
+
+  def bochsConnType()
+    return "dma"+@params[:version].to_s
+  end
+end
+
+class IntNode
+  @@num = 0
+  def initialize()
+
+  end
+end
+
+class Network < LibRubyObject
+end
+
+class Topology < LibRubyObject
+  attr :net_ports
+  param :network, Network
+  def initialize(name, net_ports)
+    super(name)
+    @net_ports = net_ports
+  end
+
+  def cppClassName
+    "Topology"
+  end
+end
+
+class Network < LibRubyObject
+  param :topology, Topology
+  def initialize(name, topo)
+    super(name)
+    @params[:topology] = topo
+    topo.network= self
+  end
+
+  def argv()
+    vec = super()
+
+    vec += " endpoint_bandwidth "+endpoint_bandwidth.to_s
+    vec += " adaptive_routing "+adaptive_routing.to_s
+    vec += " number_of_virtual_networks "+number_of_virtual_networks.to_s
+    vec += " fan_out_degree "+fan_out_degree.to_s
+
+    vec += " buffer_size "+buffer_size.to_s
+    vec += " link_latency "+adaptive_routing.to_s
+    vec += " on_chip_latency "+on_chip_latency.to_s
+
+  end
+
+  def printTopology()
+    topology.printFile
+  end
+  def cppClassName()
+    "SimpleNetwork"
+  end
+
+end
+
+class PtToPtTopology < Topology
+
+  param :connections,String
+
+  def initialize(name, net_ports)
+    super(name, net_ports)
+    @params[:connections] = ""
+    @net_ports.each_index { |idx|
+      @params[:connections] << ("ext_node:"+@net_ports[idx].port_name+":"+@net_ports[idx].port_num.to_s)
+      @params[:connections] << ("%int_node:"+ idx.to_s+ "%link_latency:"+ link_latency.to_s)
+      @params[:connections] << ("%bw_multiplier:"+external_bw.to_s+"#")
+    }
+    @net_ports.each_index { |outer_idx|
+      @net_ports.each_index { |inner_idx|
+        if (outer_idx != inner_idx)
+          @params[:connections] << ("int_node:"+ outer_idx.to_s+ "%int_node:"+ inner_idx.to_s)
+          @params[:connections] << ("%link_latency:"+link_latency.to_s+"%bw_multiplier:"+internal_bw.to_s)
+          @params[:connections] << ("%link_weight:"+1.to_s+"#")
+        end
+      }
+    }
+    # call the accessors of the parent class to initialize them
+    # need to find a better method!!
+    print_config
+  end
+
+end
+
+class CrossbarTopology < Topology
+  param :connections,String
+
+  def initialize(name, net_ports)
+    super(name, net_ports)
+    @params[:connections] = ""
+    crossbar_node = @net_ports.size
+    @net_ports.each_index { |idx|
+      @params[:connections] << ("ext_node:"+@net_ports[idx].port_name+":"+@net_ports[idx].port_num.to_s)
+      @params[:connections] << ("%int_node:"+ idx.to_s+ "%link_latency:"+ link_latency.to_s)
+      @params[:connections] << ("%bw_multiplier:"+external_bw.to_s+"#")
+    }
+    @net_ports.each_index { |idx|
+      @params[:connections] << ("int_node:"+idx.to_s+"%int_node:"+crossbar_node.to_s)
+      @params[:connections] << ("%link_latency:"+link_latency.to_s+"%bw_multiplier:"+internal_bw.to_s)
+      @params[:connections] << ("%link_weight:"+1.to_s+"#")
+    }
+    print_config
+  end
+end
+
+#added by SS
+class Tracer < LibRubyObject
+  def initialize(obj_name)
+    super(obj_name)
+  end
+
+  def cppClassName()
+    "Tracer"
+  end
+
+end
+
+class Profiler < LibRubyObject
+  def initialize(obj_name)
+    super(obj_name)
+  end
+
+  def cppClassName()
+    "Profiler"
+  end
+
+end
+
+class MI_example_CacheController < CacheController
+  def initialize(obj_name, mach_type, caches, sequencer)
+    super(obj_name, mach_type, caches, sequencer)
+  end
+  def argv()
+    vec = super()
+    vec += " issue_latency "+issue_latency.to_s
+    vec += " cache_response_latency "+cache_response_latency.to_s
+  end
+
+end
+
+class MI_example_DirectoryController < DirectoryController
+  def initialize(obj_name, mach_type, directory, memory_control)
+    super(obj_name, mach_type, directory, memory_control)
+  end
+  def argv()
+    vec = super()
+    vec += " to_mem_ctrl_latency "+to_mem_ctrl_latency.to_s
+    vec += " directory_latency "+directory_latency.to_s
+    vec += " memory_latency "+memory_latency.to_s
+  end
+
+end
+
+#added by SS
+class GarnetNetwork < Network
+  def initialize(name, topo)
+    super(name, topo)
+  end
+  def argv()
+    vec = super()
+    vec += " flit_size "+flit_size.to_s
+    vec += " number_of_pipe_stages "+number_of_pipe_stages.to_s
+    vec += " vcs_per_class "+vcs_per_class.to_s
+    vec += " buffer_size "+buffer_size.to_s
+    vec += " using_network_testing "+using_network_testing.to_s
+  end
+
+end
+
+class GarnetFixedPipeline < GarnetNetwork
+  def initialize(name, net_ports)
+    super(name, net_ports)
+  end
+
+  def argv()
+    super()
+  end
+
+  def cppClassName()
+    "GarnetNetwork_d"
+  end
+end
+
+class GarnetFlexiblePipeline < GarnetNetwork
+  def initialize(name, net_ports)
+    super(name, net_ports)
+  end
+
+  def argv()
+    super()
+  end
+
+  def cppClassName()
+    "GarnetNetwork"
+  end
+end
+
+require "defaults.rb"
 
-//
-// This file has been modified by Kevin Moore and Dan Nussbaum of the
-// Scalable Systems Research Group at Sun Microsystems Laboratories
-// (http://research.sun.com/scalable/) to support the Adaptive
-// Transactional Memory Test Platform (ATMTP).  For information about
-// ATMTP, see the GEMS website: http://www.cs.wisc.edu/gems/.
-//
-// Please send email to atmtp-interest@sun.com with feedback, questions, or
-// to request future announcements about ATMTP.
-//
-// ----------------------------------------------------------------------
-//
-// File modification date: 2008-02-23
-//
-// ----------------------------------------------------------------------
-//
-// ATMTP is distributed as part of the GEMS software toolset and is
-// available for use and modification under the terms of version 2 of the
-// GNU General Public License.  The GNU General Public License is contained
-// in the file $GEMS/LICENSE.
-//
-// Multifacet GEMS is free software; you can redistribute it and/or modify
-// it under the terms of version 2 of the GNU General Public License as
-// published by the Free Software Foundation.
-//
-// Multifacet GEMS is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with the Multifacet GEMS; if not, write to the Free Software Foundation,
-// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
-//
-// ----------------------------------------------------------------------
-//
-
-// see rubyconfig.defaults for some explanations
-
-PARAM( g_RANDOM_SEED );
-
-// Maximum number of cycles a request is can be outstanding before the
-// Sequencer of StoreBuffer declares we're in deadlock/livelock
-PARAM( g_DEADLOCK_THRESHOLD );
-PARAM_BOOL(  RANDOMIZATION );
-PARAM_BOOL(  g_SYNTHETIC_DRIVER );
-PARAM_BOOL(  g_DETERMINISTIC_DRIVER );
 
 // FOR MOESI_CMP_token
-PARAM_BOOL(  g_FILTERING_ENABLED );
-PARAM_BOOL(  g_DISTRIBUTED_PERSISTENT_ENABLED );
-PARAM_BOOL(  g_DYNAMIC_TIMEOUT_ENABLED );
-PARAM( g_RETRY_THRESHOLD );
-PARAM( g_FIXED_TIMEOUT_LATENCY );
-
-PARAM(  g_trace_warmup_length );
-PARAM_DOUBLE( g_bash_bandwidth_adaptive_threshold );
+//PARAM_BOOL(  FilteringEnabled, false, false );
+//PARAM_BOOL(  DistributedPersistentEnabled, true, false );
+//PARAM_BOOL(  DynamicTimeoutEnabled, true, false );
+//PARAM( RetryThreshold, 1, false );
+//PARAM( FixedTimeoutLatency, 300, false );
 
-PARAM( g_tester_length );
-PARAM( g_synthetic_locks );
-PARAM( g_deterministic_addrs );
-// Specified Generator: See SpecifiedGeneratorType in external.sm for valid values
-PARAM_STRING( g_SpecifiedGenerator );
-PARAM( g_callback_counter );
-PARAM( g_NUM_COMPLETIONS_BEFORE_PASS );
+//PARAM( TraceWarmupLength, 1000000, false );
 
-PARAM( g_NUM_SMT_THREADS );
+//PARAM( callback_counter, 0, false );
+//PARAM( NUM_COMPLETIONS_BEFORE_PASS, 0, false );
 
-PARAM( g_think_time );
-PARAM( g_hold_time );
-PARAM( g_wait_time );
+//PARAM( tester_length, 0, false );
+//PARAM( synthetic_locks, 2048, false );
+//PARAM( think_time, 5, false );
+//PARAM( wait_time, 5, false );
+//PARAM( hold_time, 5, false );
+//PARAM( deterministic_addrs, 1, false );
+//PARAM_STRING( SpecifiedGenerator, "DetermInvGenerator", false );
 
 // For debugging purposes, one can enable a trace of all the protocol
 // state machine changes. Unfortunately, the code to generate the
 //      "g_debug_ptr->setDebugTime(1)" to beging the following to set the
 //      debug begin time
 //
-// this use to be ruby/common/Global.h
+// this use to be ruby/common/Global.hh
 
-PARAM_BOOL(  PROTOCOL_DEBUG_TRACE );
-// a string for filtering debugging output (for all g_debug vars see Debug.h)
-PARAM_STRING( DEBUG_FILTER_STRING );
+//PARAM_BOOL(  ProtocolDebugTrace, true, false );
+// a string for filtering debugging output (for all g_debug vars see Debug.hh)
+//PARAM_STRING( DEBUG_FILTER_STRING, "", false );
 // filters debugging messages based on priority (low, med, high)
-PARAM_STRING( DEBUG_VERBOSITY_STRING );
+//PARAM_STRING( DEBUG_VERBOSITY_STRING, "", false );
 // filters debugging messages based on a ruby time
-PARAM_ULONG( DEBUG_START_TIME );
+//PARAM_ULONG( DEBUG_START_TIME, 0, false );
 // sends debugging messages to a output filename
-PARAM_STRING( DEBUG_OUTPUT_FILENAME );
-
-// defines relative (integer) clock multipliers between ruby, opal, and simics
-PARAM( SIMICS_RUBY_MULTIPLIER );
-PARAM( OPAL_RUBY_MULTIPLIER );
+//PARAM_STRING( DEBUG_OUTPUT_FILENAME, "", false );
 
-PARAM_BOOL( TRANSACTION_TRACE_ENABLED );
-PARAM_BOOL( USER_MODE_DATA_ONLY );
-PARAM_BOOL( PROFILE_HOT_LINES );
+//PARAM_BOOL( ProfileHotLines, false, false );
 
 // PROFILE_ALL_INSTRUCTIONS is used if you want Ruby to profile all instructions executed
 // The following need to be true for this to work correctly:
 // 1. Disable istc and dstc for this simulation run
 // 2. Add the following line to the object "sim" in the checkpoint you run from:
-//     instruction_profile_line_size: 4
+//      instruction_profile_line_size: 4
 // This is used to have simics report back all instruction requests
 
 // For more details on how to find out how to interpret the output physical instruction
 // address, please read the document in the simics-howto directory
-PARAM_BOOL( PROFILE_ALL_INSTRUCTIONS );
+//PARAM_BOOL( ProfileAllInstructions, false, false );
 
 // Set the following variable to true if you want a complete trace of
 // PCs (physical address of program counters, with executing processor IDs)
 // to be printed to stdout. Make sure to direct the simics output to a file.
 // Otherwise, the run will take a really long time!
 // A long run may write a file that can exceed the OS limit on file length
-PARAM_BOOL( PRINT_INSTRUCTION_TRACE );
-PARAM( g_DEBUG_CYCLE );
-
-// Don't allow any datablocks to enter the STC
-PARAM_BOOL( BLOCK_STC );
+//PARAM_BOOL( PRINT_INSTRUCTION_TRACE, false, false );
+//PARAM( DEBUG_CYCLE, 0, false );
 
 // Make the entire memory system perfect
-PARAM_BOOL( PERFECT_MEMORY_SYSTEM );
-PARAM( PERFECT_MEMORY_SYSTEM_LATENCY );
-
-PARAM_BOOL( DATA_BLOCK ); // Define NO_DATA_BLOCK to make the DataBlock take zero space
-
-PARAM_BOOL( REMOVE_SINGLE_CYCLE_DCACHE_FAST_PATH );
+//PARAM_BOOL( PERFECT_MEMORY_SYSTEM, false, false );
+//PARAM( PERFECT_MEMORY_SYSTEM_LATENCY, 0, false );
 
 // *********************************************
-// CACHE & MEMORY PARAMETERS
+// SYSTEM PARAMETERS
 // *********************************************
 
+//PARAM( NumberOfChips, 1, false );
+//PARAM( NumberOfCores, 2, false );
+//PARAM_ARRAY( NumberOfCoresPerChip, int, m_NumberOfChips, 2, false);
 
-PARAM( L1_CACHE_ASSOC );
-PARAM( L1_CACHE_NUM_SETS_BITS );
-PARAM( L2_CACHE_ASSOC );
-PARAM( L2_CACHE_NUM_SETS_BITS );
-
-PARAM_ULONG( g_MEMORY_SIZE_BYTES );
-PARAM( g_DATA_BLOCK_BYTES );
-// The following page size parameter is used by the stride prefetcher
-PARAM( g_PAGE_SIZE_BYTES );
-PARAM_STRING( g_REPLACEMENT_POLICY );
+// *********************************************
+// CACHE PARAMETERS
+// *********************************************
 
-PARAM( g_NUM_PROCESSORS );
-PARAM( g_NUM_L2_BANKS );
-PARAM( g_NUM_MEMORIES );
-PARAM( g_PROCS_PER_CHIP );
+//PARAM( NumberOfCaches, m_NumberOfCores, false );
+//PARAM( NumberOfCacheLevels, 1, false );
+/* this returns the number of discrete CacheMemories per level (i.e. a split L1 counts for 2) */
+//PARAM_ARRAY( NumberOfCachesPerLevel, int, m_NumberOfCacheLevels, m_NumberOfCores, false );   // this is the number of discrete caches if the level is private
+                                                                                             // or the number of banks if the level is shared
+//PARAM( CacheIDFromParams, 1, true );                                                         // returns a unique CacheID from the parameters (level, num, split_type)
+//PARAM_ARRAY( CacheLatency, int, m_NumberOfCaches, 1, false );                                // returns the latency for cache, indexed by CacheID
+//PARAM_ARRAY( CacheSplitType, string, m_NumberOfCaches, "unified", false );                   // returns "data", "instruction", or "unified", indexed by CacheID
+//PARAM_ARRAY( CacheType, string, m_NumberOfCaches, "SetAssociative", false );                 // returns the type of a cache, indexed by CacheID
+//PARAM_ARRAY( CacheAssoc, int, m_NumberOfCaches, 4, false );                                  // returns the cache associativity, indexed by CacheID
+//PARAM_ARRAY( NumberOfCacheSets, int, m_NumberOfCaches, 256, false );                         // returns the number of cache sets, indexed by CacheID
+//PARAM_ARRAY( NumberOfCacheSetBits, int, m_NumberOfCaches, log_int(256), false );             // returns the number of cache set bits, indexed by CacheID
+//PARAM_ARRAY( CacheReplacementPolicy, string, m_NumberOfCaches, "PSEUDO_LRU", false );        // other option is "LRU"
+
+//PARAM( DataBlockBytes, 64, false );
+//PARAM( DataBlockBits, log_int(m_DataBlockBytes), false);
+
+// ********************************************
+// MEMORY PARAMETERS
+// ********************************************
+
+//PARAM_ARRAY( NumberOfControllersPerType, int, m_NumberOfCacheLevels+2, m_NumberOfCores, false);
+//PARAM_ARRAY2D( NumberOfControllersPerTypePerChip, int, m_NumberOfCacheLevels+2, m_NumberOfChips, m_NumberOfCores, false);
+
+// ********************************************
+// DMA CONTROLLER PARAMETERS
+// ********************************************
+
+//PARAM( NumberOfDMA, 1, false );
+//PARAM_ARRAY( NumberOfDMAPerChip, int, m_NumberOfChips, 1, false);
+//PARAM_ARRAY( ChipNumFromDMAVersion, int, m_NumberOfDMA, 0, false );
+
+//PARAM_ULONG( MemorySizeBytes, 4294967296, false );
+//PARAM_ULONG( MemorySizeBits, 32, false);
+
+//PARAM( NUM_PROCESSORS, 0, false );
+//PARAM( NUM_L2_BANKS, 0, false );
+//PARAM( NUM_MEMORIES, 0, false );
+//PARAM( ProcsPerChip, 1, false );
 
 // The following group of parameters are calculated.  They must
 // _always_ be left at zero.
-PARAM( g_NUM_CHIPS );
-PARAM( g_NUM_CHIP_BITS );
-PARAM( g_MEMORY_SIZE_BITS );
-PARAM( g_DATA_BLOCK_BITS );
-PARAM( g_PAGE_SIZE_BITS );
-PARAM( g_NUM_PROCESSORS_BITS );
-PARAM( g_PROCS_PER_CHIP_BITS );
-PARAM( g_NUM_L2_BANKS_BITS );
-PARAM( g_NUM_L2_BANKS_PER_CHIP_BITS );
-PARAM( g_NUM_L2_BANKS_PER_CHIP );
-PARAM( g_NUM_MEMORIES_BITS );
-PARAM( g_NUM_MEMORIES_PER_CHIP );
-PARAM( g_MEMORY_MODULE_BITS );
-PARAM_ULONG( g_MEMORY_MODULE_BLOCKS );
-
-// determines the mapping between L2 banks and sets within L2 banks
-PARAM_BOOL( MAP_L2BANKS_TO_LOWEST_BITS );
+//PARAM( NUM_CHIPS, 0, false );
+//PARAM( NUM_CHIP_BITS, 0, false );
+//PARAM( MEMORY_SIZE_BITS, 0, false );
+//PARAM( DATA_BLOCK_BITS, 0, false );
+//PARAM( PAGE_SIZE_BITS, 0, false );
+//PARAM( NUM_PROCESSORS_BITS, 0, false );
+//PARAM( PROCS_PER_CHIP_BITS, 0, false );
+//PARAM( NUM_L2_BANKS_BITS, 0, false );
+//PARAM( NUM_L2_BANKS_PER_CHIP_BITS, 0, false );
+//PARAM( NUM_L2_BANKS_PER_CHIP, 0, false );
+//PARAM( NUM_MEMORIES_BITS, 0, false );
+//PARAM( NUM_MEMORIES_PER_CHIP, 0, false );
+//PARAM( MEMORY_MODULE_BITS, 0, false );
+//PARAM_ULONG( MEMORY_MODULE_BLOCKS, 0, false );
 
 // TIMING PARAMETERS
-PARAM( DIRECTORY_CACHE_LATENCY );
-
-PARAM( NULL_LATENCY );
-PARAM( ISSUE_LATENCY );
-PARAM( CACHE_RESPONSE_LATENCY );
-PARAM( L2_RESPONSE_LATENCY );
-PARAM( L2_TAG_LATENCY );
-PARAM( L1_RESPONSE_LATENCY );
-PARAM( MEMORY_RESPONSE_LATENCY_MINUS_2 );
-PARAM( DIRECTORY_LATENCY );
-PARAM( NETWORK_LINK_LATENCY );
-PARAM( COPY_HEAD_LATENCY );
-PARAM( ON_CHIP_LINK_LATENCY );
-PARAM( RECYCLE_LATENCY );
-PARAM( L2_RECYCLE_LATENCY );
-PARAM( TIMER_LATENCY );
-PARAM( TBE_RESPONSE_LATENCY );
-PARAM_BOOL(  PERIODIC_TIMER_WAKEUPS );
-
-// constants used by TM protocols
-PARAM_BOOL( PROFILE_EXCEPTIONS );
-PARAM_BOOL( PROFILE_XACT );
-PARAM_BOOL( PROFILE_NONXACT );
-PARAM_BOOL( XACT_DEBUG );
-PARAM ( XACT_DEBUG_LEVEL );
-PARAM_BOOL( XACT_MEMORY );
-PARAM_BOOL( XACT_ENABLE_TOURMALINE );
-PARAM( XACT_NUM_CURRENT );
-PARAM( XACT_LAST_UPDATE );
-PARAM_BOOL( XACT_ISOLATION_CHECK );
-PARAM_BOOL( PERFECT_FILTER );
-PARAM_STRING( READ_WRITE_FILTER );
-PARAM_BOOL( PERFECT_VIRTUAL_FILTER );
-PARAM_STRING( VIRTUAL_READ_WRITE_FILTER );
-PARAM_BOOL( PERFECT_SUMMARY_FILTER );
-PARAM_STRING( SUMMARY_READ_WRITE_FILTER );
-PARAM_BOOL( XACT_EAGER_CD );
-PARAM_BOOL( XACT_LAZY_VM );
-PARAM_STRING( XACT_CONFLICT_RES );
-PARAM_BOOL( XACT_VISUALIZER );
-PARAM( XACT_COMMIT_TOKEN_LATENCY ) ;
-PARAM_BOOL( XACT_NO_BACKOFF );
-PARAM ( XACT_LOG_BUFFER_SIZE );
-PARAM ( XACT_STORE_PREDICTOR_HISTORY);
-PARAM ( XACT_STORE_PREDICTOR_ENTRIES);
-PARAM ( XACT_STORE_PREDICTOR_THRESHOLD);
-PARAM ( XACT_FIRST_ACCESS_COST );
-PARAM ( XACT_FIRST_PAGE_ACCESS_COST );
-PARAM_BOOL( ENABLE_MAGIC_WAITING );
-PARAM_BOOL( ENABLE_WATCHPOINT );
-PARAM_BOOL( XACT_ENABLE_VIRTUALIZATION_LOGTM_SE );
-
-// ATMTP
-PARAM_BOOL( ATMTP_ENABLED );
-PARAM_BOOL( ATMTP_ABORT_ON_NON_XACT_INST );
-PARAM_BOOL( ATMTP_ALLOW_SAVE_RESTORE_IN_XACT );
-PARAM( ATMTP_XACT_MAX_STORES );
-PARAM( ATMTP_DEBUG_LEVEL );
+//PARAM( DIRECTORY_CACHE_LATENCY, 6, false );
+
+//PARAM( NULL_LATENCY, 1, false );
+//PARAM( ISSUE_LATENCY, 2, false );
+//PARAM( CACHE_RESPONSE_LATENCY, 12, false );
+//PARAM( L2_RESPONSE_LATENCY, 6, false );
+//PARAM( L2_TAG_LATENCY, 6, false );
+//PARAM( L1_RESPONSE_LATENCY, 3, false );
+
+//PARAM( MEMORY_RESPONSE_LATENCY_MINUS_2, 158, false );
+//PARAM( DirectoryLatency, 6, false );
+
+//PARAM( NetworkLinkLatency, 1, false );
+//PARAM( COPY_HEAD_LATENCY, 4, false );
+//PARAM( OnChipLinkLatency, 1, false );
+//PARAM( RecycleLatency, 10, false );
+//PARAM( L2_RECYCLE_LATENCY, 5, false );
+//PARAM( TIMER_LATENCY, 10000, false );
+//PARAM( TBE_RESPONSE_LATENCY, 1, false );
+//PARAM_BOOL(  PERIODIC_TIMER_WAKEUPS, true, false );
 
 // constants used by CMP protocols
-PARAM( L1_REQUEST_LATENCY );
-PARAM( L2_REQUEST_LATENCY );
-PARAM_BOOL( SINGLE_ACCESS_L2_BANKS ); // hack to simulate multi-cycle L2 bank accesses
+//PARAM( L1_REQUEST_LATENCY, 2, false );
+//PARAM( L2_REQUEST_LATENCY, 4, false );
+//PARAM_BOOL( SINGLE_ACCESS_L2_BANKS, true, false ); // hack to simulate multi-cycle L2 bank accesses
 
 // Ruby cycles between when a sequencer issues a miss it arrives at
 // the L1 cache controller
-PARAM( SEQUENCER_TO_CONTROLLER_LATENCY );
+//PARAM( SequencerToControllerLatency, 4, false );
 
 // Number of transitions each controller state machines can complete per cycle
-PARAM( L1CACHE_TRANSITIONS_PER_RUBY_CYCLE );
-PARAM( L2CACHE_TRANSITIONS_PER_RUBY_CYCLE );
-PARAM( DIRECTORY_TRANSITIONS_PER_RUBY_CYCLE );
-
-// Maximum number of requests (including prefetches) outstanding from
-// the sequencer (Note: this also include items buffered in the store
-// buffer)
-PARAM( g_SEQUENCER_OUTSTANDING_REQUESTS );
+//PARAM( L1CacheTransitionsPerCycle, 32, false );
+//PARAM( L2CACHE_TRANSITIONS_PER_RUBY_CYCLE, 32, false );
+//PARAM( DirectoryTransitionsPerCycle, 32, false );
+//PARAM( DMATransitionsPerCycle, 1, false );
 
 // Number of TBEs available for demand misses, prefetches, and replacements
-PARAM( NUMBER_OF_TBES );
-PARAM( NUMBER_OF_L1_TBES );
-PARAM( NUMBER_OF_L2_TBES );
+//PARAM( NumberOfTBEs, 128, false );
+//PARAM( NumberOfL1TBEs, 32, false );
+//PARAM( NumberOfL2TBEs, 32, false );
 
 // NOTE: Finite buffering allows us to simulate a wormhole routed network
 // with idealized flow control.  All message buffers within the network (i.e.
 // the switch's input and output buffers) are set to the size specified below
 // by the PROTOCOL_BUFFER_SIZE
-PARAM_BOOL( FINITE_BUFFERING );
-PARAM( FINITE_BUFFER_SIZE ); // Zero is unbounded buffers
+//PARAM_BOOL( FiniteBuffering, false, false );
+//PARAM( FiniteBufferSize, 3, false ); // Zero is unbounded buffers
 // Number of requests buffered between the sequencer and the L1 conroller
 // This can be more accurately simulated in Opal, therefore it's set to an
 // infinite number
 // Only effects the simualtion when FINITE_BUFFERING is enabled
-PARAM( PROCESSOR_BUFFER_SIZE );
+//PARAM( ProcessorBufferSize, 10, false );
 // The PROTOCOL_BUFFER_SIZE limits the size of all other buffers connecting to
 // Controllers.  Controlls the number of request issued by the L2 HW Prefetcher
-PARAM( PROTOCOL_BUFFER_SIZE );
-
-// Enable the TSO (Total Store Order) memory model
-PARAM_BOOL( TSO ); // Note: This also disables the "write" STCs
+//PARAM( ProtocolBufferSize, 32, false );
 
 // NETWORK PARAMETERS
 
 // Network Topology: See TopologyType in external.sm for valid values
-PARAM_STRING( g_NETWORK_TOPOLOGY );
+//PARAM_STRING( NetworkTopology, "PT_TO_PT", false );
 
 // Cache Design specifies file prefix for topology
-PARAM_STRING( g_CACHE_DESIGN );
-
-PARAM( g_endpoint_bandwidth );
-PARAM_BOOL( g_adaptive_routing );
-PARAM( NUMBER_OF_VIRTUAL_NETWORKS );
-PARAM( FAN_OUT_DEGREE );
-PARAM_BOOL( g_PRINT_TOPOLOGY );
+//PARAM_STRING( CacheDesign, "NUCA", false );
 
-// transactional memory
-PARAM( XACT_LENGTH );
-PARAM( XACT_SIZE );
-PARAM( ABORT_RETRY_TIME );
+//PARAM( EndpointBandwidth, 10000, false );
+//PARAM_BOOL( AdaptiveRouting, true, false );
+//PARAM( NumberOfVirtualNetworks, 6, false );
+//PARAM( FanOutDegree, 4, false );
+//PARAM_BOOL( PrintTopology, true, false );
 
 // Princeton Network (Garnet)
-PARAM_BOOL( g_GARNET_NETWORK );
-PARAM_BOOL( g_DETAIL_NETWORK );
-PARAM_BOOL( g_NETWORK_TESTING );
-PARAM( g_FLIT_SIZE );
-PARAM( g_NUM_PIPE_STAGES );
-PARAM( g_VCS_PER_CLASS );
-PARAM( g_BUFFER_SIZE );
+//PARAM_BOOL( UsingGarnetNetwork, true, false );
+//PARAM_BOOL( UsingDetailNetwork, false, false );
+//PARAM_BOOL( UsingNetworkTesting, false, false );
+//PARAM( FlitSize, 16, false );
+//PARAM( NumberOfPipeStages, 4, false );
+//PARAM( VCSPerClass, 4, false );
+//PARAM( BufferSize, 4, false );
 
 // MemoryControl:
-PARAM( MEM_BUS_CYCLE_MULTIPLIER );
-PARAM( BANKS_PER_RANK );
-PARAM( RANKS_PER_DIMM );
-PARAM( DIMMS_PER_CHANNEL );
-PARAM( BANK_BIT_0 );
-PARAM( RANK_BIT_0 );
-PARAM( DIMM_BIT_0 );
-PARAM( BANK_QUEUE_SIZE );
-PARAM( BANK_BUSY_TIME );
-PARAM( RANK_RANK_DELAY );
-PARAM( READ_WRITE_DELAY );
-PARAM( BASIC_BUS_BUSY_TIME );
-PARAM( MEM_CTL_LATENCY );
-PARAM( REFRESH_PERIOD );
-PARAM( TFAW );
-PARAM( MEM_RANDOM_ARBITRATE );
-PARAM( MEM_FIXED_DELAY );
+//PARAM( MEM_BUS_CYCLE_MULTIPLIER, 10, false );
+//PARAM( BANKS_PER_RANK, 8, false );
+//PARAM( RANKS_PER_DIMM, 2, false );
+//PARAM( DIMMS_PER_CHANNEL, 2, false );
+//PARAM( BANK_BIT_0, 8, false );
+//PARAM( RANK_BIT_0, 11, false );
+//PARAM( DIMM_BIT_0, 12, false );
+//PARAM( BANK_QUEUE_SIZE, 12, false );
+//PARAM( BankBusyTime, 11, false );
+//PARAM( RANK_RANK_DELAY, 1, false );
+//PARAM( READ_WRITE_DELAY, 2, false );
+//PARAM( BASIC_BUS_BUSY_TIME, 2, false );
+//PARAM( MEM_CTL_LATENCY, 12, false );
+//PARAM( REFRESH_PERIOD, 1560, false );
+//PARAM( TFAW, 0, false );
+//PARAM( MEM_RANDOM_ARBITRATE, 0, false );
+//PARAM( MEM_FIXED_DELAY, 0, false );
 
 
--- /dev/null
+#!/usr/bin/ruby
+
+
+
+class NetPort < LibRubyObject
+  # number of transitions a SLICC state machine can transition per
+  # cycle
+  default_param :transitions_per_cycle, Integer, 32
+
+  # buffer_size limits the size of all other buffers connecting to
+  # SLICC Controllers.  When 0, infinite buffering is used.
+  default_param :buffer_size, Integer, 32
+
+  # added by SS for TBE
+  default_param :number_of_TBEs, Integer, 128
+
+  default_param :recycle_latency, Integer, 10
+end
+
+class Sequencer < IfacePort
+  # Maximum number of requests (including prefetches) outstanding from
+  # the sequencer
+  default_param :max_outstanding_requests, Integer, 16
+
+  # Maximum number of cycles a request is can be outstanding before
+  # the Sequencer declares we're in deadlock/livelock
+  default_param :deadlock_threshold, Integer, 500000
+
+end
+
+class Debug < LibRubyObject
+  # For debugging purposes, one can enable a trace of all the protocol
+  # state machine changes. Unfortunately, the code to generate the
+  # trace is protocol specific. To enable the code for some of the
+  # standard protocols,
+  #   1. change protocol_trace = true
+  #   2. enable debug in the Ruby Makefile
+  #   3. set start_time = 1
+  default_param :protocol_trace, Boolean, false
+
+  # a string for filtering debugging output (for all g_debug vars see Debug.h)
+  default_param :filter_string, String, "q"
+
+  # filters debugging messages based on priority (low, med, high)
+  default_param :verbosity_string, String, "none"
+
+  # filters debugging messages based on a ruby time
+  default_param :start_time, Integer, 1
+
+  # sends debugging messages to a output filename
+  default_param :output_filename, String, ""
+end
+
+class Topology < LibRubyObject
+  # The default link latency between all nodes (internal and external)
+  # in the toplogy
+  default_param :link_latency, Integer, 1
+
+  # the bandwidth from an external network port to it's corresponding
+  # internal switch
+  default_param :external_bw, Integer, 64
+
+  # the bandwitch between internal switches in the network
+  default_param :internal_bw, Integer, 16
+
+  # indicates whether the topology config will be displayed in the
+  # stats file
+  default_param :print_config, Boolean, true
+end
+
+class Network < LibRubyObject
+  default_param :endpoint_bandwidth, Integer, 10000
+  default_param :adaptive_routing, Boolean, true
+  default_param :number_of_virtual_networks, Integer, 6
+  default_param :fan_out_degree, Integer, 4
+
+  # default buffer size.  Setting to 0 indicates infinite buffering
+  default_param :buffer_size, Integer, 3
+
+  # local memory latency ?? NetworkLinkLatency
+  default_param :link_latency, Integer, 1
+
+  # on chip latency
+  default_param :on_chip_latency, Integer, 1
+end
+
+class GarnetNetwork < Network
+  default_param :flit_size, Integer, 16
+  default_param :number_of_pipe_stages, Integer, 4
+  default_param :vcs_per_class, Integer, 4
+  default_param :buffer_size, Integer, 4
+  default_param :using_network_testing, Boolean, false
+end
+
+
+
+#added by SS
+class Tracer < LibRubyObject
+  default_param :warmup_length, Integer, 1000000
+end
+
+#added by SS
+class Profiler < LibRubyObject
+  default_param :hot_lines, Boolean, false
+  default_param :all_instructions, Boolean, false
+end
+
+#added by SS
+class MI_example_CacheController < CacheController
+  default_param :issue_latency, Integer, 2
+  default_param :cache_response_latency, Integer, 12
+end
+
+class MI_example_DirectoryController < DirectoryController
+  default_param :to_mem_ctrl_latency, Integer, 1
+  default_param :directory_latency, Integer, 6
+  default_param :memory_latency, Integer, 158
+end
+
+
+#added by SS
+class MemoryControl < LibRubyObject
+
+  default_param :mem_bus_cycle_multiplier, Integer, 10
+  default_param :banks_per_rank, Integer, 8
+  default_param :ranks_per_dimm, Integer, 2
+  default_param :dimms_per_channel, Integer, 2
+  default_param :bank_bit_0, Integer, 8
+  default_param :rank_bit_0, Integer, 11
+  default_param :dimm_bit_0, Integer, 12
+  default_param :bank_queue_size, Integer, 12
+  default_param :bank_busy_time, Integer, 11
+  default_param :rank_rank_delay, Integer, 1
+  default_param :read_write_delay, Integer, 2
+  default_param :basic_bus_busy_time, Integer, 2
+  default_param :mem_ctl_latency, Integer, 12
+  default_param :refresh_period, Integer, 1560
+  default_param :tFaw, Integer, 0
+  default_param :mem_random_arbitrate, Integer, 0
+  default_param :mem_fixed_delay, Integer, 0
+
+end
+
+class RubySystem
+
+  # Random seed used by the simulation. If set to "rand", the seed
+  # will be set to the current wall clock at libruby
+  # initialization. Otherwise, set this to an integer.
+  default_param :random_seed, Object, "rand"
+
+  # When set to true, the simulation will insert random delays on
+  # message enqueue times.  Note that even if this is set to false,
+  # you can still have a non-deterministic simulation if random seed
+  # is set to "rand".  This is because the Ruby swtiches use random
+  # link priority elevation
+  default_param :randomization, Boolean, false
+
+  # tech_nm is the device size used to calculate latency and area
+  # information about system components
+  default_param :tech_nm, Integer, 45
+
+  # default frequency for the system
+  default_param :freq_mhz, Integer, 3000
+
+  # the default cache block size in the system
+  # libruby does not currently support different block sizes
+  # among different caches
+  # Must be a power of two
+  default_param :block_size_bytes, Integer, 64
+
+  # The default debug object. There shouldn't be a reason to ever
+  # change this line.  To adjust debug paramters statically, adjust
+  # them in the Debug class above.  To adjust these fields
+  # dynamically, access this RubySystem object,
+  # e.g. RubySystem.debug.protocol_trace = true
+  default_param :debug, Debug, Debug.new("dbg0")
+  default_param :tracer, Tracer, Tracer.new("tracer0")
+
+  default_param :profiler, Profiler, Profiler.new("profiler0")
+end
+
 
--- /dev/null
+
+#include <iostream>
+#include <assert.h>
+
+#include "../libruby.hh"
+
+int main(int argc, char* argv[])
+{
+  assert(argc == 2);
+  const char* cfg_file = argv[1];
+
+  libruby_init(cfg_file);
+  libruby_print_config(std::cout);
+}
 
--- /dev/null
+
+ruby_cfg_file = nil
+$stderr.puts $*.inspect
+for i in 0..$*.size-1 do
+  if $*[i] == "-r" # ruby config file
+    i += 1
+    ruby_cfg_file = $*[i]
+    break
+  end
+end
+
+require ruby_cfg_file
+
+RubySystem.generateConfig
 
 //  (does not apply when running Opal)
 SIMICS_RUBY_MULTIPLIER: 4
 
-// corresponding parameter when using Opal+Ruby+Simics
-OPAL_RUBY_MULTIPLIER: 1
-
-
 // Ruby cycles between when a sequencer issues a request and it arrives at
 // the L1 cache controller
 //
 L2_CACHE_NUM_SETS_BITS: 16
 
 // 32 bits = 4 GB address space
-g_MEMORY_SIZE_BYTES: 4294967296
+g_MEMORY_SIZE_BYTES: 1073741824 //4294967296
 g_DATA_BLOCK_BYTES: 64
 g_PAGE_SIZE_BYTES: 4096
 g_REPLACEMENT_POLICY: PSEDUO_LRU // currently, only other option is LRU
 L2_REQUEST_LATENCY: 4
 
 
-
-
 // Number of transitions each controller state machines can complete per cycle
 // i.e. the number of ports to each controller
 // L1cache is the sum of the L1I and L1D cache ports
 // much greater constraint on the concurrency of a L2 cache bank
 L2CACHE_TRANSITIONS_PER_RUBY_CYCLE: 32
 DIRECTORY_TRANSITIONS_PER_RUBY_CYCLE: 32
+DMA_TRANSITIONS_PER_RUBY_CYCLE: 1
 
 
 // Number of TBEs available for demand misses, ALL prefetches, and replacements
 NUMBER_OF_L1_TBES: 32
 NUMBER_OF_L2_TBES: 32
 
-// TSO is deprecated
-TSO: false
-
-
 // ** INTERCONECT PARAMETERS **
 //
 g_PRINT_TOPOLOGY: true
 FAN_OUT_DEGREE: 4  // for HIERARCHICAL SWITCH topology
 
 g_adaptive_routing: true
-NUMBER_OF_VIRTUAL_NETWORKS: 4
+NUMBER_OF_VIRTUAL_NETWORKS: 6
 
 // bandwidth unit is 1/1000 byte per cycle.  the following parameter is multiplied by
 //  topology specific link weights
 SINGLE_ACCESS_L2_BANKS: true
 
 
-// constants used by TM protocols
-PROFILE_EXCEPTIONS: false
-PROFILE_XACT: true
-PROFILE_NONXACT: false
-XACT_DEBUG: true
-XACT_DEBUG_LEVEL: 1
-//XACT_MEMORY: true  // set to true for TM protocols. set it HERE for lazy systems to register the proper SIMICS interfaces
-XACT_MEMORY: false
-XACT_ENABLE_TOURMALINE: false // perfect memory system
-XACT_NUM_CURRENT: 0 // must be 0
-XACT_LAST_UPDATE: 0 // must be 0
-XACT_ISOLATION_CHECK: false // Checks whether each memory access preserves transaction isolation
-PERFECT_FILTER: true                // If true, use perfect physical read/write filters
-READ_WRITE_FILTER: Perfect_
-PERFECT_VIRTUAL_FILTER: true        // If true, use perfect virtual read/write filters
-VIRTUAL_READ_WRITE_FILTER: Perfect_
-PERFECT_SUMMARY_FILTER: true        // If true, use perfect summary read/write filters
-SUMMARY_READ_WRITE_FILTER: Perfect_
-XACT_EAGER_CD: true
-XACT_LAZY_VM: false
-XACT_CONFLICT_RES: BASE
-XACT_COMMIT_TOKEN_LATENCY: 0
-XACT_VISUALIZER: false
-XACT_NO_BACKOFF: false
-XACT_LOG_BUFFER_SIZE: 0
-XACT_STORE_PREDICTOR_ENTRIES: 256
-XACT_STORE_PREDICTOR_HISTORY: 256
-XACT_STORE_PREDICTOR_THRESHOLD: 4
-XACT_FIRST_ACCESS_COST: 0
-XACT_FIRST_PAGE_ACCESS_COST: 0
-ENABLE_MAGIC_WAITING: false
-ENABLE_WATCHPOINT: false
-XACT_ENABLE_VIRTUALIZATION_LOGTM_SE: false
-// g_NETWORK_TOPOLOGY: FILE_SPECIFIED
-// NUMBER_OF_VIRTUAL_NETWORKS: 5
-// L2_REQUEST_LATENCY: 15
-// SEQUENCER_TO_CONTROLLER_LATENCY: 3
-// L2_RESPONSE_LATENCY: 20
-// L2_TAG_LATENCY: 6
-// MEMORY_RESPONSE_LATENCY_MINUS_2: 448
-// RECYCLE_LATENCY: 1
-// g_MEMORY_SIZE_BYTES: 268435456
-// REMOVE_SINGLE_CYCLE_DCACHE_FAST_PATH: true
-
-// ATMTP
-ATMTP_ENABLED: false
-ATMTP_ABORT_ON_NON_XACT_INST: false
-ATMTP_ALLOW_SAVE_RESTORE_IN_XACT: false
-ATMTP_XACT_MAX_STORES: 32
-ATMTP_DEBUG_LEVEL: 0
-
 // MOESI_CMP_token parameters (some might be deprecated)
 g_FILTERING_ENABLED: false
 g_DISTRIBUTED_PERSISTENT_ENABLED: true
 g_wait_time:  5
 
 // Princeton Network (Garnet)
-g_GARNET_NETWORK: false
+g_GARNET_NETWORK: true
 g_DETAIL_NETWORK: false
 g_NETWORK_TESTING: false
 g_FLIT_SIZE: 16
 
 // Please: - Add new variables only to rubyconfig.defaults file.
 //         - Change them here only when necessary.
 
+g_SIMICS: false
 DATA_BLOCK: true
 RANDOMIZATION: true
-g_SYNTHETIC_DRIVER: true
-g_DETERMINISTIC_DRIVER: false
+g_SYNTHETIC_DRIVER: false
+g_DETERMINISTIC_DRIVER: true
 g_DEADLOCK_THRESHOLD: 500000
 g_SpecifiedGenerator: DetermGETXGenerator
 
 
 g_MEMORY_SIZE_BYTES: 1048576
 
-// XACT MEMORY
-XACT_LENGTH: 2000
-XACT_SIZE:   1000
-ABORT_RETRY_TIME: 400
-XACT_ISOLATION_CHECK: true
-L2CACHE_TRANSITIONS_PER_RUBY_CYCLE: 1000
-DIRECTORY_TRANSITIONS_PER_RUBY_CYCLE: 1000
-PERFECT_FILTER: true        // If true, use perfect read/write filters
-READ_WRITE_FILTER: Perfect_
-
 //g_NETWORK_TOPOLOGY: FILE_SPECIFIED
 RECYCLE_LATENCY: 1
 //NUMBER_OF_VIRTUAL_NETWORKS: 5
 //g_NUM_MEMORIES: 16
 L2CACHE_TRANSITIONS_PER_RUBY_CYCLE: 1000
 DIRECTORY_TRANSITIONS_PER_RUBY_CYCLE: 1000
-//g_PROCS_PER_CHIP: 16
+//g_PROCS_PER_CHIP: 2
 //g_NUM_L2_BANKS: 16
 //g_endpoint_bandwidth: 10000
 //g_NUM_PROCESSORS: 16
 
 
 RubyEventQueue::~RubyEventQueue()
 {
-  // delete m_prio_heap_ptr;
+  delete m_prio_heap_ptr;
 }
 
 void RubyEventQueue::init()
     assert(thisNode.m_consumer_ptr != NULL);
     DEBUG_EXPR(EVENTQUEUE_COMP,MedPrio,*(thisNode.m_consumer_ptr));
     DEBUG_EXPR(EVENTQUEUE_COMP,MedPrio,thisNode.m_time);
-    thisNode.m_consumer_ptr->triggerWakeup();
+    thisNode.m_consumer_ptr->triggerWakeup(this);
   }
   m_globalTime = t;
 }
     assert(thisNode.m_consumer_ptr != NULL);
     DEBUG_EXPR(EVENTQUEUE_COMP,MedPrio,*(thisNode.m_consumer_ptr));
     DEBUG_EXPR(EVENTQUEUE_COMP,MedPrio,thisNode.m_time);
-    thisNode.m_consumer_ptr->triggerWakeup();
+    thisNode.m_consumer_ptr->triggerWakeup(this);
   }
 }
 
 
--- /dev/null
+
+/*
+ * 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.
+ */
+
+/*
+ * AbstractBloomFilter.hh
+ *
+ * Description:
+ *
+ *
+ */
+
+#ifndef ABSTRACT_BLOOM_FILTER_H
+#define ABSTRACT_BLOOM_FILTER_H
+
+#include "mem/ruby/common/Global.hh"
+#include "mem/ruby/config/RubyConfig.hh"
+#include "mem/ruby/common/Address.hh"
+
+class AbstractBloomFilter {
+public:
+
+  virtual ~AbstractBloomFilter() {};
+  virtual void clear() = 0;
+  virtual void increment(const Address& addr) = 0;
+  virtual void decrement(const Address& addr) = 0;
+  virtual void merge(AbstractBloomFilter * other_filter) = 0;
+  virtual void set(const Address& addr) = 0;
+  virtual void unset(const Address& addr) = 0;
+
+  virtual bool isSet(const Address& addr) = 0;
+  virtual int getCount(const Address& addr) = 0;
+  virtual int getTotalCount() = 0;
+
+  virtual void print(ostream& out) const = 0;
+
+  virtual int getIndex(const Address& addr) = 0;
+  virtual int readBit(const int index) = 0;
+  virtual void writeBit(const int index, const int value) = 0;
+
+private:
+
+};
+
+
+#endif
 
--- /dev/null
+
+/*
+ * 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.
+ */
+
+/*
+ * BlockBloomFilter.cc
+ *
+ * Description:
+ *
+ *
+ */
+
+#include "mem/ruby/filters/BlockBloomFilter.hh"
+#include "mem/gems_common/Map.hh"
+#include "mem/ruby/common/Address.hh"
+
+BlockBloomFilter::BlockBloomFilter(string str)
+{
+  string tail(str);
+  string head = string_split(tail, '_');
+
+  m_filter_size = atoi(head.c_str());
+  m_filter_size_bits = log_int(m_filter_size);
+
+  m_filter.setSize(m_filter_size);
+
+  clear();
+}
+
+BlockBloomFilter::~BlockBloomFilter(){
+}
+
+void BlockBloomFilter::clear()
+{
+  for (int i = 0; i < m_filter_size; i++) {
+    m_filter[i] = 0;
+  }
+}
+
+void BlockBloomFilter::increment(const Address& addr)
+{
+  // Not used
+}
+
+
+void BlockBloomFilter::decrement(const Address& addr)
+{
+  // Not used
+}
+
+void BlockBloomFilter::merge(AbstractBloomFilter * other_filter)
+{
+  // TODO
+}
+
+void BlockBloomFilter::set(const Address& addr)
+{
+  int i = get_index(addr);
+  m_filter[i] = 1;
+}
+
+void BlockBloomFilter::unset(const Address& addr)
+{
+  int i = get_index(addr);
+  m_filter[i] = 0;
+}
+
+bool BlockBloomFilter::isSet(const Address& addr)
+{
+  int i = get_index(addr);
+  return (m_filter[i]);
+}
+
+
+int BlockBloomFilter::getCount(const Address& addr)
+{
+  return m_filter[get_index(addr)];
+}
+
+int BlockBloomFilter::getTotalCount()
+{
+  int count = 0;
+
+  for (int i = 0; i < m_filter_size; i++) {
+    if (m_filter[i]) {
+      count++;
+    }
+  }
+  return count;
+}
+
+int BlockBloomFilter::getIndex(const Address& addr)
+{
+  return get_index(addr);
+}
+
+void BlockBloomFilter::print(ostream& out) const
+{
+}
+
+int BlockBloomFilter::readBit(const int index) {
+  return m_filter[index];
+}
+
+void BlockBloomFilter::writeBit(const int index, const int value) {
+  m_filter[index] = value;
+}
+
+int BlockBloomFilter::get_index(const Address& addr)
+{
+  // Pull out some bit field ==> B1
+  // Pull out additional bits, not the same as B1 ==> B2
+  //  XOR B1 and B2 to get hash index
+  physical_address_t block_bits = addr.bitSelect( RubySystem::getBlockSizeBits(), 2*RubySystem::getBlockSizeBits() - 1);
+  int offset = 5;
+  physical_address_t other_bits = addr.bitSelect( 2*RubySystem::getBlockSizeBits() + offset, 2*RubySystem::getBlockSizeBits() + offset + m_filter_size_bits - 1);
+  int index = block_bits ^ other_bits;
+  assert(index < m_filter_size);
+  return index;
+}
+
+
 
--- /dev/null
+
+/*
+ * 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.
+ */
+
+/*
+ * BlockBloomFilter.hh
+ *
+ * Description:
+ *
+ *
+ */
+
+#ifndef BLOCK_BLOOM_FILTER_H
+#define BLOCK_BLOOM_FILTER_H
+
+#include "mem/gems_common/Map.hh"
+#include "mem/ruby/common/Global.hh"
+#include "mem/ruby/config/RubyConfig.hh"
+#include "mem/ruby/common/Address.hh"
+#include "mem/ruby/filters/AbstractBloomFilter.hh"
+
+class BlockBloomFilter : public AbstractBloomFilter {
+public:
+
+  ~BlockBloomFilter();
+  BlockBloomFilter(string config);
+
+  void clear();
+  void increment(const Address& addr);
+  void decrement(const Address& addr);
+  void merge(AbstractBloomFilter * other_filter);
+  void set(const Address& addr);
+  void unset(const Address& addr);
+
+  bool isSet(const Address& addr);
+  int getCount(const Address& addr);
+  int getTotalCount();
+  int getIndex(const Address& addr);
+  int readBit(const int index);
+  void writeBit(const int index, const int value);
+
+  void print(ostream& out) const;
+
+private:
+
+  int get_index(const Address& addr);
+
+  Vector<int> m_filter;
+  int m_filter_size;
+  int m_filter_size_bits;
+
+  int m_count_bits;
+  int m_count;
+};
+
+
+#endif
 
--- /dev/null
+
+/*
+ * 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.
+ */
+
+/*
+ * BulkBloomFilter.cc
+ *
+ * Description:
+ *
+ *
+ */
+
+#include "mem/ruby/filters/BulkBloomFilter.hh"
+#include "mem/gems_common/Map.hh"
+#include "mem/ruby/common/Address.hh"
+
+BulkBloomFilter::BulkBloomFilter(string str)
+{
+  string tail(str);
+  string head = string_split(tail, '_');
+
+  m_filter_size = atoi(head.c_str());
+  m_filter_size_bits = log_int(m_filter_size);
+  // split the filter bits in half, c0 and c1
+  m_sector_bits = m_filter_size_bits - 1;
+
+  m_temp_filter.setSize(m_filter_size);
+  m_filter.setSize(m_filter_size);
+  clear();
+
+  // clear temp filter
+  for(int i=0; i < m_filter_size; ++i){
+    m_temp_filter[i] = 0;
+  }
+}
+
+BulkBloomFilter::~BulkBloomFilter(){
+
+}
+
+void BulkBloomFilter::clear()
+{
+  for (int i = 0; i < m_filter_size; i++) {
+    m_filter[i] = 0;
+  }
+}
+
+void BulkBloomFilter::increment(const Address& addr)
+{
+  // Not used
+}
+
+
+void BulkBloomFilter::decrement(const Address& addr)
+{
+  // Not used
+}
+
+void BulkBloomFilter::merge(AbstractBloomFilter * other_filter)
+{
+  // TODO
+}
+
+void BulkBloomFilter::set(const Address& addr)
+{
+  // c0 contains the cache index bits
+  int set_bits = m_sector_bits;
+  int block_bits = RubySystem::getBlockSizeBits();
+  int c0 = addr.bitSelect( block_bits, block_bits + set_bits - 1);
+  // c1 contains the lower m_sector_bits permuted bits
+  //Address permuted_bits = permute(addr);
+  //int c1 = permuted_bits.bitSelect(0, set_bits-1);
+  int c1 = addr.bitSelect( block_bits+set_bits, (block_bits+2*set_bits) - 1);
+  //ASSERT(c0 < (m_filter_size/2));
+  //ASSERT(c0 + (m_filter_size/2) < m_filter_size);
+  //ASSERT(c1 < (m_filter_size/2));
+  // set v0 bit
+  m_filter[c0 + (m_filter_size/2)] = 1;
+  // set v1 bit
+  m_filter[c1] = 1;
+}
+
+void BulkBloomFilter::unset(const Address& addr)
+{
+  // not used
+}
+
+bool BulkBloomFilter::isSet(const Address& addr)
+{
+  // c0 contains the cache index bits
+  int set_bits = m_sector_bits;
+  int block_bits = RubySystem::getBlockSizeBits();
+  int c0 = addr.bitSelect( block_bits, block_bits + set_bits - 1);
+  // c1 contains the lower 10 permuted bits
+  //Address permuted_bits = permute(addr);
+  //int c1 = permuted_bits.bitSelect(0, set_bits-1);
+  int c1 = addr.bitSelect( block_bits+set_bits, (block_bits+2*set_bits) - 1);
+  //ASSERT(c0 < (m_filter_size/2));
+  //ASSERT(c0 + (m_filter_size/2) < m_filter_size);
+  //ASSERT(c1 < (m_filter_size/2));
+  // set v0 bit
+  m_temp_filter[c0 + (m_filter_size/2)] = 1;
+  // set v1 bit
+  m_temp_filter[c1] = 1;
+
+  // perform filter intersection. If any c part is 0, no possibility of address being in signature.
+  // get first c intersection part
+  bool zero = false;
+  for(int i=0; i < m_filter_size/2; ++i){
+    // get intersection of signatures
+    m_temp_filter[i] = m_temp_filter[i] && m_filter[i];
+    zero = zero || m_temp_filter[i];
+  }
+  zero = !zero;
+  if(zero){
+    // one section is zero, no possiblility of address in signature
+    // reset bits we just set
+    m_temp_filter[c0 + (m_filter_size/2)] = 0;
+    m_temp_filter[c1] = 0;
+    return false;
+  }
+
+  // check second section
+  zero = false;
+  for(int i=m_filter_size/2; i < m_filter_size; ++i){
+    // get intersection of signatures
+    m_temp_filter[i] =  m_temp_filter[i] && m_filter[i];
+    zero = zero || m_temp_filter[i];
+  }
+  zero = !zero;
+  if(zero){
+    // one section is zero, no possiblility of address in signature
+    m_temp_filter[c0 + (m_filter_size/2)] = 0;
+    m_temp_filter[c1] = 0;
+    return false;
+  }
+  // one section has at least one bit set
+  m_temp_filter[c0 + (m_filter_size/2)] = 0;
+  m_temp_filter[c1] = 0;
+  return true;
+}
+
+
+int BulkBloomFilter::getCount(const Address& addr)
+{
+  // not used
+  return 0;
+}
+
+int BulkBloomFilter::getTotalCount()
+{
+  int count = 0;
+  for (int i = 0; i < m_filter_size; i++) {
+    if (m_filter[i]) {
+      count++;
+    }
+  }
+  return count;
+}
+
+int BulkBloomFilter::getIndex(const Address& addr)
+{
+  return get_index(addr);
+}
+
+int BulkBloomFilter::readBit(const int index) {
+  return 0;
+  // TODO
+}
+
+void BulkBloomFilter::writeBit(const int index, const int value) {
+  // TODO
+}
+
+void BulkBloomFilter::print(ostream& out) const
+{
+}
+
+int BulkBloomFilter::get_index(const Address& addr)
+{
+  return addr.bitSelect( RubySystem::getBlockSizeBits(), RubySystem::getBlockSizeBits() + m_filter_size_bits - 1);
+}
+
+Address BulkBloomFilter::permute(const Address & addr){
+  // permutes the original address bits according to Table 5
+  int block_offset = RubySystem::getBlockSizeBits();
+  physical_address_t part1 = addr.bitSelect( block_offset, block_offset + 6 );
+  physical_address_t part2 = addr.bitSelect( block_offset + 9, block_offset + 9 );
+  physical_address_t part3 = addr.bitSelect( block_offset + 11, block_offset + 11 );
+  physical_address_t part4 = addr.bitSelect( block_offset + 17, block_offset + 17 );
+  physical_address_t part5 = addr.bitSelect( block_offset + 7, block_offset + 8 );
+  physical_address_t part6 = addr.bitSelect( block_offset + 10, block_offset + 10 );
+  physical_address_t part7 = addr.bitSelect( block_offset + 12, block_offset + 12 );
+  physical_address_t part8 = addr.bitSelect( block_offset + 13, block_offset + 13 );
+  physical_address_t part9 = addr.bitSelect( block_offset + 15, block_offset + 16 );
+  physical_address_t part10 = addr.bitSelect( block_offset + 18, block_offset + 20 );
+  physical_address_t part11 = addr.bitSelect( block_offset + 14, block_offset + 14 );
+
+  physical_address_t result = (part1 << 14 ) | (part2 << 13 ) | (part3 << 12 ) | (part4 << 11 ) | (part5 << 9) | (part6 << 8)
+    | (part7 << 7) | (part8 << 6) | (part9 << 4) | (part10 << 1) | (part11);
+  // assume 32 bit addresses (both virtual and physical)
+  // select the remaining high-order 11 bits
+  physical_address_t remaining_bits = (addr.bitSelect( block_offset + 21, 31 )) << 21;
+  result = result | remaining_bits;
+
+  return Address(result);
+}
 
--- /dev/null
+
+/*
+ * 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.
+ */
+
+/*
+ * BulkBloomFilter.hh
+ *
+ * Description:
+ *
+ *
+ */
+
+#ifndef BULK_BLOOM_FILTER_H
+#define BULK_BLOOM_FILTER_H
+
+#include "mem/gems_common/Map.hh"
+#include "mem/ruby/common/Global.hh"
+#include "mem/ruby/config/RubyConfig.hh"
+#include "mem/ruby/common/Address.hh"
+#include "mem/ruby/filters/AbstractBloomFilter.hh"
+
+class BulkBloomFilter : public AbstractBloomFilter {
+public:
+
+  ~BulkBloomFilter();
+  BulkBloomFilter(string config);
+
+  void clear();
+  void increment(const Address& addr);
+  void decrement(const Address& addr);
+  void merge(AbstractBloomFilter * other_filter);
+  void set(const Address& addr);
+  void unset(const Address& addr);
+
+  bool isSet(const Address& addr);
+  int getCount(const Address& addr);
+  int getTotalCount();
+  int getIndex(const Address& addr);
+  int readBit(const int index);
+  void writeBit(const int index, const int value);
+
+  void print(ostream& out) const;
+
+private:
+
+  int get_index(const Address& addr);
+  Address permute(const Address & addr);
+
+  Vector<int> m_filter;
+  Vector<int> m_temp_filter;
+
+  int m_filter_size;
+  int m_filter_size_bits;
+
+  int m_sector_bits;
+
+  int m_count_bits;
+  int m_count;
+};
+
+
+#endif
 
--- /dev/null
+
+/*
+ * 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.
+ */
+
+/*
+ * GenericBloomFilter.hh
+ *
+ * Description:
+ *
+ *
+ */
+
+#include "mem/ruby/common/Global.hh"
+#include "mem/ruby/config/RubyConfig.hh"
+#include "mem/ruby/common/Address.hh"
+
+#include "mem/ruby/filters/GenericBloomFilter.hh"
+#include "mem/ruby/filters/LSB_CountingBloomFilter.hh"
+#include "mem/ruby/filters/NonCountingBloomFilter.hh"
+#include "mem/ruby/filters/BulkBloomFilter.hh"
+#include "mem/ruby/filters/BlockBloomFilter.hh"
+#include "mem/ruby/filters/MultiGrainBloomFilter.hh"
+#include "mem/ruby/filters/MultiBitSelBloomFilter.hh"
+#include "mem/ruby/filters/H3BloomFilter.hh"
+
+GenericBloomFilter::GenericBloomFilter(string config)
+{
+  string tail(config);
+  string head = string_split(tail,'_');
+
+  if (head == "LSB_Counting" ) {
+    m_filter = new LSB_CountingBloomFilter(tail);
+  }
+  else if(head == "NonCounting" ) {
+    m_filter = new NonCountingBloomFilter(tail);
+  }
+  else if(head == "Bulk" ) {
+    m_filter = new BulkBloomFilter(tail);
+  }
+  else if(head == "Block") {
+    m_filter = new BlockBloomFilter(tail);
+  }
+  else if(head == "Multigrain"){
+    m_filter = new MultiGrainBloomFilter(tail);
+  }
+  else if(head == "MultiBitSel"){
+    m_filter = new MultiBitSelBloomFilter(tail);
+  }
+  else if(head == "H3"){
+    m_filter = new H3BloomFilter(tail);
+  }
+  else {
+    assert(0);
+  }
+}
+
+GenericBloomFilter::~GenericBloomFilter()
+{
+  delete m_filter;
+}
+
+void GenericBloomFilter::clear()
+{
+  m_filter->clear();
+}
+
+void GenericBloomFilter::increment(const Address& addr)
+{
+  m_filter->increment(addr);
+}
+
+void GenericBloomFilter::decrement(const Address& addr)
+{
+  m_filter->decrement(addr);
+}
+
+void GenericBloomFilter::merge(GenericBloomFilter * other_filter)
+{
+  m_filter->merge(other_filter->getFilter());
+}
+
+void GenericBloomFilter::set(const Address& addr)
+{
+  m_filter->set(addr);
+}
+
+void GenericBloomFilter::unset(const Address& addr)
+{
+  m_filter->unset(addr);
+}
+
+bool GenericBloomFilter::isSet(const Address& addr)
+{
+  return m_filter->isSet(addr);
+}
+
+int GenericBloomFilter::getCount(const Address& addr)
+{
+  return m_filter->getCount(addr);
+}
+
+int GenericBloomFilter::getTotalCount()
+{
+  return m_filter->getTotalCount();
+}
+
+int GenericBloomFilter::getIndex(const Address& addr)
+{
+  return m_filter->getIndex(addr);
+}
+
+int GenericBloomFilter::readBit(const int index) {
+  return m_filter->readBit(index);
+}
+
+void GenericBloomFilter::writeBit(const int index, const int value) {
+  m_filter->writeBit(index, value);
+}
+
+void GenericBloomFilter::print(ostream& out) const
+{
+  return m_filter->print(out);
+}
+
+
 
--- /dev/null
+
+/*
+ * 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.
+ */
+
+/*
+ * GenericBloomFilter.hh
+ *
+ * Description:
+ *
+ *
+ */
+
+#ifndef GENERIC_BLOOM_FILTER_H
+#define GENERIC_BLOOM_FILTER_H
+
+#include "mem/ruby/common/Global.hh"
+#include "mem/ruby/config/RubyConfig.hh"
+#include "mem/ruby/common/Address.hh"
+#include "mem/ruby/filters/AbstractBloomFilter.hh"
+
+class GenericBloomFilter {
+public:
+
+  // Constructors
+  GenericBloomFilter(string config);
+
+  void clear();
+  void increment(const Address& addr);
+  void decrement(const Address& addr);
+  void merge(GenericBloomFilter * other_filter);
+  void set(const Address& addr);
+  void unset(const Address& addr);
+  AbstractBloomFilter * getFilter(){
+    return m_filter;
+  }
+
+  bool isSet(const Address& addr);
+
+  int getCount(const Address& addr);
+
+  int getTotalCount();
+
+  int getIndex(const Address& addr);
+  int readBit(const int index);
+  void writeBit(const int index, const int value);
+
+  void print(ostream& out) const;
+  void printConfig(ostream& out) { out << "GenericBloomFilter" << endl; }
+
+  // Destructor
+  ~GenericBloomFilter();
+
+
+private:
+
+  AbstractBloomFilter* m_filter;
+};
+
+// Output operator definition
+extern inline
+ostream& operator<<(ostream& out, const GenericBloomFilter& obj)
+{
+  obj.print(out);
+  out << flush;
+  return out;
+}
+
+
+#endif
 
--- /dev/null
+
+/*
+ * 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.
+ */
+
+/*
+ * NonCountingBloomFilter.cc
+ *
+ * Description:
+ *
+ *
+ */
+
+#include "mem/ruby/filters/H3BloomFilter.hh"
+#include "mem/gems_common/Map.hh"
+#include "mem/ruby/common/Address.hh"
+
+H3BloomFilter::H3BloomFilter(string str)
+{
+  //TODO: change this ugly init code...
+  primes_list[0] = 9323;
+  primes_list[1] = 11279;
+  primes_list[2] = 10247;
+  primes_list[3] = 30637;
+  primes_list[4] = 25717;
+  primes_list[5] = 43711;
+
+  mults_list[0] = 255;
+  mults_list[1] = 29;
+  mults_list[2] = 51;
+  mults_list[3] = 3;
+  mults_list[4] = 77;
+  mults_list[5] = 43;
+
+  adds_list[0] = 841;
+  adds_list[1] = 627;
+  adds_list[2] = 1555;
+  adds_list[3] = 241;
+  adds_list[4] = 7777;
+  adds_list[5] = 65931;
+
+
+
+  string tail(str);
+  string head = string_split(tail, '_');
+
+  // head contains filter size, tail contains bit offset from block number
+  m_filter_size = atoi(head.c_str());
+
+  head = string_split(tail, '_');
+  m_num_hashes = atoi(head.c_str());
+
+  if(tail == "Regular") {
+    isParallel = false;
+  } else if (tail == "Parallel") {
+    isParallel = true;
+  } else {
+    cout << "ERROR: Incorrect config string for MultiHash Bloom! :" << str << endl;
+    assert(0);
+  }
+
+  m_filter_size_bits = log_int(m_filter_size);
+
+  m_par_filter_size = m_filter_size/m_num_hashes;
+  m_par_filter_size_bits = log_int(m_par_filter_size);
+
+  m_filter.setSize(m_filter_size);
+  clear();
+}
+
+H3BloomFilter::~H3BloomFilter(){
+}
+
+void H3BloomFilter::clear()
+{
+  for (int i = 0; i < m_filter_size; i++) {
+    m_filter[i] = 0;
+  }
+}
+
+void H3BloomFilter::increment(const Address& addr)
+{
+  // Not used
+}
+
+
+void H3BloomFilter::decrement(const Address& addr)
+{
+  // Not used
+}
+
+void H3BloomFilter::merge(AbstractBloomFilter * other_filter){
+  // assumes both filters are the same size!
+  H3BloomFilter * temp = (H3BloomFilter*) other_filter;
+  for(int i=0; i < m_filter_size; ++i){
+    m_filter[i] |= (*temp)[i];
+  }
+
+}
+
+void H3BloomFilter::set(const Address& addr)
+{
+  for (int i = 0; i < m_num_hashes; i++) {
+    int idx = get_index(addr, i);
+    m_filter[idx] = 1;
+
+    //Profile hash value distribution
+    //g_system_ptr->getProfiler()->getXactProfiler()->profileHashValue(i, idx); // gem5:Arka decomissiong of log_tm
+  }
+}
+
+void H3BloomFilter::unset(const Address& addr)
+{
+  cout << "ERROR: Unset should never be called in a Bloom filter";
+  assert(0);
+}
+
+bool H3BloomFilter::isSet(const Address& addr)
+{
+  bool res = true;
+
+  for (int i=0; i < m_num_hashes; i++) {
+    int idx = get_index(addr, i);
+    res = res && m_filter[idx];
+  }
+  return res;
+}
+
+
+int H3BloomFilter::getCount(const Address& addr)
+{
+  return isSet(addr)? 1: 0;
+}
+
+int H3BloomFilter::getIndex(const Address& addr)
+{
+  return 0;
+}
+
+int H3BloomFilter::readBit(const int index) {
+  return 0;
+}
+
+void H3BloomFilter::writeBit(const int index, const int value) {
+
+}
+
+int H3BloomFilter::getTotalCount()
+{
+  int count = 0;
+
+  for (int i = 0; i < m_filter_size; i++) {
+    count += m_filter[i];
+  }
+  return count;
+}
+
+void H3BloomFilter::print(ostream& out) const
+{
+}
+
+int H3BloomFilter::get_index(const Address& addr, int i)
+{
+  uint64 x = addr.getLineAddress();
+  //uint64 y = (x*mults_list[i] + adds_list[i]) % primes_list[i];
+  int y = hash_H3(x,i);
+
+  if(isParallel) {
+    return (y % m_par_filter_size) + i*m_par_filter_size;
+  } else {
+    return y % m_filter_size;
+  }
+}
+
+int H3BloomFilter::hash_H3(uint64 value, int index) {
+  uint64 mask = 1;
+  uint64 val = value;
+  int result = 0;
+
+  for(int i = 0; i < 64; i++) {
+    if(val&mask) result ^= H3[i][index];
+    val = val >> 1;
+  }
+  return result;
+  }
+
 
--- /dev/null
+
+/*
+ * 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.
+ */
+
+/*
+ * H3BloomFilter.hh
+ *
+ * Description:
+ *
+ *
+ */
+
+#ifndef H3_BLOOM_FILTER_H
+#define H3_BLOOM_FILTER_H
+
+#include "mem/gems_common/Map.hh"
+#include "mem/ruby/common/Global.hh"
+#include "mem/ruby/system/System.hh"
+#include "mem/ruby/profiler/Profiler.hh"
+#include "mem/ruby/config/RubyConfig.hh"
+#include "mem/ruby/common/Address.hh"
+#include "mem/ruby/filters/AbstractBloomFilter.hh"
+
+static int H3[64][16] = {
+{
+33268410,
+395488709,
+311024285,
+456111753,
+181495008,
+119997521,
+220697869,
+433891432,
+755927921,
+515226970,
+719448198,
+349842774,
+269183649,
+463275672,
+429800228,
+521598937
+},
+{
+628677802,
+820947732,
+809435975,
+1024657192,
+887631270,
+412050215,
+391365090,
+324227279,
+318338329,
+1038393087,
+489807930,
+387366128,
+518096428,
+324184340,
+429376066,
+447109279
+},
+{
+599747653,
+404960623,
+103933604,
+946416030,
+656460913,
+925957005,
+1047665689,
+163552053,
+88359290,
+841315415,
+899833584,
+1067336680,
+348549994,
+464045876,
+270252128,
+829897652
+},
+{
+215495230,
+966696438,
+82589012,
+750102795,
+909780866,
+920285789,
+769759214,
+331966823,
+939936006,
+439950703,
+883794828,
+1009277508,
+61634610,
+741444350,
+98689608,
+524144422
+},
+{
+93868534,
+196958667,
+774076619,
+327921978,
+122538783,
+879785030,
+690748527,
+3498564,
+83163077,
+1027963025,
+582088444,
+466152216,
+312424878,
+550064499,
+646612667,
+561099434
+},
+{
+1002047931,
+395477707,
+821317480,
+890482112,
+697094476,
+263813044,
+840275189,
+469664185,
+795625845,
+211504898,
+99204277,
+1004491153,
+725930417,
+1064479221,
+893834767,
+839719181
+},
+{
+278507126,
+985111995,
+706462983,
+1042178726,
+123281719,
+963778122,
+500881056,
+726291104,
+134293026,
+568379664,
+317050609,
+533470307,
+1022365922,
+197645211,
+315125721,
+634827678
+},
+{
+219227366,
+553960647,
+870169525,
+322232839,
+508322497,
+648672696,
+249405795,
+883596102,
+476433133,
+541372919,
+646647793,
+1042679515,
+43242483,
+600187508,
+499866821,
+135713210
+},
+{
+52837162,
+96966684,
+401840460,
+1071661176,
+733560065,
+150035417,
+341319946,
+811582750,
+636173904,
+519054065,
+196321433,
+1028294565,
+882204070,
+522965093,
+48884074,
+117810166
+},
+{
+650860353,
+789534698,
+328813544,
+473250022,
+143128306,
+173196006,
+846958825,
+174632187,
+683273509,
+405459497,
+787235556,
+773873501,
+240110267,
+426797736,
+92043842,
+711789240
+},
+{
+586637493,
+5059646,
+398035664,
+6686087,
+498300175,
+948278148,
+681227731,
+592751744,
+572019677,
+558044722,
+589368271,
+695745538,
+1073416749,
+529192035,
+550984939,
+1070620580
+},
+{
+102904663,
+647598516,
+758863940,
+313426443,
+76504114,
+1050747783,
+708436441,
+563815069,
+224107668,
+875925186,
+167675944,
+926209739,
+279737287,
+1040288182,
+768184312,
+371708956
+},
+{
+683968868,
+1027427757,
+180781926,
+742898864,
+624078545,
+645659833,
+577225838,
+987150210,
+723410002,
+224013421,
+993286634,
+33188488,
+247264323,
+888018697,
+38048664,
+189037096
+},
+{
+475612146,
+426739285,
+873726278,
+529192871,
+607715202,
+388486246,
+987001312,
+474493980,
+259747270,
+417465536,
+217062395,
+392858482,
+563810075,
+137852805,
+1051814153,
+72895217
+},
+{
+71277086,
+785496675,
+500608842,
+89633426,
+274085706,
+248467935,
+838061983,
+48106147,
+773662506,
+49545328,
+9071573,
+100739031,
+602018002,
+904371654,
+534132064,
+332211304
+},
+{
+401893602,
+735125342,
+775548339,
+210224843,
+256081130,
+482894412,
+350801633,
+1035713633,
+429458128,
+327281409,
+739927752,
+359327650,
+886942880,
+847691759,
+752417993,
+359445596
+},
+{
+267472014,
+1050659620,
+1068232362,
+1049684368,
+17130239,
+690524969,
+793224378,
+14455158,
+423092885,
+873853424,
+430535778,
+7867877,
+309731959,
+370260786,
+862353083,
+403906850
+},
+{
+993077283,
+218812656,
+389234651,
+393202875,
+413116501,
+263300295,
+470013158,
+592730725,
+441847172,
+732392823,
+407574059,
+875664777,
+271347307,
+792954404,
+554774761,
+1022424300
+},
+{
+675919719,
+637054073,
+784720745,
+149714381,
+813144874,
+502525801,
+635436670,
+1003196587,
+160786091,
+947509775,
+969788637,
+26854073,
+257964369,
+63898568,
+539767732,
+772364518
+},
+{
+943076868,
+1021732472,
+697575075,
+15843624,
+617573396,
+534113303,
+122953324,
+964873912,
+942995378,
+87830944,
+1012914818,
+455484661,
+592160054,
+599844284,
+810394353,
+836812568
+},
+{
+688992674,
+279465370,
+731582262,
+687883235,
+438178468,
+80493001,
+342701501,
+663561405,
+23360106,
+531315007,
+508931618,
+36294623,
+231216223,
+840438413,
+255665680,
+663205938
+},
+{
+857265418,
+552630887,
+8173237,
+792122963,
+210140052,
+823124938,
+667709953,
+751538219,
+991957789,
+462064153,
+19070176,
+726604748,
+714567823,
+151147895,
+1012619677,
+697114353
+},
+{
+467105652,
+683256174,
+702387467,
+28730434,
+549942998,
+48712701,
+960519696,
+1008345587,
+679267717,
+370932249,
+880419471,
+352141567,
+331640403,
+598772468,
+95160685,
+812053015
+},
+{
+1053491323,
+430526562,
+1014938507,
+109685515,
+765949103,
+177288303,
+1034642653,
+485421658,
+71850281,
+981034542,
+61620389,
+601367920,
+504420930,
+220599168,
+583051998,
+158735752
+},
+{
+103033901,
+522494916,
+658494760,
+959206022,
+931348143,
+834510661,
+21542994,
+189699884,
+679327018,
+171983002,
+96774168,
+456133168,
+543103352,
+923945936,
+970074188,
+643658485
+},
+{
+566379913,
+805798263,
+840662512,
+820206124,
+796507494,
+223712542,
+118811519,
+662246595,
+809326534,
+416471323,
+748027186,
+161169753,
+739149488,
+276330378,
+924837051,
+964873733
+},
+{
+585882743,
+135502711,
+3386031,
+625631285,
+1068193307,
+270342640,
+432739484,
+556606453,
+826419155,
+1038540977,
+158000202,
+69109538,
+207087256,
+298111218,
+678046259,
+184611498
+},
+{
+305310710,
+46237988,
+855726974,
+735975153,
+930663798,
+425764232,
+104362407,
+391371443,
+867622101,
+71645091,
+61824734,
+661902640,
+293738633,
+309416189,
+281710675,
+879317360
+},
+{
+398146324,
+398293087,
+689145387,
+1038451703,
+521637478,
+516134620,
+314658937,
+830334981,
+583400300,
+340083705,
+68029852,
+675389876,
+994635780,
+788959180,
+406967042,
+74403607
+},
+{
+69463153,
+744427484,
+191639960,
+590927798,
+969916795,
+546846769,
+728756758,
+889355646,
+520855076,
+136068426,
+776132410,
+189663815,
+252051082,
+533662856,
+362198652,
+1026161384
+},
+{
+584984279,
+1004834381,
+568439705,
+834508761,
+21812513,
+670870173,
+1052043300,
+341868768,
+473755574,
+124339439,
+36193947,
+437997647,
+137419489,
+58705193,
+337793711,
+340738909
+},
+{
+898051466,
+512792906,
+234874060,
+655358775,
+683745319,
+671676404,
+428888546,
+639928192,
+672697722,
+176477579,
+747020991,
+758211282,
+443045009,
+205395173,
+1016944273,
+5584717
+},
+{
+156038300,
+138620174,
+588466825,
+1061494056,
+1013672100,
+1064257198,
+881417791,
+839470738,
+83519030,
+100875683,
+237486447,
+461483733,
+681527127,
+777996147,
+574635362,
+815974538
+},
+{
+184168473,
+519509808,
+62531892,
+51821173,
+43787358,
+385711644,
+141325169,
+36069511,
+584183031,
+571372909,
+671503175,
+226486781,
+194932686,
+1045460970,
+753718579,
+331442433
+},
+{
+73065106,
+1015327221,
+630916840,
+1058053470,
+306737587,
+296343219,
+907194989,
+920172546,
+224516225,
+818625553,
+551143849,
+634570650,
+432966225,
+756438259,
+939564853,
+767999933
+},
+{
+884775648,
+394862257,
+446787794,
+219833788,
+727195727,
+728122304,
+249888353,
+732947974,
+289908868,
+448282580,
+618161877,
+898939716,
+739554163,
+860631799,
+1058977530,
+86916736
+},
+{
+143850006,
+352708694,
+200194048,
+979764914,
+629404175,
+546279766,
+72106714,
+860980514,
+313190585,
+897143111,
+308425797,
+953791785,
+349924906,
+221457005,
+950588925,
+908254505
+},
+{
+950032043,
+829868728,
+68623614,
+714624605,
+69760597,
+297275854,
+355894016,
+985369737,
+882852618,
+864071289,
+958512902,
+950910111,
+991368991,
+829645051,
+434698210,
+771350575
+},
+{
+552695074,
+319195551,
+80297396,
+496413831,
+944046531,
+621525571,
+617653363,
+416729825,
+441842808,
+9847464,
+99420657,
+1033914550,
+812966458,
+937053011,
+673390195,
+934577365
+},
+{
+1034695843,
+190969665,
+332900185,
+51897434,
+523888639,
+883512843,
+146908572,
+506785674,
+565814307,
+692255649,
+314052926,
+826386588,
+430691325,
+866927620,
+413880214,
+936474339
+},
+{
+129380164,
+741739952,
+1013703462,
+494392795,
+957214600,
+1010879043,
+931790677,
+94551922,
+988065869,
+120637871,
+882506912,
+395075379,
+210570485,
+812422692,
+910383687,
+817722285
+},
+{
+51850866,
+283408630,
+1053047202,
+858940389,
+818507731,
+477082181,
+353546901,
+993324368,
+407093779,
+231608253,
+1067319867,
+73159811,
+429792535,
+971320614,
+565699344,
+718823399
+},
+{
+408185106,
+491493570,
+596050720,
+310776444,
+703628192,
+454438809,
+523988035,
+728512200,
+686012353,
+976339656,
+72816924,
+116926720,
+165866591,
+452043792,
+866943072,
+968545481
+},
+{
+443231195,
+905907843,
+1061421320,
+746360489,
+1043120338,
+1069659155,
+463359031,
+688303227,
+186550710,
+155347339,
+1044842421,
+1005904570,
+69332909,
+706951903,
+422513657,
+882038450
+},
+{
+430990623,
+946501980,
+742556791,
+278398643,
+183759217,
+659404315,
+279754382,
+1069347846,
+843746517,
+222777670,
+990835599,
+548741637,
+129220580,
+1392170,
+1032654091,
+894058935
+},
+{
+452042227,
+751640705,
+259481376,
+765824585,
+145991469,
+1013683228,
+1055491225,
+536379588,
+392593350,
+913368594,
+1029429776,
+226857786,
+31505342,
+1054416381,
+32341741,
+687106649
+},
+{
+404750944,
+811417027,
+869530820,
+773491060,
+810901282,
+979340397,
+1036910290,
+461764404,
+834235095,
+765695033,
+604692390,
+452158120,
+928988098,
+442719218,
+1024059719,
+167723114
+},
+{
+974245177,
+1046377300,
+1003424287,
+787349855,
+336314155,
+875074696,
+1018462718,
+890313003,
+367376809,
+86355556,
+1020618772,
+890710345,
+444741481,
+373230261,
+767064947,
+840920177
+},
+{
+719581124,
+431808156,
+138301690,
+668222575,
+497413494,
+740492013,
+485033226,
+125301442,
+831265111,
+879071459,
+341690480,
+152975256,
+850330086,
+717444507,
+694225877,
+785340566
+},
+{
+1032766252,
+140959364,
+737474726,
+1062767538,
+364464647,
+331414723,
+356152634,
+642832379,
+158733632,
+374691640,
+285504811,
+345349905,
+876599880,
+476392727,
+479589210,
+606376325
+},
+{
+174997730,
+778177086,
+319164313,
+163614456,
+10331364,
+599358958,
+8331663,
+237538058,
+159173957,
+174533880,
+65588684,
+878222844,
+424467599,
+901803515,
+187504218,
+776690353
+},
+{
+803856182,
+965850321,
+694948067,
+218315960,
+358416571,
+683713254,
+178069303,
+428076035,
+686176454,
+579553217,
+357306738,
+315018080,
+886852373,
+568563910,
+896839725,
+257416821
+},
+{
+401650013,
+183289141,
+497957228,
+879734476,
+265024455,
+825794561,
+889237440,
+323359863,
+100258491,
+991414783,
+313986632,
+85847250,
+362520248,
+276103512,
+1041630342,
+525981595
+},
+{
+487732740,
+46201705,
+990837834,
+62744493,
+1067364756,
+58015363,
+690846283,
+680262648,
+997278956,
+469357861,
+432164624,
+996763915,
+211907847,
+167824295,
+144928194,
+454839915
+},
+{
+41404232,
+514493300,
+259546924,
+578217256,
+972345130,
+123299213,
+346040332,
+1014668104,
+520910639,
+579955198,
+36627803,
+179072921,
+547684341,
+598950511,
+269497394,
+854352266
+},
+{
+603906768,
+100863318,
+708837659,
+204175569,
+375560904,
+908375384,
+28314106,
+6303733,
+175283124,
+749851198,
+308667367,
+415293931,
+225365403,
+1032188331,
+977112710,
+819705229
+},
+{
+399767123,
+697985692,
+356790426,
+643687584,
+298624218,
+185095167,
+381653926,
+876816342,
+296720023,
+2205879,
+235816616,
+521850105,
+622753786,
+1021421218,
+726349744,
+256504902
+},
+{
+851245024,
+1022500222,
+511909628,
+313809625,
+99776025,
+39710175,
+798739932,
+741832408,
+140631966,
+898295927,
+607660421,
+870669312,
+1051422478,
+789055529,
+669113756,
+681943450
+},
+{
+853872755,
+491465269,
+503341472,
+98019440,
+258267420,
+335602837,
+320687824,
+1053324395,
+24932389,
+955011453,
+934255131,
+435625663,
+501568768,
+238967025,
+549987406,
+248619780
+},
+{
+411151284,
+576471205,
+757985419,
+544137226,
+968135693,
+877548443,
+194586894,
+74882373,
+248353663,
+21207540,
+273789651,
+853653916,
+861267970,
+533253322,
+3739570,
+661358586
+},
+{
+271430986,
+71390029,
+257643671,
+949329860,
+348156406,
+251939238,
+445808698,
+48269799,
+907589462,
+105677619,
+635451508,
+20805932,
+464874661,
+7542147,
+243619464,
+288304568
+},
+{
+368215982,
+530288964,
+770090421,
+660961164,
+614935537,
+630760399,
+931299233,
+794519275,
+779918979,
+401746493,
+561237006,
+1027202224,
+258968003,
+339508073,
+1050610516,
+1064307013
+},
+{
+1039172162,
+448331205,
+928997884,
+49813151,
+198712120,
+992335354,
+671024050,
+879525220,
+745915336,
+1038822580,
+138669665,
+917958819,
+681422342,
+792868818,
+924762727,
+816386174
+},
+{
+515190336,
+313808618,
+441296783,
+1022120897,
+792325033,
+354387581,
+59273006,
+280075434,
+411357221,
+665274694,
+4054464,
+1059046246,
+394261773,
+848616745,
+15446017,
+517723271
+}};
+
+
+class H3BloomFilter : public AbstractBloomFilter {
+public:
+
+  ~H3BloomFilter();
+  H3BloomFilter(string config);
+
+  void clear();
+  void increment(const Address& addr);
+  void decrement(const Address& addr);
+  void merge(AbstractBloomFilter * other_filter);
+  void set(const Address& addr);
+  void unset(const Address& addr);
+
+  bool isSet(const Address& addr);
+  int getCount(const Address& addr);
+  int getTotalCount();
+  void print(ostream& out) const;
+
+  int getIndex(const Address& addr);
+  int readBit(const int index);
+  void writeBit(const int index, const int value);
+
+  int operator[](const int index) const{
+    return this->m_filter[index];
+  }
+
+private:
+
+  int get_index(const Address& addr, int hashNumber);
+
+  int hash_H3(uint64 value, int index);
+
+  Vector<int> m_filter;
+  int m_filter_size;
+  int m_num_hashes;
+  int m_filter_size_bits;
+
+  int m_par_filter_size;
+  int m_par_filter_size_bits;
+
+  int m_count_bits;
+  int m_count;
+
+
+
+  int primes_list[6];// = {9323,11279,10247,30637,25717,43711};
+  int mults_list[6]; //= {255,29,51,3,77,43};
+  int adds_list[6]; //= {841,627,1555,241,7777,65391};
+
+  bool isParallel;
+
+};
+
+
+#endif
 
--- /dev/null
+
+/*
+ * 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.
+ */
+
+/*
+ * LSB_CountingBloomFilter.cc
+ *
+ * Description:
+ *
+ *
+ */
+
+#include "mem/ruby/filters/LSB_CountingBloomFilter.hh"
+#include "mem/gems_common/Map.hh"
+#include "mem/ruby/common/Address.hh"
+
+LSB_CountingBloomFilter::LSB_CountingBloomFilter(string str)
+{
+  string tail(str);
+  string head = string_split(tail, ':');
+
+  m_filter_size = atoi(head.c_str());
+  m_filter_size_bits = log_int(m_filter_size);
+
+  m_count = atoi(tail.c_str());
+  m_count_bits = log_int(m_count);
+
+  m_filter.setSize(m_filter_size);
+  clear();
+}
+
+LSB_CountingBloomFilter::~LSB_CountingBloomFilter(){
+}
+
+void LSB_CountingBloomFilter::clear()
+{
+  for (int i = 0; i < m_filter_size; i++) {
+    m_filter[i] = 0;
+  }
+}
+
+void LSB_CountingBloomFilter::increment(const Address& addr)
+{
+  int i = get_index(addr);
+  if (m_filter[i] < m_count);
+    m_filter[i] += 1;
+}
+
+
+void LSB_CountingBloomFilter::decrement(const Address& addr)
+{
+  int i = get_index(addr);
+  if (m_filter[i] > 0)
+    m_filter[i] -= 1;
+}
+
+void LSB_CountingBloomFilter::merge(AbstractBloomFilter * other_filter)
+{
+  // TODO
+}
+
+void LSB_CountingBloomFilter::set(const Address& addr)
+{
+  // TODO
+}
+
+void LSB_CountingBloomFilter::unset(const Address& addr)
+{
+  // TODO
+}
+
+bool LSB_CountingBloomFilter::isSet(const Address& addr)
+{
+  // TODO
+}
+
+
+int LSB_CountingBloomFilter::getCount(const Address& addr)
+{
+  return m_filter[get_index(addr)];
+}
+
+int LSB_CountingBloomFilter::getTotalCount()
+{
+  int count = 0;
+
+  for (int i = 0; i < m_filter_size; i++) {
+    count += m_filter[i];
+  }
+  return count;
+}
+
+int LSB_CountingBloomFilter::getIndex(const Address& addr)
+{
+  return get_index(addr);
+}
+
+void LSB_CountingBloomFilter::print(ostream& out) const
+{
+}
+
+int LSB_CountingBloomFilter::readBit(const int index) {
+  return 0;
+  // TODO
+}
+
+void LSB_CountingBloomFilter::writeBit(const int index, const int value) {
+  // TODO
+}
+
+int LSB_CountingBloomFilter::get_index(const Address& addr)
+{
+  return addr.bitSelect( RubySystem::getBlockSizeBits(), RubySystem::getBlockSizeBits() + m_filter_size_bits - 1);
+}
+
+
 
--- /dev/null
+
+/*
+ * 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.
+ */
+
+/*
+ * LSB_CountingBloomFilter.hh
+ *
+ * Description:
+ *
+ *
+ */
+
+#ifndef LSB_COUNTING_BLOOM_FILTER_H
+#define LSB_COUNTING_BLOOM_FILTER_H
+
+#include "mem/gems_common/Map.hh"
+#include "mem/ruby/common/Global.hh"
+#include "mem/ruby/config/RubyConfig.hh"
+#include "mem/ruby/common/Address.hh"
+#include "mem/ruby/filters/AbstractBloomFilter.hh"
+
+class LSB_CountingBloomFilter : public AbstractBloomFilter {
+public:
+
+  ~LSB_CountingBloomFilter();
+  LSB_CountingBloomFilter(string config);
+
+  void clear();
+  void increment(const Address& addr);
+  void decrement(const Address& addr);
+  void merge(AbstractBloomFilter * other_filter);
+  void set(const Address& addr);
+  void unset(const Address& addr);
+
+  bool isSet(const Address& addr);
+  int getCount(const Address& addr);
+  int getTotalCount();
+  int getIndex(const Address& addr);
+  int readBit(const int index);
+  void writeBit(const int index, const int value);
+
+  void print(ostream& out) const;
+
+private:
+
+  int get_index(const Address& addr);
+
+  Vector<int> m_filter;
+  int m_filter_size;
+  int m_filter_size_bits;
+
+  int m_count_bits;
+  int m_count;
+};
+
+
+#endif
 
--- /dev/null
+
+/*
+ * 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.
+ */
+
+/*
+ * NonCountingBloomFilter.cc
+ *
+ * Description:
+ *
+ *
+ */
+
+#include "mem/ruby/filters/MultiBitSelBloomFilter.hh"
+#include "mem/gems_common/Map.hh"
+#include "mem/ruby/common/Address.hh"
+
+MultiBitSelBloomFilter::MultiBitSelBloomFilter(string str)
+{
+
+  string tail(str);
+  string head = string_split(tail, '_');
+
+  // head contains filter size, tail contains bit offset from block number
+  m_filter_size = atoi(head.c_str());
+
+  head = string_split(tail, '_');
+  m_num_hashes = atoi(head.c_str());
+
+  head = string_split(tail, '_');
+  m_skip_bits = atoi(head.c_str());
+
+  if(tail == "Regular") {
+    isParallel = false;
+  } else if (tail == "Parallel") {
+    isParallel = true;
+  } else {
+    cout << "ERROR: Incorrect config string for MultiBitSel Bloom! :" << str << endl;
+    assert(0);
+  }
+
+  m_filter_size_bits = log_int(m_filter_size);
+
+  m_par_filter_size = m_filter_size/m_num_hashes;
+  m_par_filter_size_bits = log_int(m_par_filter_size);
+
+  m_filter.setSize(m_filter_size);
+  clear();
+}
+
+MultiBitSelBloomFilter::~MultiBitSelBloomFilter(){
+}
+
+void MultiBitSelBloomFilter::clear()
+{
+  for (int i = 0; i < m_filter_size; i++) {
+    m_filter[i] = 0;
+  }
+}
+
+void MultiBitSelBloomFilter::increment(const Address& addr)
+{
+  // Not used
+}
+
+
+void MultiBitSelBloomFilter::decrement(const Address& addr)
+{
+  // Not used
+}
+
+void MultiBitSelBloomFilter::merge(AbstractBloomFilter * other_filter){
+  // assumes both filters are the same size!
+  MultiBitSelBloomFilter * temp = (MultiBitSelBloomFilter*) other_filter;
+  for(int i=0; i < m_filter_size; ++i){
+    m_filter[i] |= (*temp)[i];
+  }
+
+}
+
+void MultiBitSelBloomFilter::set(const Address& addr)
+{
+  for (int i = 0; i < m_num_hashes; i++) {
+    int idx = get_index(addr, i);
+    m_filter[idx] = 1;
+
+    //Profile hash value distribution
+    //g_system_ptr->getProfiler()->getXactProfiler()->profileHashValue(i, idx); //gem5:Arka for decomissioning of log_tm
+  }
+}
+
+void MultiBitSelBloomFilter::unset(const Address& addr)
+{
+  cout << "ERROR: Unset should never be called in a Bloom filter";
+  assert(0);
+}
+
+bool MultiBitSelBloomFilter::isSet(const Address& addr)
+{
+  bool res = true;
+
+  for (int i=0; i < m_num_hashes; i++) {
+    int idx = get_index(addr, i);
+    res = res && m_filter[idx];
+  }
+  return res;
+}
+
+
+int MultiBitSelBloomFilter::getCount(const Address& addr)
+{
+  return isSet(addr)? 1: 0;
+}
+
+int MultiBitSelBloomFilter::getIndex(const Address& addr)
+{
+  return 0;
+}
+
+int MultiBitSelBloomFilter::readBit(const int index) {
+  return 0;
+}
+
+void MultiBitSelBloomFilter::writeBit(const int index, const int value) {
+
+}
+
+int MultiBitSelBloomFilter::getTotalCount()
+{
+  int count = 0;
+
+  for (int i = 0; i < m_filter_size; i++) {
+    count += m_filter[i];
+  }
+  return count;
+}
+
+void MultiBitSelBloomFilter::print(ostream& out) const
+{
+}
+
+int MultiBitSelBloomFilter::get_index(const Address& addr, int i)
+{
+  // m_skip_bits is used to perform BitSelect after skipping some bits. Used to simulate BitSel hashing on larger than cache-line granularities
+  uint64 x = (addr.getLineAddress()) >> m_skip_bits;
+  int y = hash_bitsel(x, i, m_num_hashes, 30, m_filter_size_bits);
+  //36-bit addresses, 6-bit cache lines
+
+  if(isParallel) {
+    return (y % m_par_filter_size) + i*m_par_filter_size;
+  } else {
+    return y % m_filter_size;
+  }
+}
+
+
+int MultiBitSelBloomFilter::hash_bitsel(uint64 value, int index, int jump, int maxBits, int numBits) {
+  uint64 mask = 1;
+  int result = 0;
+  int bit, i;
+
+  for(i = 0; i < numBits; i++) {
+    bit = (index + jump*i) % maxBits;
+    if (value & (mask << bit)) result += mask << i;
+  }
+  return result;
+}
 
--- /dev/null
+
+/*
+ * 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.
+ */
+
+/*
+ * MultiBitSelBloomFilter.hh
+ *
+ * Description:
+ *
+ *
+ */
+
+#ifndef MULTIBITSEL_BLOOM_FILTER_H
+#define MULTIBITSEL_BLOOM_FILTER_H
+
+#include "mem/gems_common/Map.hh"
+#include "mem/ruby/common/Global.hh"
+#include "mem/ruby/system/System.hh"
+#include "mem/ruby/profiler/Profiler.hh"
+#include "mem/ruby/config/RubyConfig.hh"
+#include "mem/ruby/common/Address.hh"
+#include "mem/ruby/filters/AbstractBloomFilter.hh"
+
+class MultiBitSelBloomFilter : public AbstractBloomFilter {
+public:
+
+  ~MultiBitSelBloomFilter();
+  MultiBitSelBloomFilter(string config);
+
+  void clear();
+  void increment(const Address& addr);
+  void decrement(const Address& addr);
+  void merge(AbstractBloomFilter * other_filter);
+  void set(const Address& addr);
+  void unset(const Address& addr);
+
+  bool isSet(const Address& addr);
+  int getCount(const Address& addr);
+  int getTotalCount();
+  void print(ostream& out) const;
+
+  int getIndex(const Address& addr);
+  int readBit(const int index);
+  void writeBit(const int index, const int value);
+
+  int operator[](const int index) const{
+    return this->m_filter[index];
+  }
+
+private:
+
+  int get_index(const Address& addr, int hashNumber);
+
+  int hash_bitsel(uint64 value, int index, int jump, int maxBits, int numBits);
+
+  Vector<int> m_filter;
+  int m_filter_size;
+  int m_num_hashes;
+  int m_filter_size_bits;
+  int m_skip_bits;
+
+  int m_par_filter_size;
+  int m_par_filter_size_bits;
+
+  int m_count_bits;
+  int m_count;
+
+  bool isParallel;
+
+};
+
+#endif
 
--- /dev/null
+
+/*
+ * 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.
+ */
+
+/*
+ * MultiGrainBloomFilter.cc
+ *
+ * Description:
+ *
+ *
+ */
+
+#include "mem/ruby/filters/MultiGrainBloomFilter.hh"
+#include "mem/gems_common/Map.hh"
+#include "mem/ruby/common/Address.hh"
+
+MultiGrainBloomFilter::MultiGrainBloomFilter(string str)
+{
+  string tail(str);
+
+  // split into the 2 filter sizes
+  string head = string_split(tail, '_');
+
+  // head contains size of 1st bloom filter, tail contains size of 2nd bloom filter
+
+  m_filter_size = atoi(head.c_str());
+  m_filter_size_bits = log_int(m_filter_size);
+
+  m_page_filter_size = atoi(tail.c_str());
+  m_page_filter_size_bits = log_int(m_page_filter_size);
+
+  m_filter.setSize(m_filter_size);
+  m_page_filter.setSize(m_page_filter_size);
+  clear();
+}
+
+MultiGrainBloomFilter::~MultiGrainBloomFilter(){
+}
+
+void MultiGrainBloomFilter::clear()
+{
+  for (int i = 0; i < m_filter_size; i++) {
+    m_filter[i] = 0;
+  }
+  for(int i=0; i < m_page_filter_size; ++i){
+    m_page_filter[i] = 0;
+  }
+}
+
+void MultiGrainBloomFilter::increment(const Address& addr)
+{
+  // Not used
+}
+
+
+void MultiGrainBloomFilter::decrement(const Address& addr)
+{
+  // Not used
+}
+
+void MultiGrainBloomFilter::merge(AbstractBloomFilter * other_filter)
+{
+  // TODO
+}
+
+void MultiGrainBloomFilter::set(const Address& addr)
+{
+  int i = get_block_index(addr);
+  int j = get_page_index(addr);
+  assert(i < m_filter_size);
+  assert(j < m_page_filter_size);
+  m_filter[i] = 1;
+  m_page_filter[i] = 1;
+
+}
+
+void MultiGrainBloomFilter::unset(const Address& addr)
+{
+  // not used
+}
+
+bool MultiGrainBloomFilter::isSet(const Address& addr)
+{
+  int i = get_block_index(addr);
+  int j = get_page_index(addr);
+  assert(i < m_filter_size);
+  assert(j < m_page_filter_size);
+  // we have to have both indices set
+  return (m_filter[i] && m_page_filter[i]);
+}
+
+int MultiGrainBloomFilter::getCount(const Address& addr)
+{
+  // not used
+  return 0;
+}
+
+int MultiGrainBloomFilter::getTotalCount()
+{
+  int count = 0;
+
+  for (int i = 0; i < m_filter_size; i++) {
+    count += m_filter[i];
+  }
+
+  for(int i=0; i < m_page_filter_size; ++i){
+    count += m_page_filter[i] = 0;
+  }
+
+  return count;
+}
+
+int MultiGrainBloomFilter::getIndex(const Address& addr)
+{
+  return 0;
+  // TODO
+}
+
+int MultiGrainBloomFilter::readBit(const int index) {
+  return 0;
+  // TODO
+}
+
+void MultiGrainBloomFilter::writeBit(const int index, const int value) {
+  // TODO
+}
+
+void MultiGrainBloomFilter::print(ostream& out) const
+{
+}
+
+int MultiGrainBloomFilter::get_block_index(const Address& addr)
+{
+  // grap a chunk of bits after byte offset
+  return addr.bitSelect( RubySystem::getBlockSizeBits(), RubySystem::getBlockSizeBits() + m_filter_size_bits - 1);
+}
+
+int MultiGrainBloomFilter::get_page_index(const Address & addr)
+{
+  // grap a chunk of bits after first chunk
+  return addr.bitSelect( RubySystem::getBlockSizeBits() + m_filter_size_bits - 1,
+                         RubySystem::getBlockSizeBits() + m_filter_size_bits - 1 + m_page_filter_size_bits  - 1);
+}
+
+
+
+
 
--- /dev/null
+
+/*
+ * 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.
+ */
+
+/*
+ * MultiGrainBloomFilter.hh
+ *
+ * Description:
+ *
+ *
+ */
+
+#ifndef MULTIGRAIN_BLOOM_FILTER_H
+#define MULTIGRAIN_BLOOM_FILTER_H
+
+#include "mem/gems_common/Map.hh"
+#include "mem/ruby/common/Global.hh"
+#include "mem/ruby/config/RubyConfig.hh"
+#include "mem/ruby/common/Address.hh"
+#include "mem/ruby/filters/AbstractBloomFilter.hh"
+
+class MultiGrainBloomFilter : public AbstractBloomFilter {
+public:
+
+  ~MultiGrainBloomFilter();
+  MultiGrainBloomFilter(string str);
+
+  void clear();
+  void increment(const Address& addr);
+  void decrement(const Address& addr);
+  void merge(AbstractBloomFilter * other_filter);
+  void set(const Address& addr);
+  void unset(const Address& addr);
+
+  bool isSet(const Address& addr);
+  int getCount(const Address& addr);
+  int getTotalCount();
+  int getIndex(const Address& addr);
+  int readBit(const int index);
+  void writeBit(const int index, const int value);
+
+  void print(ostream& out) const;
+
+private:
+
+  int get_block_index(const Address& addr);
+  int get_page_index(const Address & addr);
+
+  // The block filter
+  Vector<int> m_filter;
+  int m_filter_size;
+  int m_filter_size_bits;
+  // The page number filter
+  Vector<int> m_page_filter;
+  int m_page_filter_size;
+  int m_page_filter_size_bits;
+
+  int m_count_bits;
+  int m_count;
+};
+
+
+#endif
 
--- /dev/null
+
+/*
+ * 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.
+ */
+
+/*
+ * NonCountingBloomFilter.cc
+ *
+ * Description:
+ *
+ *
+ */
+
+#include "mem/ruby/filters/NonCountingBloomFilter.hh"
+#include "mem/gems_common/Map.hh"
+#include "mem/ruby/common/Address.hh"
+
+NonCountingBloomFilter::NonCountingBloomFilter(string str)
+{
+  string tail(str);
+  string head = string_split(tail, '_');
+
+  // head contains filter size, tail contains bit offset from block number
+  m_filter_size = atoi(head.c_str());
+  m_offset = atoi(tail.c_str());
+  m_filter_size_bits = log_int(m_filter_size);
+
+
+  m_filter.setSize(m_filter_size);
+  clear();
+}
+
+NonCountingBloomFilter::~NonCountingBloomFilter(){
+}
+
+void NonCountingBloomFilter::clear()
+{
+  for (int i = 0; i < m_filter_size; i++) {
+    m_filter[i] = 0;
+  }
+}
+
+void NonCountingBloomFilter::increment(const Address& addr)
+{
+  // Not used
+}
+
+
+void NonCountingBloomFilter::decrement(const Address& addr)
+{
+  // Not used
+}
+
+void NonCountingBloomFilter::merge(AbstractBloomFilter * other_filter){
+  // assumes both filters are the same size!
+  NonCountingBloomFilter * temp = (NonCountingBloomFilter*) other_filter;
+  for(int i=0; i < m_filter_size; ++i){
+    m_filter[i] |= (*temp)[i];
+  }
+
+}
+
+void NonCountingBloomFilter::set(const Address& addr)
+{
+  int i = get_index(addr);
+  m_filter[i] = 1;
+}
+
+void NonCountingBloomFilter::unset(const Address& addr)
+{
+  int i = get_index(addr);
+  m_filter[i] = 0;
+}
+
+bool NonCountingBloomFilter::isSet(const Address& addr)
+{
+  int i = get_index(addr);
+  return (m_filter[i]);
+}
+
+
+int NonCountingBloomFilter::getCount(const Address& addr)
+{
+  return m_filter[get_index(addr)];
+}
+
+int NonCountingBloomFilter::getTotalCount()
+{
+  int count = 0;
+
+  for (int i = 0; i < m_filter_size; i++) {
+    count += m_filter[i];
+  }
+  return count;
+}
+
+void NonCountingBloomFilter::print(ostream& out) const
+{
+}
+
+int NonCountingBloomFilter::getIndex(const Address& addr)
+{
+  return get_index(addr);
+}
+
+int NonCountingBloomFilter::readBit(const int index) {
+  return m_filter[index];
+}
+
+void NonCountingBloomFilter::writeBit(const int index, const int value) {
+  m_filter[index] = value;
+}
+
+int NonCountingBloomFilter::get_index(const Address& addr)
+{
+  return addr.bitSelect( RubySystem::getBlockSizeBits() + m_offset,
+                         RubySystem::getBlockSizeBits() + m_offset + m_filter_size_bits - 1);
+}
+
+
 
--- /dev/null
+
+/*
+ * 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.
+ */
+
+/*
+ * NonCountingBloomFilter.hh
+ *
+ * Description:
+ *
+ *
+ */
+
+#ifndef NONCOUNTING_BLOOM_FILTER_H
+#define NONCOUNTING_BLOOM_FILTER_H
+
+#include "mem/gems_common/Map.hh"
+#include "mem/ruby/common/Global.hh"
+#include "mem/ruby/config/RubyConfig.hh"
+#include "mem/ruby/common/Address.hh"
+#include "mem/ruby/filters/AbstractBloomFilter.hh"
+
+class NonCountingBloomFilter : public AbstractBloomFilter {
+public:
+
+  ~NonCountingBloomFilter();
+  NonCountingBloomFilter(string config);
+
+  void clear();
+  void increment(const Address& addr);
+  void decrement(const Address& addr);
+  void merge(AbstractBloomFilter * other_filter);
+  void set(const Address& addr);
+  void unset(const Address& addr);
+
+  bool isSet(const Address& addr);
+  int getCount(const Address& addr);
+  int getTotalCount();
+
+  int getIndex(const Address& addr);
+  int readBit(const int index);
+  void writeBit(const int index, const int value);
+
+  void print(ostream& out) const;
+
+  int operator[](const int index) const{
+    return this->m_filter[index];
+  }
+
+private:
+
+  int get_index(const Address& addr);
+
+  Vector<int> m_filter;
+  int m_filter_size;
+  int m_offset;
+  int m_filter_size_bits;
+
+  int m_count_bits;
+  int m_count;
+};
+
+
+#endif
 
+++ /dev/null
-
-/*
- * 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.
- */
-
-/*
- * init.C
- *
- * Description: See init.hh
- *
- * $Id$
- *
- */
-
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/eventqueue/RubyEventQueue.hh"
-#include "mem/ruby/system/System.hh"
-#include "mem/ruby/common/Debug.hh"
-#include "mem/ruby/common/Driver.hh"
-#include "mem/ruby/profiler/Profiler.hh"
-#include "mem/ruby/tester/Tester.hh"
-#include "mem/ruby/init.hh"
-
-using namespace std;
-#include <string>
-#include <map>
-#include <stdlib.h>
-
-#include "mem/gems_common/ioutil/confio.hh"
-#include "mem/gems_common/ioutil/initvar.hh"
-
-// A generated file containing the default parameters in string form
-// The defaults are stored in the variable global_default_param
-#include "mem/ruby/default_param.hh"
-
-static initvar_t *ruby_initvar_obj = NULL;
-
-//***************************************************************************
-static void init_generate_values( void )
-{
-    /* update generated values, based on input configuration */
-}
-
-//***************************************************************************
-
-void init_variables( void )
-{
-  // allocate the "variable initialization" package
-  ruby_initvar_obj = new initvar_t( "ruby", "../../../ruby/",
-                                    global_default_param,
-                                    &init_simulator,
-                                    &init_generate_values);
-}
-
-
- /*
-void init_variables(const char* config_str )
-{
-  // allocate the "variable initialization" package
-  ruby_initvar_obj = new initvar_t( "ruby", "../../../ruby/",
-                                    config_str,
-                                    &init_simulator,
-                                    &init_generate_values );
-}
- */
-
-void init_simulator()
-{
-    // Set things to NULL to make sure we don't de-reference them
-    // without a seg. fault.
-    g_system_ptr = NULL;
-    g_debug_ptr = NULL;
-    g_eventQueue_ptr = NULL;
-
-    cout << "Ruby Timing Mode" << endl;
-
-
-    g_debug_ptr = new Debug( DEBUG_FILTER_STRING,
-                             DEBUG_VERBOSITY_STRING,
-                             DEBUG_START_TIME,
-                             DEBUG_OUTPUT_FILENAME );
-    RubyConfig::init();
-
-    cout << "Creating event queue..." << endl;
-    g_eventQueue_ptr = new RubyEventQueue;
-    cout << "Creating event queue done" << endl;
-
-    cout << "Creating system..." << endl;
-    cout << "  Processors: " << RubyConfig::numberOfProcessors() << endl;
-
-    g_system_ptr = new RubySystem;
-    cout << "Creating system done" << endl;
-
-    cout << "Ruby initialization complete" << endl;
-}
-
-void init_simulator(Driver* _driver)
-{
-    // Set things to NULL to make sure we don't de-reference them
-    // without a seg. fault.
-    g_system_ptr = NULL;
-    g_debug_ptr = NULL;
-    g_eventQueue_ptr = NULL;
-
-    cout << "Ruby Timing Mode" << endl;
-
-
-    g_debug_ptr = new Debug( DEBUG_FILTER_STRING,
-                             DEBUG_VERBOSITY_STRING,
-                             DEBUG_START_TIME,
-                             DEBUG_OUTPUT_FILENAME );
-    RubyConfig::init();
-
-    cout << "Creating event queue..." << endl;
-    g_eventQueue_ptr = new RubyEventQueue;
-    cout << "Creating event queue done" << endl;
-
-    cout << "Creating system..." << endl;
-    cout << "  Processors: " << RubyConfig::numberOfProcessors() << endl;
-
-    g_system_ptr = new RubySystem(_driver);
-    cout << "Creating system done" << endl;
-
-    cout << "Ruby initialization complete" << endl;
-}
-
-void destroy_simulator()
-{
-    cout << "Deleting system..." << endl;
-    delete g_system_ptr;
-    cout << "Deleting system done" << endl;
-
-    cout << "Deleting event queue..." << endl;
-    delete g_eventQueue_ptr;
-    cout << "Deleting event queue done" << endl;
-
-    delete g_debug_ptr;
-}
-
-/*-------------------------------------------------------------------------+
- | DG: These are the external load and unload hooks that will be called by |
- | M5 in phase 1 integration, and possibly afterwards, too.                |
- +-------------------------------------------------------------------------*/
-
-//dsm: superfluous
-/*extern "C"
-int OnLoadRuby() {
-    init_variables();
-    return 0;
-}
-
-extern "C"
-int OnInitRuby() {
-    init_simulator();
-    return 0;
-}
-
-extern "C"
-int OnUnloadRuby() {
-  destroy_simulator();
-  return 0;
-}*/
-
-/* I have to put it somewhere for now */
-void tester_main(int argc, char **argv) {
-    std::cout << __FILE__ << "(" << __LINE__ << "): Not implemented." << std::endl;
-}
 
+++ /dev/null
-
-/*
- * 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.
- */
-
-/*
- * init.hh
- *
- * Description:
- *
- * $Id$
- *
- */
-
-#ifndef INIT_H
-#define INIT_H
-
-class Driver;
-
-extern void init_variables();
-//extern void init_variables(const char* config_str);
-extern void init_simulator();
-extern void init_simulator(Driver* _driver);
-extern void destroy_simulator();
-
-#endif //INIT_H
 
--- /dev/null
+
+#include <sys/wait.h>
+#include <algorithm>
+
+#include "mem/ruby/libruby_internal.hh"
+#include "mem/ruby/system/RubyPort.hh"
+#include "mem/ruby/system/System.hh"
+#include "mem/ruby/eventqueue/RubyEventQueue.hh"
+#include "mem/ruby/system/MemoryVector.hh"
+#include "mem/ruby/common/Address.hh"
+
+string RubyRequestType_to_string(const RubyRequestType& obj)
+{
+  switch(obj) {
+  case RubyRequestType_IFETCH:
+    return "IFETCH";
+  case RubyRequestType_LD:
+    return "LD";
+  case RubyRequestType_ST:
+    return "ST";
+  case RubyRequestType_RMW:
+    return "RMW";
+  case RubyRequestType_NULL:
+  default:
+    assert(0);
+    return "";
+  }
+}
+
+RubyRequestType string_to_RubyRequestType(std::string str)
+{
+  if (str == "IFETCH")
+    return RubyRequestType_IFETCH;
+  else if (str == "LD")
+    return RubyRequestType_LD;
+  else if (str == "ST")
+    return RubyRequestType_ST;
+  else if (str == "RMW")
+    return RubyRequestType_RMW;
+  else
+    assert(0);
+  return RubyRequestType_NULL;
+}
+
+ostream& operator<<(ostream& out, const RubyRequestType& obj)
+{
+  cerr << "in op" << endl;
+  out << RubyRequestType_to_string(obj);
+  cerr << "flushing" << endl;
+  out << flush;
+  cerr << "done" << endl;
+  return out;
+}
+
+vector<string> tokenizeString(string str, string delims)
+{
+  vector<string> tokens;
+  char* pch;
+  char* tmp;
+  const char* c_delims = delims.c_str();
+  tmp = new char[str.length()+1];
+  strcpy(tmp, str.c_str());
+  pch = strtok(tmp, c_delims);
+  while (pch != NULL) {
+    string tmp_str(pch);
+    if (tmp_str == "null") tmp_str = "";
+    tokens.push_back(tmp_str);
+
+    pch = strtok(NULL, c_delims);
+  }
+  delete [] tmp;
+  return tokens;
+}
+
+void libruby_init(const char* cfg_filename)
+{
+  stringstream cfg_output;
+
+  // first we execute the Ruby-lang configuration script
+  int fd[2];
+  int pid;
+  if (pipe(fd) == -1) {
+    perror("Error Creating Pipe");
+    exit(EXIT_FAILURE);
+  }
+
+  pid = fork();
+  if (pid == -1){
+    perror("Error forking");
+    exit(EXIT_FAILURE);
+  }
+
+  if (!pid) {
+    // child
+    close(fd[0]); // close the read end of the pipe
+    // replace stdout with the write pipe
+    if (dup2(fd[1], STDOUT_FILENO) == -1) {
+      perror("Error redirecting stdout");
+      exit(EXIT_FAILURE);
+    }
+#define QUOTE_MACRO(x, y) QUOTE_TXT(x,y)
+#define QUOTE_TXT(x, y) #x y
+    if (execlp("ruby", "ruby", "-I", QUOTE_MACRO(GEMS_ROOT, "/ruby/config"), QUOTE_MACRO(GEMS_ROOT, "/ruby/config/print_cfg.rb"), "-r", cfg_filename, NULL)) {
+      perror("execlp");
+      exit(EXIT_FAILURE);
+    }
+  } else {
+    close(fd[1]);
+
+    int child_status;
+    if (wait(&child_status) == -1) {
+      perror("wait");
+      exit(EXIT_FAILURE);
+    }
+    if (child_status != EXIT_SUCCESS) {
+      exit(EXIT_FAILURE);
+    }
+
+    char buf[100];
+    int bytes_read;
+    while( (bytes_read = read(fd[0], buf, 100)) > 0 ) {
+      for (int i=0;i<bytes_read;i++) {
+        //      cout << buf[i];
+        cfg_output << buf[i];
+      }
+    }
+    assert(bytes_read == 0);
+    close(fd[0]);
+  }
+
+  vector<RubyObjConf> * sys_conf = new vector<RubyObjConf>;
+
+  string line;
+  getline(cfg_output, line) ;
+  while ( !cfg_output.eof() ) {
+    vector<string> tokens = tokenizeString(line, " ");
+    assert(tokens.size() >= 2);
+    vector<string> argv;
+    for (size_t i=2; i<tokens.size(); i++) {
+      std::replace(tokens[i].begin(), tokens[i].end(), '%', ' ');
+      std::replace(tokens[i].begin(), tokens[i].end(), '#', '\n');
+      argv.push_back(tokens[i]);
+    }
+    sys_conf->push_back(RubyObjConf(tokens[0], tokens[1], argv));
+    tokens.clear();
+    argv.clear();
+    getline(cfg_output, line);
+  }
+
+  RubySystem::create(*sys_conf);
+  delete sys_conf;
+}
+
+RubyPortHandle libruby_get_port(const char* port_name, void (*hit_callback)(int64_t access_id))
+{
+  return static_cast<RubyPortHandle>(RubySystem::getPort(port_name, hit_callback));
+}
+
+RubyPortHandle libruby_get_port_by_name(const char* port_name)
+{
+  return static_cast<RubyPortHandle>(RubySystem::getPortOnly(port_name));
+}
+
+void libruby_write_ram(uint64_t paddr, uint8_t* data, int len)
+{
+  RubySystem::getMemoryVector()->write(Address(paddr), data, len);
+}
+
+void libruby_read_ram(uint64_t paddr, uint8_t* data, int len)
+{
+  RubySystem::getMemoryVector()->read(Address(paddr), data, len);
+}
+
+int64_t libruby_issue_request(RubyPortHandle p, struct RubyRequest request)
+{
+  return static_cast<RubyPort*>(p)->makeRequest(request);
+}
+
+int libruby_tick(int n)
+{
+  RubySystem::getEventQueue()->triggerEvents(RubySystem::getEventQueue()->getTime() + n);
+  return 0;
+}
+
+void libruby_destroy()
+{
+}
+
+const char* libruby_last_error()
+{
+  return "";
+}
+
+void libruby_print_config(std::ostream & out)
+{
+  RubySystem::printConfig(out);
+}
+
+void libruby_print_stats(std::ostream & out)
+{
+  RubySystem::printStats(out);
+}
+
+uint64_t libruby_get_time() {
+  return RubySystem::getCycleCount(0);
+}
 
--- /dev/null
+
+#ifndef LIBRUBY_H
+#define LIBRUBY_H
+
+#include <stdint.h>
+#include <ostream>
+
+typedef void* RubyPortHandle;
+enum RubyRequestType {
+  RubyRequestType_NULL,
+  RubyRequestType_IFETCH,
+  RubyRequestType_LD,
+  RubyRequestType_ST,
+  RubyRequestType_RMW
+};
+
+enum RubyAccessMode {
+  RubyAccessMode_User,
+  RubyAccessMode_Supervisor,
+  RubyAccessMode_Device
+};
+
+struct RubyRequest {
+  uint64_t paddr;
+  uint8_t* data;
+  int len;
+  uint64_t pc;
+  RubyRequestType type;
+  RubyAccessMode access_mode;
+
+  RubyRequest() {}
+  RubyRequest(uint64_t _paddr, uint8_t* _data, int _len, uint64_t _pc, RubyRequestType _type, RubyAccessMode _access_mode)
+    : paddr(_paddr), data(_data), len(_len), pc(_pc), type(_type), access_mode(_access_mode)
+  {}
+};
+
+/**
+ * Initialize the system.  cfg_file is a Ruby-lang configuration script
+ */
+void libruby_init(const char* cfg_file);
+
+/**
+ * Tear down a configured system.  Must be invoked after a call to libruby_init.
+ */
+void libruby_destroy();
+
+/**
+ * Print the last error encountered by ruby.  Currently unimplemented.
+ */
+const char* libruby_last_error();
+
+/**
+ *  Retrieve a handle to a RubyPort object, identified by name in the
+ *  configuration.  You also pass in the callback function you want
+ *  this port to use when a request completes.  Only one handle to a
+ *  port is allowed at a time.
+ */
+RubyPortHandle libruby_get_port(const char* name, void (*hit_callback)(int64_t access_id));
+
+/**
+ *  Retrieve a handle to a RubyPort object, identified by name in the
+ *  configuration.
+ */
+RubyPortHandle libruby_get_port_by_name(const char* name);
+
+
+/**
+ * issue_request returns a unique access_id to identify the ruby
+ * transaction. This access_id is later returned to the caller via
+ * hit_callback (passed to libruby_get_port)
+ */
+int64_t libruby_issue_request(RubyPortHandle p, struct RubyRequest request);
+
+/**
+ * writes data directly into Ruby's data array.  Note that this
+ * ignores caches, and should be considered incoherent after
+ * simulation starts.
+ */
+void libruby_write_ram(uint64_t paddr, uint8_t * data, int len);
+
+/**
+ * reads data directory from Ruby's data array.  Note that this
+ * ignores caches, and should be considered incoherent after
+ * simulation starts
+ */
+void libruby_read_ram(uint64_t paddr, uint8_t * data, int len);
+
+/**
+ * tick the system n cycles.  Eventually, will return the number of
+ * cycles until the next event, but for now it always returns 0
+ */
+int libruby_tick(int n);
+
+/**
+ *  self explainitory
+ */
+void libruby_print_config(std::ostream & out);
+
+/**
+ * self explainitory
+ */
+void libruby_print_stats(std::ostream & out);
+
+
+/**
+ * get time
+ */
+uint64_t libruby_get_time();
+#endif
 
--- /dev/null
+#ifndef LIBRUBY_INTERNAL_H
+#define LIBRUBY_INTERNAL_H
+
+#include "mem/ruby/libruby.hh"
+
+#include <ostream>
+#include <string>
+
+std::string RubyRequestType_to_string(const RubyRequestType& obj);
+RubyRequestType string_to_RubyRequestType(std::string);
+std::ostream& operator<<(std::ostream& out, const RubyRequestType& obj);
+
+#endif
 
--- /dev/null
+
+#include "mem/protocol/MachineType.hh"
+#include "mem/ruby/network/Network.hh"
+
+Network::Network(const string & name)
+  :  m_name(name)
+{
+  m_virtual_networks = 0;
+  m_topology_ptr = NULL;
+}
+
+void Network::init(const vector<string> & argv)
+{
+  m_nodes = MachineType_base_number(MachineType_NUM); // Total nodes in network
+
+  for (size_t i=0; i<argv.size(); i+=2) {
+   if (argv[i] == "number_of_virtual_networks")
+     m_virtual_networks = atoi(argv[i+1].c_str());
+   else if (argv[i] == "topology")
+     m_topology_ptr = RubySystem::getTopology(argv[i+1]);
+   else if (argv[i] == "buffer_size")
+     m_buffer_size = atoi(argv[i+1].c_str());
+   else if (argv[i] == "endpoint_bandwidth")
+     m_endpoint_bandwidth = atoi(argv[i+1].c_str());
+   else if (argv[i] == "adaptive_routing")
+     m_adaptive_routing = (argv[i+1]=="true");
+   else if (argv[i] == "link_latency")
+     m_link_latency = atoi(argv[i+1].c_str());
+
+  }
+  assert(m_virtual_networks != 0);
+  assert(m_topology_ptr != NULL);
+//  printf ("HERE \n");
+}
 
 #include "mem/ruby/common/Global.hh"
 #include "mem/ruby/system/NodeID.hh"
 #include "mem/protocol/MessageSizeType.hh"
+#include "mem/ruby/system/System.hh"
+#include "mem/ruby/config/RubyConfig.hh"
 
 class NetDest;
 class MessageBuffer;
 class Throttle;
+class Topology;
 
 class Network {
 public:
   // Constructors
-  Network() {}
+  Network(const string & name);
+  virtual void init(const vector<string> & argv);
 
   // Destructor
   virtual ~Network() {}
 
   // Public Methods
-
-  static Network* createNetwork(int nodes);
+  int getBufferSize() { return m_buffer_size; }
+  int getNumberOfVirtualNetworks() { return m_virtual_networks; }
+  int getEndpointBandwidth() { return m_endpoint_bandwidth; }
+  bool getAdaptiveRouting() {return m_adaptive_routing; }
+  int getLinkLatency() { return m_link_latency; }
 
   // returns the queue requested for the given component
   virtual MessageBuffer* getToNetQueue(NodeID id, bool ordered, int netNumber) = 0;
   virtual void printConfig(ostream& out) const = 0;
   virtual void print(ostream& out) const = 0;
 
-private:
+protected:
 
   // Private Methods
   // Private copy constructor and assignment operator
   Network& operator=(const Network& obj);
 
   // Data Members (m_ prefix)
+protected:
+  const string m_name;
+  int m_nodes;
+  int m_virtual_networks;
+  int m_buffer_size;
+  int m_endpoint_bandwidth;
+  Topology* m_topology_ptr;
+  bool m_adaptive_routing;
+  int m_link_latency;
 };
 
 // Output operator declaration
 
 // Code to map network message size types to an integer number of bytes
 const int CONTROL_MESSAGE_SIZE = 8;
-const int DATA_MESSAGE_SIZE = (64+8);
+const int DATA_MESSAGE_SIZE = (RubySystem::getBlockSizeBytes()+8);
 
 extern inline
 int MessageSizeType_to_int(MessageSizeType size_type)
 
 
 class CreditLink_d : public NetworkLink_d {
 public:
-        CreditLink_d(int id):NetworkLink_d(id) {}
+        CreditLink_d(int id, int link_latency, GarnetNetwork_d *net_ptr):NetworkLink_d(id, link_latency, net_ptr) {}
 };
 
 #endif
 
 #include "mem/ruby/network/garnet-fixed-pipeline/CreditLink_d.hh"
 #include "mem/ruby/common/NetDest.hh"
 
-GarnetNetwork_d::GarnetNetwork_d(int nodes)
+GarnetNetwork_d::GarnetNetwork_d(const string & name)
+  : Network(name)
 {
-        m_nodes = MachineType_base_number(MachineType_NUM); // Total nodes in network
-        m_virtual_networks = NUMBER_OF_VIRTUAL_NETWORKS; // Number of virtual networks = number of message classes in the coherence protocol
+}
+
+void GarnetNetwork_d::init(const vector<string> & argv)
+{
+        Network::init(argv);
+
+        //added by SS
+        m_network_config_ptr = new NetworkConfig;
+        m_network_config_ptr->init(argv);
+
         m_ruby_start = 0;
         m_flits_recieved = 0;
         m_flits_injected = 0;
         }
 
         // Setup the network switches
-        m_topology_ptr = new Topology(this, m_nodes);
+        m_topology_ptr->makeTopology();
 
         int number_of_routers = m_topology_ptr->numSwitches();
         for (int i=0; i<number_of_routers; i++) {
         if(!isReconfiguration)
         {
                 NetworkLink_d *net_link = new NetworkLink_d(m_link_ptr_vector.size(), link_latency, this);
-                CreditLink_d *credit_link = new CreditLink_d(m_creditlink_ptr_vector.size());
+                CreditLink_d *credit_link = new CreditLink_d(m_creditlink_ptr_vector.size(), link_latency, this);
                 m_link_ptr_vector.insertAtBottom(net_link);
                 m_creditlink_ptr_vector.insertAtBottom(credit_link);
 
         if(!isReconfiguration)
         {
                 NetworkLink_d *net_link = new NetworkLink_d(m_link_ptr_vector.size(), link_latency, this);
-                CreditLink_d *credit_link = new CreditLink_d(m_creditlink_ptr_vector.size());
+                CreditLink_d *credit_link = new CreditLink_d(m_creditlink_ptr_vector.size(), link_latency, this);
                 m_link_ptr_vector.insertAtBottom(net_link);
                 m_creditlink_ptr_vector.insertAtBottom(credit_link);
 
         if(!isReconfiguration)
         {
                 NetworkLink_d *net_link = new NetworkLink_d(m_link_ptr_vector.size(), link_latency, this);
-                CreditLink_d *credit_link = new CreditLink_d(m_creditlink_ptr_vector.size());
+                CreditLink_d *credit_link = new CreditLink_d(m_creditlink_ptr_vector.size(), link_latency, this);
                 m_link_ptr_vector.insertAtBottom(net_link);
                 m_creditlink_ptr_vector.insertAtBottom(credit_link);
 
 void GarnetNetwork_d::printStats(ostream& out) const
 {       double average_link_utilization = 0;
         Vector<double > average_vc_load;
-        average_vc_load.setSize(m_virtual_networks*NetworkConfig::getVCsPerClass());
+        average_vc_load.setSize(m_virtual_networks*m_network_config_ptr->getVCsPerClass());
 
-        for(int i = 0; i < m_virtual_networks*NetworkConfig::getVCsPerClass(); i++)
+        for(int i = 0; i < m_virtual_networks*m_network_config_ptr->getVCsPerClass(); i++)
         {
                 average_vc_load[i] = 0;
         }
                 Vector<int > vc_load = m_link_ptr_vector[i]->getVcLoad();
                 for(int j = 0; j < vc_load.size(); j++)
                 {
-                        assert(vc_load.size() == NetworkConfig::getVCsPerClass()*m_virtual_networks);
+                        assert(vc_load.size() == m_network_config_ptr->getVCsPerClass()*m_virtual_networks);
                         average_vc_load[j] += vc_load[j];
                 }
         }
         out << "Average Link Utilization :: " << average_link_utilization << " flits/cycle" << endl;
         out << "-------------" << endl;
 
-        for(int i = 0; i < NetworkConfig::getVCsPerClass()*NUMBER_OF_VIRTUAL_NETWORKS; i++)
+        for(int i = 0; i < m_network_config_ptr->getVCsPerClass()*m_virtual_networks; i++)
         {
                 average_vc_load[i] = (double(average_vc_load[i]) / (double(g_eventQueue_ptr->getTime()) - m_ruby_start));
                 out << "Average VC Load [" << i << "] = " << average_vc_load[i] << " flits/cycle " << endl;
         out << "Network Configuration" << endl;
         out << "---------------------" << endl;
         out << "network: GarnetNetwork_d" << endl;
-        out << "topology: " << g_NETWORK_TOPOLOGY << endl;
+        out << "topology: " << m_topology_ptr->getName() << endl;
         out << endl;
 
         for (int i = 0; i < m_virtual_networks; i++)
         {
                 m_router_ptr_vector[i]->printConfig(out);
         }
-        if (g_PRINT_TOPOLOGY)
-        {
-                m_topology_ptr->printConfig(out);
-        }
+        m_topology_ptr->printConfig(out);
 }
 
 void GarnetNetwork_d::print(ostream& out) const
 
 
 class GarnetNetwork_d : public Network{
 public:
-        GarnetNetwork_d(int nodes);
+        GarnetNetwork_d(const string & name);
 
         ~GarnetNetwork_d();
 
+        void init(const vector<string> & argv);
+
+        //added by SS
+        NetworkConfig* getNetworkConfig() { return m_network_config_ptr; }
+
         int getNumNodes(){ return m_nodes;}
 
         // returns the queue requested for the given component
         void makeInternalLink(SwitchID src, NodeID dest, const NetDest& routing_table_entry, int link_latency, int link_weight, int bw_multiplier, bool isReconfiguration);
 
 private:
+        NetworkConfig* m_network_config_ptr;
+
         void checkNetworkAllocation(NodeID id, bool ordered, int network_num);
 
 // Private copy constructor and assignment operator
         GarnetNetwork_d& operator=(const GarnetNetwork_d& obj);
 
 /***********Data Members*************/
-        int m_virtual_networks;
-        int m_nodes;
+//      int m_virtual_networks;
+//      int m_nodes;
         int m_flits_recieved, m_flits_injected;
         double m_network_latency, m_queueing_latency;
 
         Vector<CreditLink_d *> m_creditlink_ptr_vector; // All links in the network
         Vector<NetworkInterface_d *> m_ni_ptr_vector;   // All NI's in Network
 
-        Topology* m_topology_ptr;
+//      Topology* m_topology_ptr;
         Time m_ruby_start;
 };
 
 
         m_id = id;
         m_net_ptr = network_ptr;
         m_virtual_networks  = virtual_networks;
-        m_vc_per_vnet = NetworkConfig::getVCsPerClass();
+        m_vc_per_vnet = m_net_ptr->getNetworkConfig()->getVCsPerClass();
         m_num_vcs = m_vc_per_vnet*m_virtual_networks;
 
         m_vc_round_robin = 0;
 
          for(int i = 0; i < m_num_vcs; i++)
          {
-                m_out_vc_state.insertAtBottom(new OutVcState_d(i));
+                m_out_vc_state.insertAtBottom(new OutVcState_d(i, m_net_ptr));
                 m_out_vc_state[i]->setState(IDLE_, g_eventQueue_ptr->getTime());
          }
 }
         NetDest net_msg_dest = net_msg_ptr->getInternalDestination();
         Vector<NodeID> dest_nodes = net_msg_dest.getAllDest(); // gets all the destinations associated with this message.
 
-        int num_flits = (int) ceil((double) MessageSizeType_to_int(net_msg_ptr->getMessageSize())/NetworkConfig::getFlitSize() ); // Number of flits is dependent on the link bandwidth available. This is expressed in terms of bytes/cycle or the flit size
+        int num_flits = (int) ceil((double) MessageSizeType_to_int(net_msg_ptr->getMessageSize())/m_net_ptr->getNetworkConfig()->getFlitSize() ); // Number of flits is dependent on the link bandwidth available. This is expressed in terms of bytes/cycle or the flit size
 
         for(int ctr = 0; ctr < dest_nodes.size(); ctr++) // loop because we will be converting all multicast messages into unicast messages
         {
                 if(t_flit->get_type() == TAIL_ || t_flit->get_type() == HEAD_TAIL_)
                 {
                         free_signal = true;
-                        if(!NetworkConfig::isNetworkTesting()) // When we are doing network only testing, the messages do not have to be buffered into the message buffers
+                        if(!m_net_ptr->getNetworkConfig()->isNetworkTesting()) // When we are doing network only testing, the messages do not have to be buffered into the message buffers
                         {
                                 outNode_ptr[t_flit->get_vnet()]->enqueue(t_flit->get_msg_ptr(), 1); // enqueueing for protocol buffer. This is not required when doing network only testing
                         }
 
 int NetworkInterface_d::get_vnet(int vc)
 {
-        for(int i = 0; i < NUMBER_OF_VIRTUAL_NETWORKS; i++)
+        for(int i = 0; i < m_net_ptr->getNumberOfVirtualNetworks(); i++)
         {
                 if(vc >= (i*m_vc_per_vnet) && vc < ((i+1)*m_vc_per_vnet))
                 {
 
 #include "mem/ruby/network/garnet-flexible-pipeline/NetworkConfig.hh"
 #include "mem/ruby/network/garnet-fixed-pipeline/GarnetNetwork_d.hh"
 
+/*
 NetworkLink_d::NetworkLink_d(int id)
 {
         m_id = id;
 
         linkBuffer = new flitBuffer_d();
         m_link_utilized = 0;
-        m_vc_load.setSize(NetworkConfig::getVCsPerClass()*NUMBER_OF_VIRTUAL_NETWORKS);
+        m_vc_load.setSize(NetworkConfig::getVCsPerClass()*RubySystem::getNetwork()->getNumberOfVirtualNetworks());
 
-        for(int i = 0; i < NetworkConfig::getVCsPerClass()*NUMBER_OF_VIRTUAL_NETWORKS; i++)
+        for(int i = 0; i < NetworkConfig::getVCsPerClass()*RubySystem::getNetwork()->getNumberOfVirtualNetworks(); i++)
                 m_vc_load[i] = 0;
 }
-
+*/
 NetworkLink_d::NetworkLink_d(int id, int link_latency, GarnetNetwork_d *net_ptr)
 {
         m_net_ptr = net_ptr;
         m_latency = link_latency;
         linkBuffer = new flitBuffer_d();
         m_link_utilized = 0;
-        m_vc_load.setSize(NetworkConfig::getVCsPerClass()*NUMBER_OF_VIRTUAL_NETWORKS);
+        m_vc_load.setSize(m_net_ptr->getNetworkConfig()->getVCsPerClass()*net_ptr->getNumberOfVirtualNetworks());
 
-        for(int i = 0; i < NetworkConfig::getVCsPerClass()*NUMBER_OF_VIRTUAL_NETWORKS; i++)
+        for(int i = 0; i < m_net_ptr->getNetworkConfig()->getVCsPerClass()*net_ptr->getNumberOfVirtualNetworks(); i++)
                 m_vc_load[i] = 0;
 }
 
 
 
 class NetworkLink_d : public Consumer {
 public:
-        NetworkLink_d(int id);
+        //NetworkLink_d(int id);
         ~NetworkLink_d();
 
         NetworkLink_d(int id, int link_latency, GarnetNetwork_d *net_ptr);
 
  */
 
 /*
- * OutVCState_d.C
+ * OutVCState_d.cc
  *
  * Niket Agarwal, Princeton University
  *
 #include "mem/ruby/network/garnet-flexible-pipeline/NetworkConfig.hh"
 #include "mem/ruby/eventqueue/RubyEventQueue.hh"
 
-OutVcState_d::OutVcState_d(int id)
+OutVcState_d::OutVcState_d(int id, GarnetNetwork_d *network_ptr)
 {
+        m_network_ptr = network_ptr;
         m_id = id;
         m_vc_state = IDLE_;
         m_time = g_eventQueue_ptr->getTime();
-        m_credit_count = NetworkConfig::getBufferSize();
+        m_credit_count = m_network_ptr->getNetworkConfig()->getBufferSize();
 }
 
 #define OUT_VC_STATE_D_H
 
 #include "mem/ruby/network/garnet-fixed-pipeline/NetworkHeader.hh"
+#include "mem/ruby/network/garnet-fixed-pipeline/GarnetNetwork_d.hh"
 
 class OutVcState_d {
 public:
-        OutVcState_d(int id);
+        OutVcState_d(int id, GarnetNetwork_d *network_ptr);
 
         int get_inport() {return m_in_port; }
         int get_invc() { return m_in_vc; }
         }
 
 private:
+        GarnetNetwork_d *m_network_ptr;
         int m_id ;
         Time m_time;
         VC_state_type m_vc_state;
 
  */
 
 /*
- * OutputUnit_d.C
+ * OutputUnit_d.cc
  *
  * Niket Agarwal, Princeton University
  *
 
         for(int i = 0; i < m_num_vcs; i++)
         {
-                m_outvc_state.insertAtBottom(new OutVcState_d(i));
+                m_outvc_state.insertAtBottom(new OutVcState_d(i, m_router->get_net_ptr()));
         }
 }
 
 
 {
         m_id = id;
         m_network_ptr = network_ptr;
-        m_virtual_networks = NUMBER_OF_VIRTUAL_NETWORKS;
-        m_vc_per_vnet = NetworkConfig::getVCsPerClass();
+        m_virtual_networks = network_ptr->getNumberOfVirtualNetworks();
+        m_vc_per_vnet = m_network_ptr->getNetworkConfig()->getVCsPerClass();
         m_num_vcs = m_virtual_networks*m_vc_per_vnet;
-        m_flit_width = NetworkConfig::getFlitSize();
+        m_flit_width = m_network_ptr->getNetworkConfig()->getFlitSize();
 
         m_routing_unit = new RoutingUnit_d(this);
         m_vc_alloc = new VCallocator_d(this);
 
 
 int SWallocator_d::get_vnet(int invc)
 {
-        for(int i = 0; i < NUMBER_OF_VIRTUAL_NETWORKS; i++)
+  for(int i = 0; i < RubySystem::getNetwork()->getNumberOfVirtualNetworks(); i++)
         {
                 if(invc >= (i*m_vc_per_vnet) && invc < ((i+1)*m_vc_per_vnet))
                 {
 
 
 int VCallocator_d::get_vnet(int invc)
 {
-        for(int i = 0; i < NUMBER_OF_VIRTUAL_NETWORKS; i++)
+  for(int i = 0; i < RubySystem::getNetwork()->getNumberOfVirtualNetworks(); i++)
         {
                 if(invc >= (i*m_vc_per_vnet) && invc < ((i+1)*m_vc_per_vnet))
                 {
 
 #include "mem/ruby/network/garnet-flexible-pipeline/NetworkLink.hh"
 #include "mem/ruby/common/NetDest.hh"
 
-// calls new to abstract away from the network
-Network* Network::createNetwork(int nodes)
+GarnetNetwork::GarnetNetwork(const string & name)
+  : Network(name)
 {
-        NetworkConfig::readNetConfig();
-        // Instantiate a network depending on what kind of network is requested
-        if(NetworkConfig::isGarnetNetwork())
-        {
-                if(NetworkConfig::isDetailNetwork())
-                        return new GarnetNetwork_d(nodes);
-                else
-                        return new GarnetNetwork(nodes);
-        }
-        else
-                return new SimpleNetwork(nodes);
 }
 
-GarnetNetwork::GarnetNetwork(int nodes)
+void GarnetNetwork::init(const vector<string> & argv)
 {
-        m_nodes = MachineType_base_number(MachineType_NUM); // Total nodes in network
-        m_virtual_networks = NUMBER_OF_VIRTUAL_NETWORKS; // Number of virtual networks = number of message classes in the coherence protocol
+//        printf("hello\n");
+        Network::init(argv);
+//added by SS
+//        assert (m_topology_ptr!=NULL);
+
+        m_network_config_ptr = new NetworkConfig;
+
+        m_network_config_ptr->init(argv);
+
         m_ruby_start = 0;
 
         // Allocate to and from queues
         }
 
         // Setup the network switches
-        m_topology_ptr = new Topology(this, m_nodes);
+        assert (m_topology_ptr!=NULL);
+        m_topology_ptr->makeTopology();
 
         int number_of_routers = m_topology_ptr->numSwitches();
         for (int i=0; i<number_of_routers; i++) {
 
 void GarnetNetwork::checkNetworkAllocation(NodeID id, bool ordered, int network_num)
 {
+        printf ("id = %i, m_nodes = %i \n", id, m_nodes);
         ASSERT(id < m_nodes);
         ASSERT(network_num < m_virtual_networks);
 
 void GarnetNetwork::printStats(ostream& out) const
 {       double average_link_utilization = 0;
         Vector<double > average_vc_load;
-        average_vc_load.setSize(m_virtual_networks*NetworkConfig::getVCsPerClass());
+        average_vc_load.setSize(m_virtual_networks*m_network_config_ptr->getVCsPerClass());
 
-        for(int i = 0; i < m_virtual_networks*NetworkConfig::getVCsPerClass(); i++)
+        for(int i = 0; i < m_virtual_networks*m_network_config_ptr->getVCsPerClass(); i++)
         {
                 average_vc_load[i] = 0;
         }
                 Vector<int > vc_load = m_link_ptr_vector[i]->getVcLoad();
                 for(int j = 0; j < vc_load.size(); j++)
                 {
-                        assert(vc_load.size() == NetworkConfig::getVCsPerClass()*m_virtual_networks);
+                        assert(vc_load.size() == m_network_config_ptr->getVCsPerClass()*m_virtual_networks);
                         average_vc_load[j] += vc_load[j];
                 }
         }
         out << "Average Link Utilization :: " << average_link_utilization << " flits/cycle" <<endl;
         out << "-------------" << endl;
 
-        for(int i = 0; i < NetworkConfig::getVCsPerClass()*m_virtual_networks; i++)
+        for(int i = 0; i < m_network_config_ptr->getVCsPerClass()*m_virtual_networks; i++)
         {
                 average_vc_load[i] = (double(average_vc_load[i]) / (double(g_eventQueue_ptr->getTime()) - m_ruby_start));
                 out << "Average VC Load [" << i << "] = " << average_vc_load[i] << " flits/cycle" << endl;
         out << "Network Configuration" << endl;
         out << "---------------------" << endl;
         out << "network: GARNET_NETWORK" << endl;
-        out << "topology: " << g_NETWORK_TOPOLOGY << endl;
+        out << "topology: " << m_topology_ptr->getName() << endl;
         out << endl;
 
         for (int i = 0; i < m_virtual_networks; i++)
         {
                 m_router_ptr_vector[i]->printConfig(out);
         }
-        if (g_PRINT_TOPOLOGY)
-        {
-                m_topology_ptr->printConfig(out);
-        }
+        m_topology_ptr->printConfig(out);
 }
 
 void GarnetNetwork::print(ostream& out) const
 
 
 class GarnetNetwork : public Network{
 public:
-        GarnetNetwork(int nodes);
+        GarnetNetwork(const string & name);
 
         ~GarnetNetwork();
 
+        void init(const vector<string> & argv);
+
+        //added by SS
+        NetworkConfig* getNetworkConfig() { return m_network_config_ptr; }
+
         // returns the queue requested for the given component
         MessageBuffer* getToNetQueue(NodeID id, bool ordered, int network_num);
         MessageBuffer* getFromNetQueue(NodeID id, bool ordered, int network_num);
         GarnetNetwork(const GarnetNetwork& obj);
         GarnetNetwork& operator=(const GarnetNetwork& obj);
 
+
 /***********Data Members*************/
-        int m_virtual_networks;
-        int m_nodes;
+//      int m_virtual_networks;
+//      int m_nodes;
 
         Vector<bool> m_in_use;
         Vector<bool> m_ordered;
         Vector<NetworkLink *> m_link_ptr_vector; // All links in the network
         Vector<NetworkInterface *> m_ni_ptr_vector;     // All NI's in Network
 
-        Topology* m_topology_ptr;
+//      Topology* m_topology_ptr;
         Time m_ruby_start;
+
+        NetworkConfig* m_network_config_ptr;
 };
 
 // Output operator declaration
 
 #include "mem/ruby/config/RubyConfig.hh"
 
 class NetworkConfig {
+        private:
+                int m_flit_size;
+                int m_number_of_pipe_stages;
+                int m_vcs_per_class;
+                int m_buffer_size;
+                bool m_using_network_testing;
         public:
-                static bool isGarnetNetwork() {return g_GARNET_NETWORK; }
-                static bool isDetailNetwork() {return g_DETAIL_NETWORK; }
-                static int isNetworkTesting() {return g_NETWORK_TESTING; }
-                static int getFlitSize() {return g_FLIT_SIZE; }
-                static int getNumPipeStages() {return g_NUM_PIPE_STAGES; }
-                static int getVCsPerClass() {return g_VCS_PER_CLASS; }
-                static int getBufferSize() {return g_BUFFER_SIZE; }
+                NetworkConfig(){}
+                void init(const vector<string> & argv) {
+                  for (size_t i=0; i<argv.size(); i+=2) {
+                   if (argv[i] == "flit_size")
+                     m_flit_size = atoi(argv[i+1].c_str());
+                   else if (argv[i] == "number_of_pipe_stages")
+                     m_number_of_pipe_stages = atoi(argv[i+1].c_str());
+                   else if (argv[i] == "vcs_per_class")
+                     m_vcs_per_class = atoi(argv[i+1].c_str());
+                   else if (argv[i] == "buffer_size")
+                     m_buffer_size = atoi(argv[i+1].c_str());
+                   else if (argv[i] == "using_network_testing")
+                     m_using_network_testing = atoi(argv[i+1].c_str());
+                  }
+                }
+//              static bool isGarnetNetwork() {return RubyConfig::getUsingGarnetNetwork(); }
+//              static bool isDetailNetwork() {return RubyConfig::getUsingDetailNetwork(); }
+                bool isNetworkTesting() {return m_using_network_testing; }
+                int getFlitSize() {return m_flit_size; }
+                int getNumPipeStages() {return m_number_of_pipe_stages; }
+                int getVCsPerClass() {return m_vcs_per_class; }
+                int getBufferSize() {return m_buffer_size; }
   // This is no longer used. See config/rubyconfig.defaults to set Garnet parameters.
                 static void readNetConfig()
                 {
                         string filename = "network/garnet-flexible-pipeline/";
                         filename += NETCONFIG_DEFAULTS;
 
+                if (g_SIMICS) {
+                        filename = "../../../ruby/"+filename;
+                }
                         ifstream NetconfigFile( filename.c_str(), ios::in);
                         if(!NetconfigFile.is_open())
                         {
                                 getline(NetconfigFile, line, '\n');
                                 string var = string_split(line, ':');
 
-                                if(!var.compare("g_GARNET_NETWORK"))
+                                if(!var.compare("RubyConfig::getUsingGarnetNetwork()"))
                                 {
                                         if(!line.compare("true"))
-                                                g_GARNET_NETWORK = true;
+                                                RubyConfig::getUsingGarnetNetwork() = true;
                                         else
-                                                g_GARNET_NETWORK = false;
+                                                RubyConfig::getUsingGarnetNetwork() = false;
                                 }
-                                if(!var.compare("g_DETAIL_NETWORK"))
+                                if(!var.compare("RubyConfig::getUsingDetailNetwork()"))
                                 {
                                         if(!line.compare("true"))
-                                                g_DETAIL_NETWORK = true;
+                                                RubyConfig::getUsingDetailNetwork() = true;
                                         else
-                                                g_DETAIL_NETWORK = false;
+                                                RubyConfig::getUsingDetailNetwork() = false;
                                 }
                                 if(!var.compare("g_NETWORK_TESTING"))
                                 {
                                         else
                                                 g_NETWORK_TESTING = false;
                                 }
-                                if(!var.compare("g_FLIT_SIZE"))
-                                        g_FLIT_SIZE = atoi(line.c_str());
-                                if(!var.compare("g_NUM_PIPE_STAGES"))
-                                        g_NUM_PIPE_STAGES = atoi(line.c_str());
-                                if(!var.compare("g_VCS_PER_CLASS"))
-                                        g_VCS_PER_CLASS = atoi(line.c_str());
-                                if(!var.compare("g_BUFFER_SIZE"))
-                                        g_BUFFER_SIZE = atoi(line.c_str());
+                                if(!var.compare("RubyConfig::getFlitSize()"))
+                                        RubyConfig::getFlitSize() = atoi(line.c_str());
+                                if(!var.compare("RubyConfig::getNumberOfPipeStages()"))
+                                        RubyConfig::getNumberOfPipeStages() = atoi(line.c_str());
+                                if(!var.compare("RubyConfig::getVCSPerClass()"))
+                                        RubyConfig::getVCSPerClass() = atoi(line.c_str());
+                                if(!var.compare("RubyConfig::getBufferSize()"))
+                                        RubyConfig::getBufferSize() = atoi(line.c_str());
                         }
                         NetconfigFile.close();
       */
       /*
-      cout << "g_GARNET_NETWORK = " << g_GARNET_NETWORK << endl;
-      cout << "g_DETAIL_NETWORK = " << g_DETAIL_NETWORK << endl;
+      cout << "RubyConfig::getUsingGarnetNetwork() = " << RubyConfig::getUsingGarnetNetwork() << endl;
+      cout << "RubyConfig::getUsingDetailNetwork() = " << RubyConfig::getUsingDetailNetwork() << endl;
       cout << "g_NETWORK_TESTING = " << g_NETWORK_TESTING << endl;
-      cout << "g_FLIT_SIZE = " << g_FLIT_SIZE << endl;
-      cout << "g_NUM_PIPE_STAGES = " << g_NUM_PIPE_STAGES << endl;
-      cout << "g_VCS_PER_CLASS= " << g_VCS_PER_CLASS << endl;
-      cout << "g_BUFFER_SIZE = " << g_BUFFER_SIZE << endl;
+      cout << "RubyConfig::getFlitSize() = " << RubyConfig::getFlitSize() << endl;
+      cout << "RubyConfig::getNumberOfPipeStages() = " << RubyConfig::getNumberOfPipeStages() << endl;
+      cout << "RubyConfig::getVCSPerClass()= " << RubyConfig::getVCSPerClass() << endl;
+      cout << "RubyConfig::getBufferSize() = " << RubyConfig::getBufferSize() << endl;
       */
                 }
 };
 
+
 #endif
 
  */
 
 /*
- * NetworkInterface.C
+ * NetworkInterface.cc
  *
  * Niket Agarwal, Princeton University
  *
         m_id = id;
         m_net_ptr = network_ptr;
         m_virtual_networks  = virtual_networks;
-        m_vc_per_vnet = NetworkConfig::getVCsPerClass();
+        m_vc_per_vnet = m_net_ptr->getNetworkConfig()->getVCsPerClass();
         m_num_vcs = m_vc_per_vnet*m_virtual_networks;
 
         m_vc_round_robin = 0;
         NetworkMessage *net_msg_ptr = dynamic_cast<NetworkMessage*>(msg_ptr.ref());
         NetDest net_msg_dest = net_msg_ptr->getInternalDestination();
         Vector<NodeID> dest_nodes = net_msg_dest.getAllDest(); // gets all the destinations associated with this message.
-        int num_flits = (int) ceil((double) MessageSizeType_to_int(net_msg_ptr->getMessageSize())/NetworkConfig::getFlitSize() ); // Number of flits is dependent on the link bandwidth available. This is expressed in terms of bytes/cycle or the flit size
+        int num_flits = (int) ceil((double) MessageSizeType_to_int(net_msg_ptr->getMessageSize())/m_net_ptr->getNetworkConfig()->getFlitSize() ); // Number of flits is dependent on the link bandwidth available. This is expressed in terms of bytes/cycle or the flit size
 
         for(int ctr = 0; ctr < dest_nodes.size(); ctr++) // loop because we will be converting all multicast messages into unicast messages
         {
                         DEBUG_EXPR(NETWORK_COMP, HighPrio, m_id);
                         DEBUG_MSG(NETWORK_COMP, HighPrio, "Message got delivered");
                         DEBUG_EXPR(NETWORK_COMP, HighPrio, g_eventQueue_ptr->getTime());
-                        if(!NetworkConfig::isNetworkTesting()) // When we are doing network only testing, the messages do not have to be buffered into the message buffers
+                        if(!m_net_ptr->getNetworkConfig()->isNetworkTesting()) // When we are doing network only testing, the messages do not have to be buffered into the message buffers
                         {
                                 outNode_ptr[t_flit->get_vnet()]->enqueue(t_flit->get_msg_ptr(), 1); // enqueueing for protocol buffer. This is not required when doing network only testing
                         }
 
         m_link_utilized = 0;
         m_net_ptr = net_ptr;
         m_latency = latency;
-        int num_net = NUMBER_OF_VIRTUAL_NETWORKS;
-        int num_vc = NetworkConfig::getVCsPerClass();
+        int num_net = net_ptr->getNumberOfVirtualNetworks();
+        int num_vc = m_net_ptr->getNetworkConfig()->getVCsPerClass();
         m_vc_load.setSize(num_net*num_vc);
 
         for(int i = 0; i < num_net*num_vc; i++)
 
 {
         m_id = id;
         m_net_ptr = network_ptr;
-        m_virtual_networks = NUMBER_OF_VIRTUAL_NETWORKS;
-        m_vc_per_vnet = NetworkConfig::getVCsPerClass();
+        m_virtual_networks = m_net_ptr->getNumberOfVirtualNetworks();
+        m_vc_per_vnet = m_net_ptr->getNetworkConfig()->getVCsPerClass();
         m_round_robin_inport = 0;
         m_round_robin_start = 0;
         m_num_vcs = m_vc_per_vnet*m_virtual_networks;
         Vector<flitBuffer *> intermediateQueues;
         for(int i = 0; i < m_num_vcs; i++)
         {
-                intermediateQueues.insertAtBottom(new flitBuffer(NetworkConfig::getBufferSize()));
+                intermediateQueues.insertAtBottom(new flitBuffer(m_net_ptr->getNetworkConfig()->getBufferSize()));
         }
         m_router_buffers.insertAtBottom(intermediateQueues);
 
         int outport = m_in_vc_state[inport][invc]->get_outport();
         int outvc = m_in_vc_state[inport][invc]->get_outvc();
 
-        assert(NetworkConfig::getNumPipeStages() >= 1);
-        m_flit->set_time(g_eventQueue_ptr->getTime() + (NetworkConfig::getNumPipeStages() - 1)); // Becasuse 1 cycle will be consumed in scheduling the output link
+        assert(m_net_ptr->getNetworkConfig()->getNumPipeStages() >= 1);
+        m_flit->set_time(g_eventQueue_ptr->getTime() + (m_net_ptr->getNetworkConfig()->getNumPipeStages() - 1)); // Becasuse 1 cycle will be consumed in scheduling the output link
         m_flit->set_vc(outvc);
         m_router_buffers[outport][outvc]->insert(m_flit);
 
-        if(NetworkConfig::getNumPipeStages() > 1)
-                g_eventQueue_ptr->scheduleEvent(this, NetworkConfig::getNumPipeStages() -1 );
+        if(m_net_ptr->getNetworkConfig()->getNumPipeStages() > 1)
+                g_eventQueue_ptr->scheduleEvent(this, m_net_ptr->getNetworkConfig()->getNumPipeStages() -1 );
         if((m_flit->get_type() == HEAD_) || (m_flit->get_type() == HEAD_TAIL_))
         {
                 NetDest destination = dynamic_cast<NetworkMessage*>(m_flit->get_msg_ptr().ref())->getInternalDestination();
-                if(NetworkConfig::getNumPipeStages() > 1)
+                if(m_net_ptr->getNetworkConfig()->getNumPipeStages() > 1)
                 {
                         m_out_vc_state[outport][outvc]->setState(VC_AB_, g_eventQueue_ptr->getTime() + 1);
                         m_out_link[outport]->request_vc_link(outvc, destination, g_eventQueue_ptr->getTime() + 1);
 
--- /dev/null
+
+#include "mem/ruby/network/simple/CustomTopology.hh"
+#include "mem/protocol/MachineType.hh"
+
+static const int INFINITE_LATENCY = 10000; // Yes, this is a big hack
+static const int DEFAULT_BW_MULTIPLIER = 1;  // Just to be consistent with above :)
+
+// make a network as described by the networkFile
+void CustomTopology::construct()
+{
+
+  Vector< Vector < SwitchID > > nodePairs;  // node pairs extracted from the file
+  Vector<int> latencies;  // link latencies for each link extracted
+  Vector<int> bw_multis;  // bw multipliers for each link extracted
+  Vector<int> weights;  // link weights used to enfore e-cube deadlock free routing
+  Vector< SwitchID > int_network_switches;  // internal switches extracted from the file
+  Vector<bool> endpointConnectionExist;  // used to ensure all endpoints are connected to the network
+
+  endpointConnectionExist.setSize(m_nodes);
+
+  // initialize endpoint check vector
+  for (int k = 0; k < endpointConnectionExist.size(); k++) {
+    endpointConnectionExist[k] = false;
+  }
+
+  stringstream networkFile( m_connections );
+
+  string line = "";
+
+  while (!networkFile.eof()) {
+
+    Vector < SwitchID > nodes;
+    nodes.setSize(2);
+    int latency = -1;  // null latency
+    int weight = -1;  // null weight
+    int bw_multiplier = DEFAULT_BW_MULTIPLIER;  // default multiplier incase the network file doesn't define it
+    int i = 0;  // node pair index
+    int varsFound = 0;  // number of varsFound on the line
+    int internalNodes = 0;  // used to determine if the link is between 2 internal nodes
+    std::getline(networkFile, line, '\n');
+    string varStr = string_split(line, ' ');
+
+    // parse the current line in the file
+    while (varStr != "") {
+      string label = string_split(varStr, ':');
+
+      // valid node labels
+      if (label == "ext_node" || label == "int_node") {
+        ASSERT(i < 2); // one link between 2 switches per line
+        varsFound++;
+        bool isNewIntSwitch = true;
+        if (label == "ext_node") { // input link to node
+          MachineType machine = string_to_MachineType(string_split(varStr, ':'));
+          string nodeStr = string_split(varStr, ':');
+          nodes[i] = MachineType_base_number(machine)
+            + atoi(nodeStr.c_str());
+
+          // in nodes should be numbered 0 to m_nodes-1
+          ASSERT(nodes[i] >= 0 && nodes[i] < m_nodes);
+          isNewIntSwitch = false;
+          endpointConnectionExist[nodes[i]] = true;
+        }
+        if (label == "int_node") { // interior node
+          nodes[i] = atoi((string_split(varStr, ':')).c_str())+m_nodes*2;
+          // in nodes should be numbered >= m_nodes*2
+          ASSERT(nodes[i] >= m_nodes*2);
+          for (int k = 0; k < int_network_switches.size(); k++) {
+            if (int_network_switches[k] == nodes[i]) {
+              isNewIntSwitch = false;
+            }
+          }
+          if (isNewIntSwitch) {  // if internal switch
+            m_number_of_switches++;
+            int_network_switches.insertAtBottom(nodes[i]);
+          }
+          internalNodes++;
+        }
+        i++;
+      } else if (label == "link_latency") {
+        latency = atoi((string_split(varStr, ':')).c_str());
+        varsFound++;
+      } else if (label == "bw_multiplier") {  // not necessary, defaults to DEFAULT_BW_MULTIPLIER
+        bw_multiplier = atoi((string_split(varStr, ':')).c_str());
+      } else if (label == "link_weight") {  // not necessary, defaults to link_latency
+        weight = atoi((string_split(varStr, ':')).c_str());
+      } else {
+        cerr << "Error: Unexpected Identifier: " << label << endl;
+        exit(1);
+      }
+      varStr = string_split(line, ' ');
+    }
+    if (varsFound == 3) { // all three necessary link variables where found so add the link
+      nodePairs.insertAtBottom(nodes);
+      latencies.insertAtBottom(latency);
+      if (weight != -1) {
+        weights.insertAtBottom(weight);
+      } else {
+        weights.insertAtBottom(latency);
+      }
+      bw_multis.insertAtBottom(bw_multiplier);
+      Vector < SwitchID > otherDirectionNodes;
+      otherDirectionNodes.setSize(2);
+      otherDirectionNodes[0] = nodes[1];
+      if (internalNodes == 2) {  // this is an internal link
+        otherDirectionNodes[1] = nodes[0];
+      } else {
+        otherDirectionNodes[1] = nodes[0]+m_nodes;
+      }
+      nodePairs.insertAtBottom(otherDirectionNodes);
+      latencies.insertAtBottom(latency);
+      if (weight != -1) {
+        weights.insertAtBottom(weight);
+      } else {
+        weights.insertAtBottom(latency);
+      }
+      bw_multis.insertAtBottom(bw_multiplier);
+    } else {
+      if (varsFound != 0) {  // if this is not a valid link, then no vars should have been found
+        cerr << "Error in line: " << line << endl;
+        exit(1);
+      }
+    }
+  } // end of file
+
+  // makes sure all enpoints are connected in the soon to be created network
+  for (int k = 0; k < endpointConnectionExist.size(); k++) {
+    if (endpointConnectionExist[k] == false) {
+      cerr << "Error: Unconnected Endpoint: " << k << endl;
+      exit(1);
+    }
+  }
+
+  ASSERT(nodePairs.size() == latencies.size() && latencies.size() == bw_multis.size() && latencies.size() == weights.size())
+  for (int k = 0; k < nodePairs.size(); k++) {
+    ASSERT(nodePairs[k].size() == 2);
+    addLink(nodePairs[k][0], nodePairs[k][1], latencies[k], bw_multis[k], weights[k]);
+  }
+
+  //  networkFile.close();
+}
 
--- /dev/null
+
+#ifndef CUSTOMTOPOLOGY_H
+#define CUSTOMTOPOLOGY_H
+
+#include "mem/ruby/network/simple/Topology.hh"
+
+class CustomTopology : public Topology
+{
+public:
+  CustomTopology(const string & name);
+  void init(const vector<string> & argv);
+
+protected:
+  void construct();
+};
+
+#endif
 
--- /dev/null
+
+#include "mem/ruby/network/simple/HierarchicalSwitchTopology.hh"
+
+// hierarchical switch topology
+void Topology::construct(int fan_out_degree)
+{
+  // Make a row of switches with only one input.  This extra row makes
+  // sure the links out of the nodes have latency and limited
+  // bandwidth.
+
+  // number of inter-chip switches, i.e. the last row of switches
+  Vector<SwitchID> last_level;
+  for (int i=0; i<m_nodes; i++) {
+    SwitchID new_switch = newSwitchID();  // internal switch id #
+    addLink(i, new_switch, m_network_ptr->getLinkLatency());
+    last_level.insertAtBottom(new_switch);
+  }
+
+  // Create Hierarchical Switches
+
+  // start from the bottom level and work up to root
+  Vector<SwitchID> next_level;
+  while(last_level.size() > 1) {
+    for (int i=0; i<last_level.size(); i++) {
+      if ((i % fan_out_degree) == 0) {
+        next_level.insertAtBottom(newSwitchID());
+      }
+      // Add this link to the last switch we created
+      addLink(last_level[i], next_level[next_level.size()-1], m_network_ptr->getLinkLatency());
+    }
+
+    // Make the current level the last level to get ready for next
+    // iteration
+    last_level = next_level;
+    next_level.clear();
+  }
+
+  SwitchID root_switch = last_level[0];
+
+  Vector<SwitchID> out_level;
+  for (int i=0; i<m_nodes; i++) {
+    out_level.insertAtBottom(m_nodes+i);
+  }
+
+  // Build the down network from the endpoints to the root
+  while(out_level.size() != 1) {
+
+    // A level of switches
+    for (int i=0; i<out_level.size(); i++) {
+      if ((i % fan_out_degree) == 0) {
+        if (out_level.size() > fan_out_degree) {
+          next_level.insertAtBottom(newSwitchID());
+        } else {
+          next_level.insertAtBottom(root_switch);
+        }
+      }
+      // Add this link to the last switch we created
+      addLink(next_level[next_level.size()-1], out_level[i], m_network_ptr->getLinkLatency());
+    }
+
+    // Make the current level the last level to get ready for next
+    // iteration
+    out_level = next_level;
+    next_level.clear();
+  }
+}
 
--- /dev/null
+
+#ifndef HIERARCHICALSWITCHTOPOLOGY_H
+#define HIERARCHICALSWITCHTOPOLOGY_H
+
+#include "mem/ruby/network/simple/Topology.hh"
+
+class HierarchicalSwitchTopology : public Topology
+{
+public:
+  HierarchicalSwitchTopology(const string & name);
+  void init(const vector<string> & argv);
+
+protected:
+  void construct();
+};
+
+#endif
 
 
 PerfectSwitch::PerfectSwitch(SwitchID sid, SimpleNetwork* network_ptr)
 {
-  m_virtual_networks = NUMBER_OF_VIRTUAL_NETWORKS;  // FIXME - pass me as a parameter?
+  m_virtual_networks = network_ptr->getNumberOfVirtualNetworks();
   m_switch_id = sid;
   m_round_robin_start = 0;
   m_network_ptr = network_ptr;
   m_out.insertAtBottom(out);
   m_routing_table.insertAtBottom(routing_table_entry);
 
-  if (g_PRINT_TOPOLOGY) {
+  //  if (RubyConfig::getPrintTopology()) {
     m_out_link_vec.insertAtBottom(out);
-  }
+    //  }
 }
 
 void PerfectSwitch::clearRoutingTables()
   int highest_prio_vnet = m_virtual_networks-1;
   int lowest_prio_vnet = 0;
   int decrementer = 1;
+  bool schedule_wakeup = false;
   NetworkMessage* net_msg_ptr = NULL;
 
   // invert priorities to avoid starvation seen in the component network
 
         assert(m_link_order.size() == m_routing_table.size());
         assert(m_link_order.size() == m_out.size());
-
-        if (g_adaptive_routing) {
+//changed by SS
+//        if (RubyConfig::getAdaptiveRouting()) {
+        if (m_network_ptr->getAdaptiveRouting()) {
           if (m_network_ptr->isVNetOrdered(vnet)) {
             // Don't adaptively route
             for (int outlink=0; outlink<m_out.size(); outlink++) {
 
--- /dev/null
+
+#include "mem/protocol/MachineType.hh"
+#include "mem/ruby/network/simple/PtToPtTopology.hh"
+
+// one internal node per chip, point to point links between chips
+void PtToPtTopology::construct()
+{
+  Vector< Vector < SwitchID > > nodePairs;  // node pairs extracted from the file
+  Vector<int> latencies;  // link latencies for each link extracted
+  Vector<int> bw_multis;  // bw multipliers for each link extracted
+
+  Vector < SwitchID > nodes;
+  nodes.setSize(2);
+
+  // number of inter-chip switches
+  int numberOfChipSwitches = m_nodes/MachineType_base_level(MachineType_NUM);
+  // two switches per machine node grouping
+  // one intra-chip switch and one inter-chip switch per chip
+  for(int i=0; i<numberOfChipSwitches; i++){
+    SwitchID new_switch = newSwitchID();
+    new_switch = newSwitchID();
+  }
+
+  makeSwitchesPerChip(nodePairs, latencies, bw_multis, numberOfChipSwitches);
+
+  // connect intra-chip switch to inter-chip switch
+  for (int chip = 0; chip < RubyConfig::getNumberOfChips(); chip++) {
+
+    int latency = m_network_ptr->getOnChipLinkLatency();  // internal link latency
+    int bw_multiplier = 10;  // external link bw multiplier of the global bandwidth
+
+    nodes[0] = chip+m_nodes*2;
+    nodes[1] = chip+m_nodes*2+RubyConfig::getNumberOfChips();
+
+    // insert link
+    nodePairs.insertAtBottom(nodes);
+    latencies.insertAtBottom(latency);
+    bw_multis.insertAtBottom(bw_multiplier);
+
+    // opposite direction link
+    Vector < SwitchID > otherDirectionNodes;
+    otherDirectionNodes.setSize(2);
+    otherDirectionNodes[0] = nodes[1];
+    otherDirectionNodes[1] = nodes[0];
+    nodePairs.insertAtBottom(otherDirectionNodes);
+    latencies.insertAtBottom(latency);
+    bw_multis.insertAtBottom(bw_multiplier);
+  }
+
+  // point-to-point network between chips
+  for (int chip = 0; chip < RubyConfig::getNumberOfChips(); chip++) {
+    for (int other_chip = chip+1; other_chip < RubyConfig::getNumberOfChips(); other_chip++) {
+
+      int latency = m_network_ptr->getOffChipLinkLatency();  // external link latency
+      int bw_multiplier = 1;  // external link bw multiplier of the global bandwidth
+
+      nodes[0] = chip+m_nodes*2+RubyConfig::getNumberOfChips();
+      nodes[1] = other_chip+m_nodes*2+RubyConfig::getNumberOfChips();
+
+      // insert link
+      nodePairs.insertAtBottom(nodes);
+      latencies.insertAtBottom(latency);
+      bw_multis.insertAtBottom(bw_multiplier);
+
+      // opposite direction link
+      Vector < SwitchID > otherDirectionNodes;
+      otherDirectionNodes.setSize(2);
+      otherDirectionNodes[0] = nodes[1];
+      otherDirectionNodes[1] = nodes[0];
+      nodePairs.insertAtBottom(otherDirectionNodes);
+      latencies.insertAtBottom(latency);
+      bw_multis.insertAtBottom(bw_multiplier);
+    }
+  }
+
+  // add links
+  ASSERT(nodePairs.size() == latencies.size() && latencies.size() == bw_multis.size())
+  for (int k = 0; k < nodePairs.size(); k++) {
+    ASSERT(nodePairs[k].size() == 2);
+    addLink(nodePairs[k][0], nodePairs[k][1], latencies[k], bw_multis[k]);
+  }
+}
 
--- /dev/null
+
+#ifndef PTTOPTTOPOLOGY_H
+#define PTTOPTTOPOLOGY_H
+
+#include "mem/ruby/network/simple/Topology.hh"
+
+class PtToPtTopology : public Topology
+{
+public:
+  PtToPtTopology(const string & name);
+  void init(const vector<string> & argv);
+
+protected:
+  void construct();
+};
+
+#endif
 
 }
 */
 
+SimpleNetwork::SimpleNetwork(const string & name)
+  : Network(name)
+{
+  m_virtual_networks = 0;
+  m_topology_ptr = NULL;
+}
+
+void SimpleNetwork::init(const vector<string> & argv)
+{
+
+  Network::init(argv);
+
+  m_endpoint_switches.setSize(m_nodes);
+
+  m_in_use.setSize(m_virtual_networks);
+  m_ordered.setSize(m_virtual_networks);
+  for (int i = 0; i < m_virtual_networks; i++) {
+    m_in_use[i] = false;
+    m_ordered[i] = false;
+  }
+
+  // Allocate to and from queues
+  m_toNetQueues.setSize(m_nodes);
+  m_fromNetQueues.setSize(m_nodes);
+  for (int node = 0; node < m_nodes; node++) {
+    m_toNetQueues[node].setSize(m_virtual_networks);
+    m_fromNetQueues[node].setSize(m_virtual_networks);
+    for (int j = 0; j < m_virtual_networks; j++) {
+      cerr << "Creating new MessageBuffer for " << node << " " << j << endl;
+      m_toNetQueues[node][j] = new MessageBuffer;
+      m_fromNetQueues[node][j] = new MessageBuffer;
+    }
+  }
+
+  // Setup the network switches
+  //  m_topology_ptr = new Topology(this, m_nodes);
+  m_topology_ptr->makeTopology();
+  int number_of_switches = m_topology_ptr->numSwitches();
+  for (int i=0; i<number_of_switches; i++) {
+    m_switch_ptr_vector.insertAtBottom(new Switch(i, this));
+  }
+  m_topology_ptr->createLinks(false);  // false because this isn't a reconfiguration
+}
+/*
 SimpleNetwork::SimpleNetwork(int nodes)
 {
   m_nodes = MachineType_base_number(MachineType_NUM);
 
-  m_virtual_networks = NUMBER_OF_VIRTUAL_NETWORKS;
+  m_virtual_networks = RubyConfig::getNumberOfVirtualNetworks();
   m_endpoint_switches.setSize(m_nodes);
 
   m_in_use.setSize(m_virtual_networks);
   }
   m_topology_ptr->createLinks(false);  // false because this isn't a reconfiguration
 }
-
+*/
 void SimpleNetwork::reset()
 {
   for (int node = 0; node < m_nodes; node++) {
       // allocate a buffer
       MessageBuffer* buffer_ptr = new MessageBuffer;
       buffer_ptr->setOrdering(true);
-      if(FINITE_BUFFERING) {
-        buffer_ptr->setSize(FINITE_BUFFER_SIZE);
+      if (m_buffer_size > 0) {
+        buffer_ptr->setSize(m_buffer_size);
       }
       queues.insertAtBottom(buffer_ptr);
       // remember to deallocate it
   out << "Network Configuration" << endl;
   out << "---------------------" << endl;
   out << "network: SIMPLE_NETWORK" << endl;
-  out << "topology: " << g_NETWORK_TOPOLOGY << endl;
+  out << "topology: " << m_topology_ptr->getName() << endl;
   out << endl;
 
   for (int i = 0; i < m_virtual_networks; i++) {
     m_switch_ptr_vector[i]->printConfig(out);
   }
 
-  if (g_PRINT_TOPOLOGY) {
-    m_topology_ptr->printConfig(out);
-  }
+  m_topology_ptr->printConfig(out);
 }
 
 void SimpleNetwork::print(ostream& out) const
 
 class SimpleNetwork : public Network {
 public:
   // Constructors
-  SimpleNetwork(int nodes);
+  //  SimpleNetwork(int nodes);
+  SimpleNetwork(const string & name);
 
   // Destructor
   ~SimpleNetwork();
 
+  void init(const vector<string> & argv);
+
   // Public Methods
   void printStats(ostream& out) const;
   void clearStats();
   Vector<Vector<MessageBuffer*> > m_toNetQueues;
   Vector<Vector<MessageBuffer*> > m_fromNetQueues;
 
-  int m_nodes;
-  int m_virtual_networks;
   Vector<bool> m_in_use;
   Vector<bool> m_ordered;
   Vector<Switch*> m_switch_ptr_vector;
   Vector<MessageBuffer*> m_buffers_to_free;
   Vector<Switch*> m_endpoint_switches;
-  Topology* m_topology_ptr;
 };
 
 // Output operator declaration
 
     MessageBuffer* buffer_ptr = new MessageBuffer;
     // Make these queues ordered
     buffer_ptr->setOrdering(true);
-    if(FINITE_BUFFERING) {
-      buffer_ptr->setSize(FINITE_BUFFER_SIZE);
+    Network* net_ptr = RubySystem::getNetwork();
+    if(net_ptr->getBufferSize() > 0) {
+      buffer_ptr->setSize(net_ptr->getBufferSize());
     }
     intermediateBuffers.insertAtBottom(buffer_ptr);
     m_buffers_to_free.insertAtBottom(buffer_ptr);
 
 class NetDest;
 class SimpleNetwork;
 class Throttle;
+class Network;
 
 class Switch {
 public:
 
   // Data Members (m_ prefix)
   PerfectSwitch* m_perfect_switch_ptr;
+  Network* m_network_ptr;
   Vector<Throttle*> m_throttles;
   Vector<MessageBuffer*> m_buffers_to_free;
   SwitchID m_switch_id;
 
     }
   }
 
-  if (g_PRINT_TOPOLOGY) {
+  //  if (RubyConfig::getPrintTopology()) {
     m_out_link_vec.insertAtBottom(out_vec);
-  }
+    //  }
 }
 
 void Throttle::addVirtualNetwork(MessageBuffer* in_ptr, MessageBuffer* out_ptr)
   while ((current_time - m_last_bandwidth_sample) > ADJUST_INTERVAL) {
     double utilization = m_bandwidth_since_sample/double(ADJUST_INTERVAL * getLinkBandwidth());
 
-    if (utilization > g_bash_bandwidth_adaptive_threshold) {
-      // Used more bandwidth
-      m_bash_counter++;
-    } else {
-      // Used less bandwidth
-      m_bash_counter--;
-    }
+    // Used less bandwidth
+    m_bash_counter--;
 
     // Make sure we don't overflow
     m_bash_counter = min(HIGH_RANGE, m_bash_counter);
 
 #include "mem/gems_common/Vector.hh"
 #include "mem/ruby/common/Consumer.hh"
 #include "mem/ruby/system/NodeID.hh"
-#include "mem/ruby/config/RubyConfig.hh"
+#include "mem/ruby/system/System.hh"
+#include "mem/ruby/network/Network.hh"
 
 class MessageBuffer;
 
   void clearStats();
   void printConfig(ostream& out) const;
   double getUtilization() const; // The average utilization (a percent) since last clearStats()
-  int getLinkBandwidth() const { return g_endpoint_bandwidth * m_link_bandwidth_multiplier; }
+  int getLinkBandwidth() const { return RubySystem::getNetwork()->getEndpointBandwidth() * m_link_bandwidth_multiplier; }
   int getLatency() const { return m_link_latency; }
 
   const Vector<Vector<int> >& getCounters() const { return m_message_counters; }
 
 #include "mem/ruby/common/NetDest.hh"
 #include "mem/ruby/network/Network.hh"
 #include "mem/protocol/TopologyType.hh"
-#include "mem/ruby/config/RubyConfig.hh"
+//#include "mem/ruby/config/RubyConfig.hh"
 #include "mem/gems_common/util.hh"
 #include "mem/protocol/MachineType.hh"
 #include "mem/protocol/Protocol.hh"
+#include "mem/ruby/system/System.hh"
 #include <string>
 
 static const int INFINITE_LATENCY = 10000; // Yes, this is a big hack
 // of the network.
 
 // Helper functions based on chapter 29 of Cormen et al.
-static void extend_shortest_path(Matrix& current_dist, Matrix& latencies, Matrix& inter_switches);
+static Matrix extend_shortest_path(const Matrix& current_dist, Matrix& latencies, Matrix& inter_switches);
 static Matrix shortest_path(const Matrix& weights, Matrix& latencies, Matrix& inter_switches);
 static bool link_is_shortest_path_to_node(SwitchID src, SwitchID next, SwitchID final, const Matrix& weights, const Matrix& dist);
 static NetDest shortest_path_to_node(SwitchID src, SwitchID next, const Matrix& weights, const Matrix& dist);
 
-
-Topology::Topology(Network* network_ptr, int number_of_nodes)
+Topology::Topology(const string & name)
+  : m_name(name)
 {
-  m_network_ptr = network_ptr;
-  m_nodes = number_of_nodes;
+  m_network_ptr = NULL;
+  m_nodes = MachineType_base_number(MachineType_NUM);
   m_number_of_switches = 0;
-  init();
-}
-
-void Topology::init()
-{
-  if (m_nodes == 1) {
-    SwitchID id = newSwitchID();
-    addLink(0, id, NETWORK_LINK_LATENCY);
-    addLink(id, 1, NETWORK_LINK_LATENCY);
-    return;
-  }
-
-  // topology-specific set-up
-  TopologyType topology = string_to_TopologyType(g_NETWORK_TOPOLOGY);
-  switch (topology) {
-  case TopologyType_TORUS_2D:
-    make2DTorus();
-    break;
-  case TopologyType_HIERARCHICAL_SWITCH:
-    makeHierarchicalSwitch(FAN_OUT_DEGREE);
-    break;
-  case TopologyType_CROSSBAR:
-    makeHierarchicalSwitch(1024);
-    break;
-  case TopologyType_PT_TO_PT:
-    makePtToPt();
-    break;
-  case TopologyType_FILE_SPECIFIED:
-    makeFileSpecified();
-    break;
-  default:
-    ERROR_MSG("Unexpected typology type")
-  }
-
-  // initialize component latencies record
-  m_component_latencies.setSize(0);
-  m_component_inter_switches.setSize(0);
-}
-
-void Topology::makeSwitchesPerChip(Vector< Vector < SwitchID > > &nodePairs, Vector<int> &latencies, Vector<int> &bw_multis, int numberOfChipSwitches)
-{
-
-  Vector < SwitchID > nodes;  // temporary buffer
-  nodes.setSize(2);
-
-  Vector<bool> endpointConnectionExist;  // used to ensure all endpoints are connected to the network
-  endpointConnectionExist.setSize(m_nodes);
-  // initialize endpoint check vector
-  for (int k = 0; k < endpointConnectionExist.size(); k++) {
-    endpointConnectionExist[k] = false;
-  }
-
-  Vector<int> componentCount;
-  componentCount.setSize(MachineType_NUM);
-  for (MachineType mType = MachineType_FIRST; mType < MachineType_NUM; ++mType) {
-    componentCount[mType] = 0;
-  }
-
-  // components to/from network links
-  for (int chip = 0; chip < RubyConfig::numberOfChips(); chip++) {
-    for (MachineType mType = MachineType_FIRST; mType < MachineType_NUM; ++mType) {
-      for (int component = 0; component < MachineType_chip_count(mType, chip); component++) {
-
-        int latency = -1;
-        int bw_multiplier = -1;  // internal link bw multiplier of the global bandwidth
-        if (mType != MachineType_Directory) {
-          latency = ON_CHIP_LINK_LATENCY;  // internal link latency
-          bw_multiplier = 10;  // internal link bw multiplier of the global bandwidth
-        } else {
-          latency = NETWORK_LINK_LATENCY;  // local memory latency
-          bw_multiplier = 1;  // local memory link bw multiplier of the global bandwidth
-        }
-        nodes[0] = MachineType_base_number(mType)+componentCount[mType];
-        nodes[1] = chip+m_nodes*2; // this is the chip's internal switch id #
-
-        // insert link
-        nodePairs.insertAtBottom(nodes);
-        latencies.insertAtBottom(latency);
-        //bw_multis.insertAtBottom(bw_multiplier);
-        bw_multis.insertAtBottom(componentCount[mType]+MachineType_base_number((MachineType)mType));
-
-        // opposite direction link
-        Vector < SwitchID > otherDirectionNodes;
-        otherDirectionNodes.setSize(2);
-        otherDirectionNodes[0] = nodes[1];
-        otherDirectionNodes[1] = nodes[0]+m_nodes;
-        nodePairs.insertAtBottom(otherDirectionNodes);
-        latencies.insertAtBottom(latency);
-        bw_multis.insertAtBottom(bw_multiplier);
-
-        assert(!endpointConnectionExist[nodes[0]]);
-        endpointConnectionExist[nodes[0]] = true;
-        componentCount[mType]++;
-      }
-    }
-  }
-
-  // make sure all enpoints are connected in the soon to be created network
-  for (int k = 0; k < endpointConnectionExist.size(); k++) {
-    if (endpointConnectionExist[k] == false) {
-      cerr << "Error: Unconnected Endpoint: " << k << endl;
-      exit(1);
-    }
-  }
-
-  // secondary check to ensure we saw the correct machine counts
-  for (MachineType mType = MachineType_FIRST; mType < MachineType_NUM; ++mType) {
-    assert(componentCount[mType] == MachineType_base_count((MachineType)mType));
-  }
-
-}
-
-// 2D torus topology
-
-void Topology::make2DTorus()
-{
-  Vector< Vector < SwitchID > > nodePairs;  // node pairs extracted from the file
-  Vector<int> latencies;  // link latencies for each link extracted
-  Vector<int> bw_multis;  // bw multipliers for each link extracted
-
-  Vector < SwitchID > nodes;  // temporary buffer
-  nodes.setSize(2);
-
-  // number of inter-chip switches
-  int numberOfTorusSwitches = m_nodes/MachineType_base_level(MachineType_NUM);
-  // one switch per machine node grouping
-  Vector<SwitchID> torusSwitches;
-  for(int i=0; i<numberOfTorusSwitches; i++){
-    SwitchID new_switch = newSwitchID();
-    torusSwitches.insertAtBottom(new_switch);
-  }
-
-  makeSwitchesPerChip(nodePairs, latencies, bw_multis, numberOfTorusSwitches);
-
-  int lengthOfSide = (int)sqrt((double)numberOfTorusSwitches);
-
-  // Now connect the inter-chip torus links
-
-  int latency = NETWORK_LINK_LATENCY;  // external link latency
-  int bw_multiplier = 1;  // external link bw multiplier of the global bandwidth
-
-  for(int i=0; i<numberOfTorusSwitches; i++){
-    nodes[0] = torusSwitches[i];  // current switch
-
-    // left
-    if(nodes[0]%lengthOfSide == 0){ // determine left neighbor
-      nodes[1] = nodes[0] - 1 + lengthOfSide;
-    } else {
-      nodes[1] = nodes[0] - 1;
-    }
-    nodePairs.insertAtBottom(nodes);
-    latencies.insertAtBottom(latency);
-    bw_multis.insertAtBottom(bw_multiplier);
-
-    // right
-    if((nodes[0] + 1)%lengthOfSide == 0){ // determine right neighbor
-      nodes[1] = nodes[0] + 1 - lengthOfSide;
-    } else {
-      nodes[1] = nodes[0] + 1;
-    }
-    nodePairs.insertAtBottom(nodes);
-    latencies.insertAtBottom(latency);
-    bw_multis.insertAtBottom(bw_multiplier);
-
-    // top
-    if(nodes[0] - lengthOfSide < 2*m_nodes){ // determine if node is on the top
-      nodes[1] = nodes[0] - lengthOfSide + (lengthOfSide*lengthOfSide);
-    } else {
-      nodes[1] = nodes[0] - lengthOfSide;
-    }
-    nodePairs.insertAtBottom(nodes);
-    latencies.insertAtBottom(latency);
-    bw_multis.insertAtBottom(bw_multiplier);
-
-    // bottom
-    if(nodes[0] + lengthOfSide >= 2*m_nodes+numberOfTorusSwitches){ // determine if node is on the bottom
-      // sorin: bad bug if this is a > instead of a >=
-      nodes[1] = nodes[0] + lengthOfSide - (lengthOfSide*lengthOfSide);
-    } else {
-      nodes[1] = nodes[0] + lengthOfSide;
-    }
-    nodePairs.insertAtBottom(nodes);
-    latencies.insertAtBottom(latency);
-    bw_multis.insertAtBottom(bw_multiplier);
-
-  }
-
-  // add links
-  ASSERT(nodePairs.size() == latencies.size() && latencies.size() == bw_multis.size())
-  for (int k = 0; k < nodePairs.size(); k++) {
-    ASSERT(nodePairs[k].size() == 2);
-    addLink(nodePairs[k][0], nodePairs[k][1], latencies[k], bw_multis[k]);
-  }
-
 }
 
-// hierarchical switch topology
-void Topology::makeHierarchicalSwitch(int fan_out_degree)
+void Topology::init(const vector<string> & argv)
 {
-  // Make a row of switches with only one input.  This extra row makes
-  // sure the links out of the nodes have latency and limited
-  // bandwidth.
-
-  // number of inter-chip switches, i.e. the last row of switches
-  Vector<SwitchID> last_level;
-  for (int i=0; i<m_nodes; i++) {
-    SwitchID new_switch = newSwitchID();  // internal switch id #
-    addLink(i, new_switch, NETWORK_LINK_LATENCY);
-    last_level.insertAtBottom(new_switch);
-  }
-
-  // Create Hierarchical Switches
-
-  // start from the bottom level and work up to root
-  Vector<SwitchID> next_level;
-  while(last_level.size() > 1) {
-    for (int i=0; i<last_level.size(); i++) {
-      if ((i % fan_out_degree) == 0) {
-        next_level.insertAtBottom(newSwitchID());
-      }
-      // Add this link to the last switch we created
-      addLink(last_level[i], next_level[next_level.size()-1], NETWORK_LINK_LATENCY);
-    }
-
-    // Make the current level the last level to get ready for next
-    // iteration
-    last_level = next_level;
-    next_level.clear();
-  }
-
-  SwitchID root_switch = last_level[0];
-
-  Vector<SwitchID> out_level;
-  for (int i=0; i<m_nodes; i++) {
-    out_level.insertAtBottom(m_nodes+i);
-  }
-
-  // Build the down network from the endpoints to the root
-  while(out_level.size() != 1) {
-
-    // A level of switches
-    for (int i=0; i<out_level.size(); i++) {
-      if ((i % fan_out_degree) == 0) {
-        if (out_level.size() > fan_out_degree) {
-          next_level.insertAtBottom(newSwitchID());
-        } else {
-          next_level.insertAtBottom(root_switch);
-        }
-      }
-      // Add this link to the last switch we created
-      addLink(next_level[next_level.size()-1], out_level[i], NETWORK_LINK_LATENCY);
+  for (size_t i=0; i<argv.size(); i+=2) {
+    if (argv[i] == "network")
+      m_network_ptr = RubySystem::getNetwork();
+    else if (argv[i] == "connections")
+      m_connections = argv[i+1];
+    else if (argv[i] == "print_config") {
+      m_print_config = string_to_bool(argv[i+1]);
+      cerr << "print config: " << m_print_config << endl;
     }
-
-    // Make the current level the last level to get ready for next
-    // iteration
-    out_level = next_level;
-    next_level.clear();
   }
+  assert(m_network_ptr != NULL);
 }
 
-// one internal node per chip, point to point links between chips
-void Topology::makePtToPt()
+void Topology::makeTopology()
 {
-  Vector< Vector < SwitchID > > nodePairs;  // node pairs extracted from the file
-  Vector<int> latencies;  // link latencies for each link extracted
-  Vector<int> bw_multis;  // bw multipliers for each link extracted
-
-  Vector < SwitchID > nodes;
-  nodes.setSize(2);
-
-  // number of inter-chip switches
-  int numberOfChipSwitches = m_nodes/MachineType_base_level(MachineType_NUM);
-  // two switches per machine node grouping
-  // one intra-chip switch and one inter-chip switch per chip
-  for(int i=0; i<numberOfChipSwitches; i++){
-    SwitchID new_switch = newSwitchID();
-    new_switch = newSwitchID();
-  }
-
-  makeSwitchesPerChip(nodePairs, latencies, bw_multis, numberOfChipSwitches);
-
-  // connect intra-chip switch to inter-chip switch
-  for (int chip = 0; chip < RubyConfig::numberOfChips(); chip++) {
-
-    int latency = ON_CHIP_LINK_LATENCY;  // internal link latency
-    int bw_multiplier = 10;  // external link bw multiplier of the global bandwidth
-
-    nodes[0] = chip+m_nodes*2;
-    nodes[1] = chip+m_nodes*2+RubyConfig::numberOfChips();
-
-    // insert link
-    nodePairs.insertAtBottom(nodes);
-    latencies.insertAtBottom(latency);
-    bw_multis.insertAtBottom(bw_multiplier);
-
-    // opposite direction link
-    Vector < SwitchID > otherDirectionNodes;
-    otherDirectionNodes.setSize(2);
-    otherDirectionNodes[0] = nodes[1];
-    otherDirectionNodes[1] = nodes[0];
-    nodePairs.insertAtBottom(otherDirectionNodes);
-    latencies.insertAtBottom(latency);
-    bw_multis.insertAtBottom(bw_multiplier);
-  }
-
-  // point-to-point network between chips
-  for (int chip = 0; chip < RubyConfig::numberOfChips(); chip++) {
-    for (int other_chip = chip+1; other_chip < RubyConfig::numberOfChips(); other_chip++) {
-
-      int latency = NETWORK_LINK_LATENCY;  // external link latency
-      int bw_multiplier = 1;  // external link bw multiplier of the global bandwidth
-
-      nodes[0] = chip+m_nodes*2+RubyConfig::numberOfChips();
-      nodes[1] = other_chip+m_nodes*2+RubyConfig::numberOfChips();
-
-      // insert link
-      nodePairs.insertAtBottom(nodes);
-      latencies.insertAtBottom(latency);
-      bw_multis.insertAtBottom(bw_multiplier);
-
-      // opposite direction link
-      Vector < SwitchID > otherDirectionNodes;
-      otherDirectionNodes.setSize(2);
-      otherDirectionNodes[0] = nodes[1];
-      otherDirectionNodes[1] = nodes[0];
-      nodePairs.insertAtBottom(otherDirectionNodes);
-      latencies.insertAtBottom(latency);
-      bw_multis.insertAtBottom(bw_multiplier);
-    }
-  }
-
-  // add links
-  ASSERT(nodePairs.size() == latencies.size() && latencies.size() == bw_multis.size())
-  for (int k = 0; k < nodePairs.size(); k++) {
-    ASSERT(nodePairs[k].size() == 2);
-    addLink(nodePairs[k][0], nodePairs[k][1], latencies[k], bw_multis[k]);
+  /*
+  if (m_nodes == 1) {
+    SwitchID id = newSwitchID();
+    addLink(0, id, m_network_ptr->getOffChipLinkLatency());
+    addLink(id, 1, m_network_ptr->getOffChipLinkLatency());
+    return;
   }
-}
-
-// make a network as described by the networkFile
-void Topology::makeFileSpecified()
-{
+  */
+  assert(m_nodes > 1);
 
   Vector< Vector < SwitchID > > nodePairs;  // node pairs extracted from the file
   Vector<int> latencies;  // link latencies for each link extracted
     endpointConnectionExist[k] = false;
   }
 
-  string filename = "network/simple/Network_Files/";
-  filename = filename+g_CACHE_DESIGN
-    +"_Procs-"+int_to_string(RubyConfig::numberOfProcessors())
-    +"_ProcsPerChip-"+int_to_string(RubyConfig::numberOfProcsPerChip())
-    +"_L2Banks-"+int_to_string(RubyConfig::numberOfL2Cache())
-    +"_Memories-"+int_to_string(RubyConfig::numberOfMemories())
-    +".txt";
-
-  ifstream networkFile( filename.c_str() , ios::in);
-  if (!networkFile.is_open()) {
-    cerr << "Error: Could not open network file: " << filename << endl;
-    cerr << "Probably no network file exists for " << RubyConfig::numberOfProcessors()
-         << " processors and " << RubyConfig::numberOfProcsPerChip() << " procs per chip " << endl;
-    exit(1);
-  }
+  stringstream networkFile( m_connections );
 
   string line = "";
 
         if (label == "ext_node") { // input link to node
           MachineType machine = string_to_MachineType(string_split(varStr, ':'));
           string nodeStr = string_split(varStr, ':');
-          if (string_split(varStr, ':') == "bank") {
-            nodes[i] = MachineType_base_number(machine)
-              + atoi(nodeStr.c_str())
-              + atoi((string_split(varStr, ':')).c_str())*RubyConfig::numberOfChips();
-          } else {
-            nodes[i] = MachineType_base_number(machine)
-              + atoi(nodeStr.c_str());
-          }
+          nodes[i] = MachineType_base_number(machine)
+            + atoi(nodeStr.c_str());
+
           // in nodes should be numbered 0 to m_nodes-1
           ASSERT(nodes[i] >= 0 && nodes[i] < m_nodes);
           isNewIntSwitch = false;
         bw_multiplier = atoi((string_split(varStr, ':')).c_str());
       } else if (label == "link_weight") {  // not necessary, defaults to link_latency
         weight = atoi((string_split(varStr, ':')).c_str());
-      } else if (label == "processors") {
-        ASSERT(atoi((string_split(varStr, ':')).c_str()) == RubyConfig::numberOfProcessors());
-      } else if (label == "bw_unit") {
-        ASSERT(atoi((string_split(varStr, ':')).c_str()) == g_endpoint_bandwidth);
-      } else if (label == "procs_per_chip") {
-        ASSERT(atoi((string_split(varStr, ':')).c_str()) == RubyConfig::numberOfProcsPerChip());
-      } else if (label == "L2banks") {
-        ASSERT(atoi((string_split(varStr, ':')).c_str()) == RubyConfig::numberOfL2Cache());
-      } else if (label == "memories") {
-        ASSERT(atoi((string_split(varStr, ':')).c_str()) == RubyConfig::numberOfMemories());
       } else {
         cerr << "Error: Unexpected Identifier: " << label << endl;
         exit(1);
     addLink(nodePairs[k][0], nodePairs[k][1], latencies[k], bw_multis[k], weights[k]);
   }
 
-  networkFile.close();
+  // initialize component latencies record
+  m_component_latencies.setSize(0);
+  m_component_inter_switches.setSize(0);
 }
 
+
 void Topology::createLinks(bool isReconfiguration)
 {
   // Find maximum switchID
     }
   }
 }
+/*
+void Topology::makeSwitchesPerChip(Vector< Vector < SwitchID > > &nodePairs, Vector<int> &latencies, Vector<int> &bw_multis, int numberOfChipSwitches)
+{
+
+  Vector < SwitchID > nodes;  // temporary buffer
+  nodes.setSize(2);
+
+  Vector<bool> endpointConnectionExist;  // used to ensure all endpoints are connected to the network
+  endpointConnectionExist.setSize(m_nodes);
+  // initialize endpoint check vector
+  for (int k = 0; k < endpointConnectionExist.size(); k++) {
+    endpointConnectionExist[k] = false;
+  }
+
+  Vector<int> componentCount;
+  componentCount.setSize(MachineType_NUM);
+  for (MachineType mType = MachineType_FIRST; mType < MachineType_NUM; ++mType) {
+    componentCount[mType] = 0;
+  }
+
+  // components to/from network links
+  // TODO: drh5: bring back chips!!!
+  for (int chip = 0; chip < RubyConfig::getNumberOfChips(); chip++) {
+    for (MachineType mType = MachineType_FIRST; mType < MachineType_NUM; ++mType) {
+      for (int component = 0; component < MachineType_base_count(mType); component++) {
+
+        int latency = -1;
+        int bw_multiplier = -1;  // internal link bw multiplier of the global bandwidth
+        if (mType != MachineType_Directory) {
+          latency = RubyConfig::getOnChipLinkLatency();  // internal link latency
+          bw_multiplier = 10;  // internal link bw multiplier of the global bandwidth
+        } else {
+          latency = RubyConfig::getNetworkLinkLatency();  // local memory latency
+          bw_multiplier = 1;  // local memory link bw multiplier of the global bandwidth
+        }
+        nodes[0] = MachineType_base_number(mType)+componentCount[mType];
+        nodes[1] = chip+m_nodes*2; // this is the chip's internal switch id #
+
+        // insert link
+        nodePairs.insertAtBottom(nodes);
+        latencies.insertAtBottom(latency);
+        bw_multis.insertAtBottom(bw_multiplier);
+        //bw_multis.insertAtBottom(componentCount[mType]+MachineType_base_number((MachineType)mType));
+
+        // opposite direction link
+        Vector < SwitchID > otherDirectionNodes;
+        otherDirectionNodes.setSize(2);
+        otherDirectionNodes[0] = nodes[1];
+        otherDirectionNodes[1] = nodes[0]+m_nodes;
+        nodePairs.insertAtBottom(otherDirectionNodes);
+        latencies.insertAtBottom(latency);
+        bw_multis.insertAtBottom(bw_multiplier);
+
+        assert(!endpointConnectionExist[nodes[0]]);
+        endpointConnectionExist[nodes[0]] = true;
+        componentCount[mType]++;
+      }
+    }
+  }
+
+  // make sure all enpoints are connected in the soon to be created network
+  for (int k = 0; k < endpointConnectionExist.size(); k++) {
+    if (endpointConnectionExist[k] == false) {
+      cerr << "Error: Unconnected Endpoint: " << k << endl;
+      exit(1);
+    }
+  }
+
+  // secondary check to ensure we saw the correct machine counts
+  for (MachineType mType = MachineType_FIRST; mType < MachineType_NUM; ++mType) {
+    assert(componentCount[mType] == MachineType_base_count((MachineType)mType));
+  }
+
+}
+*/
+
 
 SwitchID Topology::newSwitchID()
 {
 
 void Topology::printConfig(ostream& out) const
 {
+  if (m_print_config == false) return;
+
   assert(m_component_latencies.size() > 0);
 
   out << "--- Begin Topology Print ---" << endl;
 
 class Topology {
 public:
   // Constructors
-  Topology(Network* network_ptr, int number_of_nodes);
+  //  Topology(Network* network_ptr, int number_of_nodes);
+  Topology(const string & name);
 
   // Destructor
-  ~Topology() {}
+  virtual ~Topology() {}
+
+  virtual void init(const vector<string> & argv);
 
   // Public Methods
+  void makeTopology();
   int numSwitches() const { return m_number_of_switches; }
   void createLinks(bool isReconfiguration);
 
+  const string getName() { return m_name; }
   void printStats(ostream& out) const {}
   void clearStats() {}
   void printConfig(ostream& out) const;
   void print(ostream& out) const { out << "[Topology]"; }
 
-private:
+protected:
   // Private Methods
   void init();
   SwitchID newSwitchID();
   void addLink(SwitchID src, SwitchID dest, int link_latency, int bw_multiplier, int link_weight);
   void makeLink(SwitchID src, SwitchID dest, const NetDest& routing_table_entry, int link_latency, int weight, int bw_multiplier, bool isReconfiguration);
 
-  void makeHierarchicalSwitch(int fan_out_degree);
-  void make2DTorus();
-  void makePtToPt();
-  void makeFileSpecified();
-
-  void makeSwitchesPerChip(Vector< Vector < SwitchID > > &nodePairs, Vector<int> &latencies, Vector<int> &bw_multis, int numberOfChips);
+  //  void makeSwitchesPerChip(Vector< Vector < SwitchID > > &nodePairs, Vector<int> &latencies, Vector<int> &bw_multis, int numberOfChips);
 
   string getDesignStr();
   // Private copy constructor and assignment operator
   Topology& operator=(const Topology& obj);
 
   // Data Members (m_ prefix)
+  string m_name;
+  bool m_print_config;
   Network* m_network_ptr;
+  string m_connections;
   NodeID m_nodes;
   int m_number_of_switches;
 
 
--- /dev/null
+
+// 2D torus topology
+
+void Torus2DTopology::construct()
+{
+  Vector< Vector < SwitchID > > nodePairs;  // node pairs extracted from the file
+  Vector<int> latencies;  // link latencies for each link extracted
+  Vector<int> bw_multis;  // bw multipliers for each link extracted
+
+  Vector < SwitchID > nodes;  // temporary buffer
+  nodes.setSize(2);
+
+  // number of inter-chip switches
+  int numberOfTorusSwitches = m_nodes/MachineType_base_level(MachineType_NUM);
+  // one switch per machine node grouping
+  Vector<SwitchID> torusSwitches;
+  for(int i=0; i<numberOfTorusSwitches; i++){
+    SwitchID new_switch = newSwitchID();
+    torusSwitches.insertAtBottom(new_switch);
+  }
+
+  makeSwitchesPerChip(nodePairs, latencies, bw_multis, numberOfTorusSwitches);
+
+  int lengthOfSide = (int)sqrt((double)numberOfTorusSwitches);
+
+  // Now connect the inter-chip torus links
+
+  int latency = m_network_ptr->getLinkLatency();  // external link latency
+  int bw_multiplier = 1;  // external link bw multiplier of the global bandwidth
+
+  for(int i=0; i<numberOfTorusSwitches; i++){
+    nodes[0] = torusSwitches[i];  // current switch
+
+    // left
+    if(nodes[0]%lengthOfSide == 0){ // determine left neighbor
+      nodes[1] = nodes[0] - 1 + lengthOfSide;
+    } else {
+      nodes[1] = nodes[0] - 1;
+    }
+    nodePairs.insertAtBottom(nodes);
+    latencies.insertAtBottom(latency);
+    bw_multis.insertAtBottom(bw_multiplier);
+
+    // right
+    if((nodes[0] + 1)%lengthOfSide == 0){ // determine right neighbor
+      nodes[1] = nodes[0] + 1 - lengthOfSide;
+    } else {
+      nodes[1] = nodes[0] + 1;
+    }
+    nodePairs.insertAtBottom(nodes);
+    latencies.insertAtBottom(latency);
+    bw_multis.insertAtBottom(bw_multiplier);
+
+    // top
+    if(nodes[0] - lengthOfSide < 2*m_nodes){ // determine if node is on the top
+      nodes[1] = nodes[0] - lengthOfSide + (lengthOfSide*lengthOfSide);
+    } else {
+      nodes[1] = nodes[0] - lengthOfSide;
+    }
+    nodePairs.insertAtBottom(nodes);
+    latencies.insertAtBottom(latency);
+    bw_multis.insertAtBottom(bw_multiplier);
+
+    // bottom
+    if(nodes[0] + lengthOfSide >= 2*m_nodes+numberOfTorusSwitches){ // determine if node is on the bottom
+      // sorin: bad bug if this is a > instead of a >=
+      nodes[1] = nodes[0] + lengthOfSide - (lengthOfSide*lengthOfSide);
+    } else {
+      nodes[1] = nodes[0] + lengthOfSide;
+    }
+    nodePairs.insertAtBottom(nodes);
+    latencies.insertAtBottom(latency);
+    bw_multis.insertAtBottom(bw_multiplier);
+
+  }
+
+  // add links
+  ASSERT(nodePairs.size() == latencies.size() && latencies.size() == bw_multis.size())
+  for (int k = 0; k < nodePairs.size(); k++) {
+    ASSERT(nodePairs[k].size() == 2);
+    addLink(nodePairs[k][0], nodePairs[k][1], latencies[k], bw_multis[k]);
+  }
+
+}
 
--- /dev/null
+
+#ifndef TORUS2DTOPOLOGY_H
+#define TORUS2DTOPOLOGY_H
+
+#include "mem/ruby/network/simple/Topology.hh"
+
+class Torus2DTopology : public Topology
+{
+public:
+  Torus2DTopology(const string & name);
+  void init(const vector<string> & argv);
+
+protected:
+  void construct();
+};
+
+#endif
 
   delete m_persistentPredictionProfileMap;
 }
 
+void AddressProfiler::setHotLines(bool hot_lines){
+  m_hot_lines = hot_lines;
+}
+void AddressProfiler::setAllInstructions(bool all_instructions){
+  m_all_instructions = all_instructions;
+}
+
 void AddressProfiler::printStats(ostream& out) const
 {
-  if (PROFILE_HOT_LINES) {
+  if (m_hot_lines) {
     out << endl;
     out << "AddressProfiler Stats" << endl;
     out << "---------------------" << endl;
     printSorted(out, m_programCounterAccessTrace, "pc_address");
   }
 
-  if (PROFILE_ALL_INSTRUCTIONS){
+  if (m_all_instructions){
     out << endl;
     out << "All Instructions Profile:" << endl;
     out << "-------------------------" << endl;
 
 void AddressProfiler::addTraceSample(Address data_addr, Address pc_addr, CacheRequestType type, AccessModeType access_mode, NodeID id, bool sharing_miss)
 {
-  if (PROFILE_HOT_LINES) {
+  if (m_all_instructions) {
     if (sharing_miss) {
       m_sharing_miss_counter++;
     }
     lookupTraceForAddress(pc_addr, m_programCounterAccessTrace).update(type, access_mode, id, sharing_miss);
   }
 
-  if (PROFILE_ALL_INSTRUCTIONS) {
+  if (m_all_instructions) {
     // This code is used if the address profiler is an all-instructions profiler
     // record program counter address trace info
     lookupTraceForAddress(pc_addr, m_programCounterAccessTrace).update(type, access_mode, id, sharing_miss);
   }
 
   out << "Total_entries_" << description << ": " << keys.size() << endl;
-  if (PROFILE_ALL_INSTRUCTIONS)
+  if (g_system_ptr->getProfiler()->getAllInstructions())
     out << "Total_Instructions_" << description << ": " << misses << endl;
   else
     out << "Total_data_misses_" << description << ": " << misses << endl;
   // Allows us to track how many lines where touched by n processors
   Vector<int64> m_touched_vec;
   Vector<int64> m_touched_weighted_vec;
-  m_touched_vec.setSize(RubyConfig::numberOfProcessors()+1);
-  m_touched_weighted_vec.setSize(RubyConfig::numberOfProcessors()+1);
+  m_touched_vec.setSize(RubySystem::getNumberOfSequencers()+1);
+  m_touched_weighted_vec.setSize(RubySystem::getNumberOfSequencers()+1);
   for (int i=0; i<m_touched_vec.size(); i++) {
     m_touched_vec[i] = 0;
     m_touched_weighted_vec[i] = 0;
 
   void profileGetS(const Address& datablock, const Address& PC, const Set& owner, const Set& sharers, NodeID requestor);
 
   void print(ostream& out) const;
+
+  //added by SS
+  void setHotLines(bool hot_lines);
+  void setAllInstructions(bool all_instructions);
 private:
   // Private Methods
 
   Histogram m_retryProfileHistoRead;
   Histogram m_getx_sharing_histogram;
   Histogram m_gets_sharing_histogram;
+//added by SS
+  bool m_hot_lines;
+  bool m_all_instructions;
+
 };
 
 // Output operator declaration
 
 #include "mem/ruby/network/Network.hh"
 #include "mem/gems_common/PrioHeap.hh"
 #include "mem/protocol/CacheMsg.hh"
-#include "mem/ruby/common/Driver.hh"
 #include "mem/protocol/Protocol.hh"
 #include "mem/gems_common/util.hh"
 #include "mem/gems_common/Map.hh"
 static double process_memory_total();
 static double process_memory_resident();
 
-Profiler::Profiler()
+Profiler::Profiler(const string & name)
   : m_conflicting_histogram(-1)
 {
+  m_name = name;
   m_requestProfileMap_ptr = new Map<string, int>;
   m_L1D_cache_profiler_ptr = new CacheProfiler("L1D_cache");
   m_L1I_cache_profiler_ptr = new CacheProfiler("L1I_cache");
 
   m_L2_cache_profiler_ptr = new CacheProfiler("L2_cache");
 
+  m_inst_profiler_ptr = NULL;
+  m_address_profiler_ptr = NULL;
+
+/*
   m_address_profiler_ptr = new AddressProfiler;
   m_inst_profiler_ptr = NULL;
-  if (PROFILE_ALL_INSTRUCTIONS) {
+  if (m_all_instructions) {
     m_inst_profiler_ptr = new AddressProfiler;
   }
-
+*/
   m_conflicting_map_ptr = new Map<Address, Time>;
 
   m_real_time_start_time = time(NULL); // Not reset in clearStats()
   m_stats_period = 1000000; // Default
   m_periodic_output_file_ptr = &cerr;
 
+//changed by SS
+/*
   // for MemoryControl:
   m_memReq = 0;
   m_memBankBusy = 0;
                  * RubyConfig::ranksPerDimm()
                  * RubyConfig::dimmsPerChannel();
   m_memBankCount.setSize(totalBanks);
-
-  clearStats();
+*/
 }
 
 Profiler::~Profiler()
   delete m_conflicting_map_ptr;
 }
 
+void Profiler::init(const vector<string> & argv, vector<string> memory_control_names)
+{
+  // added by SS
+  vector<string>::iterator it;
+  memory_control_profiler* mcp;
+  m_memory_control_names = memory_control_names;
+//  printf ( "Here in Profiler::init \n");
+  for ( it=memory_control_names.begin() ; it < memory_control_names.end(); it++ ){
+//    printf ( "Here in Profiler::init memory control name %s \n", (*it).c_str());
+    mcp = new memory_control_profiler;
+    mcp->m_memReq = 0;
+    mcp->m_memBankBusy = 0;
+    mcp->m_memBusBusy = 0;
+    mcp->m_memReadWriteBusy = 0;
+    mcp->m_memDataBusBusy = 0;
+    mcp->m_memTfawBusy = 0;
+    mcp->m_memRefresh = 0;
+    mcp->m_memRead = 0;
+    mcp->m_memWrite = 0;
+    mcp->m_memWaitCycles = 0;
+    mcp->m_memInputQ = 0;
+    mcp->m_memBankQ = 0;
+    mcp->m_memArbWait = 0;
+    mcp->m_memRandBusy = 0;
+    mcp->m_memNotOld = 0;
+
+    mcp->m_banks_per_rank = RubySystem::getMemoryControl((*it).c_str())->getBanksPerRank();
+    mcp->m_ranks_per_dimm = RubySystem::getMemoryControl((*it).c_str())->getRanksPerDimm();
+    mcp->m_dimms_per_channel = RubySystem::getMemoryControl((*it).c_str())->getDimmsPerChannel();
+
+    int totalBanks = mcp->m_banks_per_rank
+                 * mcp->m_ranks_per_dimm
+                 * mcp->m_dimms_per_channel;
+
+    mcp->m_memBankCount.setSize(totalBanks);
+
+    m_memory_control_profilers [(*it).c_str()] = mcp;
+  }
+
+  clearStats();
+  m_hot_lines = false;
+  m_all_instructions = false;
+
+  for (size_t i=0; i<argv.size(); i+=2) {
+    if ( argv[i] == "hot_lines") {
+      m_hot_lines = (argv[i+1]=="true");
+    } else if ( argv[i] == "all_instructions") {
+      m_all_instructions = (argv[i+1]=="true");
+    }else {
+      cerr << "WARNING: Profiler: Unkown configuration parameter: " << argv[i] << endl;
+      assert(false);
+    }
+  }
+
+  m_address_profiler_ptr = new AddressProfiler;
+  m_address_profiler_ptr -> setHotLines(m_hot_lines);
+  m_address_profiler_ptr -> setAllInstructions(m_all_instructions);
+
+  if (m_all_instructions) {
+    m_inst_profiler_ptr = new AddressProfiler;
+    m_inst_profiler_ptr -> setHotLines(m_hot_lines);
+    m_inst_profiler_ptr -> setAllInstructions(m_all_instructions);
+  }
+}
+
 void Profiler::wakeup()
 {
   // FIXME - avoid the repeated code
 
   Vector<integer_t> perProcInstructionCount;
-  perProcInstructionCount.setSize(RubyConfig::numberOfProcessors());
+  perProcInstructionCount.setSize(RubySystem::getNumberOfSequencers());
 
   Vector<integer_t> perProcCycleCount;
-  perProcCycleCount.setSize(RubyConfig::numberOfProcessors());
+  perProcCycleCount.setSize(RubySystem::getNumberOfSequencers());
 
-  for(int i=0; i < RubyConfig::numberOfProcessors(); i++) {
-    perProcInstructionCount[i] = g_system_ptr->getDriver()->getInstructionCount(i) - m_instructions_executed_at_start[i] + 1;
-    perProcCycleCount[i] = g_system_ptr->getDriver()->getCycleCount(i) - m_cycles_executed_at_start[i] + 1;
+  for(int i=0; i < RubySystem::getNumberOfSequencers(); i++) {
+    perProcInstructionCount[i] = g_system_ptr->getInstructionCount(i) - m_instructions_executed_at_start[i] + 1;
+    perProcCycleCount[i] = g_system_ptr->getCycleCount(i) - m_cycles_executed_at_start[i] + 1;
     // The +1 allows us to avoid division by zero
   }
 
   integer_t total_misses = m_perProcTotalMisses.sum();
   integer_t instruction_executed = perProcInstructionCount.sum();
-  integer_t cycles_executed = perProcCycleCount.sum();
+  integer_t simics_cycles_executed = perProcCycleCount.sum();
   integer_t transactions_started = m_perProcStartTransaction.sum();
   integer_t transactions_ended = m_perProcEndTransaction.sum();
 
   (*m_periodic_output_file_ptr) << "ruby_cycles: " << g_eventQueue_ptr->getTime()-m_ruby_start << endl;
   (*m_periodic_output_file_ptr) << "total_misses: " << total_misses << " " << m_perProcTotalMisses << endl;
   (*m_periodic_output_file_ptr) << "instruction_executed: " << instruction_executed << " " << perProcInstructionCount << endl;
-  (*m_periodic_output_file_ptr) << "cycles_executed: " << cycles_executed << " " << perProcCycleCount << endl;
+  (*m_periodic_output_file_ptr) << "simics_cycles_executed: " << simics_cycles_executed << " " << perProcCycleCount << endl;
   (*m_periodic_output_file_ptr) << "transactions_started: " << transactions_started << " " << m_perProcStartTransaction << endl;
   (*m_periodic_output_file_ptr) << "transactions_ended: " << transactions_ended << " " << m_perProcEndTransaction << endl;
   (*m_periodic_output_file_ptr) << "L1TBE_usage: " << m_L1tbeProfile << endl;
 
   *m_periodic_output_file_ptr << endl;
 
-  if (PROFILE_ALL_INSTRUCTIONS) {
+  if (m_all_instructions) {
     m_inst_profiler_ptr->printStats(*m_periodic_output_file_ptr);
   }
 
   Vector<double> perProcCyclesPerTrans;
   Vector<double> perProcMissesPerTrans;
 
-  perProcInstructionCount.setSize(RubyConfig::numberOfProcessors());
-  perProcCycleCount.setSize(RubyConfig::numberOfProcessors());
-  perProcCPI.setSize(RubyConfig::numberOfProcessors());
-  perProcMissesPerInsn.setSize(RubyConfig::numberOfProcessors());
+  perProcInstructionCount.setSize(RubySystem::getNumberOfSequencers());
+  perProcCycleCount.setSize(RubySystem::getNumberOfSequencers());
+  perProcCPI.setSize(RubySystem::getNumberOfSequencers());
+  perProcMissesPerInsn.setSize(RubySystem::getNumberOfSequencers());
 
-  perProcInsnPerTrans.setSize(RubyConfig::numberOfProcessors());
-  perProcCyclesPerTrans.setSize(RubyConfig::numberOfProcessors());
-  perProcMissesPerTrans.setSize(RubyConfig::numberOfProcessors());
+  perProcInsnPerTrans.setSize(RubySystem::getNumberOfSequencers());
+  perProcCyclesPerTrans.setSize(RubySystem::getNumberOfSequencers());
+  perProcMissesPerTrans.setSize(RubySystem::getNumberOfSequencers());
 
-  for(int i=0; i < RubyConfig::numberOfProcessors(); i++) {
-    perProcInstructionCount[i] = g_system_ptr->getDriver()->getInstructionCount(i) - m_instructions_executed_at_start[i] + 1;
-    perProcCycleCount[i] = g_system_ptr->getDriver()->getCycleCount(i) - m_cycles_executed_at_start[i] + 1;
+  for(int i=0; i < RubySystem::getNumberOfSequencers(); i++) {
+    perProcInstructionCount[i] = g_system_ptr->getInstructionCount(i) - m_instructions_executed_at_start[i] + 1;
+    perProcCycleCount[i] = g_system_ptr->getCycleCount(i) - m_cycles_executed_at_start[i] + 1;
     // The +1 allows us to avoid division by zero
     perProcCPI[i] = double(ruby_cycles)/perProcInstructionCount[i];
     perProcMissesPerInsn[i] = 1000.0 * (double(m_perProcTotalMisses[i]) / double(perProcInstructionCount[i]));
   integer_t user_misses = m_perProcUserMisses.sum();
   integer_t supervisor_misses = m_perProcSupervisorMisses.sum();
   integer_t instruction_executed = perProcInstructionCount.sum();
-  integer_t cycles_executed = perProcCycleCount.sum();
+  integer_t simics_cycles_executed = perProcCycleCount.sum();
   integer_t transactions_started = m_perProcStartTransaction.sum();
   integer_t transactions_ended = m_perProcEndTransaction.sum();
 
   double instructions_per_transaction = (transactions_ended != 0) ? double(instruction_executed) / double(transactions_ended) : 0;
-  double cycles_per_transaction = (transactions_ended != 0) ? (RubyConfig::numberOfProcessors() * double(ruby_cycles)) / double(transactions_ended) : 0;
+  double cycles_per_transaction = (transactions_ended != 0) ? (RubySystem::getNumberOfSequencers() * double(ruby_cycles)) / double(transactions_ended) : 0;
   double misses_per_transaction = (transactions_ended != 0) ? double(total_misses) / double(transactions_ended) : 0;
 
   out << "Total_misses: " << total_misses << endl;
   out << "supervisor_misses: " << supervisor_misses << " " << m_perProcSupervisorMisses << endl;
   out << endl;
   out << "instruction_executed: " << instruction_executed << " " << perProcInstructionCount << endl;
-  out << "cycles_executed: " << cycles_executed << " " << perProcCycleCount << endl;
-  out << "cycles_per_instruction: " << (RubyConfig::numberOfProcessors()*double(ruby_cycles))/double(instruction_executed) << " " << perProcCPI << endl;
+  out << "ruby_cycles_executed: " << simics_cycles_executed << " " << perProcCycleCount << endl;
+  out << "cycles_per_instruction: " << (RubySystem::getNumberOfSequencers()*double(ruby_cycles))/double(instruction_executed) << " " << perProcCPI << endl;
   out << "misses_per_thousand_instructions: " << 1000.0 * (double(total_misses) / double(instruction_executed)) << " " << perProcMissesPerInsn << endl;
   out << endl;
   out << "transactions_started: " << transactions_started << " " << m_perProcStartTransaction << endl;
 
   out << endl;
 
-  if (m_memReq || m_memRefresh) {    // if there's a memory controller at all
-    long long int total_stalls = m_memInputQ + m_memBankQ + m_memWaitCycles;
-    double stallsPerReq = total_stalls * 1.0 / m_memReq;
-    out << "Memory control:" << endl;
-    out << "  memory_total_requests: " << m_memReq << endl;  // does not include refreshes
-    out << "  memory_reads: " << m_memRead << endl;
-    out << "  memory_writes: " << m_memWrite << endl;
-    out << "  memory_refreshes: " << m_memRefresh << endl;
-    out << "  memory_total_request_delays: " << total_stalls << endl;
-    out << "  memory_delays_per_request: " << stallsPerReq << endl;
-    out << "  memory_delays_in_input_queue: " << m_memInputQ << endl;
-    out << "  memory_delays_behind_head_of_bank_queue: " << m_memBankQ << endl;
-    out << "  memory_delays_stalled_at_head_of_bank_queue: " << m_memWaitCycles << endl;
-    // Note:  The following "memory stalls" entries are a breakdown of the
-    // cycles which already showed up in m_memWaitCycles.  The order is
-    // significant; it is the priority of attributing the cycles.
-    // For example, bank_busy is before arbitration because if the bank was
-    // busy, we didn't even check arbitration.
-    // Note:  "not old enough" means that since we grouped waiting heads-of-queues
-    // into batches to avoid starvation, a request in a newer batch
-    // didn't try to arbitrate yet because there are older requests waiting.
-    out << "  memory_stalls_for_bank_busy: " << m_memBankBusy << endl;
-    out << "  memory_stalls_for_random_busy: " << m_memRandBusy << endl;
-    out << "  memory_stalls_for_anti_starvation: " << m_memNotOld << endl;
-    out << "  memory_stalls_for_arbitration: " << m_memArbWait << endl;
-    out << "  memory_stalls_for_bus: " << m_memBusBusy << endl;
-    out << "  memory_stalls_for_tfaw: " << m_memTfawBusy << endl;
-    out << "  memory_stalls_for_read_write_turnaround: " << m_memReadWriteBusy << endl;
-    out << "  memory_stalls_for_read_read_turnaround: " << m_memDataBusBusy << endl;
-    out << "  accesses_per_bank: ";
-    for (int bank=0; bank < m_memBankCount.size(); bank++) {
-      out << m_memBankCount[bank] << "  ";
-      //if ((bank % 8) == 7) out << "                     " << endl;
+  vector<string>::iterator it;
+
+  for ( it=m_memory_control_names.begin() ; it < m_memory_control_names.end(); it++ ){
+    long long int m_memReq = m_memory_control_profilers[(*it).c_str()] -> m_memReq;
+    long long int m_memRefresh = m_memory_control_profilers[(*it).c_str()] -> m_memRefresh;
+    long long int m_memInputQ = m_memory_control_profilers[(*it).c_str()] -> m_memInputQ;
+    long long int m_memBankQ = m_memory_control_profilers[(*it).c_str()] -> m_memBankQ;
+    long long int m_memWaitCycles = m_memory_control_profilers[(*it).c_str()] -> m_memWaitCycles;
+    long long int m_memRead = m_memory_control_profilers[(*it).c_str()] -> m_memRead;
+    long long int m_memWrite = m_memory_control_profilers[(*it).c_str()] -> m_memWrite;
+    long long int m_memBankBusy = m_memory_control_profilers[(*it).c_str()] -> m_memBankBusy;
+    long long int m_memRandBusy = m_memory_control_profilers[(*it).c_str()] -> m_memRandBusy;
+    long long int m_memNotOld = m_memory_control_profilers[(*it).c_str()] -> m_memNotOld;
+    long long int m_memArbWait = m_memory_control_profilers[(*it).c_str()] -> m_memArbWait;
+    long long int m_memBusBusy = m_memory_control_profilers[(*it).c_str()] -> m_memBusBusy;
+    long long int m_memTfawBusy = m_memory_control_profilers[(*it).c_str()] -> m_memTfawBusy;
+    long long int m_memReadWriteBusy = m_memory_control_profilers[(*it).c_str()] -> m_memReadWriteBusy;
+    long long int m_memDataBusBusy = m_memory_control_profilers[(*it).c_str()] -> m_memDataBusBusy;
+    Vector<long long int> m_memBankCount = m_memory_control_profilers[(*it).c_str()] -> m_memBankCount;
+
+    if (m_memReq || m_memRefresh) {    // if there's a memory controller at all
+      long long int total_stalls = m_memInputQ + m_memBankQ + m_memWaitCycles;
+      double stallsPerReq = total_stalls * 1.0 / m_memReq;
+      out << "Memory control:" << endl;
+      out << "  memory_total_requests: " << m_memReq << endl;  // does not include refreshes
+      out << "  memory_reads: " << m_memRead << endl;
+      out << "  memory_writes: " << m_memWrite << endl;
+      out << "  memory_refreshes: " << m_memRefresh << endl;
+      out << "  memory_total_request_delays: " << total_stalls << endl;
+      out << "  memory_delays_per_request: " << stallsPerReq << endl;
+      out << "  memory_delays_in_input_queue: " << m_memInputQ << endl;
+      out << "  memory_delays_behind_head_of_bank_queue: " << m_memBankQ << endl;
+      out << "  memory_delays_stalled_at_head_of_bank_queue: " << m_memWaitCycles << endl;
+      // Note:  The following "memory stalls" entries are a breakdown of the
+      // cycles which already showed up in m_memWaitCycles.  The order is
+      // significant; it is the priority of attributing the cycles.
+      // For example, bank_busy is before arbitration because if the bank was
+      // busy, we didn't even check arbitration.
+      // Note:  "not old enough" means that since we grouped waiting heads-of-queues
+      // into batches to avoid starvation, a request in a newer batch
+      // didn't try to arbitrate yet because there are older requests waiting.
+      out << "  memory_stalls_for_bank_busy: " << m_memBankBusy << endl;
+      out << "  memory_stalls_for_random_busy: " << m_memRandBusy << endl;
+      out << "  memory_stalls_for_anti_starvation: " << m_memNotOld << endl;
+      out << "  memory_stalls_for_arbitration: " << m_memArbWait << endl;
+      out << "  memory_stalls_for_bus: " << m_memBusBusy << endl;
+      out << "  memory_stalls_for_tfaw: " << m_memTfawBusy << endl;
+      out << "  memory_stalls_for_read_write_turnaround: " << m_memReadWriteBusy << endl;
+      out << "  memory_stalls_for_read_read_turnaround: " << m_memDataBusBusy << endl;
+      out << "  accesses_per_bank: ";
+      for (int bank=0; bank < m_memBankCount.size(); bank++) {
+        out << m_memBankCount[bank] << "  ";
+        //if ((bank % 8) == 7) out << "                     " << endl;
+      }
+      out << endl;
+      out << endl;
     }
-    out << endl;
-    out << endl;
   }
-
   if (!short_stats) {
     out << "Busy Controller Counts:" << endl;
     for(int i=0; i < MachineType_NUM; i++) {
     out << "miss_latency: " << m_allMissLatencyHistogram << endl;
     for(int i=0; i<m_missLatencyHistograms.size(); i++) {
       if (m_missLatencyHistograms[i].size() > 0) {
-        out << "miss_latency_" << CacheRequestType(i) << ": " << m_missLatencyHistograms[i] << endl;
+        out << "miss_latency_" << RubyRequestType(i) << ": " << m_missLatencyHistograms[i] << endl;
       }
     }
     for(int i=0; i<m_machLatencyHistograms.size(); i++) {
 
     out << "filter_action: " << m_filter_action_histogram << endl;
 
-    if (!PROFILE_ALL_INSTRUCTIONS) {
+    if (!m_all_instructions) {
       m_address_profiler_ptr->printStats(out);
     }
 
-    if (PROFILE_ALL_INSTRUCTIONS) {
+    if (m_all_instructions) {
       m_inst_profiler_ptr->printStats(out);
     }
 
 
   m_ruby_start = g_eventQueue_ptr->getTime();
 
-  m_instructions_executed_at_start.setSize(RubyConfig::numberOfProcessors());
-  m_cycles_executed_at_start.setSize(RubyConfig::numberOfProcessors());
-  for (int i=0; i < RubyConfig::numberOfProcessors(); i++) {
+  m_instructions_executed_at_start.setSize(RubySystem::getNumberOfSequencers());
+  m_cycles_executed_at_start.setSize(RubySystem::getNumberOfSequencers());
+  for (int i=0; i < RubySystem::getNumberOfSequencers(); i++) {
     if (g_system_ptr == NULL) {
       m_instructions_executed_at_start[i] = 0;
       m_cycles_executed_at_start[i] = 0;
     } else {
-      m_instructions_executed_at_start[i] = g_system_ptr->getDriver()->getInstructionCount(i);
-      m_cycles_executed_at_start[i] = g_system_ptr->getDriver()->getCycleCount(i);
+      m_instructions_executed_at_start[i] = g_system_ptr->getInstructionCount(i);
+      m_cycles_executed_at_start[i] = g_system_ptr->getCycleCount(i);
     }
   }
 
-  m_perProcTotalMisses.setSize(RubyConfig::numberOfProcessors());
-  m_perProcUserMisses.setSize(RubyConfig::numberOfProcessors());
-  m_perProcSupervisorMisses.setSize(RubyConfig::numberOfProcessors());
-  m_perProcStartTransaction.setSize(RubyConfig::numberOfProcessors());
-  m_perProcEndTransaction.setSize(RubyConfig::numberOfProcessors());
+  m_perProcTotalMisses.setSize(RubySystem::getNumberOfSequencers());
+  m_perProcUserMisses.setSize(RubySystem::getNumberOfSequencers());
+  m_perProcSupervisorMisses.setSize(RubySystem::getNumberOfSequencers());
+  m_perProcStartTransaction.setSize(RubySystem::getNumberOfSequencers());
+  m_perProcEndTransaction.setSize(RubySystem::getNumberOfSequencers());
 
-  for(int i=0; i < RubyConfig::numberOfProcessors(); i++) {
+  for(int i=0; i < RubySystem::getNumberOfSequencers(); i++) {
     m_perProcTotalMisses[i] = 0;
     m_perProcUserMisses[i] = 0;
     m_perProcSupervisorMisses[i] = 0;
 
   m_delayedCyclesHistogram.clear();
   m_delayedCyclesNonPFHistogram.clear();
-  m_delayedCyclesVCHistograms.setSize(NUMBER_OF_VIRTUAL_NETWORKS);
-  for (int i = 0; i < NUMBER_OF_VIRTUAL_NETWORKS; i++) {
+  m_delayedCyclesVCHistograms.setSize(RubySystem::getNetwork()->getNumberOfVirtualNetworks());
+  for (int i = 0; i < RubySystem::getNetwork()->getNumberOfVirtualNetworks(); i++) {
     m_delayedCyclesVCHistograms[i].clear();
   }
 
   m_L2_cache_profiler_ptr->clearStats();
 
   // for MemoryControl:
+/*
   m_memReq = 0;
   m_memBankBusy = 0;
   m_memBusBusy = 0;
   for (int bank=0; bank < m_memBankCount.size(); bank++) {
     m_memBankCount[bank] = 0;
   }
-
+*/
+//added by SS
+  vector<string>::iterator it;
+
+  for ( it=m_memory_control_names.begin() ; it < m_memory_control_names.end(); it++ ){
+    m_memory_control_profilers[(*it).c_str()] -> m_memReq = 0;
+    m_memory_control_profilers[(*it).c_str()] -> m_memBankBusy = 0;
+    m_memory_control_profilers[(*it).c_str()] -> m_memBusBusy = 0;
+    m_memory_control_profilers[(*it).c_str()] -> m_memTfawBusy = 0;
+    m_memory_control_profilers[(*it).c_str()] -> m_memReadWriteBusy = 0;
+    m_memory_control_profilers[(*it).c_str()] -> m_memDataBusBusy = 0;
+    m_memory_control_profilers[(*it).c_str()] -> m_memRefresh = 0;
+    m_memory_control_profilers[(*it).c_str()] -> m_memRead = 0;
+    m_memory_control_profilers[(*it).c_str()] -> m_memWrite = 0;
+    m_memory_control_profilers[(*it).c_str()] -> m_memWaitCycles = 0;
+    m_memory_control_profilers[(*it).c_str()] -> m_memInputQ = 0;
+    m_memory_control_profilers[(*it).c_str()] -> m_memBankQ = 0;
+    m_memory_control_profilers[(*it).c_str()] -> m_memArbWait = 0;
+    m_memory_control_profilers[(*it).c_str()] -> m_memRandBusy = 0;
+    m_memory_control_profilers[(*it).c_str()] -> m_memNotOld = 0;
+
+    for (int bank=0; bank < m_memory_control_profilers[(*it).c_str()] -> m_memBankCount.size(); bank++) {
+        m_memory_control_profilers[(*it).c_str()] -> m_memBankCount[bank] = 0;
+    }
+  }
   // Flush the prefetches through the system - used so that there are no outstanding requests after stats are cleared
   //g_eventQueue_ptr->triggerAllEvents();
 
   assert(addr == line_address(addr));
   Time last_time = m_ruby_start;
   if (m_conflicting_map_ptr->exist(addr)) {
-    last_time = m_conflicting_map_ptr->lookup(addr);
+    Time last_time = m_conflicting_map_ptr->lookup(addr);
   }
   Time current_time = g_eventQueue_ptr->getTime();
   assert (current_time - last_time > 0);
     // Note: The following line should be commented out if you want to
     // use the special profiling that is part of the GS320 protocol
 
-    // NOTE: Unless PROFILE_HOT_LINES or PROFILE_ALL_INSTRUCTIONS are enabled, nothing will be profiled by the AddressProfiler
-    m_address_profiler_ptr->addTraceSample(msg.getAddress(), msg.getProgramCounter(), msg.getType(), msg.getAccessMode(), id, false);
+    // NOTE: Unless PROFILE_HOT_LINES or RubyConfig::getProfileAllInstructions() are enabled, nothing will be profiled by the AddressProfiler
+    m_address_profiler_ptr->addTraceSample(msg.getLineAddress(), msg.getProgramCounter(), msg.getType(), msg.getAccessMode(), id, false);
   }
 }
 
 }
 
 // non-zero cycle demand request
-void Profiler::missLatency(Time t, CacheRequestType type, GenericMachineType respondingMach)
+void Profiler::missLatency(Time t, RubyRequestType type)
 {
   m_allMissLatencyHistogram.add(t);
   m_missLatencyHistograms[type].add(t);
+  /*
   m_machLatencyHistograms[respondingMach].add(t);
   if(respondingMach == GenericMachineType_Directory || respondingMach == GenericMachineType_NUM) {
     m_L2MissLatencyHistogram.add(t);
   }
+  */
 }
 
 // non-zero cycle prefetch request
   }
 }
 
-void Profiler::profileTransition(const string& component, NodeID id, NodeID version, Address addr,
+void Profiler::profileTransition(const string& component, NodeID version, Address addr,
                                  const string& state, const string& event,
                                  const string& next_state, const string& note)
 {
       (g_eventQueue_ptr->getTime() >= g_debug_ptr->getDebugTime())) {
     (* debug_cout_ptr).flags(ios::right);
     (* debug_cout_ptr) << setw(TIME_SPACES) << g_eventQueue_ptr->getTime() << " ";
-    (* debug_cout_ptr) << setw(ID_SPACES) << id << " ";
     (* debug_cout_ptr) << setw(ID_SPACES) << version << " ";
     (* debug_cout_ptr) << setw(COMP_SPACES) << component;
     (* debug_cout_ptr) << setw(EVENT_SPACES) << event << " ";
-    for (int i=0; i < RubyConfig::numberOfProcessors(); i++) {
-
-      if (i == id) {
-        (* debug_cout_ptr).flags(ios::right);
-        (* debug_cout_ptr) << setw(STATE_SPACES) << state;
-        (* debug_cout_ptr) << ">";
-        (* debug_cout_ptr).flags(ios::left);
-        (* debug_cout_ptr) << setw(STATE_SPACES) << next_state;
-      } else {
-        // cout << setw(STATE_SPACES) << " " << " " << setw(STATE_SPACES) << " ";
-      }
-    }
+
+    (* debug_cout_ptr).flags(ios::right);
+    (* debug_cout_ptr) << setw(STATE_SPACES) << state;
+    (* debug_cout_ptr) << ">";
+    (* debug_cout_ptr).flags(ios::left);
+    (* debug_cout_ptr) << setw(STATE_SPACES) << next_state;
+
     (* debug_cout_ptr) << " " << addr << " " << note;
 
     (* debug_cout_ptr) << endl;
   m_explicit_training_mask.add(pred_set.count());
 }
 
-// For MemoryControl:
-void Profiler::profileMemReq(int bank) {
-  m_memReq++;
-  m_memBankCount[bank]++;
-}
-
-void Profiler::profileMemBankBusy() { m_memBankBusy++; }
-void Profiler::profileMemBusBusy() { m_memBusBusy++; }
-void Profiler::profileMemReadWriteBusy() { m_memReadWriteBusy++; }
-void Profiler::profileMemDataBusBusy() { m_memDataBusBusy++; }
-void Profiler::profileMemTfawBusy() { m_memTfawBusy++; }
-void Profiler::profileMemRefresh() { m_memRefresh++; }
-void Profiler::profileMemRead() { m_memRead++; }
-void Profiler::profileMemWrite() { m_memWrite++; }
-void Profiler::profileMemWaitCycles(int cycles) { m_memWaitCycles += cycles; }
-void Profiler::profileMemInputQ(int cycles) { m_memInputQ += cycles; }
-void Profiler::profileMemBankQ(int cycles) { m_memBankQ += cycles; }
-void Profiler::profileMemArbWait(int cycles) { m_memArbWait += cycles; }
-void Profiler::profileMemRandBusy() { m_memRandBusy++; }
-void Profiler::profileMemNotOld() { m_memNotOld++; }
-
 int64 Profiler::getTotalInstructionsExecuted() const
 {
   int64 sum = 1;     // Starting at 1 allows us to avoid division by zero
-  for(int i=0; i < RubyConfig::numberOfProcessors(); i++) {
-    sum += (g_system_ptr->getDriver()->getInstructionCount(i) - m_instructions_executed_at_start[i]);
+  for(int i=0; i < RubySystem::getNumberOfSequencers(); i++) {
+    sum += (g_system_ptr->getInstructionCount(i) - m_instructions_executed_at_start[i]);
   }
   return sum;
 }
   }
 }
 
+void Profiler::rubyWatch(int id){
+  int rn_g1 = 0;//SIMICS_get_register_number(id, "g1");
+  uint64 tr = 0;//SIMICS_read_register(id, rn_g1);
+    Address watch_address = Address(tr);
+    const int ID_SPACES = 3;
+    const int TIME_SPACES = 7;
+
+    (* debug_cout_ptr).flags(ios::right);
+    (* debug_cout_ptr) << setw(TIME_SPACES) << g_eventQueue_ptr->getTime() << " ";
+    (* debug_cout_ptr) << setw(ID_SPACES) << id << " "
+                       << "RUBY WATCH "
+                       << watch_address
+                       << endl;
+
+    if(!m_watch_address_list_ptr->exist(watch_address)){
+      m_watch_address_list_ptr->add(watch_address, 1);
+    }
+}
+
+bool Profiler::watchAddress(Address addr){
+    if (m_watch_address_list_ptr->exist(addr))
+      return true;
+    else
+      return false;
+}
+
+// For MemoryControl:
+void Profiler::profileMemReq(string name, int bank) {
+//  printf("name is %s", name.c_str());
+  assert(m_memory_control_profilers.count(name) == 1);
+  m_memory_control_profilers[name] -> m_memReq++;
+  m_memory_control_profilers[name] -> m_memBankCount[bank]++;
+}
+void Profiler::profileMemBankBusy(string name) {   assert(m_memory_control_profilers.count(name) == 1); m_memory_control_profilers[name] -> m_memBankBusy++; }
+void Profiler::profileMemBusBusy(string name) {   assert(m_memory_control_profilers.count(name) == 1); m_memory_control_profilers[name] -> m_memBusBusy++; }
+void Profiler::profileMemReadWriteBusy(string name) {   assert(m_memory_control_profilers.count(name) == 1); m_memory_control_profilers[name] -> m_memReadWriteBusy++; }
+void Profiler::profileMemDataBusBusy(string name) {   assert(m_memory_control_profilers.count(name) == 1); m_memory_control_profilers[name] -> m_memDataBusBusy++; }
+void Profiler::profileMemTfawBusy(string name) {   assert(m_memory_control_profilers.count(name) == 1); m_memory_control_profilers[name] -> m_memTfawBusy++; }
+void Profiler::profileMemRefresh(string name) {   assert(m_memory_control_profilers.count(name) == 1); m_memory_control_profilers[name] -> m_memRefresh++; }
+void Profiler::profileMemRead(string name) {   assert(m_memory_control_profilers.count(name) == 1); m_memory_control_profilers[name] -> m_memRead++; }
+void Profiler::profileMemWrite(string name) {   assert(m_memory_control_profilers.count(name) == 1); m_memory_control_profilers[name] -> m_memWrite++; }
+void Profiler::profileMemWaitCycles(string name, int cycles) {   assert(m_memory_control_profilers.count(name) == 1); m_memory_control_profilers[name] -> m_memWaitCycles += cycles; }
+void Profiler::profileMemInputQ(string name, int cycles) {   assert(m_memory_control_profilers.count(name) == 1); m_memory_control_profilers[name] -> m_memInputQ += cycles; }
+void Profiler::profileMemBankQ(string name, int cycles) {   assert(m_memory_control_profilers.count(name) == 1); m_memory_control_profilers[name] -> m_memBankQ += cycles; }
+void Profiler::profileMemArbWait(string name, int cycles) {   assert(m_memory_control_profilers.count(name) == 1); m_memory_control_profilers[name] -> m_memArbWait += cycles; }
+void Profiler::profileMemRandBusy(string name) {   assert(m_memory_control_profilers.count(name) == 1); m_memory_control_profilers[name] -> m_memRandBusy++; }
+void Profiler::profileMemNotOld(string name) {   assert(m_memory_control_profilers.count(name) == 1); m_memory_control_profilers[name] -> m_memNotOld++; }
+
 
 #ifndef PROFILER_H
 #define PROFILER_H
 
+#include "mem/ruby/libruby.hh"
+
 #include "mem/ruby/common/Global.hh"
 #include "mem/protocol/GenericMachineType.hh"
 #include "mem/ruby/config/RubyConfig.hh"
 #include "mem/ruby/common/Set.hh"
 #include "mem/protocol/CacheRequestType.hh"
 #include "mem/protocol/GenericRequestType.hh"
+#include "mem/ruby/system/MemoryControl.hh"
 
 class CacheMsg;
 class CacheProfiler;
 
 template <class KEY_TYPE, class VALUE_TYPE> class Map;
 
+struct memory_control_profiler {
+  long long int m_memReq;
+  long long int m_memBankBusy;
+  long long int m_memBusBusy;
+  long long int m_memTfawBusy;
+  long long int m_memReadWriteBusy;
+  long long int m_memDataBusBusy;
+  long long int m_memRefresh;
+  long long int m_memRead;
+  long long int m_memWrite;
+  long long int m_memWaitCycles;
+  long long int m_memInputQ;
+  long long int m_memBankQ;
+  long long int m_memArbWait;
+  long long int m_memRandBusy;
+  long long int m_memNotOld;
+  Vector<long long int> m_memBankCount;
+  int m_banks_per_rank;
+  int m_ranks_per_dimm;
+  int m_dimms_per_channel;
+};
+
+
 class Profiler : public Consumer {
 public:
-    // Constructors
-    Profiler();
-
-    // Destructor
-    ~Profiler();
-
-    // Public Methods
-    void wakeup();
-
-    void setPeriodicStatsFile(const string& filename);
-    void setPeriodicStatsInterval(integer_t period);
-
-    void printStats(ostream& out, bool short_stats=false);
-    void printShortStats(ostream& out) { printStats(out, true); }
-    void printTraceStats(ostream& out) const;
-    void clearStats();
-    void printConfig(ostream& out) const;
-    void printResourceUsage(ostream& out) const;
-
-    AddressProfiler* getAddressProfiler() { return m_address_profiler_ptr; }
-    AddressProfiler* getInstructionProfiler() { return m_inst_profiler_ptr; }
-
-    void addPrimaryStatSample(const CacheMsg& msg, NodeID id);
-    void addSecondaryStatSample(GenericRequestType requestType,
-                                AccessModeType type, int msgSize,
-                                PrefetchBit pfBit, NodeID id);
-    void addSecondaryStatSample(CacheRequestType requestType,
-                                AccessModeType type, int msgSize,
-                                PrefetchBit pfBit, NodeID id);
-    void addAddressTraceSample(const CacheMsg& msg, NodeID id);
-
-    void profileRequest(const string& requestStr);
-    void profileSharing(const Address& addr, AccessType type,
-                        NodeID requestor, const Set& sharers,
-                        const Set& owner);
-
-    void profileMulticastRetry(const Address& addr, int count);
-
-    void profileFilterAction(int action);
-
-    void profileConflictingRequests(const Address& addr);
-    void profileOutstandingRequest(int outstanding) {
-        m_outstanding_requests.add(outstanding);
-    }
-
-    void profileOutstandingPersistentRequest(int outstanding) {
-        m_outstanding_persistent_requests.add(outstanding);
-    }
-    void profileAverageLatencyEstimate(int latency) {
-        m_average_latency_estimate.add(latency);
-    }
-
-    void countBAUnicast() { m_num_BA_unicasts++; }
-    void countBABroadcast() { m_num_BA_broadcasts++; }
-
-    void recordPrediction(bool wasGood, bool wasPredicted);
-
-    void startTransaction(int cpu);
-    void endTransaction(int cpu);
-    void profilePFWait(Time waitTime);
-
-    void controllerBusy(MachineID machID);
-    void bankBusy();
-    void missLatency(Time t, CacheRequestType type,
-                     GenericMachineType respondingMach);
-    void swPrefetchLatency(Time t, CacheRequestType type,
-                           GenericMachineType respondingMach);
-    void stopTableUsageSample(int num) { m_stopTableProfile.add(num); }
-    void L1tbeUsageSample(int num) { m_L1tbeProfile.add(num); }
-    void L2tbeUsageSample(int num) { m_L2tbeProfile.add(num); }
-    void sequencerRequests(int num) { m_sequencer_requests.add(num); }
-    void storeBuffer(int size, int blocks) {
-        m_store_buffer_size.add(size);
-        m_store_buffer_blocks.add(blocks);
-    }
-
-    void profileGetXMaskPrediction(const Set& pred_set);
-    void profileGetSMaskPrediction(const Set& pred_set);
-    void profileTrainingMask(const Set& pred_set);
-    void profileTransition(const string& component, NodeID id, NodeID version,
-                           Address addr, const string& state,
-                           const string& event, const string& next_state,
-                           const string& note);
-    void profileMsgDelay(int virtualNetwork, int delayCycles);
-
-    void print(ostream& out) const;
-
-    int64 getTotalInstructionsExecuted() const;
-    int64 getTotalTransactionsExecuted() const;
-
-    Time getRubyStartTime(){
-      return m_ruby_start;
-    }
-
-    // added for MemoryControl:
-    void profileMemReq(int bank);
-    void profileMemBankBusy();
-    void profileMemBusBusy();
-    void profileMemTfawBusy();
-    void profileMemReadWriteBusy();
-    void profileMemDataBusBusy();
-    void profileMemRefresh();
-    void profileMemRead();
-    void profileMemWrite();
-    void profileMemWaitCycles(int cycles);
-    void profileMemInputQ(int cycles);
-    void profileMemBankQ(int cycles);
-    void profileMemArbWait(int cycles);
-    void profileMemRandBusy();
-    void profileMemNotOld();
+  // Constructors
+  Profiler(const string & name);
+
+  void init(const vector<string> & argv, vector<string> memory_control_names);
+
+  // Destructor
+  ~Profiler();
+
+  // Public Methods
+  void wakeup();
+
+  void setPeriodicStatsFile(const string& filename);
+  void setPeriodicStatsInterval(integer_t period);
+
+  void printStats(ostream& out, bool short_stats=false);
+  void printShortStats(ostream& out) { printStats(out, true); }
+  void printTraceStats(ostream& out) const;
+  void clearStats();
+  void printConfig(ostream& out) const;
+  void printResourceUsage(ostream& out) const;
+
+  AddressProfiler* getAddressProfiler() { return m_address_profiler_ptr; }
+  AddressProfiler* getInstructionProfiler() { return m_inst_profiler_ptr; }
+
+  void addPrimaryStatSample(const CacheMsg& msg, NodeID id);
+  void addSecondaryStatSample(GenericRequestType requestType, AccessModeType type, int msgSize, PrefetchBit pfBit, NodeID id);
+  void addSecondaryStatSample(CacheRequestType requestType, AccessModeType type, int msgSize, PrefetchBit pfBit, NodeID id);
+  void addAddressTraceSample(const CacheMsg& msg, NodeID id);
+
+  void profileRequest(const string& requestStr);
+  void profileSharing(const Address& addr, AccessType type, NodeID requestor, const Set& sharers, const Set& owner);
+
+  void profileMulticastRetry(const Address& addr, int count);
+
+  void profileFilterAction(int action);
+
+  void profileConflictingRequests(const Address& addr);
+  void profileOutstandingRequest(int outstanding) { m_outstanding_requests.add(outstanding); }
+  void profileOutstandingPersistentRequest(int outstanding) { m_outstanding_persistent_requests.add(outstanding); }
+  void profileAverageLatencyEstimate(int latency) { m_average_latency_estimate.add(latency); }
+
+  void countBAUnicast() { m_num_BA_unicasts++; }
+  void countBABroadcast() { m_num_BA_broadcasts++; }
+
+  void recordPrediction(bool wasGood, bool wasPredicted);
+
+  void startTransaction(int cpu);
+  void endTransaction(int cpu);
+  void profilePFWait(Time waitTime);
+
+  void controllerBusy(MachineID machID);
+  void bankBusy();
+  void missLatency(Time t, RubyRequestType type);
+  void swPrefetchLatency(Time t, CacheRequestType type, GenericMachineType respondingMach);
+  void stopTableUsageSample(int num) { m_stopTableProfile.add(num); }
+  void L1tbeUsageSample(int num) { m_L1tbeProfile.add(num); }
+  void L2tbeUsageSample(int num) { m_L2tbeProfile.add(num); }
+  void sequencerRequests(int num) { m_sequencer_requests.add(num); }
+  void storeBuffer(int size, int blocks) { m_store_buffer_size.add(size); m_store_buffer_blocks.add(blocks);}
+
+  void profileGetXMaskPrediction(const Set& pred_set);
+  void profileGetSMaskPrediction(const Set& pred_set);
+  void profileTrainingMask(const Set& pred_set);
+  void profileTransition(const string& component, NodeID version, Address addr,
+                         const string& state, const string& event,
+                         const string& next_state, const string& note);
+  void profileMsgDelay(int virtualNetwork, int delayCycles);
+
+  void print(ostream& out) const;
+
+  int64 getTotalInstructionsExecuted() const;
+  int64 getTotalTransactionsExecuted() const;
+
+  void rubyWatch(int proc);
+  bool watchAddress(Address addr);
+
+  // return Ruby's start time
+  Time getRubyStartTime(){
+    return m_ruby_start;
+  }
+
+  // added for MemoryControl:
+  void profileMemReq(string name, int bank);
+  void profileMemBankBusy(string name);
+  void profileMemBusBusy(string name);
+  void profileMemTfawBusy(string name);
+  void profileMemReadWriteBusy(string name);
+  void profileMemDataBusBusy(string name);
+  void profileMemRefresh(string name);
+  void profileMemRead(string name);
+  void profileMemWrite(string name);
+  void profileMemWaitCycles(string name, int cycles);
+  void profileMemInputQ(string name, int cycles);
+  void profileMemBankQ(string name, int cycles);
+  void profileMemArbWait(string name, int cycles);
+  void profileMemRandBusy(string name);
+  void profileMemNotOld(string name);
+  //added by SS
+  bool getHotLines() { return m_hot_lines; }
+  bool getAllInstructions() { return m_all_instructions; }
 
 private:
-    // Private Methods
-    void addL2StatSample(GenericRequestType requestType, AccessModeType type,
-                         int msgSize, PrefetchBit pfBit, NodeID id);
-    void addL1DStatSample(const CacheMsg& msg, NodeID id);
-    void addL1IStatSample(const CacheMsg& msg, NodeID id);
-
-    GenericRequestType CacheRequestType_to_GenericRequestType(const CacheRequestType& type);
-
-    // Private copy constructor and assignment operator
-    Profiler(const Profiler& obj);
-    Profiler& operator=(const Profiler& obj);
-
-    // Data Members (m_ prefix)
-    CacheProfiler* m_L1D_cache_profiler_ptr;
-    CacheProfiler* m_L1I_cache_profiler_ptr;
-    CacheProfiler* m_L2_cache_profiler_ptr;
-    AddressProfiler* m_address_profiler_ptr;
-    AddressProfiler* m_inst_profiler_ptr;
-
-    Vector<int64> m_instructions_executed_at_start;
-    Vector<int64> m_cycles_executed_at_start;
-
-    ostream* m_periodic_output_file_ptr;
-    integer_t m_stats_period;
-
-    Time m_ruby_start;
-    time_t m_real_time_start_time;
-
-    int m_num_BA_unicasts;
-    int m_num_BA_broadcasts;
-
-    Vector<integer_t> m_perProcTotalMisses;
-    Vector<integer_t> m_perProcUserMisses;
-    Vector<integer_t> m_perProcSupervisorMisses;
-    Vector<integer_t> m_perProcStartTransaction;
-    Vector<integer_t> m_perProcEndTransaction;
-    Vector < Vector < integer_t > > m_busyControllerCount;
-    integer_t m_busyBankCount;
-    Histogram m_multicast_retry_histogram;
-
-    Histogram m_L1tbeProfile;
-    Histogram m_L2tbeProfile;
-    Histogram m_stopTableProfile;
-
-    Histogram m_filter_action_histogram;
-    Histogram m_tbeProfile;
-
-    Histogram m_sequencer_requests;
-    Histogram m_store_buffer_size;
-    Histogram m_store_buffer_blocks;
-    Histogram m_read_sharing_histogram;
-    Histogram m_write_sharing_histogram;
-    Histogram m_all_sharing_histogram;
-    int64 m_cache_to_cache;
-    int64 m_memory_to_cache;
-
-    Histogram m_prefetchWaitHistogram;
-
-    Vector<Histogram> m_missLatencyHistograms;
-    Vector<Histogram> m_machLatencyHistograms;
-    Histogram m_L2MissLatencyHistogram;
-    Histogram m_allMissLatencyHistogram;
-
-    Histogram  m_allSWPrefetchLatencyHistogram;
-    Histogram  m_SWPrefetchL2MissLatencyHistogram;
-    Vector<Histogram> m_SWPrefetchLatencyHistograms;
-    Vector<Histogram> m_SWPrefetchMachLatencyHistograms;
-
-    Histogram m_delayedCyclesHistogram;
-    Histogram m_delayedCyclesNonPFHistogram;
-    Vector<Histogram> m_delayedCyclesVCHistograms;
-
-    int m_predictions;
-    int m_predictionOpportunities;
-    int m_goodPredictions;
-
-    Histogram m_gets_mask_prediction;
-    Histogram m_getx_mask_prediction;
-    Histogram m_explicit_training_mask;
-
-    // For profiling possibly conflicting requests
-    Map<Address, Time>* m_conflicting_map_ptr;
-    Histogram m_conflicting_histogram;
-
-    Histogram m_outstanding_requests;
-    Histogram m_outstanding_persistent_requests;
-
-    Histogram m_average_latency_estimate;
-
-    Map<Address, int>* m_watch_address_list_ptr;
-    // counts all initiated cache request including PUTs
-    int m_requests;
-    Map <string, int>* m_requestProfileMap_ptr;
-
-    // added for MemoryControl:
-    long long int m_memReq;
-    long long int m_memBankBusy;
-    long long int m_memBusBusy;
-    long long int m_memTfawBusy;
-    long long int m_memReadWriteBusy;
-    long long int m_memDataBusBusy;
-    long long int m_memRefresh;
-    long long int m_memRead;
-    long long int m_memWrite;
-    long long int m_memWaitCycles;
-    long long int m_memInputQ;
-    long long int m_memBankQ;
-    long long int m_memArbWait;
-    long long int m_memRandBusy;
-    long long int m_memNotOld;
-    Vector<long long int> m_memBankCount;
+  //added by SS
+  vector<string> m_memory_control_names;
+  // Private Methods
+  void addL2StatSample(GenericRequestType requestType, AccessModeType type, int msgSize, PrefetchBit pfBit, NodeID id);
+  void addL1DStatSample(const CacheMsg& msg, NodeID id);
+  void addL1IStatSample(const CacheMsg& msg, NodeID id);
+
+  GenericRequestType CacheRequestType_to_GenericRequestType(const CacheRequestType& type);
+
+  // Private copy constructor and assignment operator
+  Profiler(const Profiler& obj);
+  Profiler& operator=(const Profiler& obj);
+
+  // Data Members (m_ prefix)
+  CacheProfiler* m_L1D_cache_profiler_ptr;
+  CacheProfiler* m_L1I_cache_profiler_ptr;
+  CacheProfiler* m_L2_cache_profiler_ptr;
+  AddressProfiler* m_address_profiler_ptr;
+  AddressProfiler* m_inst_profiler_ptr;
+
+  Vector<int64> m_instructions_executed_at_start;
+  Vector<int64> m_cycles_executed_at_start;
+
+  ostream* m_periodic_output_file_ptr;
+  integer_t m_stats_period;
+
+  Time m_ruby_start;
+  time_t m_real_time_start_time;
+
+  int m_num_BA_unicasts;
+  int m_num_BA_broadcasts;
+
+  Vector<integer_t> m_perProcTotalMisses;
+  Vector<integer_t> m_perProcUserMisses;
+  Vector<integer_t> m_perProcSupervisorMisses;
+  Vector<integer_t> m_perProcStartTransaction;
+  Vector<integer_t> m_perProcEndTransaction;
+  Vector < Vector < integer_t > > m_busyControllerCount;
+  integer_t m_busyBankCount;
+  Histogram m_multicast_retry_histogram;
+
+  Histogram m_L1tbeProfile;
+  Histogram m_L2tbeProfile;
+  Histogram m_stopTableProfile;
+
+  Histogram m_filter_action_histogram;
+  Histogram m_tbeProfile;
+
+  Histogram m_sequencer_requests;
+  Histogram m_store_buffer_size;
+  Histogram m_store_buffer_blocks;
+  Histogram m_read_sharing_histogram;
+  Histogram m_write_sharing_histogram;
+  Histogram m_all_sharing_histogram;
+  int64 m_cache_to_cache;
+  int64 m_memory_to_cache;
+
+  Histogram m_prefetchWaitHistogram;
+
+  Vector<Histogram> m_missLatencyHistograms;
+  Vector<Histogram> m_machLatencyHistograms;
+  Histogram m_L2MissLatencyHistogram;
+  Histogram m_allMissLatencyHistogram;
+
+  Histogram  m_allSWPrefetchLatencyHistogram;
+  Histogram  m_SWPrefetchL2MissLatencyHistogram;
+  Vector<Histogram> m_SWPrefetchLatencyHistograms;
+  Vector<Histogram> m_SWPrefetchMachLatencyHistograms;
+
+  Histogram m_delayedCyclesHistogram;
+  Histogram m_delayedCyclesNonPFHistogram;
+  Vector<Histogram> m_delayedCyclesVCHistograms;
+
+  int m_predictions;
+  int m_predictionOpportunities;
+  int m_goodPredictions;
+
+  Histogram m_gets_mask_prediction;
+  Histogram m_getx_mask_prediction;
+  Histogram m_explicit_training_mask;
+
+  // For profiling possibly conflicting requests
+  Map<Address, Time>* m_conflicting_map_ptr;
+  Histogram m_conflicting_histogram;
+
+  Histogram m_outstanding_requests;
+  Histogram m_outstanding_persistent_requests;
+
+  Histogram m_average_latency_estimate;
+
+  Map<Address, int>* m_watch_address_list_ptr;
+  // counts all initiated cache request including PUTs
+  int m_requests;
+  Map <string, int>* m_requestProfileMap_ptr;
+
+  // added for MemoryControl:
+  //added by SS
+  map< string, memory_control_profiler* > m_memory_control_profilers;
+
+  //added by SS
+  bool m_hot_lines;
+  bool m_all_instructions;
+  string m_name;
 
 };
 
 extern inline
 ostream& operator<<(ostream& out, const Profiler& obj)
 {
-    obj.print(out);
-    out << flush;
-    return out;
+  obj.print(out);
+  out << flush;
+  return out;
 }
 
 #endif //PROFILER_H
 
 #include "mem/ruby/recorder/TraceRecord.hh"
 #include "mem/ruby/eventqueue/RubyEventQueue.hh"
 #include "mem/gems_common/PrioHeap.hh"
+#include "gzstream.hh"
 
 CacheRecorder::CacheRecorder()
 {
-  std::cout << __FILE__ << "(" << __LINE__ << "): Not implemented" << std::endl;
-  // m_records_ptr = new PrioHeap<TraceRecord>;
+  m_records_ptr = new PrioHeap<TraceRecord>;
 }
 
 CacheRecorder::~CacheRecorder()
 {
-  std::cout << __FILE__ << "(" << __LINE__ << "): Not implemented" << std::endl;
-  // delete m_records_ptr;
+  delete m_records_ptr;
 }
 
-void CacheRecorder::addRecord(NodeID id, const Address& data_addr, const Address& pc_addr, CacheRequestType type, Time time)
+void CacheRecorder::addRecord(const string & sequencer_name, const Address& data_addr, const Address& pc_addr, RubyRequestType type, Time time)
 {
-  std::cout << __FILE__ << "(" << __LINE__ << "): Not implemented" << std::endl;
-  // m_records_ptr->insert(TraceRecord(id, data_addr, pc_addr, type, time));
+  m_records_ptr->insert(TraceRecord(sequencer_name, data_addr, pc_addr, type, time));
 }
 
 int CacheRecorder::dumpRecords(string filename)
 {
-  std::cout << __FILE__ << "(" << __LINE__ << "): Not implemented" << std::endl;
-  // ogzstream out(filename.c_str());
-  // if (out.fail()) {
-  //   cout << "Error: error opening file '" << filename << "'" << endl;
-  //   return 0;
-  // }
+  ogzstream out(filename.c_str());
+  if (out.fail()) {
+    cout << "Error: error opening file '" << filename << "'" << endl;
+    return 0;
+  }
 
-  // int counter = 0;
-  // while (m_records_ptr->size() != 0) {
-  //   TraceRecord record = m_records_ptr->extractMin();
-  //   record.output(out);
-  //   counter++;
-  // }
-  // return counter;
+  int counter = 0;
+  while (m_records_ptr->size() != 0) {
+    TraceRecord record = m_records_ptr->extractMin();
+    record.output(out);
+    counter++;
+  }
+  return counter;
 }
 
 void CacheRecorder::print(ostream& out) const
 {
-  std::cout << __FILE__ << "(" << __LINE__ << "): Not implemented" << std::endl;
 }
 
 #ifndef CACHERECORDER_H
 #define CACHERECORDER_H
 
+#include "mem/ruby/libruby_internal.hh"
+
 #include "mem/ruby/common/Global.hh"
 #include "mem/ruby/system/NodeID.hh"
 #include "mem/protocol/CacheRequestType.hh"
   ~CacheRecorder();
 
   // Public Methods
-  void addRecord(NodeID id, const Address& data_addr, const Address& pc_addr, CacheRequestType type, Time time);
+  void addRecord(const string & sequencer_name, const Address& data_addr, const Address& pc_addr, RubyRequestType type, Time time);
   int dumpRecords(string filename);
 
   void print(ostream& out) const;
 
 #include "mem/ruby/recorder/TraceRecord.hh"
 #include "mem/ruby/system/Sequencer.hh"
 #include "mem/ruby/system/System.hh"
-#include "mem/ruby/slicc_interface/AbstractChip.hh"
 #include "mem/protocol/CacheMsg.hh"
-#include "mem/packet.hh"
 
-TraceRecord::TraceRecord(NodeID id, const Address& data_addr, const Address& pc_addr, CacheRequestType type, Time time)
+TraceRecord::TraceRecord(const string & sequencer_name, const Address& data_addr, const Address& pc_addr, RubyRequestType type, Time time)
 {
-  m_node_num = id;
+  m_sequencer_name = sequencer_name;
   m_data_address = data_addr;
   m_pc_address = pc_addr;
   m_time = time;
 
   // Don't differentiate between store misses and atomic requests in
   // the trace
-  if (m_type == CacheRequestType_ATOMIC) {
-    m_type = CacheRequestType_ST;
+  if (m_type == RubyRequestType_RMW) {
+    m_type = RubyRequestType_ST;
   }
 }
 
 
 TraceRecord& TraceRecord::operator=(const TraceRecord& obj)
 {
-  m_node_num = obj.m_node_num;
+  m_sequencer_name = obj.m_sequencer_name;
   m_time = obj.m_time;
   m_data_address = obj.m_data_address;
   m_pc_address = obj.m_pc_address;
 {
   // Lookup sequencer pointer from system
   // Note that the chip index also needs to take into account SMT configurations
-  AbstractChip* chip_ptr = g_system_ptr->getChip(m_node_num/RubyConfig::numberOfProcsPerChip()/RubyConfig::numberofSMTThreads());
-  assert(chip_ptr != NULL);
-  Sequencer* sequencer_ptr = chip_ptr->getSequencer((m_node_num/RubyConfig::numberofSMTThreads())%RubyConfig::numberOfProcsPerChip());
+  Sequencer* sequencer_ptr = RubySystem::getSequencer(m_sequencer_name);
   assert(sequencer_ptr != NULL);
 
-  Addr data_addr = m_data_address.getAddress();
-  Addr pc_addr = m_pc_address.getAddress();
-  Request request(0, data_addr, 0, Flags<unsigned int>(Request::PREFETCH), pc_addr, m_node_num, 0);
-  MemCmd::Command command;
-  if (m_type == CacheRequestType_LD || m_type == CacheRequestType_IFETCH)
-    command = MemCmd::ReadReq;
-  else if (m_type == CacheRequestType_ST)
-    command = MemCmd::WriteReq;
-  else if (m_type == CacheRequestType_ATOMIC)
-    command = MemCmd::SwapReq; // TODO -- differentiate between atomic types
-  else
-    assert(false);
-
-  Packet pkt(&request, command, 0); // TODO -- make dest a real NodeID
+  RubyRequest request(m_data_address.getAddress(), NULL, RubySystem::getBlockSizeBytes(), m_pc_address.getAddress(), m_type, RubyAccessMode_User);
 
   // Clear out the sequencer
   while (!sequencer_ptr->empty()) {
     g_eventQueue_ptr->triggerEvents(g_eventQueue_ptr->getTime() + 100);
   }
 
-  sequencer_ptr->makeRequest(&pkt);
+  sequencer_ptr->makeRequest(request);
 
   // Clear out the sequencer
   while (!sequencer_ptr->empty()) {
 
 void TraceRecord::print(ostream& out) const
 {
-  out << "[TraceRecord: Node, " << m_node_num << ", " << m_data_address << ", " << m_pc_address << ", " << m_type << ", Time: " << m_time << "]";
+  out << "[TraceRecord: Node, " << m_sequencer_name << ", " << m_data_address << ", " << m_pc_address << ", " << m_type << ", Time: " << m_time << "]";
 }
 
 void TraceRecord::output(ostream& out) const
 {
-  out << m_node_num << " ";
+  out << m_sequencer_name << " ";
   m_data_address.output(out);
   out << " ";
   m_pc_address.output(out);
 
 bool TraceRecord::input(istream& in)
 {
-  in >> m_node_num;
+  in >> m_sequencer_name;
   m_data_address.input(in);
   m_pc_address.input(in);
   string type;
   if (!in.eof()) {
     in >> type;
-    m_type = string_to_CacheRequestType(type);
+    m_type = string_to_RubyRequestType(type);
 
     // Ignore the rest of the line
     char c = '\0';
 
 #ifndef TRACERECORD_H
 #define TRACERECORD_H
 
+#include "mem/ruby/libruby_internal.hh"
+
 #include "mem/ruby/common/Global.hh"
 #include "mem/ruby/common/Address.hh"
 #include "mem/ruby/system/NodeID.hh"
-#include "mem/protocol/CacheRequestType.hh"
 class CacheMsg;
 
 class TraceRecord {
 public:
   // Constructors
-  TraceRecord(NodeID id, const Address& data_addr, const Address& pc_addr, CacheRequestType type, Time time);
-  TraceRecord() { m_node_num = 0; m_time = 0; m_type = CacheRequestType_NULL; }
+  TraceRecord(const string & sequencer_name, const Address& data_addr, const Address& pc_addr, RubyRequestType type, Time time);
+  TraceRecord() { m_sequencer_name = ""; m_time = 0; m_type = RubyRequestType_NULL; }
 
   // Destructor
   //  ~TraceRecord();
   // Private Methods
 
   // Data Members (m_ prefix)
-  NodeID m_node_num;
+  string m_sequencer_name;
   Time m_time;
   Address m_data_address;
   Address m_pc_address;
-  CacheRequestType m_type;
+  RubyRequestType m_type;
 };
 
 inline extern bool node_less_then_eq(const TraceRecord& n1, const TraceRecord& n2);
 
 #include "mem/ruby/eventqueue/RubyEventQueue.hh"
 #include "mem/gems_common/PrioHeap.hh"
 #include "mem/ruby/system/System.hh"
+#include "mem/ruby/config/RubyConfig.hh"
 
-Tracer::Tracer()
+//added by SS
+Tracer::Tracer(const string & name)
 {
+  m_name = name;
   m_enabled = false;
 }
 
+//commented by SS
+//Tracer::Tracer()
+//{
+//  m_enabled = false;
+//}
+
 Tracer::~Tracer()
 {
 }
 
+void Tracer::init(const vector<string> & argv)
+{
+  m_warmup_length = 0;
+
+  for (size_t i=0; i<argv.size(); i+=2) {
+    if ( argv[i] == "warmup_length") {
+      m_warmup_length = atoi(argv[i+1].c_str());
+    }
+    else {
+      cerr << "WARNING: Tracer: Unkown configuration parameter: " << argv[i] << endl;
+      assert(false);
+    }
+  }
+  assert(m_warmup_length  > 0);
+}
+
 void Tracer::startTrace(string filename)
 {
   if (m_enabled) {
   m_enabled = false;
 }
 
-void Tracer::traceRequest(NodeID id, const Address& data_addr, const Address& pc_addr, CacheRequestType type, Time time)
+void Tracer::traceRequest(const string & sequencer_name, const Address& data_addr, const Address& pc_addr, RubyRequestType type, Time time)
 {
   assert(m_enabled == true);
-  TraceRecord tr(id, data_addr, pc_addr, type, time);
+  TraceRecord tr(sequencer_name, data_addr, pc_addr, type, time);
   tr.output(m_trace_file);
 }
 
     ok = record.input(in);
 
     // Clear the statistics after warmup
-    if (counter == g_trace_warmup_length) {
-      cout << "Clearing stats after warmup of length " << g_trace_warmup_length << endl;
+/*    if (counter == RubyConfig::getTraceWarmupLength()) {
+      cout << "Clearing stats after warmup of length " << RubyConfig::getTraceWarmupLength() << endl;
       g_system_ptr->clearStats();
     }
+*/
+    if (counter == m_warmup_length) {
+      cout << "Clearing stats after warmup of length " << m_warmup_length << endl;
+      g_system_ptr->clearStats();
+    }
+
   }
 
   // Flush the prefetches through the system
 
 #ifndef TRACER_H
 #define TRACER_H
 
+#include "mem/ruby/libruby_internal.hh"
+
 #include "mem/ruby/common/Global.hh"
 #include "mem/ruby/system/NodeID.hh"
 #include "mem/protocol/CacheRequestType.hh"
 class Tracer {
 public:
   // Constructors
-  Tracer();
+//  Tracer();
+  Tracer(const string & name);
 
   // Destructor
   ~Tracer();
   void startTrace(string filename);
   void stopTrace();
   bool traceEnabled() { return m_enabled; }
-  void traceRequest(NodeID id, const Address& data_addr, const Address& pc_addr, CacheRequestType type, Time time);
+  void traceRequest(const string & sequencer_name, const Address& data_addr, const Address& pc_addr, RubyRequestType type, Time time);
 
   void print(ostream& out) const;
 
   // Public Class Methods
-  static int playbackTrace(string filename);
+  int playbackTrace(string filename);
+  void init(const vector<string> & argv);
 private:
   // Private Methods
 
   // Data Members (m_ prefix)
   ogzstream m_trace_file;
   bool m_enabled;
+
+  //added by SS
+  int m_warmup_length;
+  string m_name;
 };
 
 // Output operator declaration
 
 #include "mem/ruby/slicc_interface/AbstractCacheEntry.hh"
 
 AbstractCacheEntry::AbstractCacheEntry() {
+  m_Address.setAddress(0);
+  m_Permission = AccessPermission_NotPresent;
 }
 
 // still need to define destructor for subclasses
 
 #include "mem/ruby/common/Address.hh"
 #include "mem/protocol/AccessPermission.hh"
 
+class DataBlock;
+
 class AbstractCacheEntry {
 public:
   // Constructors
 
   // The methods below are those called by ruby runtime, add when it is
   // absolutely necessary and should all be virtual function.
+  virtual DataBlock& getDataBlk() = 0;
 
 
   virtual void print(ostream& out) const = 0;
 
+++ /dev/null
-
-/*
- * 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.
- */
-
-/*
- * $Id$
- *
- * Description: See AbstractChip.hh
- *
- */
-
-#include "mem/ruby/slicc_interface/AbstractChip.hh"
-
-AbstractChip::AbstractChip(NodeID id, Network* net_ptr) {
-  m_id = id;
-  m_net_ptr = net_ptr;
-  m_L1Cache_sequencer_vec.setSize(0);
-}
-
-// still need to be defined for subclasses
-AbstractChip::~AbstractChip() {
-}
 
+++ /dev/null
-
-/*
- * 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.
- */
-
-/*
- * $Id$
- *
- * Description: Common base class for a machine chip.
- *
- */
-
-#ifndef ABSTRACT_CHIP_H
-#define ABSTRACT_CHIP_H
-
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/system/NodeID.hh"
-#include "mem/ruby/config/RubyConfig.hh"
-#include "mem/protocol/L1Cache_Entry.hh"
-#include "mem/ruby/common/Address.hh"
-#include "mem/gems_common/Vector.hh"
-
-class Network;
-class Sequencer;
-class StoreBuffer;
-class ENTRY;
-class MessageBuffer;
-class CacheRecorder;
-class TransactionInterfaceManager;
-
-template<class ENTRY> class CacheMemory;
-
-class AbstractChip {
-public:
-  // Constructors
-  AbstractChip(NodeID chip_number, Network* net_ptr);
-
-  // Destructor, prevent from being instantiated
-  virtual ~AbstractChip() = 0;
-
-  // Public Methods
-  NodeID getID() const { return m_id; };
-  Network* getNetwork() const { return m_net_ptr; };
-  Sequencer* getSequencer(int index) const { return m_L1Cache_sequencer_vec[index]; };
-  TransactionInterfaceManager* getTransactionInterfaceManager(int index) const { return m_L1Cache_xact_mgr_vec[index]; };
-  void setTransactionInterfaceManager(TransactionInterfaceManager* manager, int index) { m_L1Cache_xact_mgr_vec[index] = manager; }
-
-  // used when CHECK_COHERENCE is enabled.  See RubySystem::checkGlobalCoherence()
-  virtual bool isBlockExclusive(const Address& addr) const { return false; }
-  virtual bool isBlockShared(const Address& addr) const { return false; }
-
-  // cache dump functions
-  virtual void recordCacheContents(CacheRecorder& tr) const = 0;
-  virtual void dumpCaches(ostream& out) const = 0;
-  virtual void dumpCacheData(ostream& out) const = 0;
-
-  virtual void printConfig(ostream& out) = 0;
-  virtual void print(ostream& out) const = 0;
-
-  // pulic data structures
-  Vector < CacheMemory<L1Cache_Entry>* > m_L1Cache_L1DcacheMemory_vec;
-  Vector < CacheMemory<L1Cache_Entry>* > m_L1Cache_L1IcacheMemory_vec;
-  Vector < CacheMemory<L1Cache_Entry>* > m_L1Cache_cacheMemory_vec;
-  Vector < CacheMemory<L1Cache_Entry>* > m_L1Cache_L2cacheMemory_vec;
-  Vector < CacheMemory<L1Cache_Entry>* > m_L2Cache_L2cacheMemory_vec;
-
-  // added so that the prefetcher and sequencer can access the L1 and L2 request queues
-  Vector < MessageBuffer* > m_L1Cache_optionalQueue_vec;
-  Vector < MessageBuffer* >m_L1Cache_mandatoryQueue_vec;
-
-  // TSO storebuffer
-  Vector < StoreBuffer* > m_L1Cache_storeBuffer_vec;
-
-  // TM transaction manager
-  Vector < TransactionInterfaceManager* >  m_L1Cache_xact_mgr_vec;
-
-protected:
-
-  // Data Members (m_ prefix)
-  NodeID                 m_id;            // Chip id
-  Network*               m_net_ptr;       // Points to the Network simulator
-  Vector < Sequencer* >  m_L1Cache_sequencer_vec; // All chip should have a sequencer
-
-
-};
-
-// Output operator declaration
-ostream& operator<<(ostream& out, const AbstractChip& obj);
-
-// ******************* Definitions *******************
-
-// Output operator definition
-extern inline
-ostream& operator<<(ostream& out, const AbstractChip& obj)
-{
-  obj.print(out);
-  out << flush;
-  return out;
-}
-
-#endif //ABSTRACT_CHIP_H
-
 
--- /dev/null
+
+#ifndef ABSTRACTCONTROLLER_H
+#define ABSTRACTCONTROLLER_H
+
+#include "mem/ruby/common/Consumer.hh"
+#include "mem/protocol/MachineType.hh"
+
+class MessageBuffer;
+class Network;
+
+class AbstractController : public Consumer {
+public:
+  AbstractController() {}
+  virtual void init(Network* net_ptr, const vector<string> & argv) = 0;
+
+  // returns the number of controllers created of the specific subtype
+  //  virtual int getNumberOfControllers() const = 0;
+  virtual MessageBuffer* getMandatoryQueue() const = 0;
+  virtual const int & getVersion() const = 0;
+  virtual const string toString() const = 0;  // returns text version of controller type
+  virtual const string getName() const = 0;   // return instance name
+  virtual const MachineType getMachineType() const = 0;
+
+  virtual void print(ostream & out) const = 0;
+  virtual void printStats(ostream & out) const = 0;
+  virtual void printConfig(ostream & out) const = 0;
+  virtual void wakeup() = 0;
+  //  virtual void dumpStats(ostream & out) = 0;
+  virtual void clearStats() = 0;
+
+};
+
+#endif
 
 #include "mem/ruby/common/Set.hh"
 #include "mem/ruby/common/NetDest.hh"
 #include "mem/protocol/GenericMachineType.hh"
+#include "mem/ruby/system/DirectoryMemory.hh"
 
 #ifdef MACHINETYPE_L1Cache
 #define MACHINETYPE_L1CACHE_ENUM MachineType_L1Cache
 #define MACHINETYPE_L3CACHE_ENUM MachineType_NUM
 #endif
 
+/*
 #ifdef MACHINETYPE_PersistentArbiter
 #define MACHINETYPE_PERSISTENTARBITER_ENUM MachineType_PersistentArbiter
 #else
 #define MACHINETYPE_PERSISTENTARBITER_ENUM MachineType_NUM
 #endif
-
-#ifdef MACHINETYPE_Collector
-#define MACHINETYPE_COLLECTOR_ENUM MachineType_Collector
-#else
-#define MACHINETYPE_COLLECTOR_ENUM MachineType_NUM
-#endif
-
-
-// used to determine the correct L1 set
-// input parameters are the address and number of set bits for the L1 cache
-// returns a value between 0 and the total number of L1 cache sets
-inline
-int map_address_to_L1CacheSet(const Address& addr, int cache_num_set_bits)
-{
-  return addr.bitSelect(RubyConfig::dataBlockBits(),
-                        RubyConfig::dataBlockBits()+cache_num_set_bits-1);
-}
-
-// used to determine the correct L2 set
-// input parameters are the address and number of set bits for the L2 cache
-// returns a value between 0 and the total number of L2 cache sets
-inline
-int map_address_to_L2CacheSet(const Address& addr, int cache_num_set_bits)
+*/
+/*
+inline MachineID map_Address_to_L2Cache(const Address & addr)
 {
-  assert(cache_num_set_bits == L2_CACHE_NUM_SETS_BITS);  // ensure the l2 bank mapping functions agree with l2 set bits
-
-  if (MAP_L2BANKS_TO_LOWEST_BITS) {
-    return addr.bitSelect(RubyConfig::dataBlockBits()+RubyConfig::L2CachePerChipBits(),
-                          RubyConfig::dataBlockBits()+RubyConfig::L2CachePerChipBits()+cache_num_set_bits-1);
-  } else {
-    return addr.bitSelect(RubyConfig::dataBlockBits(),
-                          RubyConfig::dataBlockBits()+cache_num_set_bits-1);
-  }
+  int L2bank = 0;
+  MachineID mach = {MACHINETYPE_L2CACHE_ENUM, 0};
+  L2bank = addr.bitSelect(RubySystem::getBlockSizeBits(),
+                          RubySystem::getBlockSizeBits() + RubyConfig::getNumberOfCachesPerLevel(2)-1);
+  mach.num = L2bank;
+  return mach;
 }
 
 // input parameter is the base ruby node of the L1 cache
 inline
 MachineID map_L1CacheMachId_to_L2Cache(const Address& addr, MachineID L1CacheMachId)
 {
+  return map_Address_to_L2Cache(addr);
+
   int L2bank = 0;
   MachineID mach = {MACHINETYPE_L2CACHE_ENUM, 0};
 
   if (RubyConfig::L2CachePerChipBits() > 0) {
-    if (MAP_L2BANKS_TO_LOWEST_BITS) {
-      L2bank = addr.bitSelect(RubyConfig::dataBlockBits(),
-                         RubyConfig::dataBlockBits()+RubyConfig::L2CachePerChipBits()-1);
+    if (RubyConfig::getMAP_L2BANKS_TO_LOWEST_BITS()) {
+      L2bank = addr.bitSelect(RubySystem::getBlockSizeBits(),
+                         RubySystem::getBlockSizeBits()+RubyConfig::L2CachePerChipBits()-1);
     } else {
-      L2bank = addr.bitSelect(RubyConfig::dataBlockBits()+L2_CACHE_NUM_SETS_BITS,
-                         RubyConfig::dataBlockBits()+L2_CACHE_NUM_SETS_BITS+RubyConfig::L2CachePerChipBits()-1);
+      L2bank = addr.bitSelect(RubySystem::getBlockSizeBits()+RubyConfig::getL2_CACHE_NUM_SETS_BITS(),
+                         RubySystem::getBlockSizeBits()+RubyConfig::getL2_CACHE_NUM_SETS_BITS()+RubyConfig::L2CachePerChipBits()-1);
     }
   }
 
     + L2bank;  // bank #
   assert(mach.num < RubyConfig::numberOfL2Cache());
   return mach;
+
 }
 
+
 // used to determine the correct L2 bank
 // input parameter is the base ruby node of the L2 cache
 // returns a value between 0 and total_L2_Caches_within_the_system
+
 inline
 MachineID map_L2ChipId_to_L2Cache(const Address& addr, NodeID L2ChipId)
 {
+  return map_Address_to_L2Cache(addr);
+
   assert(L2ChipId < RubyConfig::numberOfChips());
 
   int L2bank = 0;
   MachineID mach = {MACHINETYPE_L2CACHE_ENUM, 0};
+  L2bank = addr.bitSelect(RubySystem::getBlockSizeBits(),
+                          RubySystem::getBlockSizeBits() + RubyConfig::numberOfCachesPerLevel(2)-1);
+  mach.num = L2bank;
+  return mach
 
-  if (RubyConfig::L2CachePerChipBits() > 0) {
-    if (MAP_L2BANKS_TO_LOWEST_BITS) {
-      L2bank = addr.bitSelect(RubyConfig::dataBlockBits(),
-                         RubyConfig::dataBlockBits()+RubyConfig::L2CachePerChipBits()-1);
-    } else {
-      L2bank = addr.bitSelect(RubyConfig::dataBlockBits()+L2_CACHE_NUM_SETS_BITS,
-                         RubyConfig::dataBlockBits()+L2_CACHE_NUM_SETS_BITS+RubyConfig::L2CachePerChipBits()-1);
-    }
-  }
-
-  assert(L2bank < RubyConfig::numberOfL2CachePerChip());
-  assert(L2bank >= 0);
-
-  mach.num = L2ChipId*RubyConfig::numberOfL2CachePerChip() // base #
-    + L2bank; // bank #
-  assert(mach.num < RubyConfig::numberOfL2Cache());
-  return mach;
 }
+  */
+
 
 // used to determine the home directory
 // returns a value between 0 and total_directories_within_the_system
 inline
 NodeID map_Address_to_DirectoryNode(const Address& addr)
 {
-  NodeID dirNode = 0;
-
-  if (RubyConfig::memoryBits() > 0) {
-    dirNode = addr.bitSelect(RubyConfig::dataBlockBits(),
-                        RubyConfig::dataBlockBits()+RubyConfig::memoryBits()-1);
-  }
-
-  //  Index indexHighPortion = address.bitSelect(MEMORY_SIZE_BITS-1, PAGE_SIZE_BITS+NUMBER_OF_MEMORY_MODULE_BITS);
-  //  Index indexLowPortion  = address.bitSelect(DATA_BLOCK_BITS, PAGE_SIZE_BITS-1);
-
-  //Index index = indexLowPortion | (indexHighPortion << (PAGE_SIZE_BITS - DATA_BLOCK_BITS));
-
-/*
-
-ADDRESS_WIDTH    MEMORY_SIZE_BITS        PAGE_SIZE_BITS  DATA_BLOCK_BITS
-  |                    |                       |               |
- \ /                  \ /                     \ /             \ /       0
-  -----------------------------------------------------------------------
-  |       unused        |xxxxxxxxxxxxxxx|       |xxxxxxxxxxxxxxx|       |
-  |                     |xxxxxxxxxxxxxxx|       |xxxxxxxxxxxxxxx|       |
-  -----------------------------------------------------------------------
-                        indexHighPortion         indexLowPortion
-                                        <------->
-                               NUMBER_OF_MEMORY_MODULE_BITS
-  */
-
-  assert(dirNode < RubyConfig::numberOfMemories());
-  assert(dirNode >= 0);
-  return dirNode;
+  return DirectoryMemory::mapAddressToDirectoryVersion(addr);
 }
 
 // used to determine the home directory
 }
 
 inline
-MachineID map_Address_to_CentralArbiterNode(const Address& addr)
-{
-  MachineType t = MACHINETYPE_PERSISTENTARBITER_ENUM;
-  MachineID mach = {t, map_Address_to_DirectoryNode(addr)};
-
-  assert(mach.num < RubyConfig::numberOfMemories());
-  assert(mach.num >= 0);
-  return mach;
-}
-
-inline
-NetDest getMultiStaticL2BankNetDest(const Address& addr, const Set& sharers)  // set of L2RubyNodes
+MachineID map_Address_to_DMA(const Address & addr)
 {
-  NetDest dest;
-
-  for (int i = 0; i < sharers.getSize(); i++) {
-    if (sharers.isElement(i)) {
-      dest.add(map_L2ChipId_to_L2Cache(addr,i));
-    }
-  }
-  return dest;
+  MachineID dma = {MachineType_DMA, 0};
+  return dma;
 }
 
+/*
 inline
 NetDest getOtherLocalL1IDs(MachineID L1)
 {
 
   return ret;
 }
-
-inline
-NetDest getLocalL1IDs(MachineID mach)
-{
-  assert(MACHINETYPE_L1CACHE_ENUM != MachineType_NUM);
-
-  NetDest ret;
-
-  if (mach.type == MACHINETYPE_L1CACHE_ENUM) {
-
-    int start = (mach.num / RubyConfig::numberOfL1CachePerChip()) * RubyConfig::numberOfProcsPerChip();
-
-    for (int i = start; i < (start + RubyConfig::numberOfProcsPerChip()); i++) {
-      MachineID mach = { MACHINETYPE_L1CACHE_ENUM, i };
-      ret.add( mach );
-    }
-  }
-  else if (mach.type == MACHINETYPE_L2CACHE_ENUM) {
-
-    int chip = mach.num/RubyConfig::numberOfL2CachePerChip();
-    int start = ( chip*RubyConfig::numberOfL1CachePerChip());
-    for (int i = start; i < (start + RubyConfig::numberOfL1CachePerChip()); i++) {
-      MachineID mach = { MACHINETYPE_L1CACHE_ENUM, i };
-      ret.add( mach );
-    }
-  }
-
-  return ret;
-}
-
-inline
-NetDest getExternalL1IDs(MachineID L1)
-{
-  NetDest ret;
-
-  assert(MACHINETYPE_L1CACHE_ENUM != MachineType_NUM);
-
-  for (int i = 0; i < RubyConfig::numberOfProcessors(); i++) {
-    // ret.add( (NodeID) i);
-    MachineID mach = { MACHINETYPE_L1CACHE_ENUM, i };
-    ret.add( mach );
-  }
-
-  ret.removeNetDest(getLocalL1IDs(L1));
-
-  return ret;
-}
-
-inline
-bool isLocalProcessor(MachineID thisId, MachineID tarID)
-{
-  int start = (thisId.num / RubyConfig::numberOfProcsPerChip()) * RubyConfig::numberOfProcsPerChip();
-
-  for (int i = start; i < (start + RubyConfig::numberOfProcsPerChip()); i++) {
-    if (i == tarID.num) {
-      return true;
-    }
-  }
-  return false;
-}
-
-
-inline
-NetDest getAllPertinentL2Banks(const Address& addr)  // set of L2RubyNodes
-{
-  NetDest dest;
-
-  for (int i = 0; i < RubyConfig::numberOfChips(); i++) {
-    dest.add(map_L2ChipId_to_L2Cache(addr,i));
-  }
-  return dest;
-}
-
-inline
-bool isL1OnChip(MachineID L1machID, NodeID L2NodeID)
-{
-  if (L1machID.type == MACHINETYPE_L1CACHE_ENUM) {
-    return (L1machID.num == L2NodeID);
-  } else {
-    return false;
-  }
-}
-
-inline
-bool isL2OnChip(MachineID L2machID, NodeID L2NodeID)
-{
-  if (L2machID.type == MACHINETYPE_L2CACHE_ENUM) {
-    return (L2machID.num == L2NodeID);
-  } else {
-    return false;
-  }
-}
-
-inline
-NodeID closest_clockwise_distance(NodeID this_node, NodeID next_node)
-{
-  if (this_node <= next_node) {
-    return (next_node - this_node);
-  } else {
-    return (next_node - this_node + RubyConfig::numberOfChips());
-  }
-}
-
-inline
-bool closer_clockwise_processor(NodeID this_node, NodeID newer, NodeID older)
-{
-  return (closest_clockwise_distance(this_node, newer) < closest_clockwise_distance(this_node, older));
-}
-
-extern inline NodeID getChipID(MachineID L2machID)
-{
-  return (L2machID.num%RubyConfig::numberOfChips())/RubyConfig::numberOfProcsPerChip();
-}
+*/
 
 extern inline NodeID machineIDToNodeID(MachineID machID)
 {
   return machID.num;
 }
 
-extern inline NodeID machineIDToVersion(MachineID machID)
-{
-  return machID.num/RubyConfig::numberOfChips();
-}
-
 extern inline MachineType machineIDToMachineType(MachineID machID)
 {
   return machID.type;
   assert(machID.type == MachineType_L1Cache);
   return machID.num;
 }
-
+/*
 extern inline NodeID L2CacheMachIDToChipID(MachineID machID)
 {
   assert(machID.type == MACHINETYPE_L2CACHE_ENUM);
-  return machID.num/RubyConfig::numberOfL2CachePerChip();
-}
-
-extern inline MachineID getCollectorDest(MachineID L1MachID)
-{
-  MachineID mach = {MACHINETYPE_COLLECTOR_ENUM, L1MachID.num};
-  return mach;
-}
-
-extern inline MachineID getCollectorL1Cache(MachineID colID)
-{
-  MachineID mach = {MACHINETYPE_L1CACHE_ENUM, colID.num};
-  return mach;
+  int L2bank = machID.num;
+  int banks_seen = 0;
+  for (int i=0;i<RubyConfig::getNumberOfChips();i++) {
+    for (int j=0;j<RubyConfig::getNumberOfCachesPerLevelPerChip(2,i);j++) {
+      if (banks_seen == L2bank)
+        return i;
+      banks_seen++;
+    }
+  }
+  assert(0);
 }
-
+*/
 extern inline MachineID getL1MachineID(NodeID L1RubyNode)
 {
   MachineID mach = {MACHINETYPE_L1CACHE_ENUM, L1RubyNode};
     return GenericMachineType_L3Cache;
   } else if (machType == MachineType_Directory) {
     return GenericMachineType_Directory;
-  } else if (machType == MACHINETYPE_COLLECTOR_ENUM) {
-    return GenericMachineType_Collector;
   } else {
     ERROR_MSG("cannot convert to a GenericMachineType");
     return GenericMachineType_NULL;
 
   ASSERT (!Protocol::m_CMP);
   g_system_ptr->getProfiler()->addAddressTraceSample(msg, id);
 
-  g_system_ptr->getProfiler()->profileConflictingRequests(msg.getAddress());
+  g_system_ptr->getProfiler()->profileConflictingRequests(msg.getLineAddress());
 
   g_system_ptr->getProfiler()->addSecondaryStatSample(msg.getType(),
                                                       msg.getAccessMode(), msg.getSize(), msg.getPrefetch(), id);
 
 void profile_L1Cache_miss(const CacheMsg& msg, NodeID id)
 {
-  // only called by protocols assuming non-zero cycle hits
-  ASSERT (REMOVE_SINGLE_CYCLE_DCACHE_FAST_PATH);
-
   g_system_ptr->getProfiler()->addPrimaryStatSample(msg, id);
 }
 
   g_system_ptr->getProfiler()->getAddressProfiler()->profileGetS(datablock, PC, owner, sharers, requestor);
 }
 
-void profileOverflow(const Address & addr, MachineID mach)
-{
-#if 0
-  if(mach.type == MACHINETYPE_L1CACHE_ENUM){
-    // for L1 overflows
-    int proc_num = L1CacheMachIDToProcessorNum(mach);
-    int chip_num = proc_num/RubyConfig::numberOfProcsPerChip();
-    assert(0);
-    // g_system_ptr->getChip(chip_num)->m_L1Cache_xact_mgr_vec[proc_num]->profileOverflow(addr, true);
-  }
-  else if(mach.type == MACHINETYPE_L2CACHE_ENUM){
-    // for L2 overflows
-    int chip_num = L2CacheMachIDToChipID(mach);
-    for(int p=0; p < RubyConfig::numberOfProcessors(); ++p){
-      assert(0);
-      // g_system_ptr->getChip(chip_num)->m_L1Cache_xact_mgr_vec[p]->profileOverflow(addr, false);
-    }
-  }
-#endif
-}
 
 
 
 #include "mem/protocol/MessageSizeType.hh"
 #include "mem/ruby/network/Network.hh"
 #include "mem/protocol/PrefetchBit.hh"
+#include "mem/ruby/system/System.hh"
 
 #include "mem/ruby/slicc_interface/RubySlicc_ComponentMapping.hh"
 
 
 extern inline bool multicast_retry()
 {
-  if (RANDOMIZATION) {
+  if (RubySystem::getRandomization()) {
     return (random() & 0x1);
   } else {
     return true;
   return MessageSizeType_to_int(size_type);
 }
 
+/*
 extern inline int numberOfNodes()
 {
   return RubyConfig::numberOfChips();
 }
-
+*/
+/*
 extern inline int numberOfL1CachePerChip()
 {
-  return RubyConfig::numberOfL1CachePerChip();
+  return RubyConfig::getNumberOfCachesPerLevelPerChip(1,0);
 }
+*/
 
 extern inline bool long_enough_ago(Time event)
 {
 
 extern inline Time getPreviousDelayedCycles(Time t1, Time t2)
 {
-  if (RANDOMIZATION) {  // when randomizing delayed
+  if (RubySystem::getRandomization()) {  // when randomizing delayed
     return 0;
   } else {
     return getTimeMinusTime(t1, t2);
   return time;
 }
 
-
+/*
 extern inline bool getFilteringEnabled()
 {
-  return g_FILTERING_ENABLED;
+  return RubyConfig::getFilteringEnabled();
 }
 
+
 extern inline int getRetryThreshold()
 {
-  return g_RETRY_THRESHOLD;
+  return RubyConfig::getRetryThreshold();
 }
 
 extern inline int getFixedTimeoutLatency()
 {
-  return g_FIXED_TIMEOUT_LATENCY;
+  return RubyConfig::getFixedTimeoutLatency();
 }
 
 extern inline int N_tokens()
 {
   // return N+1 to handle clean writeback
-  return g_PROCS_PER_CHIP + 1;
+  return RubyConfig::getProcsPerChip() + 1;
   // return 1;
 }
 
 extern inline bool distributedPersistentEnabled()
 {
-  return g_DISTRIBUTED_PERSISTENT_ENABLED;
+  return RubyConfig::getDistributedPersistentEnabled();
 }
 
 extern inline bool getDynamicTimeoutEnabled()
 {
-  return g_DYNAMIC_TIMEOUT_ENABLED;
+  return RubyConfig::getDynamicTimeoutEnabled();
 }
-
+*/
 // Appends an offset to an address
 extern inline Address setOffset(Address addr, int offset)
 {
 
--- /dev/null
+/*
+ * 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.
+ */
+
+// this code was modified to fit into Rochs
+
+#ifndef _HFA_H_
+#define _HFA_H_
+
+using namespace std;
+
+/*
+ * Global include file for entire project.
+ * Should be included first in all ".cc" project files
+ */
+
+/*------------------------------------------------------------------------*/
+/* Includes                                                               */
+/*------------------------------------------------------------------------*/
+#include "mem/ruby/common/Global.hh"
+#include <string>
+#include <map>
+#include <set>
+#include <list>
+#include <fstream>
+#include <iostream>
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>             // va_start(), va_end()
+#include <strings.h>            // declaration of bzero()
+
+#include <sys/time.h>           // gettimeofday() includes
+#include <errno.h>
+#include <unistd.h>
+
+/*------------------------------------------------------------------------*/
+/* Type Includes                                                          */
+/*------------------------------------------------------------------------*/
+
+#include "mem/ruby/storebuffer/hfatypes.hh"
+
+/*------------------------------------------------------------------------*/
+/* Forward class declaration(s)                                           */
+/*------------------------------------------------------------------------*/
+
+class wait_list_t;
+class waiter_t;
+class free_list_t;
+class pipestate_t;
+class pipepool_t;
+
+
+/** Maximum size of a load or store that may occur to/from the memory system.
+ *  (in 64-bit quantities). Currently this is set to 8 * 64-bits = 64-bytes.
+ */
+const uint32 MEMOP_MAX_SIZE = 8;
+
+/** 64-bit int memory masks */
+#define MEM_BYTE_MASK 0x00000000000000ffULL
+#define MEM_HALF_MASK 0x000000000000ffffULL
+#define MEM_WORD_MASK 0x00000000ffffffffULL
+#define MEM_EXTD_MASK 0xffffffffffffffffULL
+#define MEM_QUAD_MASK 0xffffffffffffffffULL
+
+#define ISEQ_MASK     0x0000ffffffffffffULL
+
+/*------------------------------------------------------------------------*/
+/* Configuration Parameters                                               */
+/*------------------------------------------------------------------------*/
+
+#define  SIM_HALT  assert(0);
+
+#include <assert.h>
+
+#endif  /* _HFA_H_ */
+
+
 
--- /dev/null
+/*
+ * 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.
+ */
+
+#ifndef _HFATYPES_H_
+#define _HFATYPES_H_
+
+/*
+ * Global include file for entire project.
+ * Should be included first in all ".cc" project files
+ */
+
+/*------------------------------------------------------------------------*/
+/* Includes                                                               */
+/*------------------------------------------------------------------------*/
+/*------------------------------------------------------------------------*/
+/* SimIcs Includes                                                        */
+/*------------------------------------------------------------------------*/
+
+/* import C functions */
+
+
+/*------------------------------------------------------------------------*/
+/* Forward class declaration(s)                                           */
+/*------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------*/
+/* Macro declarations                                                     */
+/*------------------------------------------------------------------------*/
+
+// definitions of MAX / MIN (if needed)
+#ifndef MAX
+#define MAX(a, b)       ((a) > (b) ? (a) : (b))
+#endif
+
+#ifndef MIN
+#define MIN(a, b)       ((a) < (b) ? (a) : (b))
+#endif
+
+/* Statistics tracking definition */
+#define STAT_INC(A) (A)++
+
+/*------------------------------------------------------------------------*/
+/* Enumerations                                                           */
+/*------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------*/
+/* Project Includes                                                       */
+/*------------------------------------------------------------------------*/
+
+typedef unsigned char  byte_t;          /* byte - 8 bits */
+typedef unsigned short half_t;          /* half - 16 bits */
+typedef unsigned int   word_t;          /* word - 32 bits */
+typedef uint64         tick_t;          /* time - 64 bit */
+
+#endif  /* _HFATYPES_H_ */
 
--- /dev/null
+/*
+ * 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.
+ */
+
+#include "mem/ruby/libruby.hh"
+#include "writebuffer.hh"
+#include <iostream>
+
+writebuffer_status_t handleStore (writebuffer_t * writebuffer, const RubyRequest & request) {
+  assert(request.type == RubyRequestType_ST);
+  if (writebuffer->writeBufferFull()){
+    return WB_FULL;
+  }
+  else if (writebuffer->writeBufferFlushing()) {
+    return WB_FLUSHING;
+  }
+  else {
+    writebuffer->addToWriteBuffer(request);
+    return WB_OK;
+  }
+}
+
+uint64_t handleLoad(writebuffer_t * writebuffer, const RubyRequest & request) {
+  assert(request.type == RubyRequestType_LD);
+  return writebuffer->handleLoad(request);
+}
+
+uint64_t handleAtomic(writebuffer_t * writebuffer, const RubyRequest & request) {
+  // flush the store buffer
+  writebuffer->flushWriteBuffer();
+  // let writebuffer issue atomic
+  //return writebuffer->issueAtomic(request);
+}
+
+void flushSTB(writebuffer_t * writebuffer) {
+  // in in-order can't get a request to flushSTB if already flushing
+  // on out of order, have to check if already flushing
+  writebuffer->flushWriteBuffer();
+}
+
+void registerHitCallback(writebuffer_t * writebuffer, void (*hit_callback)(int64_t access_id)) {
+  writebuffer->registerHitCallback(hit_callback);
+}
 
--- /dev/null
+/*
+ * 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.
+ */
+
+#ifndef STB_H
+#define STB_H
+
+#include "mem/ruby/libruby.hh"
+#include "writebuffer.hh"
+#include <iostream>
+
+writebuffer_status_t handleStore (writebuffer_t * writebuffer, const RubyRequest & request);
+
+uint64_t handleLoad(writebuffer_t * writebuffer, const RubyRequest & request);
+
+uint64_t handleAtomic(writebuffer_t * writebuffer, const RubyRequest & request);
+
+void flushSTB(writebuffer_t * writebuffer);
+
+void registerHitCallback(writebuffer_t * writebuffer, void (*hit_callback)(int64_t access_id));
+
+#endif
 
--- /dev/null
+/*
+ * 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.
+ */
+
+#include <iostream>
+#include "mem/ruby/storebuffer/stb_interface.hh"
+
+StoreBuffer * createNewSTB(uint32 id, uint32 block_bits, int storebuffer_size) {
+  StoreBuffer * stb = new StoreBuffer(id, block_bits, storebuffer_size);
+  return stb;
+}
+
+storebuffer_status_t handleStore (StoreBuffer * storebuffer, const RubyRequest & request) {
+  assert(request.type == RubyRequestType_ST);
+  if (storebuffer->storeBufferFull()){
+    return WB_FULL;
+  }
+  else if (storebuffer->storeBufferFlushing()) {
+    return WB_FLUSHING;
+  }
+  else {
+    storebuffer->addToStoreBuffer(request);
+    return WB_OK;
+  }
+}
+
+uint64_t handleLoad(StoreBuffer * storebuffer, const RubyRequest & request) {
+  assert(request.type == RubyRequestType_LD);
+  return storebuffer->handleLoad(request);
+}
+
+uint64_t handleAtomic(StoreBuffer * storebuffer, const RubyRequest & request) {
+  // flush the store buffer
+  storebuffer->flushStoreBuffer();
+  // let storebuffer issue atomic
+  //return storebuffer->issueAtomic(request);
+}
+
+void flushSTB(StoreBuffer * storebuffer) {
+  // in in-order can't get a request to flushSTB if already flushing
+  // on out of order, have to check if already flushing
+  storebuffer->flushStoreBuffer();
+}
+
+void registerHitCallback(StoreBuffer * storebuffer, void (*hit_callback)(int64_t access_id)) {
+  storebuffer->registerHitCallback(hit_callback);
+}
+
+
 
--- /dev/null
+/*
+ * 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.
+ */
+
+#include "mem/ruby/storebuffer/storebuffer.hh"
+#include <iostream>
+
+StoreBuffer * createNewSTB (uint32 id, uint32 block_bits, int storebuffer_size);
+
+storebuffer_status_t handleStore (StoreBuffer * storebuffer, const RubyRequest & request);
+
+uint64_t handleLoad(StoreBuffer * storebuffer, const RubyRequest & request);
+
+uint64_t handleAtomic(StoreBuffer * storebuffer, const RubyRequest & request);
+
+void flushSTB(StoreBuffer * storebuffer);
+
+void registerHitCallback(StoreBuffer * storebuffer, void (*hit_callback)(int64_t access_id));
 
--- /dev/null
+/*
+ * 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.
+ */
+
+/*------------------------------------------------------------------------*/
+/* Includes                                                                             */
+/*------------------------------------------------------------------------*/
+
+#include "mem/ruby/storebuffer/hfa.hh"
+#include "mem/ruby/storebuffer/storebuffer.hh"
+#include <map>
+#include "mem/ruby/common/Global.hh"
+#include "TsoChecker.hh"
+
+#define SYSTEM_EXIT ASSERT(0)
+
+
+// global map of request id_s to map them back to storebuffer pointers
+map <uint64_t, StoreBuffer *> request_map;
+
+Tso::TsoChecker * g_tsoChecker;
+
+void hit(int64_t id) {
+  if (request_map.find(id) == request_map.end()) {
+    ERROR_OUT("Request ID not found in the map");
+    DEBUG_EXPR(STOREBUFFER_COMP, MedPrio, id);
+    ASSERT(0);
+  }
+  else {
+    request_map[id]->complete(id);
+    request_map.erase(id);
+  }
+}
+
+
+//*****************************************************************************************
+StoreBuffer::StoreBuffer(uint32 id, uint32 block_bits, int storebuffer_size) {
+#ifdef TSO_CHECK
+  if (id == 0) {
+    g_tsoChecker = new Tso::TsoChecker();
+    g_tsoChecker->init(64);
+  }
+#endif
+  iseq = 0;
+  tso_iseq = 0;
+  char name [] = "Sequencer_";
+  char port_name [13];
+  sprintf(port_name, "%s%d", name, id);
+  m_port = libruby_get_port(port_name, hit);
+  m_hit_callback = NULL;
+  ASSERT(storebuffer_size >= 0);
+  m_storebuffer_size = storebuffer_size;
+  m_id = id;
+  m_block_size = 1 << block_bits;
+  m_block_mask = ~(m_block_size - 1);
+  m_buffer_size = 0;
+  m_use_storebuffer = false;
+  m_storebuffer_full = false;
+  m_storebuffer_flushing = false;
+  m_stalled_issue = true;
+  if(m_storebuffer_size > 0){
+    m_use_storebuffer = true;
+  }
+
+  #ifdef DEBUG_WRITE_BUFFER
+      DEBUG_OUT("*******storebuffer_t::Using Write Buffer? %d\n",m_use_storebuffer);
+  #endif
+}
+
+//******************************************************************************************
+StoreBuffer::~StoreBuffer(){
+#ifdef TSO_CHECK
+  if (m_id == 0) {
+    delete g_tsoChecker;
+  }
+#endif
+}
+
+//*****************************************************************************************************
+void StoreBuffer::registerHitCallback(void (*hit_callback)(int64_t request_id)) {
+  assert(m_hit_callback == NULL); // can't assign hit_callback twice
+  m_hit_callback = hit_callback;
+}
+
+
+//*****************************************************************************************************
+void StoreBuffer::addToStoreBuffer(struct RubyRequest request){
+  if(m_use_storebuffer){
+    #ifdef DEBUG_WRITE_BUFFER
+       DEBUG_OUT("\n***StoreBuffer: addToStoreBuffer BEGIN, contents:\n");
+       DEBUG_OUT("\n");
+    #endif
+
+    #ifdef DEBUG_WRITE_BUFFER
+       DEBUG_OUT("\t INSERTING new request\n");
+    #endif
+
+
+    buffer.push_front(SBEntry(request, NULL));
+
+    m_buffer_size++;
+
+    if (m_buffer_size >= m_storebuffer_size) {
+      m_storebuffer_full = true;
+    }
+    else if (m_stalled_issue) {
+      m_stalled_issue = false;
+      issueNextStore();
+    }
+
+    iseq++;
+
+     #ifdef DEBUG_WRITE_BUFFER
+       DEBUG_OUT("***StoreBuffer: addToStoreBuffer END, contents:\n");
+       DEBUG_OUT("\n");
+     #endif
+  }  //end if(m_use_storebuffer)
+  else {
+    // make request to libruby
+    uint64_t id = libruby_issue_request(m_port, request);
+    if (request_map.find(id) != request_map.end()) {
+      ERROR_OUT("Request ID is already in the map");
+      DEBUG_EXPR(STOREBUFFER_COMP, MedPrio, id);
+      ASSERT(0);
+    }
+    else {
+      request_map.insert(make_pair(id, this));
+      outstanding_requests.insert(make_pair(id, request));
+    }
+  }
+}
+
+
+//*****************************************************************************************************
+// Return value of -2 indicates that the load request was satisfied by the store buffer
+// Return value of -3 indicates a partial match, so the load has to retry until NO_MATCH
+// Alternatively we could satisfy the partial match, but tso gets complicated and more races
+//*****************************************************************************************************
+int64_t StoreBuffer::handleLoad(struct RubyRequest request) {
+  if (m_use_storebuffer) {
+    load_match match = checkForLoadHit(request);
+    if (match == FULL_MATCH) {
+      // fill data
+      returnMatchedData(request);
+      iseq++;
+      return -2;
+    }
+    else if (match == NO_MATCH) {
+      // make request to libruby and return the id
+      uint64_t id = libruby_issue_request(m_port, request);
+      if (request_map.find(id) != request_map.end()) {
+        ERROR_OUT("Request ID is already in the map");
+        DEBUG_EXPR(STOREBUFFER_COMP, MedPrio, id);
+        ASSERT(0);
+      }
+      else {
+        request_map.insert(make_pair(id, this));
+        outstanding_requests.insert(make_pair(id, request));
+      }
+      iseq++;
+      return id;
+    }
+    else { // partial match
+      return -3;
+    }
+  }
+  else {
+    // make a request to ruby
+    return libruby_issue_request(m_port, request);
+  }
+}
+
+
+//*****************************************************************************************************
+// This function will fill the data array if any match is found
+//*****************************************************************************************************
+load_match StoreBuffer::checkForLoadHit(struct RubyRequest request) {
+  if (m_use_storebuffer) {
+    physical_address_t physical_address = request.paddr;
+    int len = request.len;
+
+    uint8_t * data = new uint8_t[64];
+    memset(data, 0, 64);
+    for (int i = physical_address%64; i < len; i++) {
+      data[i] = 1;
+    }
+
+    bool found = false;
+    physical_address_t lineaddr = physical_address & m_block_mask;
+
+    // iterate over the buffer looking for hits
+    for (deque<struct SBEntry>::iterator it = buffer.begin(); it != buffer.end(); it++) {
+      if ((it->m_request.paddr & m_block_mask) == lineaddr) {
+        found = true;
+        for (int i = it->m_request.paddr%64; i < it->m_request.len; i++) {
+          data[i] = 0;
+        }
+      }
+    }
+
+    // if any matching entry is found, determine if all the requested bytes have been matched
+    if (found) {
+      ASSERT(m_buffer_size > 0);
+      int unmatched_bytes = 0;
+      for (int i = physical_address%64; i < len; i++) {
+        unmatched_bytes = unmatched_bytes + data[i];
+      }
+      if (unmatched_bytes == 0) {
+        delete data;
+        return FULL_MATCH;
+      }
+      else {
+        delete data;
+        return PARTIAL_MATCH;
+      }
+    }
+    else {
+      delete data;
+      return NO_MATCH;
+    }
+  } // end of if (m_use_storebuffer)
+  else {
+    // this function should never be called if we are not using a store buffer
+    ERROR_OUT("checkForLoadHit called while write buffer is not in use");
+    ASSERT(0);
+  }
+}
+
+
+//***************************************************************************************************
+void StoreBuffer::returnMatchedData(struct RubyRequest request) {
+  if (m_use_storebuffer) {
+
+    uint8_t * data = new uint8_t[64];
+    memset(data, 0, 64);
+    uint8_t * written = new uint8_t[64];
+    memset(written, 0, 64);
+
+    physical_address_t physical_address = request.paddr;
+    int len = request.len;
+
+    ASSERT(checkForLoadHit(request) != NO_MATCH);
+    physical_address_t lineaddr = physical_address & m_block_mask;
+    bool found = false;
+    Tso::TsoCheckerCmd * cmd;
+    deque<struct SBEntry>::iterator satisfying_store;
+    for (deque<struct SBEntry>::iterator it = buffer.begin(); it != buffer.end(); it++) {
+      if ((it->m_request.paddr & m_block_mask) == lineaddr) {
+        if (!found) {
+          found = true;
+#ifdef TSO_CHECK
+          satisfying_store = it;
+          cmd = new Tso::TsoCheckerCmd(m_id, // this thread id
+                            iseq, // instruction sequence
+                            ITYPE_LOAD, // is a store
+                            MEM_LOAD_DATA, // commit
+                            request.paddr, // the address
+                            NULL, // and data
+                            request.len,  // and len
+                            DSRC_STB, // shouldn't matter
+                            libruby_get_time(), // macc: for store macc and time are the same and it
+                            0, // gobs
+                            0);
+#endif
+        }
+        uint8_t * dataPtr = it->m_request.data;
+        int offset = it->m_request.paddr%64;
+        for (int i = offset; i < it->m_request.len; i++) {
+          if (!written[i]) { // don't overwrite data with earlier data
+            data[i] = dataPtr[i-offset];
+            written[i] = 1;
+          }
+        }
+      }
+    }
+
+    int i = physical_address%64;
+    for (int j = 0; (i < physical_address%64 + len) && (j < len); i++, j++) {
+      if (written[i]) {
+        request.data[j] = data[i];
+      }
+    }
+
+#ifdef TSO_CHECK
+    uint64_t tso_data = 0;
+    memcpy(&tso_data, request.data, request.len);
+    cmd->setData(tso_data);
+
+    Tso::TsoCheckerCmd * adjust_cmd = satisfying_store->m_next_ptr;
+    if (adjust_cmd == NULL) {
+      adjust_cmd = cmd;
+    }
+    else {
+      while (adjust_cmd->getNext() != NULL) {
+        adjust_cmd = adjust_cmd->getNext();
+      }
+      adjust_cmd->setNext(cmd);
+    }
+#endif
+
+    delete data;
+    delete written;
+  }
+  else {
+    ERROR_OUT("returnMatchedData called while write buffer is not in use");
+    ASSERT(0);
+  }
+}
+
+
+//******************************************************************************************
+void StoreBuffer::flushStoreBuffer(){
+  if (m_use_storebuffer) {
+     #ifdef DEBUG_WRITE_BUFFER
+         DEBUG_OUT("\n***StoreBuffer: flushStoreBuffer BEGIN, contents:\n");
+         DEBUG_OUT("\n");
+     #endif
+
+     if(m_buffer_size > 0) {
+       m_storebuffer_flushing = true; // indicate that we are flushing
+     }
+     else {
+       m_storebuffer_flushing = false;
+       return;
+     }
+  }
+  else {
+    // do nothing
+    return;
+  }
+}
+
+//****************************************************************************************
+void StoreBuffer::issueNextStore() {
+  SBEntry request = buffer.back();
+  uint64_t id = libruby_issue_request(m_port, request.m_request);
+  if (request_map.find(id) != request_map.end()) {
+    assert(0);
+  }
+  else {
+    request_map.insert(make_pair(id, this));
+    outstanding_requests.insert(make_pair(id, request.m_request));
+  }
+}
+
+//****************************************************************************************
+void StoreBuffer::complete(uint64_t id) {
+  if (m_use_storebuffer) {
+    ASSERT(outstanding_requests.find(id) != outstanding_requests.end());
+    physical_address_t physical_address = outstanding_requests.find(id)->second.paddr;
+    RubyRequestType type = outstanding_requests.find(id)->second.type;
+    int len = outstanding_requests.find(id)->second.len;
+#ifdef DEBUG_WRITE_BUFFER
+    DEBUG_OUT("\n***StoreBuffer: complete BEGIN, contents:\n");
+    DEBUG_OUT("\n");
+#endif
+
+    if (type == RubyRequestType_ST) {
+      physical_address_t lineaddr = physical_address & m_block_mask;
+
+      //Note fastpath hits are handled like regular requests - they must remove the WB entry!
+      if ( lineaddr != physical_address ) {
+        ERROR_OUT("error: StoreBuffer: ruby returns pa 0x%0llx which is not a cache line: 0x%0llx\n", physical_address, lineaddr );
+      }
+
+      SBEntry from_buffer = buffer.back();
+      if (((from_buffer.m_request.paddr & m_block_mask) == lineaddr) && (from_buffer.m_request.type == type)) {
+        buffer.pop_back();
+        m_buffer_size--;
+        ASSERT(m_buffer_size >= 0);
+
+#ifdef TSO_CHECK
+        uint64_t data = 0;
+        memcpy(&data, from_buffer.m_request.data, 4);
+
+        cerr << m_id << " INSERTING STORE" << endl << flush;
+        // add to the tsoChecker
+        g_tsoChecker->input(m_id, // this thread id
+                          (id & ISEQ_MASK), // instruction sequence
+                          ITYPE_STORE, // is a store
+                          MEM_STORE_COMMIT, // commit
+                          physical_address, // the address
+                          data, // and data
+                          len,  // and len
+                          DSRC_STB, // shouldn't matter
+                          libruby_get_time(), // macc
+                          libruby_get_time(), // gobs
+                          libruby_get_time()); // time
+        tso_iseq++;
+
+        // also add the loads that are satisfied by this store
+        if (from_buffer.m_next_ptr != NULL) {
+          from_buffer.m_next_ptr->setGobs(libruby_get_time());
+          g_tsoChecker->input(*(from_buffer.m_next_ptr));
+          cerr << m_id << " INSERTING LOAD for STORE: " << from_buffer.m_next_ptr->getIseq()  << endl << flush;
+          tso_iseq++;
+          Tso::TsoCheckerCmd * to_input = from_buffer.m_next_ptr->getNext();
+          while (to_input != NULL) {
+            if (to_input->getGobs() == 0) {
+              to_input->setGobs(libruby_get_time());
+            }
+            cerr << m_id << " INSERTING LOAD iseq for STORE: " << to_input->getIseq() << endl << flush;
+            g_tsoChecker->input(*to_input);
+            tso_iseq++;
+            to_input = to_input->getNext();
+          }
+        }
+#endif
+        // schedule the next request
+        if (m_buffer_size > 0) {
+          issueNextStore();
+        }
+        else if (m_buffer_size == 0) {
+          m_storebuffer_flushing = false;
+          m_stalled_issue = true;
+        }
+
+        m_storebuffer_full = false;
+
+      }
+      else {
+        ERROR_OUT("[%d] error: StoreBuffer: at complete, address 0x%0llx not found.\n", m_id, lineaddr);
+        ERROR_OUT("StoreBuffer:: complete FAILS\n");
+        ASSERT(0);
+      }
+
+#ifdef DEBUG_WRITE_BUFFER
+      DEBUG_OUT("***StoreBuffer: complete END, contents:\n");
+      DEBUG_OUT("\n");
+#endif
+    } // end if (type == ST)
+    else if (type == RubyRequestType_LD) {
+#ifdef TSO_CHECK
+      RubyRequest request = outstanding_requests.find(id)->second;
+      uint64_t data = 0;
+      memcpy(&data, request.data, request.len);
+
+      // add to the tsoChecker if in order, otherwise, find a place to put ourselves
+      if ((id & ISEQ_MASK) == tso_iseq) {
+        tso_iseq++;
+        cerr << m_id << " INSERTING LOAD" << endl << flush;
+        g_tsoChecker->input(m_id, // this thread id
+                          (id & ISEQ_MASK), // instruction sequence
+                          ITYPE_LOAD, // is a store
+                          MEM_LOAD_DATA, // commit
+                          request.paddr, // the address
+                          data, // and data
+                          request.len,  // and len
+                          DSRC_L2_MEMORY, // shouldn't matter  DSRC_L1
+                          libruby_get_time(), // macc: for store macc and time are the same and it
+                          libruby_get_time(), // macc
+                          libruby_get_time()); // time
+      }
+      else {
+        Tso::TsoCheckerCmd * cmd;
+        cmd = new Tso::TsoCheckerCmd(m_id, // this thread id
+                          (id & ISEQ_MASK), // instruction sequence
+                          ITYPE_LOAD, // is a store
+                          MEM_LOAD_DATA, // commit
+                          request.paddr, // the address
+                          data, // and data
+                          request.len,  // and len
+                          DSRC_L2_MEMORY, // shouldn't matter  DSRC_L1
+                          libruby_get_time(), // macc: for store macc and time are the same and it
+                          libruby_get_time(), // macc
+                          libruby_get_time()); // time
+        insertTsoLL(cmd);
+      }
+#endif
+      m_hit_callback(id);
+    }
+
+    // LD, ST or FETCH hit callback
+    outstanding_requests.erase(id);
+
+  } // end if(m_use_storebuffer)
+  else {
+    m_hit_callback(id);
+  }
+}
+
+
+void StoreBuffer::insertTsoLL(Tso::TsoCheckerCmd * cmd) {
+  uint64_t count = cmd->getIseq();
+  Tso::TsoCheckerCmd * current = NULL;
+  Tso::TsoCheckerCmd * previous = NULL;
+  deque<struct SBEntry>::reverse_iterator iter;
+  bool found = false;
+  for (iter = buffer.rbegin(); iter != buffer.rend(); ++ iter) {
+    if (iter->m_next_ptr != NULL) {
+      current = iter->m_next_ptr->getNext(); // initalize both to the beginning of the linked list
+      previous = current;
+      while (current != NULL) {
+        if (current->getIseq() > count) {
+          found = true;
+          break;
+        }
+        previous = current;
+        current = current->getNext();
+      }
+    }
+    // break out if found a match, iterator should still point to the right SBEntry
+    if (found) {
+      break;
+    }
+  }
+
+  // will insert at the end if not found
+  if (!found) {
+    buffer.front().m_next_ptr = cmd;
+  }
+  else if (current == previous) {
+    cerr << "INSERTING " << count << " BEFORE: " << iter->m_next_ptr->getIseq();
+    Tso::TsoCheckerCmd * temp = iter->m_next_ptr;
+    iter->m_next_ptr = cmd;
+    cmd->setNext(temp);
+  }
+  else {
+    cerr << "INSERTING " << count << " BETWEEN: " << previous->getIseq() << " AND " << current->getIseq();
+    cmd->setNext(current);
+    previous->setNext(cmd);
+  }
+}
+
+
+//***************************************************************************************************
+void StoreBuffer::print( void )
+{
+  DEBUG_OUT("[%d] StoreBuffer: Total entries: %d Outstanding: %d\n", m_id, m_buffer_size);
+
+  if(m_use_storebuffer){
+  }
+  else{
+    DEBUG_OUT("\t WRITE BUFFER NOT USED\n");
+  }
+}
+
+
+
+
 
--- /dev/null
+/*
+ * 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.
+ */
+
+#ifndef _STOREBUFFER_H_
+#define _STOREBUFFER_H_
+
+#include <map>
+#include <deque>
+#include "mem/ruby/storebuffer/hfa.hh"
+#include "mem/ruby/libruby.hh"
+#include "TsoCheckerCmd.hh"
+
+#define TSO_CHECK
+/**
+ *  Status for write buffer accesses. The Write buffer can hit in fastpath, be full, or
+ *     successfully enqueue the store request
+ */
+enum storebuffer_status_t { WB_FULL, WB_OK, WB_FLUSHING };
+
+/**
+ *  Status of a load match
+ */
+enum load_match { NO_MATCH, PARTIAL_MATCH, FULL_MATCH };
+
+struct SBEntry {
+  struct RubyRequest m_request;
+  Tso::TsoCheckerCmd * m_next_ptr;
+  SBEntry(struct RubyRequest request, void * ptr) { m_request = request; m_next_ptr = (Tso::TsoCheckerCmd*) ptr; }
+};
+
+class StoreBuffer {
+ public:
+  ///Constructor
+  /// Note that the size of the Write Buffer is determined by the WRITE_BUFFER_SIZE config parameter
+  StoreBuffer(uint32 id, uint32 block_bits, int storebuffer_size);
+
+  /// Register hitcallback back to CPU
+  void registerHitCallback(void (*hit_callback)(int64_t request_id));
+
+  /// Destructor
+  ~StoreBuffer();
+
+  ///Adds a store entry to the write buffer
+  void addToStoreBuffer(struct RubyRequest request);
+
+  ///Flushes the entire write buffer
+  void flushStoreBuffer();
+
+  ///A pseq object calls this when Ruby completes our request
+  void complete(uint64_t);
+
+  /// Returns ID. If ID == -2, HIT, else it's an ID to wait on
+  int64_t handleLoad(struct RubyRequest request);
+
+  /// Used by all load insts to check whether it hits to any entry in the WB. If so, the WB is flushed
+  load_match checkForLoadHit(struct RubyRequest request);
+
+  /// Used to fill the load in case of FULL_MATCH
+  void returnMatchedData(struct RubyRequest request);
+
+  /// Issue next store in line
+  void issueNextStore();
+
+  /// prints out the contents of the Write Buffer
+  void print();
+
+  /// if load completes before store, insert correctly to be issued to TSOChecker
+  void insertTsoLL(Tso::TsoCheckerCmd * cmd);
+
+  /// Returns flag indicating whether we are using the write buffer
+  bool useStoreBuffer() { return m_use_storebuffer; }
+
+  bool storeBufferFull() { return m_storebuffer_full; }
+
+  bool storeBufferFlushing() { return m_storebuffer_flushing; }
+
+ private:
+  /// id of this write buffer (one per sequencer object)
+  uint32          m_id;
+
+  /// number of bytes in cacheline
+  uint32          m_block_size;
+
+  /// the size of the write buffer
+  uint32          m_storebuffer_size;
+
+  /// mask to strip off non-cache line bits
+  pa_t            m_block_mask;
+
+  /// list of store requests in the write buffer
+  deque <struct SBEntry> buffer;
+
+  /// the current length of the write buffer
+  uint32          m_buffer_size;
+
+  /// whether we want to simulate the write buffer or not:
+  bool            m_use_storebuffer;
+
+  /// indicates whether the write buffer is full or not
+  bool            m_storebuffer_full;
+
+  /// indicates that we are currently flushing the write buffer
+  bool            m_storebuffer_flushing;
+
+  /// indicates that automatic issue is stalled and the next store to be added should issue itself
+  bool            m_stalled_issue;
+
+  /// RubyPort to make requests to
+  RubyPortHandle  m_port;
+
+  /// HitCallback to CPU
+  void            (*m_hit_callback)(int64_t);
+
+  /// Map the request id to rubyrequest
+  map<uint64_t, struct RubyRequest> outstanding_requests;
+
+  /// current instruction counter
+  uint64_t iseq;
+
+
+  /// input into tso counter
+  uint64_t tso_iseq;
+};
+
+#endif
 
 #define ABSTRACT_MEM_OR_CACHE_H
 
 #include "mem/ruby/common/Global.hh"
-#include "mem/ruby/slicc_interface/AbstractChip.hh"
 #include "mem/ruby/config/RubyConfig.hh"
 #include "mem/ruby/common/Address.hh"
 
 
 #ifndef CACHEMEMORY_H
 #define CACHEMEMORY_H
 
-#include "mem/ruby/slicc_interface/AbstractChip.hh"
 #include "mem/ruby/common/Global.hh"
 #include "mem/protocol/AccessPermission.hh"
 #include "mem/ruby/common/Address.hh"
-
-//dsm: PRUNED
-//#include "mem/ruby/recorder/CacheRecorder.hh"
+#include "mem/ruby/recorder/CacheRecorder.hh"
 #include "mem/protocol/CacheRequestType.hh"
 #include "mem/gems_common/Vector.hh"
 #include "mem/ruby/common/DataBlock.hh"
 #include "mem/ruby/slicc_interface/RubySlicc_ComponentMapping.hh"
 #include "mem/ruby/system/PseudoLRUPolicy.hh"
 #include "mem/ruby/system/LRUPolicy.hh"
+#include "mem/ruby/slicc_interface/AbstractCacheEntry.hh"
+#include "mem/ruby/system/System.hh"
+#include "mem/ruby/slicc_interface/AbstractController.hh"
 #include <vector>
 
-template<class ENTRY>
 class CacheMemory {
 public:
 
   // Constructors
-  CacheMemory(AbstractChip* chip_ptr, int numSetBits, int cacheAssoc, const MachineType machType, const string& description);
+  CacheMemory(const string & name);
+  void init(const vector<string> & argv);
 
   // Destructor
   ~CacheMemory();
 
+  // factory
+  //  static CacheMemory* createCache(int level, int num, char split_type, AbstractCacheEntry* (*entry_factory)());
+  //  static CacheMemory* getCache(int cache_id);
+
   // Public Methods
   void printConfig(ostream& out);
 
   bool cacheAvail(const Address& address) const;
 
   // find an unused entry and sets the tag appropriate for the address
-  void allocate(const Address& address);
+  void allocate(const Address& address, AbstractCacheEntry* new_entry);
 
   // Explicitly free up this address
   void deallocate(const Address& address);
   Address cacheProbe(const Address& address) const;
 
   // looks an address up in the cache
-  ENTRY& lookup(const Address& address);
-  const ENTRY& lookup(const Address& address) const;
+  AbstractCacheEntry& lookup(const Address& address);
+  const AbstractCacheEntry& lookup(const Address& address) const;
 
   // Get/Set permission of cache block
   AccessPermission getPermission(const Address& address) const;
   void changePermission(const Address& address, AccessPermission new_perm);
 
+  int getLatency() const { return m_latency; }
+
   // Hook for checkpointing the contents of the cache
   void recordCacheContents(CacheRecorder& tr) const;
-  void setAsInstructionCache(bool is_icache) { m_is_instruction_cache = is_icache; }
+  void setAsInstructionCache(bool is_icache) { m_is_instruction_only_cache = is_icache; }
 
   // Set this address to most recently used
   void setMRU(const Address& address);
   CacheMemory(const CacheMemory& obj);
   CacheMemory& operator=(const CacheMemory& obj);
 
+private:
+  const string m_cache_name;
+  AbstractController* m_controller;
+  int m_latency;
+
   // Data Members (m_prefix)
-  AbstractChip* m_chip_ptr;
-  MachineType m_machType;
-  string m_description;
-  bool m_is_instruction_cache;
+  bool m_is_instruction_only_cache;
+  bool m_is_data_only_cache;
 
   // The first index is the # of cache lines.
   // The second index is the the amount associativity.
-  Vector<Vector<ENTRY> > m_cache;
+  Vector<Vector<AbstractCacheEntry*> > m_cache;
 
   AbstractReplacementPolicy *m_replacementPolicy_ptr;
 
   int m_cache_num_set_bits;
   int m_cache_assoc;
 
-  bool is_locked; // for LL/SC
+  static Vector< CacheMemory* > m_all_caches;
 };
+/*
+inline
+CacheMemory* CacheMemory::getCache(int cache_id)
+{
+  assert(cache_id < RubyConfig::getNumberOfCaches());
+  if (m_all_caches[cache_id] == NULL) {
+    cerr << "ERROR: Tried to obtain CacheMemory that hasn't been created yet." << endl;
+    assert(0);
+  }
+  return m_all_caches[cache_id];
+}
 
+inline
+CacheMemory* CacheMemory::createCache(int level, int num, char split_type_c, AbstractCacheEntry* (*entry_factory)())
+{
+  string split_type;
+  switch(split_type_c) {
+  case 'i':
+    split_type = "instruction"; break;
+  case 'd':
+    split_type = "data"; break;
+  default:
+    split_type = "unified"; break;
+  }
+  int cache_id = RubyConfig::getCacheIDFromParams(level, num, split_type);
+  assert(cache_id < RubyConfig::getNumberOfCaches());
+  if (m_all_caches.size() == 0) {
+    m_all_caches.setSize(RubyConfig::getNumberOfCaches());
+    for (int i=0; i<m_all_caches.size(); i++)
+      m_all_caches[i] = NULL;
+  }
+
+  string type = RubyConfig::getCacheType(cache_id);
+  if ( type == "SetAssociativeCache" ) {
+    m_all_caches[cache_id] = new CacheMemory(cache_id, entry_factory);
+  }
+  return m_all_caches[cache_id];
+}
+*/
 // Output operator declaration
 //ostream& operator<<(ostream& out, const CacheMemory<ENTRY>& obj);
 
 // ******************* Definitions *******************
 
 // Output operator definition
-template<class ENTRY>
 inline
-ostream& operator<<(ostream& out, const CacheMemory<ENTRY>& obj)
+ostream& operator<<(ostream& out, const CacheMemory& obj)
 {
   obj.print(out);
   out << flush;
 
 // ****************************************************************
 
-template<class ENTRY>
 inline
-CacheMemory<ENTRY>::CacheMemory(AbstractChip* chip_ptr, int numSetBits,
-                                      int cacheAssoc, const MachineType machType, const string& description)
+CacheMemory::CacheMemory(const string & name)
+  : m_cache_name(name)
+{
+}
 
+inline
+void CacheMemory::init(const vector<string> & argv)
 {
-  //cout << "CacheMemory constructor numThreads = " << numThreads << endl;
-  m_chip_ptr = chip_ptr;
-  m_machType = machType;
-  m_description = MachineType_to_string(m_machType)+"_"+description;
-  m_cache_num_set_bits = numSetBits;
-  m_cache_num_sets = 1 << numSetBits;
-  m_cache_assoc = cacheAssoc;
-  m_is_instruction_cache = false;
+  int cache_size = 0;
+  string policy;
+
+  m_controller = NULL;
+  for (uint32 i=0; i<argv.size(); i+=2) {
+    if (argv[i] == "size_kb") {
+      cache_size = atoi(argv[i+1].c_str());
+    } else if (argv[i] == "latency") {
+      m_latency = atoi(argv[i+1].c_str());
+    } else if (argv[i] == "assoc") {
+      m_cache_assoc = atoi(argv[i+1].c_str());
+    } else if (argv[i] == "replacement_policy") {
+      policy = argv[i+1];
+    } else if (argv[i] == "controller") {
+      m_controller = RubySystem::getController(argv[i+1]);
+    } else {
+      cerr << "WARNING: CacheMemory: Unknown configuration parameter: " << argv[i] << endl;
+    }
+  }
 
-  m_cache.setSize(m_cache_num_sets);
-  if(strcmp(g_REPLACEMENT_POLICY, "PSEDUO_LRU") == 0)
+  m_cache_num_sets = cache_size / m_cache_assoc;
+  m_cache_num_set_bits = log_int(m_cache_num_sets);
+
+  if(policy == "PSEUDO_LRU")
     m_replacementPolicy_ptr = new PseudoLRUPolicy(m_cache_num_sets, m_cache_assoc);
-  else if(strcmp(g_REPLACEMENT_POLICY, "LRU") == 0)
+  else if (policy == "LRU")
     m_replacementPolicy_ptr = new LRUPolicy(m_cache_num_sets, m_cache_assoc);
   else
     assert(false);
+
+  m_cache.setSize(m_cache_num_sets);
   for (int i = 0; i < m_cache_num_sets; i++) {
     m_cache[i].setSize(m_cache_assoc);
     for (int j = 0; j < m_cache_assoc; j++) {
-      m_cache[i][j].m_Address.setAddress(0);
-      m_cache[i][j].m_Permission = AccessPermission_NotPresent;
+      m_cache[i][j] = NULL;
     }
   }
+}
+/*
+inline
+CacheMemory::CacheMemory(int cache_id, AbstractCacheEntry* (*entry_factory)())
+{
+  string split_type;
+
+  m_cache_id = cache_id;
+  m_entry_factory = entry_factory;
+
+  m_cache_num_set_bits = RubyConfig::getNumberOfCacheSetBits(cache_id);
+  m_cache_num_sets = RubyConfig::getNumberOfCacheSets(cache_id);
+  m_cache_assoc = RubyConfig::getCacheAssoc(cache_id);
+  split_type = RubyConfig::getCacheSplitType(cache_id);
+  m_is_instruction_only_cache = m_is_data_only_cache = false;
+  if (split_type == "instruction")
+    m_is_instruction_only_cache = true;
+  else if (split_type == "data")
+    m_is_data_only_cache = true;
+  else
+    assert(split_type == "unified");
 
+  if(RubyConfig::getCacheReplacementPolicy(cache_id) == "PSEUDO_LRU")
+    m_replacementPolicy_ptr = new PseudoLRUPolicy(m_cache_num_sets, m_cache_assoc);
+  else if(RubyConfig::getCacheReplacementPolicy(cache_id) == "LRU")
+    m_replacementPolicy_ptr = new LRUPolicy(m_cache_num_sets, m_cache_assoc);
+  else
+    assert(false);
 
-  //  cout << "Before setting trans address list size" << endl;
-  //create a trans address for each SMT thread
-//   m_trans_address_list.setSize(numThreads);
-//   for(ThreadID tid = 0; tid < numThreads; ++tid){
-//     cout << "Setting list size for list " << tid << endl;
-//     m_trans_address_list[tid].setSize(30);
-//   }
-  //cout << "CacheMemory constructor finished" << endl;
+  m_cache.setSize(m_cache_num_sets);
+  for (int i = 0; i < m_cache_num_sets; i++) {
+    m_cache[i].setSize(m_cache_assoc);
+    for (int j = 0; j < m_cache_assoc; j++) {
+      m_cache[i][j] = m_entry_factory();
+    }
+  }
 }
-
-template<class ENTRY>
+*/
 inline
-CacheMemory<ENTRY>::~CacheMemory()
+CacheMemory::~CacheMemory()
 {
   if(m_replacementPolicy_ptr != NULL)
     delete m_replacementPolicy_ptr;
 }
 
-template<class ENTRY>
 inline
-void CacheMemory<ENTRY>::printConfig(ostream& out)
+void CacheMemory::printConfig(ostream& out)
 {
-  out << "Cache config: " << m_description << endl;
+  out << "Cache config: " << m_cache_name << endl;
+  if (m_controller != NULL)
+    out << "  controller: " << m_controller->getName() << endl;
   out << "  cache_associativity: " << m_cache_assoc << endl;
   out << "  num_cache_sets_bits: " << m_cache_num_set_bits << endl;
   const int cache_num_sets = 1 << m_cache_num_set_bits;
   out << "  num_cache_sets: " << cache_num_sets << endl;
-  out << "  cache_set_size_bytes: " << cache_num_sets * RubyConfig::dataBlockBytes() << endl;
+  out << "  cache_set_size_bytes: " << cache_num_sets * RubySystem::getBlockSizeBytes() << endl;
   out << "  cache_set_size_Kbytes: "
-      << double(cache_num_sets * RubyConfig::dataBlockBytes()) / (1<<10) << endl;
+      << double(cache_num_sets * RubySystem::getBlockSizeBytes()) / (1<<10) << endl;
   out << "  cache_set_size_Mbytes: "
-      << double(cache_num_sets * RubyConfig::dataBlockBytes()) / (1<<20) << endl;
+      << double(cache_num_sets * RubySystem::getBlockSizeBytes()) / (1<<20) << endl;
   out << "  cache_size_bytes: "
-      << cache_num_sets * RubyConfig::dataBlockBytes() * m_cache_assoc << endl;
+      << cache_num_sets * RubySystem::getBlockSizeBytes() * m_cache_assoc << endl;
   out << "  cache_size_Kbytes: "
-      << double(cache_num_sets * RubyConfig::dataBlockBytes() * m_cache_assoc) / (1<<10) << endl;
+      << double(cache_num_sets * RubySystem::getBlockSizeBytes() * m_cache_assoc) / (1<<10) << endl;
   out << "  cache_size_Mbytes: "
-      << double(cache_num_sets * RubyConfig::dataBlockBytes() * m_cache_assoc) / (1<<20) << endl;
+      << double(cache_num_sets * RubySystem::getBlockSizeBytes() * m_cache_assoc) / (1<<20) << endl;
 }
 
 // PRIVATE METHODS
 
 // convert a Address to its location in the cache
-template<class ENTRY>
 inline
-Index CacheMemory<ENTRY>::addressToCacheSet(const Address& address) const
+Index CacheMemory::addressToCacheSet(const Address& address) const
 {
   assert(address == line_address(address));
   Index temp = -1;
-  switch (m_machType) {
-  case MACHINETYPE_L1CACHE_ENUM:
-    temp = map_address_to_L1CacheSet(address, m_cache_num_set_bits);
-    break;
-  case MACHINETYPE_L2CACHE_ENUM:
-    temp = map_address_to_L2CacheSet(address, m_cache_num_set_bits);
-    break;
-  default:
-    ERROR_MSG("Don't recognize m_machType");
-  }
-  assert(temp < m_cache_num_sets);
-  assert(temp >= 0);
-  return temp;
+  return address.bitSelect(RubySystem::getBlockSizeBits(), RubySystem::getBlockSizeBits() + m_cache_num_set_bits-1);
 }
 
 // Given a cache index: returns the index of the tag in a set.
 // returns -1 if the tag is not found.
-template<class ENTRY>
 inline
-int CacheMemory<ENTRY>::findTagInSet(Index cacheSet, const Address& tag) const
+int CacheMemory::findTagInSet(Index cacheSet, const Address& tag) const
 {
   assert(tag == line_address(tag));
   // search the set for the tags
   for (int i=0; i < m_cache_assoc; i++) {
-    if ((m_cache[cacheSet][i].m_Address == tag) &&
-        (m_cache[cacheSet][i].m_Permission != AccessPermission_NotPresent)) {
+    if ((m_cache[cacheSet][i] != NULL) &&
+        (m_cache[cacheSet][i]->m_Address == tag) &&
+        (m_cache[cacheSet][i]->m_Permission != AccessPermission_NotPresent)) {
       return i;
     }
   }
 
 // Given a cache index: returns the index of the tag in a set.
 // returns -1 if the tag is not found.
-template<class ENTRY>
 inline
-int CacheMemory<ENTRY>::findTagInSetIgnorePermissions(Index cacheSet, const Address& tag) const
+int CacheMemory::findTagInSetIgnorePermissions(Index cacheSet, const Address& tag) const
 {
   assert(tag == line_address(tag));
   // search the set for the tags
   for (int i=0; i < m_cache_assoc; i++) {
-    if (m_cache[cacheSet][i].m_Address == tag)
+    if (m_cache[cacheSet][i] != NULL && m_cache[cacheSet][i]->m_Address == tag)
       return i;
   }
   return -1; // Not found
 }
 
 // PUBLIC METHODS
-template<class ENTRY>
 inline
-bool CacheMemory<ENTRY>::tryCacheAccess(const Address& address,
-                                           CacheRequestType type,
-                                           DataBlock*& data_ptr)
+bool CacheMemory::tryCacheAccess(const Address& address,
+                                 CacheRequestType type,
+                                 DataBlock*& data_ptr)
 {
   assert(address == line_address(address));
   DEBUG_EXPR(CACHE_COMP, HighPrio, address);
   Index cacheSet = addressToCacheSet(address);
   int loc = findTagInSet(cacheSet, address);
   if(loc != -1){ // Do we even have a tag match?
-    ENTRY& entry = m_cache[cacheSet][loc];
+    AbstractCacheEntry* entry = m_cache[cacheSet][loc];
     m_replacementPolicy_ptr->touch(cacheSet, loc, g_eventQueue_ptr->getTime());
-    data_ptr = &(entry.getDataBlk());
+    data_ptr = &(entry->getDataBlk());
 
-    if(entry.m_Permission == AccessPermission_Read_Write) {
+    if(entry->m_Permission == AccessPermission_Read_Write) {
       return true;
     }
-    if ((entry.m_Permission == AccessPermission_Read_Only) &&
+    if ((entry->m_Permission == AccessPermission_Read_Only) &&
         (type == CacheRequestType_LD || type == CacheRequestType_IFETCH)) {
       return true;
     }
   return false;
 }
 
-template<class ENTRY>
 inline
-bool CacheMemory<ENTRY>::testCacheAccess(const Address& address,
-                                           CacheRequestType type,
-                                           DataBlock*& data_ptr)
+bool CacheMemory::testCacheAccess(const Address& address,
+                                  CacheRequestType type,
+                                  DataBlock*& data_ptr)
 {
   assert(address == line_address(address));
   DEBUG_EXPR(CACHE_COMP, HighPrio, address);
   Index cacheSet = addressToCacheSet(address);
   int loc = findTagInSet(cacheSet, address);
   if(loc != -1){ // Do we even have a tag match?
-    ENTRY& entry = m_cache[cacheSet][loc];
+    AbstractCacheEntry* entry = m_cache[cacheSet][loc];
     m_replacementPolicy_ptr->touch(cacheSet, loc, g_eventQueue_ptr->getTime());
-    data_ptr = &(entry.getDataBlk());
+    data_ptr = &(entry->getDataBlk());
 
-    return (m_cache[cacheSet][loc].m_Permission != AccessPermission_NotPresent);
+    return (m_cache[cacheSet][loc]->m_Permission != AccessPermission_NotPresent);
   }
   data_ptr = NULL;
   return false;
 }
 
 // tests to see if an address is present in the cache
-template<class ENTRY>
 inline
-bool CacheMemory<ENTRY>::isTagPresent(const Address& address) const
+bool CacheMemory::isTagPresent(const Address& address) const
 {
   assert(address == line_address(address));
   Index cacheSet = addressToCacheSet(address);
 // Returns true if there is:
 //   a) a tag match on this address or there is
 //   b) an unused line in the same cache "way"
-template<class ENTRY>
 inline
-bool CacheMemory<ENTRY>::cacheAvail(const Address& address) const
+bool CacheMemory::cacheAvail(const Address& address) const
 {
   assert(address == line_address(address));
 
   Index cacheSet = addressToCacheSet(address);
 
   for (int i=0; i < m_cache_assoc; i++) {
-    if (m_cache[cacheSet][i].m_Address == address) {
-      // Already in the cache
-      return true;
-    }
-
-    if (m_cache[cacheSet][i].m_Permission == AccessPermission_NotPresent) {
-      // We found an empty entry
+    AbstractCacheEntry* entry = m_cache[cacheSet][i];
+    if (entry != NULL) {
+      if (entry->m_Address == address ||                         // Already in the cache
+          entry->m_Permission == AccessPermission_NotPresent) {  // We found an empty entry
+        return true;
+      }
+    } else {
       return true;
     }
   }
   return false;
 }
 
-template<class ENTRY>
 inline
-void CacheMemory<ENTRY>::allocate(const Address& address)
+void CacheMemory::allocate(const Address& address, AbstractCacheEntry* entry)
 {
   assert(address == line_address(address));
   assert(!isTagPresent(address));
   // Find the first open slot
   Index cacheSet = addressToCacheSet(address);
   for (int i=0; i < m_cache_assoc; i++) {
-    if (m_cache[cacheSet][i].m_Permission == AccessPermission_NotPresent) {
-      m_cache[cacheSet][i] = ENTRY();  // Init entry
-      m_cache[cacheSet][i].m_Address = address;
-      m_cache[cacheSet][i].m_Permission = AccessPermission_Invalid;
+    if (m_cache[cacheSet][i] == NULL ||
+        m_cache[cacheSet][i]->m_Permission == AccessPermission_NotPresent) {
+      m_cache[cacheSet][i] = entry;  // Init entry
+      m_cache[cacheSet][i]->m_Address = address;
+      m_cache[cacheSet][i]->m_Permission = AccessPermission_Invalid;
 
       m_replacementPolicy_ptr->touch(cacheSet, i, g_eventQueue_ptr->getTime());
 
   ERROR_MSG("Allocate didn't find an available entry");
 }
 
-template<class ENTRY>
 inline
-void CacheMemory<ENTRY>::deallocate(const Address& address)
+void CacheMemory::deallocate(const Address& address)
 {
   assert(address == line_address(address));
   assert(isTagPresent(address));
   DEBUG_EXPR(CACHE_COMP, HighPrio, address);
-  lookup(address).m_Permission = AccessPermission_NotPresent;
+  Index cacheSet = addressToCacheSet(address);
+  int location = findTagInSet(cacheSet, address);
+  if (location != -1){
+    delete m_cache[cacheSet][location];
+    m_cache[cacheSet][location] = NULL;
+  }
 }
 
 // Returns with the physical address of the conflicting cache line
-template<class ENTRY>
 inline
-Address CacheMemory<ENTRY>::cacheProbe(const Address& address) const
+Address CacheMemory::cacheProbe(const Address& address) const
 {
   assert(address == line_address(address));
   assert(!cacheAvail(address));
 
   Index cacheSet = addressToCacheSet(address);
-  return m_cache[cacheSet][m_replacementPolicy_ptr->getVictim(cacheSet)].m_Address;
+  return m_cache[cacheSet][m_replacementPolicy_ptr->getVictim(cacheSet)]->m_Address;
 }
 
 // looks an address up in the cache
-template<class ENTRY>
 inline
-ENTRY& CacheMemory<ENTRY>::lookup(const Address& address)
+AbstractCacheEntry& CacheMemory::lookup(const Address& address)
 {
   assert(address == line_address(address));
   Index cacheSet = addressToCacheSet(address);
   int loc = findTagInSet(cacheSet, address);
   assert(loc != -1);
-  return m_cache[cacheSet][loc];
+  return *m_cache[cacheSet][loc];
 }
 
 // looks an address up in the cache
-template<class ENTRY>
 inline
-const ENTRY& CacheMemory<ENTRY>::lookup(const Address& address) const
+const AbstractCacheEntry& CacheMemory::lookup(const Address& address) const
 {
   assert(address == line_address(address));
   Index cacheSet = addressToCacheSet(address);
   int loc = findTagInSet(cacheSet, address);
   assert(loc != -1);
-  return m_cache[cacheSet][loc];
+  return *m_cache[cacheSet][loc];
 }
 
-template<class ENTRY>
 inline
-AccessPermission CacheMemory<ENTRY>::getPermission(const Address& address) const
+AccessPermission CacheMemory::getPermission(const Address& address) const
 {
   assert(address == line_address(address));
   return lookup(address).m_Permission;
 }
 
-template<class ENTRY>
 inline
-void CacheMemory<ENTRY>::changePermission(const Address& address, AccessPermission new_perm)
+void CacheMemory::changePermission(const Address& address, AccessPermission new_perm)
 {
   assert(address == line_address(address));
   lookup(address).m_Permission = new_perm;
 }
 
 // Sets the most recently used bit for a cache block
-template<class ENTRY>
 inline
-void CacheMemory<ENTRY>::setMRU(const Address& address)
+void CacheMemory::setMRU(const Address& address)
 {
   Index cacheSet;
 
                                  g_eventQueue_ptr->getTime());
 }
 
-template<class ENTRY>
 inline
-void CacheMemory<ENTRY>::recordCacheContents(CacheRecorder& tr) const
+void CacheMemory::recordCacheContents(CacheRecorder& tr) const
 {
-//dsm: Uses CacheRecorder, PRUNED
-assert(false);
-
-/*  for (int i = 0; i < m_cache_num_sets; i++) {
+  for (int i = 0; i < m_cache_num_sets; i++) {
     for (int j = 0; j < m_cache_assoc; j++) {
-      AccessPermission perm = m_cache[i][j].m_Permission;
+      AccessPermission perm = m_cache[i][j]->m_Permission;
       CacheRequestType request_type = CacheRequestType_NULL;
       if (perm == AccessPermission_Read_Only) {
-        if (m_is_instruction_cache) {
+        if (m_is_instruction_only_cache) {
           request_type = CacheRequestType_IFETCH;
         } else {
           request_type = CacheRequestType_LD;
       }
 
       if (request_type != CacheRequestType_NULL) {
-        tr.addRecord(m_chip_ptr->getID(), m_cache[i][j].m_Address,
-                     Address(0), request_type, m_replacementPolicy_ptr->getLastAccess(i, j));
+        //        tr.addRecord(m_chip_ptr->getID(), m_cache[i][j].m_Address,
+        //                     Address(0), request_type, m_replacementPolicy_ptr->getLastAccess(i, j));
       }
     }
-  }*/
+  }
 }
 
-template<class ENTRY>
 inline
-void CacheMemory<ENTRY>::print(ostream& out) const
+void CacheMemory::print(ostream& out) const
 {
-  out << "Cache dump: " << m_description << endl;
+  out << "Cache dump: " << m_cache_name << endl;
   for (int i = 0; i < m_cache_num_sets; i++) {
     for (int j = 0; j < m_cache_assoc; j++) {
-      out << "  Index: " << i
-          << " way: " << j
-          << " entry: " << m_cache[i][j] << endl;
+      if (m_cache[i][j] != NULL) {
+        out << "  Index: " << i
+            << " way: " << j
+            << " entry: " << *m_cache[i][j] << endl;
+      } else {
+        out << "  Index: " << i
+            << " way: " << j
+            << " entry: NULL" << endl;
+      }
     }
   }
 }
 
-template<class ENTRY>
 inline
-void CacheMemory<ENTRY>::printData(ostream& out) const
+void CacheMemory::printData(ostream& out) const
 {
   out << "printData() not supported" << endl;
 }
 
-template<class ENTRY>
-void CacheMemory<ENTRY>::getMemoryValue(const Address& addr, char* value,
-                                           unsigned int size_in_bytes ){
-  ENTRY entry = lookup(line_address(addr));
+inline
+void CacheMemory::getMemoryValue(const Address& addr, char* value,
+                                 unsigned int size_in_bytes ){
+  AbstractCacheEntry& entry = lookup(line_address(addr));
   unsigned int startByte = addr.getAddress() - line_address(addr).getAddress();
   for(unsigned int i=0; i<size_in_bytes; ++i){
-    value[i] = entry.m_DataBlk.getByte(i + startByte);
+    value[i] = entry.getDataBlk().getByte(i + startByte);
   }
 }
 
-template<class ENTRY>
-void CacheMemory<ENTRY>::setMemoryValue(const Address& addr, char* value,
-                                           unsigned int size_in_bytes ){
-  ENTRY& entry = lookup(line_address(addr));
+inline
+void CacheMemory::setMemoryValue(const Address& addr, char* value,
+                                 unsigned int size_in_bytes ){
+  AbstractCacheEntry& entry = lookup(line_address(addr));
   unsigned int startByte = addr.getAddress() - line_address(addr).getAddress();
   assert(size_in_bytes > 0);
   for(unsigned int i=0; i<size_in_bytes; ++i){
-    entry.m_DataBlk.setByte(i + startByte, value[i]);
+    entry.getDataBlk().setByte(i + startByte, value[i]);
   }
 
-  entry = lookup(line_address(addr));
+  //  entry = lookup(line_address(addr));
 }
 
 #endif //CACHEMEMORY_H
 
--- /dev/null
+
+#include "mem/ruby/system/DMASequencer.hh"
+#include "mem/ruby/buffers/MessageBuffer.hh"
+#include "mem/ruby/slicc_interface/AbstractController.hh"
+
+/* SLICC generated types */
+#include "mem/protocol/DMARequestMsg.hh"
+#include "mem/protocol/DMARequestType.hh"
+#include "mem/protocol/DMAResponseMsg.hh"
+#include "mem/ruby/system/System.hh"
+
+DMASequencer::DMASequencer(const string & name)
+  : RubyPort(name)
+{
+}
+
+void DMASequencer::init(const vector<string> & argv)
+{
+  m_version = -1;
+  m_controller = NULL;
+  for (size_t i=0;i<argv.size();i+=2) {
+    if (argv[i] == "controller")
+      m_controller = RubySystem::getController(argv[i+1]);
+    else if (argv[i] == "version")
+      m_version = atoi(argv[i+1].c_str());
+  }
+  assert(m_controller != NULL);
+  assert(m_version != -1);
+
+  m_mandatory_q_ptr = m_controller->getMandatoryQueue();
+  m_is_busy = false;
+}
+
+int64_t DMASequencer::makeRequest(const RubyRequest & request)
+{
+  uint64_t paddr = request.paddr;
+  uint8_t* data = request.data;
+  int len = request.len;
+  bool write = false;
+  switch(request.type) {
+  case RubyRequestType_LD:
+    write = false;
+    break;
+  case RubyRequestType_ST:
+    write = true;
+    break;
+  case RubyRequestType_NULL:
+  case RubyRequestType_IFETCH:
+  case RubyRequestType_RMW:
+    assert(0);
+  }
+
+  assert(!m_is_busy);
+  m_is_busy = true;
+
+  active_request.start_paddr = paddr;
+  active_request.write = write;
+  active_request.data = data;
+  active_request.len = len;
+  active_request.bytes_completed = 0;
+  active_request.bytes_issued = 0;
+  active_request.id = makeUniqueRequestID();
+
+  DMARequestMsg msg;
+  msg.getPhysicalAddress() = Address(paddr);
+  msg.getType() = write ? DMARequestType_WRITE : DMARequestType_READ;
+  msg.getOffset() = paddr & RubyConfig::dataBlockMask();
+  msg.getLen() = (msg.getOffset() + len) < RubySystem::getBlockSizeBytes() ?
+    (msg.getOffset() + len) :
+    RubySystem::getBlockSizeBytes() - msg.getOffset();
+  if (write) {
+    msg.getType() = DMARequestType_WRITE;
+    msg.getDataBlk().setData(data, 0, msg.getLen());
+  } else {
+    msg.getType() = DMARequestType_READ;
+  }
+  m_mandatory_q_ptr->enqueue(msg);
+  active_request.bytes_issued += msg.getLen();
+
+  return active_request.id;
+}
+
+void DMASequencer::issueNext()
+{
+  assert(m_is_busy == true);
+  active_request.bytes_completed = active_request.bytes_issued;
+  if (active_request.len == active_request.bytes_completed) {
+    m_hit_callback(active_request.id);
+    m_is_busy = false;
+    return;
+  }
+
+  DMARequestMsg msg;
+  msg.getPhysicalAddress() = Address(active_request.start_paddr + active_request.bytes_completed);
+  assert((msg.getPhysicalAddress().getAddress() & RubyConfig::dataBlockMask()) == 0);
+  msg.getOffset() = 0;
+  msg.getType() = active_request.write ? DMARequestType_WRITE : DMARequestType_READ;
+  msg.getLen() = active_request.len - active_request.bytes_completed < RubySystem::getBlockSizeBytes() ?
+    active_request.len - active_request.bytes_completed :
+    RubySystem::getBlockSizeBytes();
+  if (active_request.write) {
+    msg.getDataBlk().setData(&active_request.data[active_request.bytes_completed], 0, msg.getLen());
+    msg.getType() = DMARequestType_WRITE;
+  } else {
+    msg.getType() = DMARequestType_READ;
+  }
+  m_mandatory_q_ptr->enqueue(msg);
+  active_request.bytes_issued += msg.getLen();
+}
+
+void DMASequencer::dataCallback(const DataBlock & dblk)
+{
+  assert(m_is_busy == true);
+  int len = active_request.bytes_issued - active_request.bytes_completed;
+  int offset = 0;
+  if (active_request.bytes_completed == 0)
+    offset = active_request.start_paddr & RubyConfig::dataBlockMask();
+  memcpy(&active_request.data[active_request.bytes_completed], dblk.getData(offset, len), len);
+  issueNext();
+}
+
+void DMASequencer::ackCallback()
+{
+  issueNext();
+}
+
+void DMASequencer::printConfig(ostream & out)
+{
+
+}
 
--- /dev/null
+
+#ifndef DMASEQUENCER_H
+#define DMASEQUENCER_H
+
+#include <ostream>
+#include "mem/ruby/common/DataBlock.hh"
+#include "mem/ruby/system/RubyPort.hh"
+
+struct DMARequest {
+  uint64_t start_paddr;
+  int len;
+  bool write;
+  int bytes_completed;
+  int bytes_issued;
+  uint8* data;
+  int64_t id;
+};
+
+class MessageBuffer;
+class AbstractController;
+
+class DMASequencer :public RubyPort {
+public:
+  DMASequencer(const string & name);
+  void init(const vector<string> & argv);
+  /* external interface */
+  int64_t makeRequest(const RubyRequest & request);
+  //  void issueRequest(uint64_t paddr, uint8* data, int len, bool rw);
+  bool busy() { return m_is_busy;}
+
+  /* SLICC callback */
+  void dataCallback(const DataBlock & dblk);
+  void ackCallback();
+
+  void printConfig(std::ostream & out);
+
+private:
+  void issueNext();
+
+private:
+  int m_version;
+  AbstractController* m_controller;
+  bool m_is_busy;
+  DMARequest active_request;
+  int num_active_requests;
+  MessageBuffer* m_mandatory_q_ptr;
+};
+
+#endif // DMACONTROLLER_H
 
  */
 
 #include "mem/ruby/system/System.hh"
-#include "mem/ruby/common/Driver.hh"
 #include "mem/ruby/system/DirectoryMemory.hh"
 #include "mem/ruby/slicc_interface/RubySlicc_Util.hh"
 #include "mem/ruby/config/RubyConfig.hh"
-#include "mem/protocol/Chip.hh"
+#include "mem/ruby/slicc_interface/AbstractController.hh"
+#include "mem/gems_common/util.hh"
 
-DirectoryMemory::DirectoryMemory(Chip* chip_ptr, int version)
+int DirectoryMemory::m_num_directories = 0;
+int DirectoryMemory::m_num_directories_bits = 0;
+int DirectoryMemory::m_total_size_bytes = 0;
+
+DirectoryMemory::DirectoryMemory(const string & name)
+ : m_name(name)
 {
-  m_chip_ptr = chip_ptr;
-  m_version = version;
-  // THIS DOESN'T SEEM TO WORK -- MRM
-  // m_size = RubyConfig::memoryModuleBlocks()/RubyConfig::numberOfDirectory();
-  m_size = RubyConfig::memoryModuleBlocks();
-  assert(m_size > 0);
-  /*********************************************************************
-  // allocates an array of directory entry pointers & sets them to NULL
-  m_entries = new Directory_Entry*[m_size];
-  if (m_entries == NULL) {
-    ERROR_MSG("Directory Memory: unable to allocate memory.");
+}
+
+void DirectoryMemory::init(const vector<string> & argv)
+{
+  m_controller = NULL;
+  for (vector<string>::const_iterator it = argv.begin(); it != argv.end(); it++) {
+    if ( (*it) == "version" )
+      m_version = atoi( (*(++it)).c_str() );
+    else if ( (*it) == "size_mb" ) {
+      m_size_bytes = atoi((*(++it)).c_str()) * (1<<20);
+      m_size_bits = log_int(m_size_bytes);
+    } else if ( (*it) == "controller" ) {
+      m_controller = RubySystem::getController((*(++it)));
+    } else
+      assert(0);
   }
+  assert(m_controller != NULL);
 
-  for (int i=0; i < m_size; i++) {
+  m_num_entries = m_size_bytes / RubySystem::getBlockSizeBytes();
+  m_entries = new Directory_Entry*[m_num_entries];
+  for (int i=0; i < m_num_entries; i++)
     m_entries[i] = NULL;
-  }
-  */////////////////////////////////////////////////////////////////////
+
+  m_ram = g_system_ptr->getMemoryVector();
+
+  m_num_directories++;
+  m_num_directories_bits = log_int(m_num_directories);
+  m_total_size_bytes += m_size_bytes;
 }
 
 DirectoryMemory::~DirectoryMemory()
 {
-  /*********************************************************************
   // free up all the directory entries
-  for (int i=0; i < m_size; i++) {
-    if (m_entries[i] != NULL) {
-      delete m_entries[i];
-      m_entries[i] = NULL;
-    }
-  }
+  for (int i=0;i<m_num_entries;i++)
+    if (m_entries[i] != NULL)
+      delete m_entries;
+  if (m_entries != NULL)
+    delete [] m_entries;
+}
 
-  // free up the array of directory entries
-  delete[] m_entries;
-  *//////////////////////////////////////////////////////////////////////
-  m_entries.clear();
+void DirectoryMemory::printConfig(ostream& out) const
+{
+  out << "DirectoryMemory module config: " << m_name << endl;
+  out << "  controller: " << m_controller->getName() << endl;
+  out << "  version: " << m_version << endl;
+  out << "  memory_bits: " << m_size_bits << endl;
+  out << "  memory_size_bytes: " << m_size_bytes << endl;
+  out << "  memory_size_Kbytes: " << double(m_size_bytes) / (1<<10) << endl;
+  out << "  memory_size_Mbytes: " << double(m_size_bytes) / (1<<20) << endl;
+  out << "  memory_size_Gbytes: " << double(m_size_bytes) / (1<<30) << endl;
 }
 
 // Static method
-void DirectoryMemory::printConfig(ostream& out)
+void DirectoryMemory::printGlobalConfig(ostream & out)
+{
+  out << "DirectoryMemory Global Config: " << endl;
+  out << "  number of directory memories: " << m_num_directories << endl;
+  if (m_num_directories > 1) {
+    out << "  number of selection bits: " << m_num_directories_bits << endl;
+    out << "  selection bits: " << RubySystem::getBlockSizeBits()+m_num_directories_bits-1
+        << "-" << RubySystem::getBlockSizeBits() << endl;
+  }
+  out << "  total memory size bytes: " << m_total_size_bytes << endl;
+  out << "  total memory size bits: " << log_int(m_total_size_bytes) << endl;
+
+}
+
+int DirectoryMemory::mapAddressToDirectoryVersion(PhysAddress address)
 {
-  out << "Memory config:" << endl;
-  out << "  memory_bits: " << RubyConfig::memorySizeBits() << endl;
-  out << "  memory_size_bytes: " << RubyConfig::memorySizeBytes() << endl;
-  out << "  memory_size_Kbytes: " << double(RubyConfig::memorySizeBytes()) / (1<<10) << endl;
-  out << "  memory_size_Mbytes: " << double(RubyConfig::memorySizeBytes()) / (1<<20) << endl;
-  out << "  memory_size_Gbytes: " << double(RubyConfig::memorySizeBytes()) / (1<<30) << endl;
-
-  out << "  module_bits: " << RubyConfig::memoryModuleBits() << endl;
-  out << "  module_size_lines: " << RubyConfig::memoryModuleBlocks() << endl;
-  out << "  module_size_bytes: " << RubyConfig::memoryModuleBlocks() * RubyConfig::dataBlockBytes() << endl;
-  out << "  module_size_Kbytes: " << double(RubyConfig::memoryModuleBlocks() * RubyConfig::dataBlockBytes()) / (1<<10) << endl;
-  out << "  module_size_Mbytes: " << double(RubyConfig::memoryModuleBlocks() * RubyConfig::dataBlockBytes()) / (1<<20) << endl;
+  if (m_num_directories_bits == 0) return 0;
+  int ret = address.bitSelect(RubySystem::getBlockSizeBits(),
+                              RubySystem::getBlockSizeBits()+m_num_directories_bits-1);
+  return ret;
 }
 
 // Public method
 bool DirectoryMemory::isPresent(PhysAddress address)
 {
-  return (map_Address_to_DirectoryNode(address) == m_chip_ptr->getID()*RubyConfig::numberOfDirectoryPerChip()+m_version);
+  bool ret = (mapAddressToDirectoryVersion(address) == m_version);
+  return ret;
 }
 
-void DirectoryMemory::readPhysMem(uint64 address, int size, void * data)
+int DirectoryMemory::mapAddressToLocalIdx(PhysAddress address)
 {
+  int ret = address.getAddress() >> (RubySystem::getBlockSizeBits() + m_num_directories_bits);
+  return ret;
 }
 
+Directory_Entry& DirectoryMemory::lookup(PhysAddress address)
+{
+  assert(isPresent(address));
+  Directory_Entry* entry;
+  int idx = mapAddressToLocalIdx(address);
+  entry = m_entries[idx];
+  if (entry == NULL) {
+    entry = new Directory_Entry;
+    entry->getDataBlk().assign(m_ram->getBlockPtr(address));
+    m_entries[idx] = entry;
+  }
+  return (*entry);
+}
+/*
 Directory_Entry& DirectoryMemory::lookup(PhysAddress address)
 {
   assert(isPresent(address));
   Index index = address.memoryModuleIndex();
 
   if (index < 0 || index > m_size) {
-    WARN_EXPR(m_chip_ptr->getID());
     WARN_EXPR(address.getAddress());
     WARN_EXPR(index);
     WARN_EXPR(m_size);
     ERROR_MSG("Directory Memory Assertion: accessing memory out of range.");
   }
-
-  map<Index, Directory_Entry*>::iterator iter =  m_entries.find(index);
-  Directory_Entry* entry = m_entries.find(index)->second;
+  Directory_Entry* entry = m_entries[index];
 
   // allocate the directory entry on demand.
-  if (iter == m_entries.end()) {
+  if (entry == NULL) {
     entry = new Directory_Entry;
+    entry->getDataBlk().assign(m_ram->getBlockPtr(address));
 
-    //    entry->getProcOwner() = m_chip_ptr->getID(); // FIXME - This should not be hard coded
-    //    entry->getDirOwner() = true;        // FIXME - This should not be hard-coded
-
-    // load the data from physicalMemory when first initalizing
-    physical_address_t physAddr = address.getAddress();
-    int8 * dataArray = (int8 * )malloc(RubyConfig::dataBlockBytes() * sizeof(int8));
-    readPhysMem(physAddr, RubyConfig::dataBlockBytes(), dataArray);
-
-    for(int j=0; j < RubyConfig::dataBlockBytes(); j++) {
-      entry->getDataBlk().setByte(j, dataArray[j]);
-    }
-    DEBUG_EXPR(NODE_COMP, MedPrio,entry->getDataBlk());
     // store entry to the table
-    m_entries.insert(make_pair(index, entry));
+    m_entries[index] = entry;
   }
+
   return (*entry);
 }
+*/
 
-/*
 void DirectoryMemory::invalidateBlock(PhysAddress address)
 {
+  /*
   assert(isPresent(address));
 
   Index index = address.memoryModuleIndex();
     delete m_entries[index];
     m_entries[index] = NULL;
   }
-
+  */
 }
-*/
 
 void DirectoryMemory::print(ostream& out) const
 {
-  out << "Directory dump: " << endl;
-  for(map<Index, Directory_Entry*>::const_iterator it = m_entries.begin(); it != m_entries.end(); ++it) {
-      out << it->first << ": ";
-      out << *(it->second) << endl;
-  }
+
 }
 
 
 
 #include "mem/ruby/common/Global.hh"
 #include "mem/ruby/common/Address.hh"
+#include "mem/ruby/system/MemoryVector.hh"
 #include "mem/protocol/Directory_Entry.hh"
-#include <map>
 
-class Chip;
+class AbstractController;
 
 class DirectoryMemory {
 public:
   // Constructors
-  DirectoryMemory(Chip* chip_ptr, int version);
+  DirectoryMemory(const string & name);
+  void init(const vector<string> & argv);
+  //  DirectoryMemory(int version);
 
   // Destructor
   ~DirectoryMemory();
 
+  int mapAddressToLocalIdx(PhysAddress address);
+  static int mapAddressToDirectoryVersion(PhysAddress address);
+
+  int getSize() { return m_size_bytes; }
+
   // Public Methods
-  static void printConfig(ostream& out);
+  void printConfig(ostream& out) const;
+  static void printGlobalConfig(ostream & out);
   bool isPresent(PhysAddress address);
-  // dummy function
-  void readPhysMem(uint64 address, int size, void * data);
   Directory_Entry& lookup(PhysAddress address);
 
+  void invalidateBlock(PhysAddress address);
+
   void print(ostream& out) const;
 
 private:
   DirectoryMemory(const DirectoryMemory& obj);
   DirectoryMemory& operator=(const DirectoryMemory& obj);
 
+private:
+  const string m_name;
+  AbstractController* m_controller;
   // Data Members (m_ prefix)
-  map<Index, Directory_Entry*> m_entries;
-  Chip* m_chip_ptr;
-  int m_size;  // # of memory module blocks for this directory
+  Directory_Entry **m_entries;
+  //  int m_size;  // # of memory module blocks this directory is responsible for
+  uint32 m_size_bytes;
+  uint32 m_size_bits;
+  int m_num_entries;
   int m_version;
+
+  static int m_num_directories;
+  static int m_num_directories_bits;
+  static int m_total_size_bytes;
+
+  MemoryVector* m_ram;
 };
 
 // Output operator declaration
 
  *
  */
 
-#include <list>
-
-#include "base/cprintf.hh"
 #include "mem/ruby/common/Global.hh"
 #include "mem/gems_common/Map.hh"
 #include "mem/ruby/common/Address.hh"
 #include "mem/ruby/profiler/Profiler.hh"
-#include "mem/ruby/slicc_interface/AbstractChip.hh"
 #include "mem/ruby/system/System.hh"
 #include "mem/ruby/slicc_interface/RubySlicc_ComponentMapping.hh"
 #include "mem/ruby/slicc_interface/NetworkMessage.hh"
 #include "mem/ruby/network/Network.hh"
+
 #include "mem/ruby/common/Consumer.hh"
+
 #include "mem/ruby/system/MemoryControl.hh"
 
+#include <list>
+
 class Consumer;
 
 // Value to reset watchdog timer to.
 // ****************************************************************
 
 // CONSTRUCTOR
+MemoryControl::MemoryControl(const string & name)
+ : m_name(name)
+{
+  m_name = name;
+//  printf ("MemoryControl name is %s \n", m_name.c_str());
+}
+
+void MemoryControl::init(const vector<string> & argv)
+{
+
+  for (vector<string>::const_iterator it = argv.begin(); it != argv.end(); it++) {
+    if ( (*it) == "version" )
+      m_version = atoi( (*(++it)).c_str() );
+    else if ( (*it) == "mem_bus_cycle_multiplier" ) {
+      m_mem_bus_cycle_multiplier = atoi((*(++it)).c_str());
+    } else if ( (*it) == "banks_per_rank" ) {
+      m_banks_per_rank = atoi((*(++it)).c_str());
+    } else if ( (*it) == "ranks_per_dimm" ) {
+      m_ranks_per_dimm = atoi((*(++it)).c_str());
+    } else if ( (*it) == "dimms_per_channel" ) {
+      m_dimms_per_channel = atoi((*(++it)).c_str());
+    } else if ( (*it) == "bank_bit_0" ) {
+      m_bank_bit_0 = atoi((*(++it)).c_str());
+    } else if ( (*it) == "rank_bit_0" ) {
+      m_rank_bit_0 = atoi((*(++it)).c_str());
+    } else if ( (*it) == "dimm_bit_0" ) {
+      m_dimm_bit_0 = atoi((*(++it)).c_str());
+    } else if ( (*it) == "bank_queue_size" ) {
+      m_bank_queue_size = atoi((*(++it)).c_str());
+    } else if ( (*it) == "bank_busy_time" ) {
+      m_bank_busy_time = atoi((*(++it)).c_str());
+    } else if ( (*it) == "rank_rank_delay" ) {
+      m_rank_rank_delay = atoi((*(++it)).c_str());
+    } else if ( (*it) == "read_write_delay" ) {
+      m_read_write_delay = atoi((*(++it)).c_str());
+    } else if ( (*it) == "basic_bus_busy_time" ) {
+      m_basic_bus_busy_time = atoi((*(++it)).c_str());
+    } else if ( (*it) == "mem_ctl_latency" ) {
+      m_mem_ctl_latency = atoi((*(++it)).c_str());
+    } else if ( (*it) == "refresh_period" ) {
+      m_refresh_period = atoi((*(++it)).c_str());
+    } else if ( (*it) == "tFaw" ) {
+      m_tFaw = atoi((*(++it)).c_str());
+    } else if ( (*it) == "mem_random_arbitrate" ) {
+      m_mem_random_arbitrate = atoi((*(++it)).c_str());
+    } else if ( (*it) == "mem_fixed_delay" ) {
+      m_mem_fixed_delay = atoi((*(++it)).c_str());
+    }
+//    } else
+//      assert(0);
+  }
+
 
-MemoryControl::MemoryControl (AbstractChip* chip_ptr, int version) {
-  m_chip_ptr = chip_ptr;
-  m_version = version;
+///////
+  //m_version = version;
   m_msg_counter = 0;
 
   m_debug = 0;
   //if (m_version == 0) m_debug = 1;
 
-  m_mem_bus_cycle_multiplier = RubyConfig::memBusCycleMultiplier();
-  m_banks_per_rank           = RubyConfig::banksPerRank();
-  m_ranks_per_dimm           = RubyConfig::ranksPerDimm();
-  m_dimms_per_channel        = RubyConfig::dimmsPerChannel();
-  m_bank_bit_0               = RubyConfig::bankBit0();
-  m_rank_bit_0               = RubyConfig::rankBit0();
-  m_dimm_bit_0               = RubyConfig::dimmBit0();
-  m_bank_queue_size          = RubyConfig::bankQueueSize();
-  m_bank_busy_time           = RubyConfig::bankBusyTime();
-  m_rank_rank_delay          = RubyConfig::rankRankDelay();
-  m_read_write_delay         = RubyConfig::readWriteDelay();
-  m_basic_bus_busy_time      = RubyConfig::basicBusBusyTime();
-  m_mem_ctl_latency          = RubyConfig::memCtlLatency();
-  m_refresh_period           = RubyConfig::refreshPeriod();
-  m_memRandomArbitrate       = RubyConfig::memRandomArbitrate();
-  m_tFaw                     = RubyConfig::tFaw();
-  m_memFixedDelay            = RubyConfig::memFixedDelay();
 
   assert(m_tFaw <= 62); // must fit in a uint64 shift register
 
   Time arrival_time = memRef.m_time;
   uint64 at = arrival_time;
   bool is_mem_read = memRef.m_is_mem_read;
+  bool dirtyWB = memRef.m_is_dirty_wb;
   physical_address_t addr = memRef.m_addr;
   int bank = getBank(addr);
   if (m_debug) {
-    cprintf("New memory request%7d: %#08x %c arrived at %10d bank =%3x\n",
-            m_msg_counter, addr, is_mem_read? 'R':'W', at, bank);
+    printf("New memory request%7d: 0x%08llx %c arrived at %10lld  ", m_msg_counter, addr, is_mem_read? 'R':'W', at);
+    printf("bank =%3x\n", bank);
   }
-  g_system_ptr->getProfiler()->profileMemReq(bank);
+//  printf ("m_name is %s \n", m_name.c_str());
+  g_system_ptr->getProfiler()->profileMemReq(m_name, bank);
   m_input_queue.push_back(memRef);
   if (!m_awakened) {
     g_eventQueue_ptr->scheduleEvent(this, 1);
   MemoryNode req = m_response_queue.front();
   uint64 returnTime = req.m_time;
   if (m_debug) {
-    cprintf("Old memory request%7d: %#08x %c peeked at  %10d\n",
+    printf("Old memory request%7d: 0x%08llx %c peeked at  %10lld\n",
         req.m_msg_counter, req.m_addr, req.m_is_mem_read? 'R':'W', returnTime);
   }
   return req;
   out << "Memory Control " << m_version << ":" << endl;
   out << "  Ruby cycles per memory cycle: " << m_mem_bus_cycle_multiplier << endl;
   out << "  Basic read latency: " << m_mem_ctl_latency << endl;
-  if (m_memFixedDelay) {
-    out << "  Fixed Latency mode:  Added cycles = " << m_memFixedDelay << endl;
+  if (m_mem_fixed_delay) {
+    out << "  Fixed Latency mode:  Added cycles = " << m_mem_fixed_delay << endl;
   } else {
-    out << "  Bank busy time: " << BANK_BUSY_TIME << " memory cycles" << endl;
+    out << "  Bank busy time: " << m_bank_busy_time << " memory cycles" << endl;
     out << "  Memory channel busy time: " << m_basic_bus_busy_time << endl;
     out << "  Dead cycles between reads to different ranks: " << m_rank_rank_delay << endl;
     out << "  Dead cycle between a read and a write: " << m_read_write_delay << endl;
   out << "  LSB of DIMM field in address: " << m_dimm_bit_0 << endl;
   out << "  Max size of each bank queue: " << m_bank_queue_size << endl;
   out << "  Refresh period (within one bank): " << m_refresh_period << endl;
-  out << "  Arbitration randomness: " << m_memRandomArbitrate << endl;
+  out << "  Arbitration randomness: " << m_mem_random_arbitrate << endl;
 }
 
 
 // can be issued this cycle
 
 bool MemoryControl::queueReady (int bank) {
-  if ((m_bankBusyCounter[bank] > 0) && !m_memFixedDelay) {
-    g_system_ptr->getProfiler()->profileMemBankBusy();
-    //if (m_debug) cprintf("  bank %x busy %d\n", bank, m_bankBusyCounter[bank]);
+  if ((m_bankBusyCounter[bank] > 0) && !m_mem_fixed_delay) {
+    g_system_ptr->getProfiler()->profileMemBankBusy(m_name);
+    //if (m_debug) printf("  bank %x busy %d\n", bank, m_bankBusyCounter[bank]);
     return false;
   }
-  if (m_memRandomArbitrate >= 2) {
-    if ((random() % 100) < m_memRandomArbitrate) {
-      g_system_ptr->getProfiler()->profileMemRandBusy();
+  if (m_mem_random_arbitrate >= 2) {
+    if ((random() % 100) < m_mem_random_arbitrate) {
+      g_system_ptr->getProfiler()->profileMemRandBusy(m_name);
       return false;
     }
   }
-  if (m_memFixedDelay) return true;
+  if (m_mem_fixed_delay) return true;
   if ((m_ageCounter > (2 * m_bank_busy_time)) && !m_oldRequest[bank]) {
-    g_system_ptr->getProfiler()->profileMemNotOld();
+    g_system_ptr->getProfiler()->profileMemNotOld(m_name);
     return false;
   }
   if (m_busBusyCounter_Basic == m_basic_bus_busy_time) {
     // a bus wait.  This is a little inaccurate since it MIGHT
     // have also been blocked waiting for a read-write or a
     // read-read instead, but it's pretty close.
-    g_system_ptr->getProfiler()->profileMemArbWait(1);
+    g_system_ptr->getProfiler()->profileMemArbWait(m_name, 1);
     return false;
   }
   if (m_busBusyCounter_Basic > 0) {
-    g_system_ptr->getProfiler()->profileMemBusBusy();
+    g_system_ptr->getProfiler()->profileMemBusBusy(m_name);
     return false;
   }
   int rank = getRank(bank);
   if (m_tfaw_count[rank] >= ACTIVATE_PER_TFAW) {
-    g_system_ptr->getProfiler()->profileMemTfawBusy();
+    g_system_ptr->getProfiler()->profileMemTfawBusy(m_name);
     return false;
   }
   bool write = !m_bankQueues[bank].front().m_is_mem_read;
   if (write && (m_busBusyCounter_Write > 0)) {
-    g_system_ptr->getProfiler()->profileMemReadWriteBusy();
+    g_system_ptr->getProfiler()->profileMemReadWriteBusy(m_name);
     return false;
   }
   if (!write && (rank != m_busBusy_WhichRank)
              && (m_busBusyCounter_ReadNewRank > 0)) {
-    g_system_ptr->getProfiler()->profileMemDataBusBusy();
+    g_system_ptr->getProfiler()->profileMemDataBusBusy(m_name);
     return false;
   }
   return true;
 
   //if (m_debug) {
     //uint64 current_time = g_eventQueue_ptr->getTime();
-    //cprintf("    Refresh bank %3x at %d\n", bank, current_time);
+    //printf("    Refresh bank %3x at %lld\n", bank, current_time);
   //}
-  g_system_ptr->getProfiler()->profileMemRefresh();
+  g_system_ptr->getProfiler()->profileMemRefresh(m_name);
   m_need_refresh--;
   m_refresh_bank++;
   if (m_refresh_bank >= m_total_banks) m_refresh_bank = 0;
   m_bankQueues[bank].pop_front();
   if (m_debug) {
     uint64 current_time = g_eventQueue_ptr->getTime();
-    cprintf("    Mem issue request%7d: %#08x %c         at %10d  bank =%3x\n",
+    printf("    Mem issue request%7d: 0x%08llx %c         at %10lld  bank =%3x\n",
         req.m_msg_counter, req.m_addr, req.m_is_mem_read? 'R':'W', current_time, bank);
   }
   if (req.m_msgptr.ref() != NULL) {  // don't enqueue L3 writebacks
-    enqueueToDirectory(req, m_mem_ctl_latency + m_memFixedDelay);
+    enqueueToDirectory(req, m_mem_ctl_latency + m_mem_fixed_delay);
   }
   m_oldRequest[bank] = 0;
   markTfaw(rank);
   m_bankBusyCounter[bank] = m_bank_busy_time;
   m_busBusy_WhichRank = rank;
   if (req.m_is_mem_read) {
-    g_system_ptr->getProfiler()->profileMemRead();
+    g_system_ptr->getProfiler()->profileMemRead(m_name);
     m_busBusyCounter_Basic = m_basic_bus_busy_time;
     m_busBusyCounter_Write = m_basic_bus_busy_time + m_read_write_delay;
     m_busBusyCounter_ReadNewRank = m_basic_bus_busy_time + m_rank_rank_delay;
   } else {
-    g_system_ptr->getProfiler()->profileMemWrite();
+    g_system_ptr->getProfiler()->profileMemWrite(m_name);
     m_busBusyCounter_Basic = m_basic_bus_busy_time;
     m_busBusyCounter_Write = m_basic_bus_busy_time;
     m_busBusyCounter_ReadNewRank = m_basic_bus_busy_time;
   }
 
   // After time period expires, latch an indication that we need a refresh.
-  // Disable refresh if in memFixedDelay mode.
-  if (!m_memFixedDelay) m_refresh_count--;
+  // Disable refresh if in mem_fixed_delay mode.
+  if (!m_mem_fixed_delay) m_refresh_count--;
   if (m_refresh_count == 0) {
     m_refresh_count = m_refresh_period_system;
     assert (m_need_refresh < 10);  // Are we overrunning our ability to refresh?
   }
 
   // If randomness desired, re-randomize round-robin position each cycle
-  if (m_memRandomArbitrate) {
+  if (m_mem_random_arbitrate) {
     m_roundRobin = random() % m_total_banks;
   }
 
   // request and issue it.  Treat a refresh request as if it
   // were at the head of its bank queue.  After we issue something,
   // keep scanning the queues just to gather statistics about
-  // how many are waiting.  If in memFixedDelay mode, we can issue
+  // how many are waiting.  If in mem_fixed_delay mode, we can issue
   // more than one request per cycle.
 
   int queueHeads = 0;
     issueRefresh(m_roundRobin);
     int qs = m_bankQueues[m_roundRobin].size();
     if (qs > 1) {
-      g_system_ptr->getProfiler()->profileMemBankQ(qs-1);
+      g_system_ptr->getProfiler()->profileMemBankQ(m_name, qs-1);
     }
     if (qs > 0) {
       m_idleCount = IDLECOUNT_MAX_VALUE; // we're not idle if anything is queued
       if (queueReady(m_roundRobin)) {
         issueRequest(m_roundRobin);
         banksIssued++;
-        if (m_memFixedDelay) {
-          g_system_ptr->getProfiler()->profileMemWaitCycles(m_memFixedDelay);
+        if (m_mem_fixed_delay) {
+          g_system_ptr->getProfiler()->profileMemWaitCycles(m_name, m_mem_fixed_delay);
         }
       }
     }
   }
 
   // memWaitCycles is a redundant catch-all for the specific counters in queueReady
-  g_system_ptr->getProfiler()->profileMemWaitCycles(queueHeads - banksIssued);
+  g_system_ptr->getProfiler()->profileMemWaitCycles(m_name, queueHeads - banksIssued);
 
   // Check input queue and move anything to bank queues if not full.
   // Since this is done here at the end of the cycle, there will always
       m_input_queue.pop_front();
       m_bankQueues[bank].push_back(req);
     }
-    g_system_ptr->getProfiler()->profileMemInputQ(m_input_queue.size());
+    g_system_ptr->getProfiler()->profileMemInputQ(m_name, m_input_queue.size());
   }
 }
 
 
 #include "mem/gems_common/Map.hh"
 #include "mem/ruby/common/Address.hh"
 #include "mem/ruby/profiler/Profiler.hh"
-#include "mem/ruby/slicc_interface/AbstractChip.hh"
 #include "mem/ruby/system/System.hh"
 #include "mem/ruby/slicc_interface/Message.hh"
 #include "mem/gems_common/util.hh"
 public:
 
   // Constructors
-  MemoryControl (AbstractChip* chip_ptr, int version);
+  MemoryControl(const string & name);
+  void init(const vector<string> & argv);
 
   // Destructor
   ~MemoryControl ();
 
   void setConsumer (Consumer* consumer_ptr);
   Consumer* getConsumer () { return m_consumer_ptr; };
-  void setDescription (const string& name) { m_name = name; };
-  string getDescription () { return m_name; };
+  void setDescription (const string& name) { m_description = name; };
+  string getDescription () { return m_description; };
 
   // Called from the directory:
   void enqueue (const MsgPtr& message, int latency );
   void print (ostream& out) const;
   void setDebug (int debugFlag);
 
+
+  //added by SS
+  int getBanksPerRank() { return m_banks_per_rank; };
+  int getRanksPerDimm() { return m_ranks_per_dimm; };
+  int getDimmsPerChannel() { return m_dimms_per_channel; }
+
 private:
 
   void enqueueToDirectory (MemoryNode req, int latency);
   MemoryControl& operator=(const MemoryControl& obj);
 
   // data members
-  AbstractChip* m_chip_ptr;
   Consumer* m_consumer_ptr;  // Consumer to signal a wakeup()
   string m_name;
+  string m_description;
   int m_version;
   int m_msg_counter;
   int m_awakened;
   int m_basic_bus_busy_time;
   int m_mem_ctl_latency;
   int m_refresh_period;
-  int m_memRandomArbitrate;
+  int m_mem_random_arbitrate;
   int m_tFaw;
-  int m_memFixedDelay;
+  int m_mem_fixed_delay;
 
   int m_total_banks;
   int m_total_ranks;
 
--- /dev/null
+
+#ifndef MEMORYVECTOR_H
+#define MEMORYVECTOR_H
+
+#include "mem/ruby/common/Address.hh"
+
+class DirectoryMemory;
+
+/**
+ *  MemoryVector holds memory data (DRAM only)
+ */
+class MemoryVector {
+ public:
+  MemoryVector();
+  MemoryVector(uint32 size);
+  ~MemoryVector();
+  friend class DirectoryMemory;
+
+  void setSize(uint32 size);  // destructive
+
+  void write(const Address & paddr, uint8* data, int len);
+  uint8* read(const Address & paddr, uint8* data, int len);
+
+ private:
+  uint8* getBlockPtr(const Address & paddr);
+
+  uint32 m_size;
+  uint8* m_vec;
+};
+
+inline
+MemoryVector::MemoryVector()
+{
+  m_size = 0;
+  m_vec = NULL;
+}
+
+inline
+MemoryVector::MemoryVector(uint32 size)
+{
+  m_size = size;
+  m_vec = new uint8[size];
+}
+
+inline
+MemoryVector::~MemoryVector()
+{
+  delete [] m_vec;
+}
+
+inline
+void MemoryVector::setSize(uint32 size)
+{
+  m_size = size;
+  if (m_vec != NULL)
+    delete [] m_vec;
+  m_vec = new uint8[size];
+}
+
+inline
+void MemoryVector::write(const Address & paddr, uint8* data, int len)
+{
+  assert(paddr.getAddress() + len <= m_size);
+  memcpy(m_vec + paddr.getAddress(), data, len);
+}
+
+inline
+uint8* MemoryVector::read(const Address & paddr, uint8* data, int len)
+{
+  assert(paddr.getAddress() + len <= m_size);
+  memcpy(data, m_vec + paddr.getAddress(), len);
+  return data;
+}
+
+inline
+uint8* MemoryVector::getBlockPtr(const Address & paddr)
+{
+  return m_vec + paddr.getAddress();
+}
+
+#endif // MEMORYVECTOR_H
 
+++ /dev/null
-
-/*
- * 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.
- */
-
-/*
- * $Id: NodePersistentTable.C 1.3 04/08/16 14:12:33-05:00 beckmann@c2-143.cs.wisc.edu $
- *
- */
-
-#include "mem/ruby/system/NodePersistentTable.hh"
-#include "mem/ruby/common/Set.hh"
-#include "mem/gems_common/Map.hh"
-#include "mem/ruby/common/Address.hh"
-#include "mem/ruby/slicc_interface/AbstractChip.hh"
-#include "mem/gems_common/util.hh"
-
-// randomize so that handoffs are not locality-aware
-// int persistent_randomize[] = {0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15};
-int persistent_randomize[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
-
-
-class NodePersistentTableEntry {
-public:
-  Set m_starving;
-  Set m_marked;
-  Set m_request_to_write;
-};
-
-NodePersistentTable::NodePersistentTable(AbstractChip* chip_ptr, int version)
-{
-  m_chip_ptr = chip_ptr;
-  m_map_ptr = new Map<Address, NodePersistentTableEntry>;
-  m_version = version;
-}
-
-NodePersistentTable::~NodePersistentTable()
-{
-  delete m_map_ptr;
-  m_map_ptr = NULL;
-  m_chip_ptr = NULL;
-}
-
-void NodePersistentTable::persistentRequestLock(const Address& address, NodeID llocker, AccessType type)
-{
-
-  // if (locker == m_chip_ptr->getID()  )
-  // cout << "Chip " << m_chip_ptr->getID() << ": " << llocker << " requesting lock for " << address << endl;
-
-  NodeID locker = (NodeID) persistent_randomize[llocker];
-
-  assert(address == line_address(address));
-  if (!m_map_ptr->exist(address)) {
-    // Allocate if not present
-    NodePersistentTableEntry entry;
-    entry.m_starving.add(locker);
-    if (type == AccessType_Write) {
-      entry.m_request_to_write.add(locker);
-    }
-    m_map_ptr->add(address, entry);
-  } else {
-    NodePersistentTableEntry& entry = m_map_ptr->lookup(address);
-    assert(!(entry.m_starving.isElement(locker))); // Make sure we're not already in the locked set
-
-    entry.m_starving.add(locker);
-    if (type == AccessType_Write) {
-      entry.m_request_to_write.add(locker);
-    }
-    assert(entry.m_marked.isSubset(entry.m_starving));
-  }
-}
-
-void NodePersistentTable::persistentRequestUnlock(const Address& address, NodeID uunlocker)
-{
-  // if (unlocker == m_chip_ptr->getID() )
-  // cout << "Chip " << m_chip_ptr->getID() << ": " << uunlocker << " requesting unlock for " << address << endl;
-
-  NodeID unlocker = (NodeID) persistent_randomize[uunlocker];
-
-  assert(address == line_address(address));
-  assert(m_map_ptr->exist(address));
-  NodePersistentTableEntry& entry = m_map_ptr->lookup(address);
-  assert(entry.m_starving.isElement(unlocker)); // Make sure we're in the locked set
-  assert(entry.m_marked.isSubset(entry.m_starving));
-  entry.m_starving.remove(unlocker);
-  entry.m_marked.remove(unlocker);
-  entry.m_request_to_write.remove(unlocker);
-  assert(entry.m_marked.isSubset(entry.m_starving));
-
-  // Deallocate if empty
-  if (entry.m_starving.isEmpty()) {
-    assert(entry.m_marked.isEmpty());
-    m_map_ptr->erase(address);
-  }
-}
-
-bool NodePersistentTable::okToIssueStarving(const Address& address) const
-{
-  assert(address == line_address(address));
-  if (!m_map_ptr->exist(address)) {
-    return true; // No entry present
-  } else if (m_map_ptr->lookup(address).m_starving.isElement(m_chip_ptr->getID())) {
-    return false; // We can't issue another lockdown until are previous unlock has occurred
-  } else {
-    return (m_map_ptr->lookup(address).m_marked.isEmpty());
-  }
-}
-
-NodeID NodePersistentTable::findSmallest(const Address& address) const
-{
-  assert(address == line_address(address));
-  assert(m_map_ptr->exist(address));
-  const NodePersistentTableEntry& entry = m_map_ptr->lookup(address);
-  // cout << "Node " <<  m_chip_ptr->getID() << " returning " << persistent_randomize[entry.m_starving.smallestElement()] << " for findSmallest(" << address << ")" << endl;
-  return (NodeID) persistent_randomize[entry.m_starving.smallestElement()];
-}
-
-AccessType NodePersistentTable::typeOfSmallest(const Address& address) const
-{
-  assert(address == line_address(address));
-  assert(m_map_ptr->exist(address));
-  const NodePersistentTableEntry& entry = m_map_ptr->lookup(address);
-  if (entry.m_request_to_write.isElement(entry.m_starving.smallestElement())) {
-    return AccessType_Write;
-  } else {
-    return AccessType_Read;
-  }
-}
-
-void NodePersistentTable::markEntries(const Address& address)
-{
-  assert(address == line_address(address));
-  if (m_map_ptr->exist(address)) {
-    NodePersistentTableEntry& entry = m_map_ptr->lookup(address);
-    assert(entry.m_marked.isEmpty());  // None should be marked
-    entry.m_marked = entry.m_starving; // Mark all the nodes currently in the table
-  }
-}
-
-bool NodePersistentTable::isLocked(const Address& address) const
-{
-  assert(address == line_address(address));
-  // If an entry is present, it must be locked
-  return (m_map_ptr->exist(address));
-}
-
-int NodePersistentTable::countStarvingForAddress(const Address& address) const
-{
-  if (m_map_ptr->exist(address)) {
-    NodePersistentTableEntry& entry = m_map_ptr->lookup(address);
-    return (entry.m_starving.count());
-  }
-  else {
-    return 0;
-  }
-}
-
-int NodePersistentTable::countReadStarvingForAddress(const Address& address) const
-{
-  if (m_map_ptr->exist(address)) {
-    NodePersistentTableEntry& entry = m_map_ptr->lookup(address);
-    return (entry.m_starving.count() - entry.m_request_to_write.count());
-  }
-  else {
-    return 0;
-  }
-}
-
-
 
+++ /dev/null
-
-/*
- * 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.
- */
-
-/*
- * $Id: NodePersistentTable.hh 1.3 04/08/16 14:12:33-05:00 beckmann@c2-143.cs.wisc.edu $
- *
- * Description:
- *
- */
-
-#ifndef NodePersistentTable_H
-#define NodePersistentTable_H
-
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/system/NodeID.hh"
-#include "mem/protocol/AccessType.hh"
-
-class AbstractChip;
-
-template <class KEY_TYPE, class VALUE_TYPE> class Map;
-class Address;
-class NodePersistentTableEntry;
-
-class NodePersistentTable {
-public:
-  // Constructors
-  NodePersistentTable(AbstractChip* chip_ptr, int version);
-
-  // Destructor
-  ~NodePersistentTable();
-
-  // Public Methods
-  void persistentRequestLock(const Address& address, NodeID locker, AccessType type);
-  void persistentRequestUnlock(const Address& address, NodeID unlocker);
-  bool okToIssueStarving(const Address& address) const;
-  NodeID findSmallest(const Address& address) const;
-  AccessType typeOfSmallest(const Address& address) const;
-  void markEntries(const Address& address);
-  bool isLocked(const Address& addr) const;
-  int countStarvingForAddress(const Address& addr) const;
-  int countReadStarvingForAddress(const Address& addr) const;
-
-  static void printConfig(ostream& out) {}
-
-  void print(ostream& out) const;
-private:
-  // Private Methods
-
-  // Private copy constructor and assignment operator
-  NodePersistentTable(const NodePersistentTable& obj);
-  NodePersistentTable& operator=(const NodePersistentTable& obj);
-
-  // Data Members (m_prefix)
-  Map<Address, NodePersistentTableEntry>* m_map_ptr;
-  AbstractChip* m_chip_ptr;
-  int m_version;
-};
-
-// Output operator declaration
-ostream& operator<<(ostream& out, const NodePersistentTable& obj);
-
-// ******************* Definitions *******************
-
-// Output operator definition
-extern inline
-ostream& operator<<(ostream& out, const NodePersistentTable& obj)
-{
-  obj.print(out);
-  out << flush;
-  return out;
-}
-
-#endif //NodePersistentTable_H
 
+++ /dev/null
-
-/*
- * 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.
- */
-
-#include "mem/ruby/system/PersistentArbiter.hh"
-#include "mem/ruby/common/Address.hh"
-#include "mem/ruby/slicc_interface/AbstractChip.hh"
-#include "mem/gems_common/util.hh"
-
-PersistentArbiter::PersistentArbiter(AbstractChip* chip_ptr)
-{
-  m_chip_ptr = chip_ptr;
-
-  // wastes entries, but who cares
-  m_entries.setSize(RubyConfig::numberOfProcessors());
-
-  for (int i = 0; i < m_entries.size(); i++) {
-    m_entries[i].valid = false;
-  }
-
-  m_busy = false;
-  m_locker = -1;
-
-}
-
-PersistentArbiter::~PersistentArbiter()
-{
-  m_chip_ptr = NULL;
-}
-
-
-void PersistentArbiter::addLocker(NodeID id, Address addr, AccessType type) {
-  //cout << "Arbiter " << getArbiterId() << " adding locker " << id << " " << addr << endl;
-  assert(m_entries[id].valid == false);
-  m_entries[id].valid = true;
-  m_entries[id].address = addr;
-  m_entries[id].type = type;
-  m_entries[id].localId = id;
-
-}
-
-void PersistentArbiter::removeLocker(NodeID id) {
-  //cout << "Arbiter " << getArbiterId() << " removing locker " << id << " " << m_entries[id].address << endl;
-  assert(m_entries[id].valid == true);
-  m_entries[id].valid = false;
-
-  if (!lockersExist()) {
-    m_busy = false;
-  }
-}
-
-bool PersistentArbiter::successorRequestPresent(Address addr, NodeID id) {
-  for (int i = (id + 1); i < m_entries.size(); i++) {
-    if (m_entries[i].address == addr && m_entries[i].valid) {
-      //cout << "m_entries[" << id << ", address " << m_entries[id].address << " is equal to " << addr << endl;
-      return true;
-    }
-  }
-  return false;
-}
-
-bool PersistentArbiter::lockersExist() {
-  for (int i = 0; i < m_entries.size(); i++) {
-    if (m_entries[i].valid == true) {
-      return true;
-    }
-  }
-  //cout << "no lockers found" << endl;
-  return false;
-}
-
-void PersistentArbiter::advanceActiveLock() {
-  assert(lockersExist());
-
-  //cout << "arbiter advancing lock from " << m_locker;
-  m_busy = false;
-
-  if (m_locker < (m_entries.size() - 1)) {
-    for (int i = (m_locker+1); i < m_entries.size(); i++) {
-      if (m_entries[i].valid == true) {
-        m_locker = i;
-        m_busy = true;
-        //cout << " to " << m_locker << endl;
-        return;
-      }
-    }
-  }
-
-  if (!m_busy) {
-    for (int i = 0; i < m_entries.size(); i++) {
-      if (m_entries[i].valid == true) {
-        m_locker = i;
-        m_busy = true;
-        //cout << " to " << m_locker << endl;
-        return;
-      }
-    }
-
-    assert(m_busy)
-  }
-}
-
-Address PersistentArbiter::getActiveLockAddress() {
-  assert( m_entries[m_locker].valid = true );
-  return m_entries[m_locker].address;
-}
-
-
-NodeID PersistentArbiter::getArbiterId() {
-  return m_chip_ptr->getID()*RubyConfig::numberOfProcsPerChip();
-}
-
-bool PersistentArbiter::isBusy() {
-  return m_busy;
-}
-
-NodeID PersistentArbiter::getActiveLocalId() {
-  assert( m_entries[m_locker].valid = true );
-  return m_entries[m_locker].localId;
-}
-
-void PersistentArbiter::setIssuedAddress(Address addr) {
-  m_issued_address = addr;
-}
-
-bool PersistentArbiter::isIssuedAddress(Address addr) {
-  return (m_issued_address == addr);
-}
-
-void PersistentArbiter::print(ostream& out) const {
-
-  out << "[";
-  for (int i = 0; i < m_entries.size(); i++) {
-    if (m_entries[i].valid == true) {
-      out << "( " << m_entries[i].localId  << ", " << m_entries[i].address << ") ";
-    }
-  }
-  out << "]" << endl;
-
-}
 
+++ /dev/null
-
-/*
- * 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.
- */
-
-/*
- * PersistentArbiter.hh
- *
- * Description:
- *
- * Used for hierarchical distributed persistent request scheme
- *
- */
-
-#ifndef PERSISTENTARBITER_H
-#define PERSISTENTARBITER_H
-
-#include "mem/ruby/common/Global.hh"
-#include "mem/gems_common/Vector.hh"
-#include "mem/ruby/slicc_interface/AbstractChip.hh"
-#include "mem/protocol/AccessPermission.hh"
-#include "mem/protocol/AccessType.hh"
-#include "mem/ruby/config/RubyConfig.hh"
-#include "mem/ruby/common/Address.hh"
-
-struct ArbiterEntry {
-  bool valid;
-  Address address;
-  AccessType type;
-  NodeID localId;
-};
-
-class PersistentArbiter {
-public:
-
-  // Constructors
-  PersistentArbiter(AbstractChip* chip_ptr);
-
-  // Destructor
-  ~PersistentArbiter();
-
-  // Public Methods
-
-  void addLocker(NodeID id, Address addr, AccessType type);
-  void removeLocker(NodeID id);
-  bool successorRequestPresent(Address addr, NodeID id);
-  bool lockersExist();
-  void advanceActiveLock();
-  Address getActiveLockAddress();
-  NodeID getArbiterId();
-  bool isBusy();
-
-  void setIssuedAddress(Address addr);
-  bool isIssuedAddress(Address addr);
-
-
-  Address getIssuedAddress() { return m_issued_address; }
-
-  static void printConfig(ostream& out) {}
-  void print(ostream& out) const;
-
-  NodeID getActiveLocalId();
-
-private:
-
-  Address m_issued_address;
-  AbstractChip* m_chip_ptr;
-  int m_locker;
-  bool m_busy;
-  Vector<ArbiterEntry> m_entries;
-};
-
-// Output operator definition
-extern inline
-ostream& operator<<(ostream& out, const PersistentArbiter& obj)
-{
-  obj.print(out);
-  out << flush;
-  return out;
-}
-
-
-#endif //PERFECTCACHEMEMORY_H
 
+++ /dev/null
-
-/*
- * 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.
- */
-
-/*
- * $Id$
- *
- */
-
-#include "mem/ruby/system/PersistentTable.hh"
-#include "mem/ruby/common/NetDest.hh"
-#include "mem/gems_common/Map.hh"
-#include "mem/ruby/common/Address.hh"
-#include "mem/ruby/slicc_interface/AbstractChip.hh"
-#include "mem/gems_common/util.hh"
-
-// randomize so that handoffs are not locality-aware
-// int persistent_randomize[] = {0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15};
-// int persistent_randomize[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
-
-
-class PersistentTableEntry {
-public:
-  NetDest m_starving;
-  NetDest m_marked;
-  NetDest m_request_to_write;
-};
-
-PersistentTable::PersistentTable(AbstractChip* chip_ptr, int version)
-{
-  m_chip_ptr = chip_ptr;
-  m_map_ptr = new Map<Address, PersistentTableEntry>;
-  m_version = version;
-}
-
-PersistentTable::~PersistentTable()
-{
-  delete m_map_ptr;
-  m_map_ptr = NULL;
-  m_chip_ptr = NULL;
-}
-
-void PersistentTable::persistentRequestLock(const Address& address, MachineID locker, AccessType type)
-{
-
-  // if (locker == m_chip_ptr->getID()  )
-  // cout << "Chip " << m_chip_ptr->getID() << ": " << llocker << " requesting lock for " << address << endl;
-
-  // MachineID locker = (MachineID) persistent_randomize[llocker];
-
-  assert(address == line_address(address));
-  if (!m_map_ptr->exist(address)) {
-    // Allocate if not present
-    PersistentTableEntry entry;
-    entry.m_starving.add(locker);
-    if (type == AccessType_Write) {
-      entry.m_request_to_write.add(locker);
-    }
-    m_map_ptr->add(address, entry);
-  } else {
-    PersistentTableEntry& entry = m_map_ptr->lookup(address);
-    assert(!(entry.m_starving.isElement(locker))); // Make sure we're not already in the locked set
-
-    entry.m_starving.add(locker);
-    if (type == AccessType_Write) {
-      entry.m_request_to_write.add(locker);
-    }
-    assert(entry.m_marked.isSubset(entry.m_starving));
-  }
-}
-
-void PersistentTable::persistentRequestUnlock(const Address& address, MachineID unlocker)
-{
-  // if (unlocker == m_chip_ptr->getID() )
-  // cout << "Chip " << m_chip_ptr->getID() << ": " << uunlocker << " requesting unlock for " << address << endl;
-
-  // MachineID unlocker = (MachineID) persistent_randomize[uunlocker];
-
-  assert(address == line_address(address));
-  assert(m_map_ptr->exist(address));
-  PersistentTableEntry& entry = m_map_ptr->lookup(address);
-  assert(entry.m_starving.isElement(unlocker)); // Make sure we're in the locked set
-  assert(entry.m_marked.isSubset(entry.m_starving));
-  entry.m_starving.remove(unlocker);
-  entry.m_marked.remove(unlocker);
-  entry.m_request_to_write.remove(unlocker);
-  assert(entry.m_marked.isSubset(entry.m_starving));
-
-  // Deallocate if empty
-  if (entry.m_starving.isEmpty()) {
-    assert(entry.m_marked.isEmpty());
-    m_map_ptr->erase(address);
-  }
-}
-
-bool PersistentTable::okToIssueStarving(const Address& address) const
-{
-  assert(address == line_address(address));
-  if (!m_map_ptr->exist(address)) {
-    return true; // No entry present
-  } else if (m_map_ptr->lookup(address).m_starving.isElement( (MachineID) {MachineType_L1Cache, m_version})) {
-    return false; // We can't issue another lockdown until are previous unlock has occurred
-  } else {
-    return (m_map_ptr->lookup(address).m_marked.isEmpty());
-  }
-}
-
-MachineID PersistentTable::findSmallest(const Address& address) const
-{
-  assert(address == line_address(address));
-  assert(m_map_ptr->exist(address));
-  const PersistentTableEntry& entry = m_map_ptr->lookup(address);
-  // cout << "Node " <<  m_chip_ptr->getID() << " returning " << persistent_randomize[entry.m_starving.smallestElement()] << " for findSmallest(" << address << ")" << endl;
-  // return (MachineID) persistent_randomize[entry.m_starving.smallestElement()];
-  return (MachineID) { MachineType_L1Cache, entry.m_starving.smallestElement() };
-}
-
-AccessType PersistentTable::typeOfSmallest(const Address& address) const
-{
-  assert(address == line_address(address));
-  assert(m_map_ptr->exist(address));
-  const PersistentTableEntry& entry = m_map_ptr->lookup(address);
-  if (entry.m_request_to_write.isElement((MachineID) {MachineType_L1Cache, entry.m_starving.smallestElement()})) {
-    return AccessType_Write;
-  } else {
-    return AccessType_Read;
-  }
-}
-
-void PersistentTable::markEntries(const Address& address)
-{
-  assert(address == line_address(address));
-  if (m_map_ptr->exist(address)) {
-    PersistentTableEntry& entry = m_map_ptr->lookup(address);
-    assert(entry.m_marked.isEmpty());  // None should be marked
-    entry.m_marked = entry.m_starving; // Mark all the nodes currently in the table
-  }
-}
-
-bool PersistentTable::isLocked(const Address& address) const
-{
-  assert(address == line_address(address));
-  // If an entry is present, it must be locked
-  return (m_map_ptr->exist(address));
-}
-
-int PersistentTable::countStarvingForAddress(const Address& address) const
-{
-  if (m_map_ptr->exist(address)) {
-    PersistentTableEntry& entry = m_map_ptr->lookup(address);
-    return (entry.m_starving.count());
-  }
-  else {
-    return 0;
-  }
-}
-
-int PersistentTable::countReadStarvingForAddress(const Address& address) const
-{
-  if (m_map_ptr->exist(address)) {
-    PersistentTableEntry& entry = m_map_ptr->lookup(address);
-    return (entry.m_starving.count() - entry.m_request_to_write.count());
-  }
-  else {
-    return 0;
-  }
-}
-
-
 
+++ /dev/null
-
-/*
- * 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.
- */
-
-/*
- * $Id$
- *
- * Description:
- *
- */
-
-#ifndef PersistentTable_H
-#define PersistentTable_H
-
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/system/MachineID.hh"
-#include "mem/protocol/AccessType.hh"
-
-class AbstractChip;
-
-template <class KEY_TYPE, class VALUE_TYPE> class Map;
-class Address;
-class PersistentTableEntry;
-
-class PersistentTable {
-public:
-  // Constructors
-  PersistentTable(AbstractChip* chip_ptr, int version);
-
-  // Destructor
-  ~PersistentTable();
-
-  // Public Methods
-  void persistentRequestLock(const Address& address, MachineID locker, AccessType type);
-  void persistentRequestUnlock(const Address& address, MachineID unlocker);
-  bool okToIssueStarving(const Address& address) const;
-  MachineID findSmallest(const Address& address) const;
-  AccessType typeOfSmallest(const Address& address) const;
-  void markEntries(const Address& address);
-  bool isLocked(const Address& addr) const;
-  int countStarvingForAddress(const Address& addr) const;
-  int countReadStarvingForAddress(const Address& addr) const;
-
-  static void printConfig(ostream& out) {}
-
-  void print(ostream& out) const;
-private:
-  // Private Methods
-
-  // Private copy constructor and assignment operator
-  PersistentTable(const PersistentTable& obj);
-  PersistentTable& operator=(const PersistentTable& obj);
-
-  // Data Members (m_prefix)
-  Map<Address, PersistentTableEntry>* m_map_ptr;
-  AbstractChip* m_chip_ptr;
-  int m_version;
-};
-
-// Output operator declaration
-ostream& operator<<(ostream& out, const PersistentTable& obj);
-
-// ******************* Definitions *******************
-
-// Output operator definition
-extern inline
-ostream& operator<<(ostream& out, const PersistentTable& obj)
-{
-  obj.print(out);
-  out << flush;
-  return out;
-}
-
-#endif //PersistentTable_H
 
--- /dev/null
+
+struct ProcessorRequest {
+  vector<CacheRequest*> cache_requests;
+};
+
+class ProcessorInterface {
+
+public:
+
+  void read_atomic(const Address & paddr, void* data, int len) {
+    assert(paddr.getLineAddress() + RubyConfig::dataBlockBytes() >= paddr + len);
+    // for now, atomics can't span two blocks.  Maybe fix this later
+  }
+
+  void read(const Address & paddr, const Address & rip, AccessModeType atype, void* data, const int len) {
+
+    // create the CacheRequests
+    ProcessorRequest* this_request = new ProcessorRequest;
+    Address split_addr = paddr;
+    int len_remaining = len;
+    while (split_addr.getAddress() < paddr.getAddress() + len) {
+      int split_len = (split_addr.getAddress() + len_remaining <= split_addr.getLineAddress() + RubyConfig::dataBlockBytes()) ?
+        len_remaining :
+        RubyConfig::dataBlockBytes() - split_addr.getOffset();
+      CacheRequest creq = new CacheRequest( line_address(split_addr),
+                                            split_addr,
+                                            CacheRequestType_LD,
+                                            rip,
+                                            atype,
+                                            split_len,
+                                            PretchBit_No,
+                                            laddr,
+                                            0);  // SMT thread id);
+      this_request->cache_requests.push_back(creq);
+      split_addr += split_len;
+      len_remaining -= split_len;
+    }
+    outstanding_requests.push_back(this_request);
+
+  }
+
+private:
+  vector<ProcessorRequest*> outstanding_requests;
+  Sequencer* m_sequencer;
+};
 
--- /dev/null
+
+#include "mem/ruby/system/RubyPort.hh"
+
+//void (*RubyPort::m_hit_callback)(int64_t) = NULL;
+uint16_t RubyPort::m_num_ports = 0;
 
--- /dev/null
+#ifndef RUBYPORT_H
+#define RUBYPORT_H
+
+#include "mem/ruby/libruby.hh"
+#include <string>
+#include <assert.h>
+
+using namespace std;
+
+class RubyPort {
+public:
+  RubyPort(const string & name)
+    : m_name(name)
+  {
+    m_port_id = m_num_ports++;
+    m_request_cnt = 0;
+    m_hit_callback = NULL;
+    assert(m_num_ports <= 2048); // see below for reason
+  }
+  virtual ~RubyPort() {}
+
+  virtual int64_t makeRequest(const RubyRequest & request) = 0;
+
+  void registerHitCallback(void (*hit_callback)(int64_t request_id)) {
+    assert(m_hit_callback == NULL); // can't assign hit_callback twice
+    m_hit_callback = hit_callback;
+  }
+
+protected:
+  const string m_name;
+  void (*m_hit_callback)(int64_t);
+
+  int64_t makeUniqueRequestID() {
+    // The request ID is generated by combining the port ID with a request count
+    // so that request IDs can be formed concurrently by multiple threads.
+    // IDs are formed as follows:
+    //
+    //
+    //   0        PortID                         Request Count
+    // +----+---------------+-----------------------------------------------------+
+    // | 63 |     62-48     |                         47-0                        |
+    // +----+---------------+-----------------------------------------------------+
+    //
+    //
+    //  This limits the system to a maximum of 2^11 == 2048 components
+    //  and 2^48 ~= 3x10^14 requests per component
+
+    int64_t id = (static_cast<uint64_t>(m_port_id) << 48) | m_request_cnt;
+    m_request_cnt++;
+    // assert((m_request_cnt & (1<<48)) == 0);
+    return id;
+  }
+
+private:
+  static uint16_t m_num_ports;
+  uint16_t m_port_id;
+  uint64_t m_request_cnt;
+};
+
+#endif
 
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-/*
- * $Id: Sequencer.C 1.131 2006/11/06 17:41:01-06:00 bobba@gratiano.cs.wisc.edu $
- *
- */
-
 #include "mem/ruby/common/Global.hh"
 #include "mem/ruby/system/Sequencer.hh"
 #include "mem/ruby/system/System.hh"
 #include "mem/protocol/Protocol.hh"
 #include "mem/ruby/profiler/Profiler.hh"
 #include "mem/ruby/system/CacheMemory.hh"
-#include "mem/ruby/config/RubyConfig.hh"
-//#include "mem/ruby/recorder/Tracer.hh"
-#include "mem/ruby/slicc_interface/AbstractChip.hh"
-#include "mem/protocol/Chip.hh"
-#include "mem/ruby/tester/Tester.hh"
+#include "mem/protocol/CacheMsg.hh"
+#include "mem/ruby/recorder/Tracer.hh"
 #include "mem/ruby/common/SubBlock.hh"
 #include "mem/protocol/Protocol.hh"
 #include "mem/gems_common/Map.hh"
-#include "mem/packet.hh"
+#include "mem/ruby/buffers/MessageBuffer.hh"
+#include "mem/ruby/slicc_interface/AbstractController.hh"
 
-Sequencer::Sequencer(AbstractChip* chip_ptr, int version) {
-  m_chip_ptr = chip_ptr;
-  m_version = version;
+//Sequencer::Sequencer(int core_id, MessageBuffer* mandatory_q)
 
+Sequencer::Sequencer(const string & name)
+  :RubyPort(name)
+{
+}
+
+void Sequencer::init(const vector<string> & argv)
+{
   m_deadlock_check_scheduled = false;
   m_outstanding_count = 0;
 
-  int smt_threads = RubyConfig::numberofSMTThreads();
-  m_writeRequestTable_ptr = new Map<Address, CacheMsg>*[smt_threads];
-  m_readRequestTable_ptr = new Map<Address, CacheMsg>*[smt_threads];
-
-  m_packetTable_ptr = new Map<Address, Packet*>;
-
-  for(int p=0; p < smt_threads; ++p){
-    m_writeRequestTable_ptr[p] = new Map<Address, CacheMsg>;
-    m_readRequestTable_ptr[p] = new Map<Address, CacheMsg>;
+  m_max_outstanding_requests = 0;
+  m_deadlock_threshold = 0;
+  m_version = -1;
+  m_instCache_ptr = NULL;
+  m_dataCache_ptr = NULL;
+  m_controller = NULL;
+  for (size_t i=0; i<argv.size(); i+=2) {
+    if ( argv[i] == "controller") {
+      m_controller = RubySystem::getController(argv[i+1]); // args[i] = "L1Cache"
+      m_mandatory_q_ptr = m_controller->getMandatoryQueue();
+    } else if ( argv[i] == "icache")
+      m_instCache_ptr = RubySystem::getCache(argv[i+1]);
+    else if ( argv[i] == "dcache")
+      m_dataCache_ptr = RubySystem::getCache(argv[i+1]);
+    else if ( argv[i] == "version")
+      m_version = atoi(argv[i+1].c_str());
+    else if ( argv[i] == "max_outstanding_requests")
+      m_max_outstanding_requests = atoi(argv[i+1].c_str());
+    else if ( argv[i] == "deadlock_threshold")
+      m_deadlock_threshold = atoi(argv[i+1].c_str());
+    else {
+      cerr << "WARNING: Sequencer: Unkown configuration parameter: " << argv[i] << endl;
+      assert(false);
+    }
   }
-
+  assert(m_max_outstanding_requests > 0);
+  assert(m_deadlock_threshold > 0);
+  assert(m_version > -1);
+  assert(m_instCache_ptr != NULL);
+  assert(m_dataCache_ptr != NULL);
+  assert(m_controller != NULL);
 }
 
 Sequencer::~Sequencer() {
-  int smt_threads = RubyConfig::numberofSMTThreads();
-  for(int i=0; i < smt_threads; ++i){
-    if(m_writeRequestTable_ptr[i]){
-      delete m_writeRequestTable_ptr[i];
-    }
-    if(m_readRequestTable_ptr[i]){
-      delete m_readRequestTable_ptr[i];
-    }
-  }
-  if(m_writeRequestTable_ptr){
-    delete [] m_writeRequestTable_ptr;
-  }
-  if(m_readRequestTable_ptr){
-    delete [] m_readRequestTable_ptr;
-  }
+
 }
 
 void Sequencer::wakeup() {
   // Check for deadlock of any of the requests
   Time current_time = g_eventQueue_ptr->getTime();
-  bool deadlock = false;
 
   // Check across all outstanding requests
-  int smt_threads = RubyConfig::numberofSMTThreads();
   int total_outstanding = 0;
-  for(int p=0; p < smt_threads; ++p){
-    Vector<Address> keys = m_readRequestTable_ptr[p]->keys();
-    for (int i=0; i<keys.size(); i++) {
-      CacheMsg& request = m_readRequestTable_ptr[p]->lookup(keys[i]);
-      if (current_time - request.getTime() >= g_DEADLOCK_THRESHOLD) {
-        WARN_MSG("Possible Deadlock detected");
-        WARN_EXPR(request);
-        WARN_EXPR(m_chip_ptr->getID());
-        WARN_EXPR(m_version);
-        WARN_EXPR(keys.size());
-        WARN_EXPR(current_time);
-        WARN_EXPR(request.getTime());
-        WARN_EXPR(current_time - request.getTime());
-        WARN_EXPR(*m_readRequestTable_ptr[p]);
-        ERROR_MSG("Aborting");
-        deadlock = true;
-      }
-    }
 
-    keys = m_writeRequestTable_ptr[p]->keys();
-    for (int i=0; i<keys.size(); i++) {
-      CacheMsg& request = m_writeRequestTable_ptr[p]->lookup(keys[i]);
-      if (current_time - request.getTime() >= g_DEADLOCK_THRESHOLD) {
-        WARN_MSG("Possible Deadlock detected");
-        WARN_EXPR(request);
-        WARN_EXPR(m_chip_ptr->getID());
-        WARN_EXPR(m_version);
-        WARN_EXPR(current_time);
-        WARN_EXPR(request.getTime());
-        WARN_EXPR(current_time - request.getTime());
-        WARN_EXPR(keys.size());
-        WARN_EXPR(*m_writeRequestTable_ptr[p]);
-        ERROR_MSG("Aborting");
-        deadlock = true;
-      }
-    }
-    total_outstanding += m_writeRequestTable_ptr[p]->size() + m_readRequestTable_ptr[p]->size();
-  }  // across all request tables
+  Vector<Address> keys = m_readRequestTable.keys();
+  for (int i=0; i<keys.size(); i++) {
+    SequencerRequest* request = m_readRequestTable.lookup(keys[i]);
+    if (current_time - request->issue_time >= m_deadlock_threshold) {
+      WARN_MSG("Possible Deadlock detected");
+      WARN_EXPR(request);
+      WARN_EXPR(m_version);
+      WARN_EXPR(keys.size());
+      WARN_EXPR(current_time);
+      WARN_EXPR(request->issue_time);
+      WARN_EXPR(current_time - request->issue_time);
+      ERROR_MSG("Aborting");
+    }
+  }
+
+  keys = m_writeRequestTable.keys();
+  for (int i=0; i<keys.size(); i++) {
+    SequencerRequest* request = m_writeRequestTable.lookup(keys[i]);
+    if (current_time - request->issue_time >= m_deadlock_threshold) {
+      WARN_MSG("Possible Deadlock detected");
+      WARN_EXPR(request);
+      WARN_EXPR(m_version);
+      WARN_EXPR(current_time);
+      WARN_EXPR(request->issue_time);
+      WARN_EXPR(current_time - request->issue_time);
+      WARN_EXPR(keys.size());
+      ERROR_MSG("Aborting");
+    }
+  }
+  total_outstanding += m_writeRequestTable.size() + m_readRequestTable.size();
+
   assert(m_outstanding_count == total_outstanding);
 
   if (m_outstanding_count > 0) { // If there are still outstanding requests, keep checking
-    g_eventQueue_ptr->scheduleEvent(this, g_DEADLOCK_THRESHOLD);
+    g_eventQueue_ptr->scheduleEvent(this, m_deadlock_threshold);
   } else {
     m_deadlock_check_scheduled = false;
   }
 }
 
-//returns the total number of requests
-int Sequencer::getNumberOutstanding(){
-  return m_outstanding_count;
-}
-
-// returns the total number of demand requests
-int Sequencer::getNumberOutstandingDemand(){
-  int smt_threads = RubyConfig::numberofSMTThreads();
-  int total_demand = 0;
-  for(int p=0; p < smt_threads; ++p){
-    Vector<Address> keys = m_readRequestTable_ptr[p]->keys();
-    for (int i=0; i< keys.size(); i++) {
-      CacheMsg& request = m_readRequestTable_ptr[p]->lookup(keys[i]);
-      if(request.getPrefetch() == PrefetchBit_No){
-        total_demand++;
-      }
-    }
-
-    keys = m_writeRequestTable_ptr[p]->keys();
-    for (int i=0; i< keys.size(); i++) {
-      CacheMsg& request = m_writeRequestTable_ptr[p]->lookup(keys[i]);
-      if(request.getPrefetch() == PrefetchBit_No){
-        total_demand++;
-      }
-    }
-  }
-
-  return total_demand;
-}
-
-int Sequencer::getNumberOutstandingPrefetch(){
-  int smt_threads = RubyConfig::numberofSMTThreads();
-  int total_prefetch = 0;
-  for(int p=0; p < smt_threads; ++p){
-    Vector<Address> keys = m_readRequestTable_ptr[p]->keys();
-    for (int i=0; i< keys.size(); i++) {
-      CacheMsg& request = m_readRequestTable_ptr[p]->lookup(keys[i]);
-      if(request.getPrefetch() == PrefetchBit_Yes){
-        total_prefetch++;
-      }
-    }
-
-    keys = m_writeRequestTable_ptr[p]->keys();
-    for (int i=0; i< keys.size(); i++) {
-      CacheMsg& request = m_writeRequestTable_ptr[p]->lookup(keys[i]);
-      if(request.getPrefetch() == PrefetchBit_Yes){
-        total_prefetch++;
-      }
-    }
-  }
-
-  return total_prefetch;
-}
-
-bool Sequencer::isPrefetchRequest(const Address & lineaddr){
-  int smt_threads = RubyConfig::numberofSMTThreads();
-  for(int p=0; p < smt_threads; ++p){
-    // check load requests
-    Vector<Address> keys = m_readRequestTable_ptr[p]->keys();
-    for (int i=0; i< keys.size(); i++) {
-      CacheMsg& request = m_readRequestTable_ptr[p]->lookup(keys[i]);
-      if(line_address(request.getAddress()) == lineaddr){
-        if(request.getPrefetch() == PrefetchBit_Yes){
-          return true;
-        }
-        else{
-          return false;
-        }
-      }
-    }
-
-    // check store requests
-    keys = m_writeRequestTable_ptr[p]->keys();
-    for (int i=0; i< keys.size(); i++) {
-      CacheMsg& request = m_writeRequestTable_ptr[p]->lookup(keys[i]);
-      if(line_address(request.getAddress()) == lineaddr){
-        if(request.getPrefetch() == PrefetchBit_Yes){
-          return true;
-        }
-        else{
-          return false;
-        }
-      }
-    }
-  }
-  // we should've found a matching request
-  cout << "isRequestPrefetch() ERROR request NOT FOUND : " << lineaddr << endl;
-  printProgress(cout);
-  assert(0);
-}
-
-AccessModeType Sequencer::getAccessModeOfRequest(Address addr, int thread){
-  if(m_readRequestTable_ptr[thread]->exist(line_address(addr))){
-    CacheMsg& request = m_readRequestTable_ptr[thread]->lookup(addr);
-    return request.getAccessMode();
-  } else if(m_writeRequestTable_ptr[thread]->exist(line_address(addr))){
-    CacheMsg& request = m_writeRequestTable_ptr[thread]->lookup(addr);
-    return request.getAccessMode();
-  } else {
-    printProgress(cout);
-    ERROR_MSG("Request not found in RequestTables");
-  }
-}
-
-Address Sequencer::getLogicalAddressOfRequest(Address addr, int thread){
-  assert(thread >= 0);
-  if(m_readRequestTable_ptr[thread]->exist(line_address(addr))){
-    CacheMsg& request = m_readRequestTable_ptr[thread]->lookup(addr);
-    return request.getLogicalAddress();
-  } else if(m_writeRequestTable_ptr[thread]->exist(line_address(addr))){
-    CacheMsg& request = m_writeRequestTable_ptr[thread]->lookup(addr);
-    return request.getLogicalAddress();
-  } else {
-    printProgress(cout);
-    WARN_MSG("Request not found in RequestTables");
-    WARN_MSG(addr);
-    WARN_MSG(thread);
-    ASSERT(0);
-  }
-}
-
-// returns the ThreadID of the request
-int Sequencer::getRequestThreadID(const Address & addr){
-  int smt_threads = RubyConfig::numberofSMTThreads();
-  int thread = -1;
-  int num_found = 0;
-  for(int p=0; p < smt_threads; ++p){
-    if(m_readRequestTable_ptr[p]->exist(addr)){
-      num_found++;
-      thread = p;
-    }
-    if(m_writeRequestTable_ptr[p]->exist(addr)){
-      num_found++;
-      thread = p;
-    }
-  }
-  if(num_found != 1){
-    cout << "getRequestThreadID ERROR too many matching requests addr = " << addr << endl;
-    printProgress(cout);
-  }
-  ASSERT(num_found == 1);
-  ASSERT(thread != -1);
-
-  return thread;
-}
-
-// given a line address, return the request's physical address
-Address Sequencer::getRequestPhysicalAddress(const Address & lineaddr){
-  int smt_threads = RubyConfig::numberofSMTThreads();
-  Address physaddr;
-  int num_found = 0;
-  for(int p=0; p < smt_threads; ++p){
-    if(m_readRequestTable_ptr[p]->exist(lineaddr)){
-      num_found++;
-      physaddr = (m_readRequestTable_ptr[p]->lookup(lineaddr)).getAddress();
-    }
-    if(m_writeRequestTable_ptr[p]->exist(lineaddr)){
-      num_found++;
-      physaddr = (m_writeRequestTable_ptr[p]->lookup(lineaddr)).getAddress();
-    }
-  }
-  if(num_found != 1){
-    cout << "getRequestPhysicalAddress ERROR too many matching requests addr = " << lineaddr << endl;
-    printProgress(cout);
-  }
-  ASSERT(num_found == 1);
-
-  return physaddr;
-}
-
 void Sequencer::printProgress(ostream& out) const{
-
+  /*
   int total_demand = 0;
   out << "Sequencer Stats Version " << m_version << endl;
   out << "Current time = " << g_eventQueue_ptr->getTime() << endl;
   out << "---------------" << endl;
   out << "outstanding requests" << endl;
 
-  int smt_threads = RubyConfig::numberofSMTThreads();
-  for(int p=0; p < smt_threads; ++p){
-    Vector<Address> rkeys = m_readRequestTable_ptr[p]->keys();
-    int read_size = rkeys.size();
-    out << "proc " << m_chip_ptr->getID() << " thread " << p << " Read Requests = " << read_size << endl;
-    // print the request table
-    for(int i=0; i < read_size; ++i){
-      CacheMsg & request = m_readRequestTable_ptr[p]->lookup(rkeys[i]);
-      out << "\tRequest[ " << i << " ] = " << request.getType() << " Address " << rkeys[i]  << " Posted " << request.getTime() << " PF " << request.getPrefetch() << endl;
-      if( request.getPrefetch() == PrefetchBit_No ){
-        total_demand++;
-      }
-    }
-
-    Vector<Address> wkeys = m_writeRequestTable_ptr[p]->keys();
-    int write_size = wkeys.size();
-    out << "proc " << m_chip_ptr->getID() << " thread " << p << " Write Requests = " << write_size << endl;
-    // print the request table
-    for(int i=0; i < write_size; ++i){
-      CacheMsg & request = m_writeRequestTable_ptr[p]->lookup(wkeys[i]);
+  Vector<Address> rkeys = m_readRequestTable.keys();
+  int read_size = rkeys.size();
+  out << "proc " << m_version << " Read Requests = " << read_size << endl;
+  // print the request table
+  for(int i=0; i < read_size; ++i){
+    SequencerRequest * request = m_readRequestTable.lookup(rkeys[i]);
+    out << "\tRequest[ " << i << " ] = " << request->type << " Address " << rkeys[i]  << " Posted " << request->issue_time << " PF " << PrefetchBit_No << endl;
+    total_demand++;
+  }
+
+  Vector<Address> wkeys = m_writeRequestTable.keys();
+  int write_size = wkeys.size();
+  out << "proc " << m_version << " Write Requests = " << write_size << endl;
+  // print the request table
+  for(int i=0; i < write_size; ++i){
+      CacheMsg & request = m_writeRequestTable.lookup(wkeys[i]);
       out << "\tRequest[ " << i << " ] = " << request.getType() << " Address " << wkeys[i]  << " Posted " << request.getTime() << " PF " << request.getPrefetch() << endl;
       if( request.getPrefetch() == PrefetchBit_No ){
         total_demand++;
       }
-    }
-
-    out << endl;
   }
+
+  out << endl;
+
   out << "Total Number Outstanding: " << m_outstanding_count << endl;
   out << "Total Number Demand     : " << total_demand << endl;
   out << "Total Number Prefetches : " << m_outstanding_count - total_demand << endl;
   out << endl;
   out << endl;
-
+  */
 }
 
-void Sequencer::printConfig(ostream& out) {
-  if (TSO) {
-    out << "sequencer: Sequencer - TSO" << endl;
-  } else {
-    out << "sequencer: Sequencer - SC" << endl;
-  }
-  out << "  max_outstanding_requests: " << g_SEQUENCER_OUTSTANDING_REQUESTS << endl;
-}
-
-bool Sequencer::empty() const {
-  return m_outstanding_count == 0;
+void Sequencer::printConfig(ostream& out) const {
+  out << "Seqeuncer config: " << m_name << endl;
+  out << "  controller: " << m_controller->getName() << endl;
+  out << "  version: " << m_version << endl;
+  out << "  max_outstanding_requests: " << m_max_outstanding_requests << endl;
+  out << "  deadlock_threshold: " << m_deadlock_threshold << endl;
 }
 
 // Insert the request on the correct request table.  Return true if
 // the entry was already present.
-bool Sequencer::insertRequest(const CacheMsg& request) {
-  int thread = request.getThreadID();
-  assert(thread >= 0);
-  int total_outstanding = 0;
-  int smt_threads = RubyConfig::numberofSMTThreads();
-  for(int p=0; p < smt_threads; ++p){
-    total_outstanding += m_writeRequestTable_ptr[p]->size() + m_readRequestTable_ptr[p]->size();
-  }
+bool Sequencer::insertRequest(SequencerRequest* request) {
+  int total_outstanding = m_writeRequestTable.size() + m_readRequestTable.size();
+
   assert(m_outstanding_count == total_outstanding);
 
   // See if we should schedule a deadlock check
   if (m_deadlock_check_scheduled == false) {
-    g_eventQueue_ptr->scheduleEvent(this, g_DEADLOCK_THRESHOLD);
+    g_eventQueue_ptr->scheduleEvent(this, m_deadlock_threshold);
     m_deadlock_check_scheduled = true;
   }
 
-  if ((request.getType() == CacheRequestType_ST) ||
-      (request.getType() == CacheRequestType_ATOMIC)) {
-    if (m_writeRequestTable_ptr[thread]->exist(line_address(request.getAddress()))) {
-      m_writeRequestTable_ptr[thread]->lookup(line_address(request.getAddress())) = request;
-      return true;
+  Address line_addr(request->ruby_request.paddr);
+  line_addr.makeLineAddress();
+  if ((request->ruby_request.type == RubyRequestType_ST) ||
+      (request->ruby_request.type == RubyRequestType_RMW)) {
+    if (m_writeRequestTable.exist(line_addr)) {
+      m_writeRequestTable.lookup(line_addr) = request;
+      //      return true;
+      assert(0); // drh5: isn't this an error?  do you lose the initial request?
     }
-    m_writeRequestTable_ptr[thread]->allocate(line_address(request.getAddress()));
-    m_writeRequestTable_ptr[thread]->lookup(line_address(request.getAddress())) = request;
+    m_writeRequestTable.allocate(line_addr);
+    m_writeRequestTable.lookup(line_addr) = request;
     m_outstanding_count++;
   } else {
-    if (m_readRequestTable_ptr[thread]->exist(line_address(request.getAddress()))) {
-      m_readRequestTable_ptr[thread]->lookup(line_address(request.getAddress())) = request;
-      return true;
+    if (m_readRequestTable.exist(line_addr)) {
+      m_readRequestTable.lookup(line_addr) = request;
+      //      return true;
+      assert(0); // drh5: isn't this an error?  do you lose the initial request?
     }
-    m_readRequestTable_ptr[thread]->allocate(line_address(request.getAddress()));
-    m_readRequestTable_ptr[thread]->lookup(line_address(request.getAddress())) = request;
+    m_readRequestTable.allocate(line_addr);
+    m_readRequestTable.lookup(line_addr) = request;
     m_outstanding_count++;
   }
 
   g_system_ptr->getProfiler()->sequencerRequests(m_outstanding_count);
 
-  total_outstanding = 0;
-  for(int p=0; p < smt_threads; ++p){
-    total_outstanding += m_writeRequestTable_ptr[p]->size() + m_readRequestTable_ptr[p]->size();
-  }
-
+  total_outstanding = m_writeRequestTable.size() + m_readRequestTable.size();
   assert(m_outstanding_count == total_outstanding);
+
   return false;
 }
 
-void Sequencer::removeRequest(const CacheMsg& request) {
-  int thread = request.getThreadID();
-  assert(thread >= 0);
-  int total_outstanding = 0;
-  int smt_threads = RubyConfig::numberofSMTThreads();
-  for(int p=0; p < smt_threads; ++p){
-    total_outstanding += m_writeRequestTable_ptr[p]->size() + m_readRequestTable_ptr[p]->size();
-  }
-  assert(m_outstanding_count == total_outstanding);
+void Sequencer::removeRequest(SequencerRequest* srequest) {
+
+  assert(m_outstanding_count == m_writeRequestTable.size() + m_readRequestTable.size());
 
-  if ((request.getType() == CacheRequestType_ST) ||
-      (request.getType() == CacheRequestType_ATOMIC)) {
-    m_writeRequestTable_ptr[thread]->deallocate(line_address(request.getAddress()));
+  const RubyRequest & ruby_request = srequest->ruby_request;
+  Address line_addr(ruby_request.paddr);
+  line_addr.makeLineAddress();
+  if ((ruby_request.type == RubyRequestType_ST) ||
+      (ruby_request.type == RubyRequestType_RMW)) {
+    m_writeRequestTable.deallocate(line_addr);
   } else {
-    m_readRequestTable_ptr[thread]->deallocate(line_address(request.getAddress()));
+    m_readRequestTable.deallocate(line_addr);
   }
   m_outstanding_count--;
 
-  total_outstanding = 0;
-  for(int p=0; p < smt_threads; ++p){
-    total_outstanding += m_writeRequestTable_ptr[p]->size() + m_readRequestTable_ptr[p]->size();
-  }
-  assert(m_outstanding_count == total_outstanding);
-}
-
-void Sequencer::writeCallback(const Address& address) {
-  DataBlock data;
-  writeCallback(address, data);
+  assert(m_outstanding_count == m_writeRequestTable.size() + m_readRequestTable.size());
 }
 
 void Sequencer::writeCallback(const Address& address, DataBlock& data) {
-  // process oldest thread first
-  int thread = -1;
-  Time oldest_time = 0;
-  int smt_threads = RubyConfig::numberofSMTThreads();
-  for(int t=0; t < smt_threads; ++t){
-    if(m_writeRequestTable_ptr[t]->exist(address)){
-      CacheMsg & request = m_writeRequestTable_ptr[t]->lookup(address);
-      if(thread == -1 || (request.getTime() < oldest_time) ){
-        thread = t;
-        oldest_time = request.getTime();
-      }
-    }
-  }
-  // make sure we found an oldest thread
-  ASSERT(thread != -1);
-
-  CacheMsg & request = m_writeRequestTable_ptr[thread]->lookup(address);
-
-  writeCallback(address, data, GenericMachineType_NULL, PrefetchBit_No, thread);
-}
-
-void Sequencer::writeCallback(const Address& address, DataBlock& data, GenericMachineType respondingMach, PrefetchBit pf, int thread) {
 
   assert(address == line_address(address));
-  assert(thread >= 0);
-  assert(m_writeRequestTable_ptr[thread]->exist(line_address(address)));
+  assert(m_writeRequestTable.exist(line_address(address)));
 
-  writeCallback(address, data, respondingMach, thread);
-
-}
-
-void Sequencer::writeCallback(const Address& address, DataBlock& data, GenericMachineType respondingMach, int thread) {
-  assert(address == line_address(address));
-  assert(m_writeRequestTable_ptr[thread]->exist(line_address(address)));
-  CacheMsg request = m_writeRequestTable_ptr[thread]->lookup(address);
-  assert( request.getThreadID() == thread);
+  SequencerRequest* request = m_writeRequestTable.lookup(address);
   removeRequest(request);
 
-  assert((request.getType() == CacheRequestType_ST) ||
-         (request.getType() == CacheRequestType_ATOMIC));
-
-  hitCallback(request, data, respondingMach, thread);
+  assert((request->ruby_request.type == RubyRequestType_ST) ||
+         (request->ruby_request.type == RubyRequestType_RMW));
 
-}
-
-void Sequencer::readCallback(const Address& address) {
-  DataBlock data;
-  readCallback(address, data);
+  hitCallback(request, data);
 }
 
 void Sequencer::readCallback(const Address& address, DataBlock& data) {
-  // process oldest thread first
-  int thread = -1;
-  Time oldest_time = 0;
-  int smt_threads = RubyConfig::numberofSMTThreads();
-  for(int t=0; t < smt_threads; ++t){
-    if(m_readRequestTable_ptr[t]->exist(address)){
-      CacheMsg & request = m_readRequestTable_ptr[t]->lookup(address);
-      if(thread == -1 || (request.getTime() < oldest_time) ){
-        thread = t;
-        oldest_time = request.getTime();
-      }
-    }
-  }
-  // make sure we found an oldest thread
-  ASSERT(thread != -1);
-
-  CacheMsg & request = m_readRequestTable_ptr[thread]->lookup(address);
-
-  readCallback(address, data, GenericMachineType_NULL, PrefetchBit_No, thread);
-}
-
-void Sequencer::readCallback(const Address& address, DataBlock& data, GenericMachineType respondingMach, PrefetchBit pf, int thread) {
 
   assert(address == line_address(address));
-  assert(m_readRequestTable_ptr[thread]->exist(line_address(address)));
+  assert(m_readRequestTable.exist(line_address(address)));
 
-  readCallback(address, data, respondingMach, thread);
-}
-
-void Sequencer::readCallback(const Address& address, DataBlock& data, GenericMachineType respondingMach, int thread) {
-  assert(address == line_address(address));
-  assert(m_readRequestTable_ptr[thread]->exist(line_address(address)));
-
-  CacheMsg request = m_readRequestTable_ptr[thread]->lookup(address);
-  assert( request.getThreadID() == thread );
+  SequencerRequest* request = m_readRequestTable.lookup(address);
   removeRequest(request);
 
-  assert((request.getType() == CacheRequestType_LD) ||
-         (request.getType() == CacheRequestType_IFETCH)
-         );
+  assert((request->ruby_request.type == RubyRequestType_LD) ||
+         (request->ruby_request.type == RubyRequestType_IFETCH));
 
-  hitCallback(request, data, respondingMach, thread);
+  hitCallback(request, data);
 }
 
-void Sequencer::hitCallback(const CacheMsg& request, DataBlock& data, GenericMachineType respondingMach, int thread) {
-  int size = request.getSize();
-  Address request_address = request.getAddress();
-  Address request_logical_address = request.getLogicalAddress();
-  Address request_line_address = line_address(request_address);
-  CacheRequestType type = request.getType();
-  int threadID = request.getThreadID();
-  Time issued_time = request.getTime();
-  int logical_proc_no = ((m_chip_ptr->getID() * RubyConfig::numberOfProcsPerChip()) + m_version) * RubyConfig::numberofSMTThreads() + threadID;
-
-  DEBUG_MSG(SEQUENCER_COMP, MedPrio, size);
+void Sequencer::hitCallback(SequencerRequest* srequest, DataBlock& data) {
+  const RubyRequest & ruby_request = srequest->ruby_request;
+  int size = ruby_request.len;
+  Address request_address(ruby_request.paddr);
+  Address request_line_address(ruby_request.paddr);
+  request_line_address.makeLineAddress();
+  RubyRequestType type = ruby_request.type;
+  Time issued_time = srequest->issue_time;
 
   // Set this cache entry to the most recently used
-  if (type == CacheRequestType_IFETCH) {
-    if (Protocol::m_TwoLevelCache) {
-      if (m_chip_ptr->m_L1Cache_L1IcacheMemory_vec[m_version]->isTagPresent(request_line_address)) {
-        m_chip_ptr->m_L1Cache_L1IcacheMemory_vec[m_version]->setMRU(request_line_address);
-      }
-    }
-    else {
-      if (m_chip_ptr->m_L1Cache_cacheMemory_vec[m_version]->isTagPresent(request_line_address)) {
-        m_chip_ptr->m_L1Cache_cacheMemory_vec[m_version]->setMRU(request_line_address);
-      }
-    }
+  if (type == RubyRequestType_IFETCH) {
+    if (m_instCache_ptr->isTagPresent(request_line_address) )
+      m_instCache_ptr->setMRU(request_line_address);
   } else {
-    if (Protocol::m_TwoLevelCache) {
-      if (m_chip_ptr->m_L1Cache_L1DcacheMemory_vec[m_version]->isTagPresent(request_line_address)) {
-        m_chip_ptr->m_L1Cache_L1DcacheMemory_vec[m_version]->setMRU(request_line_address);
-      }
-    }
-    else {
-      if (m_chip_ptr->m_L1Cache_cacheMemory_vec[m_version]->isTagPresent(request_line_address)) {
-        m_chip_ptr->m_L1Cache_cacheMemory_vec[m_version]->setMRU(request_line_address);
-      }
-    }
+    if (m_dataCache_ptr->isTagPresent(request_line_address) )
+      m_dataCache_ptr->setMRU(request_line_address);
   }
 
   assert(g_eventQueue_ptr->getTime() >= issued_time);
   Time miss_latency = g_eventQueue_ptr->getTime() - issued_time;
 
-  if (PROTOCOL_DEBUG_TRACE) {
-    g_system_ptr->getProfiler()->profileTransition("Seq", (m_chip_ptr->getID()*RubyConfig::numberOfProcsPerChip()+m_version), -1, request.getAddress(), "", "Done", "",
-                                                   int_to_string(miss_latency)+" cycles "+GenericMachineType_to_string(respondingMach)+" "+CacheRequestType_to_string(request.getType())+" "+PrefetchBit_to_string(request.getPrefetch()));
-  }
-
-  DEBUG_MSG(SEQUENCER_COMP, MedPrio, request_address);
-  DEBUG_MSG(SEQUENCER_COMP, MedPrio, request.getPrefetch());
-  if (request.getPrefetch() == PrefetchBit_Yes) {
-    DEBUG_MSG(SEQUENCER_COMP, MedPrio, "return");
-    g_system_ptr->getProfiler()->swPrefetchLatency(miss_latency, type, respondingMach);
-    return; // Ignore the software prefetch, don't callback the driver
-  }
-
   // Profile the miss latency for all non-zero demand misses
   if (miss_latency != 0) {
-    g_system_ptr->getProfiler()->missLatency(miss_latency, type, respondingMach);
-
-  }
-
-  bool write =
-    (type == CacheRequestType_ST) ||
-    (type == CacheRequestType_ATOMIC);
+    g_system_ptr->getProfiler()->missLatency(miss_latency, type);
 
-  if (TSO && write) {
-    m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->callBack(line_address(request.getAddress()), data,
-                                                               m_packetTable_ptr->lookup(request.getAddress()));
-  } else {
-
-    // Copy the correct bytes out of the cache line into the subblock
-    SubBlock subblock(request_address, request_logical_address, size);
-    subblock.mergeFrom(data);  // copy the correct bytes from DataBlock in the SubBlock
-
-    // Scan the store buffer to see if there are any outstanding stores we need to collect
-    if (TSO) {
-      m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->updateSubBlock(subblock);
+    if (Debug::getProtocolTrace()) {
+      g_system_ptr->getProfiler()->profileTransition("Seq", m_version, Address(ruby_request.paddr),
+                                                     "", "Done", "", int_to_string(miss_latency)+" cycles");
     }
+  }
+  /*
+  if (request.getPrefetch() == PrefetchBit_Yes) {
+    return; // Ignore the prefetch
+  }
+  */
 
-    // Call into the Driver and let it read and/or modify the sub-block
-    Packet* pkt = m_packetTable_ptr->lookup(request.getAddress());
-
-    // update data if this is a store/atomic
-
-    /*
-    if (pkt->req->isCondSwap()) {
-      L1Cache_Entry entry = m_L1Cache_vec[m_version]->lookup(Address(pkt->req->physAddr()));
-      DataBlk datablk = entry->getDataBlk();
-      uint8_t *orig_data = datablk.getArray();
-      if ( datablk.equal(pkt->req->getExtraData()) )
-        datablk->setArray(pkt->getData());
-      pkt->setData(orig_data);
-    }
-    */
-
-    g_system_ptr->getDriver()->hitCallback(pkt);
-    m_packetTable_ptr->remove(request.getAddress());
-
-    // If the request was a Store or Atomic, apply the changes in the SubBlock to the DataBlock
-    // (This is only triggered for the non-TSO case)
-    if (write) {
-      assert(!TSO);
-      subblock.mergeTo(data);    // copy the correct bytes from SubBlock into the DataBlock
+  // update the data
+  if (ruby_request.data != NULL) {
+    if ((type == RubyRequestType_LD) ||
+        (type == RubyRequestType_IFETCH)) {
+      memcpy(ruby_request.data, data.getData(request_address.getOffset(), ruby_request.len), ruby_request.len);
+    } else {
+      data.setData(ruby_request.data, request_address.getOffset(), ruby_request.len);
     }
   }
-}
 
-void Sequencer::printDebug(){
-  //notify driver of debug
-  g_system_ptr->getDriver()->printDebug();
+  m_hit_callback(srequest->id);
+  delete srequest;
 }
 
-//dsm: breaks build, delayed
 // Returns true if the sequencer already has a load or store outstanding
-bool
-Sequencer::isReady(const Packet* pkt) const
-{
-
-  int cpu_number = pkt->req->contextId();
-  la_t logical_addr = pkt->req->getVaddr();
-  pa_t physical_addr = pkt->req->getPaddr();
-  CacheRequestType type_of_request;
-  if ( pkt->req->isInstFetch() ) {
-    type_of_request = CacheRequestType_IFETCH;
-  } else if ( pkt->req->isLocked() || pkt->req->isSwap() ) {
-    type_of_request = CacheRequestType_ATOMIC;
-  } else if ( pkt->isRead() ) {
-    type_of_request = CacheRequestType_LD;
-  } else if ( pkt->isWrite() ) {
-    type_of_request = CacheRequestType_ST;
-  } else {
-    assert(false);
+bool Sequencer::isReady(const RubyRequest& request) const {
+  // POLINA: check if we are currently flushing the write buffer, if so Ruby is returned as not ready
+  // to simulate stalling of the front-end
+  // Do we stall all the sequencers? If it is atomic instruction - yes!
+  if (m_outstanding_count >= m_max_outstanding_requests) {
+    return false;
   }
-  int thread = pkt->req->threadId();
-
-  CacheMsg request(Address( physical_addr ),
-                   Address( physical_addr ),
-                   type_of_request,
-                   Address(0),
-                   AccessModeType_UserMode,   // User/supervisor mode
-                   0,   // Size in bytes of request
-                   PrefetchBit_No,  // Not a prefetch
-                   0,              // Version number
-                   Address(logical_addr),   // Virtual Address
-                   thread              // SMT thread
-                   );
-  return isReady(request);
-}
 
-bool
-Sequencer::isReady(const CacheMsg& request) const
-{
-  if (m_outstanding_count >= g_SEQUENCER_OUTSTANDING_REQUESTS) {
-    //cout << "TOO MANY OUTSTANDING: " << m_outstanding_count << " " << g_SEQUENCER_OUTSTANDING_REQUESTS << " VER " << m_version << endl;
+  if( m_writeRequestTable.exist(line_address(Address(request.paddr))) ||
+      m_readRequestTable.exist(line_address(Address(request.paddr))) ){
+    //cout << "OUTSTANDING REQUEST EXISTS " << p << " VER " << m_version << endl;
     //printProgress(cout);
     return false;
   }
 
-  // This code allows reads to be performed even when we have a write
-  // request outstanding for the line
-  bool write =
-    (request.getType() == CacheRequestType_ST) ||
-    (request.getType() == CacheRequestType_ATOMIC);
-
-  // LUKE - disallow more than one request type per address
-  //     INVARIANT: at most one request type per address, per processor
-  int smt_threads = RubyConfig::numberofSMTThreads();
-  for(int p=0; p < smt_threads; ++p){
-    if( m_writeRequestTable_ptr[p]->exist(line_address(request.getAddress())) ||
-        m_readRequestTable_ptr[p]->exist(line_address(request.getAddress())) ){
-      //cout << "OUTSTANDING REQUEST EXISTS " << p << " VER " << m_version << endl;
-      //printProgress(cout);
-      return false;
-    }
-  }
-
-  if (TSO) {
-    return m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->isReady();
-  }
   return true;
 }
 
-//dsm: breaks build, delayed
-// Called by Driver (Simics or Tester).
-void
-Sequencer::makeRequest(Packet* pkt)
-{
-  int cpu_number = pkt->req->contextId();
-  la_t logical_addr = pkt->req->getVaddr();
-  pa_t physical_addr = pkt->req->getPaddr();
-  int request_size = pkt->getSize();
-  CacheRequestType type_of_request;
-  PrefetchBit prefetch;
-  bool write = false;
-  if ( pkt->req->isInstFetch() ) {
-    type_of_request = CacheRequestType_IFETCH;
-  } else if ( pkt->req->isLocked() || pkt->req->isSwap() ) {
-    type_of_request = CacheRequestType_ATOMIC;
-    write = true;
-  } else if ( pkt->isRead() ) {
-    type_of_request = CacheRequestType_LD;
-  } else if ( pkt->isWrite() ) {
-    type_of_request = CacheRequestType_ST;
-    write = true;
-  } else {
-    assert(false);
-  }
-  if (pkt->req->isPrefetch()) {
-    prefetch = PrefetchBit_Yes;
-  } else {
-    prefetch = PrefetchBit_No;
-  }
-  la_t virtual_pc = pkt->req->getPC();
-  int isPriv = false;  // TODO: get permission data
-  int thread = pkt->req->threadId();
-
-  AccessModeType access_mode = AccessModeType_UserMode; // TODO: get actual permission
-
-  CacheMsg request(Address( physical_addr ),
-                   Address( physical_addr ),
-                   type_of_request,
-                   Address(virtual_pc),
-                   access_mode,   // User/supervisor mode
-                   request_size,   // Size in bytes of request
-                   prefetch,
-                   0,              // Version number
-                   Address(logical_addr),   // Virtual Address
-                   thread         // SMT thread
-                   );
-
-  if ( TSO && write && !pkt->req->isPrefetch() ) {
-    assert(m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->isReady());
-    m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->insertStore(pkt, request);
-    return;
-  }
-
-  m_packetTable_ptr->insert(Address( physical_addr ), pkt);
-
-  doRequest(request);
-}
-
-bool Sequencer::doRequest(const CacheMsg& request) {
-  bool hit = false;
-  // Check the fast path
-  DataBlock* data_ptr;
-
-  int thread = request.getThreadID();
-
-  hit = tryCacheAccess(line_address(request.getAddress()),
-                       request.getType(),
-                       request.getProgramCounter(),
-                       request.getAccessMode(),
-                       request.getSize(),
-                       data_ptr);
-
-  if (hit && (request.getType() == CacheRequestType_IFETCH || !REMOVE_SINGLE_CYCLE_DCACHE_FAST_PATH) ) {
-    DEBUG_MSG(SEQUENCER_COMP, MedPrio, "Fast path hit");
-    hitCallback(request, *data_ptr, GenericMachineType_L1Cache, thread);
-    return true;
-  }
-
-  if (TSO && (request.getType() == CacheRequestType_LD || request.getType() == CacheRequestType_IFETCH)) {
-
-    // See if we can satisfy the load entirely from the store buffer
-    SubBlock subblock(line_address(request.getAddress()), request.getSize());
-    if (m_chip_ptr->m_L1Cache_storeBuffer_vec[m_version]->trySubBlock(subblock)) {
-      DataBlock dummy;
-      hitCallback(request, dummy, GenericMachineType_NULL, thread);  // Call with an 'empty' datablock, since the data is in the store buffer
-      return true;
-    }
-  }
-
-  DEBUG_MSG(SEQUENCER_COMP, MedPrio, "Fast path miss");
-  issueRequest(request);
-  return hit;
+bool Sequencer::empty() const {
+  return (m_writeRequestTable.size() == 0) && (m_readRequestTable.size() == 0);
 }
 
-void Sequencer::issueRequest(const CacheMsg& request) {
-  bool found = insertRequest(request);
-
-  if (!found) {
-    CacheMsg msg = request;
-    msg.getAddress() = line_address(request.getAddress()); // Make line address
-
-    // Fast Path L1 misses are profiled here - all non-fast path misses are profiled within the generated protocol code
-    if (!REMOVE_SINGLE_CYCLE_DCACHE_FAST_PATH) {
-      g_system_ptr->getProfiler()->addPrimaryStatSample(msg, m_chip_ptr->getID());
-    }
-
-    if (PROTOCOL_DEBUG_TRACE) {
-      g_system_ptr->getProfiler()->profileTransition("Seq", (m_chip_ptr->getID()*RubyConfig::numberOfProcsPerChip() + m_version), -1, msg.getAddress(),"", "Begin", "", CacheRequestType_to_string(request.getType()));
-    }
-
-#if 0
-    // Commented out by nate binkert because I removed the trace stuff
-    if (g_system_ptr->getTracer()->traceEnabled()) {
-      g_system_ptr->getTracer()->traceRequest((m_chip_ptr->getID()*RubyConfig::numberOfProcsPerChip()+m_version), msg.getAddress(), msg.getProgramCounter(),
-                                              msg.getType(), g_eventQueue_ptr->getTime());
-    }
-#endif
-
-    Time latency = 0;  // initialzed to an null value
-
-    latency = SEQUENCER_TO_CONTROLLER_LATENCY;
-
-    // Send the message to the cache controller
-    assert(latency > 0);
-    m_chip_ptr->m_L1Cache_mandatoryQueue_vec[m_version]->enqueue(msg, latency);
-
-  }  // !found
+int64_t Sequencer::makeRequest(const RubyRequest & request)
+{
+  assert(Address(request.paddr).getOffset() + request.len <= RubySystem::getBlockSizeBytes());
+  if (isReady(request)) {
+    int64_t id = makeUniqueRequestID();
+    SequencerRequest *srequest = new SequencerRequest(request, id, g_eventQueue_ptr->getTime());
+    bool found = insertRequest(srequest);
+    if (!found)
+      issueRequest(request);
+
+    // TODO: issue hardware prefetches here
+    return id;
+  }
+  else {
+    return -1;
+  }
+}
+
+void Sequencer::issueRequest(const RubyRequest& request) {
+
+  // TODO: get rid of CacheMsg, CacheRequestType, and AccessModeTYpe, & have SLICC use RubyRequest and subtypes natively
+  CacheRequestType ctype;
+  switch(request.type) {
+  case RubyRequestType_IFETCH:
+    ctype = CacheRequestType_IFETCH;
+    break;
+  case RubyRequestType_LD:
+    ctype = CacheRequestType_LD;
+    break;
+  case RubyRequestType_ST:
+    ctype = CacheRequestType_ST;
+    break;
+  case RubyRequestType_RMW:
+    ctype = CacheRequestType_ATOMIC;
+    break;
+  default:
+    assert(0);
+  }
+  AccessModeType amtype;
+  switch(request.access_mode){
+  case RubyAccessMode_User:
+    amtype = AccessModeType_UserMode;
+    break;
+  case RubyAccessMode_Supervisor:
+    amtype = AccessModeType_SupervisorMode;
+    break;
+  case RubyAccessMode_Device:
+    amtype = AccessModeType_UserMode;
+    break;
+  default:
+    assert(0);
+  }
+  Address line_addr(request.paddr);
+  line_addr.makeLineAddress();
+  CacheMsg msg(line_addr, Address(request.paddr), ctype, Address(request.pc), amtype, request.len, PrefetchBit_No);
+
+  if (Debug::getProtocolTrace()) {
+    g_system_ptr->getProfiler()->profileTransition("Seq", m_version, Address(request.paddr),
+                                                   "", "Begin", "", RubyRequestType_to_string(request.type));
+  }
+
+  if (g_system_ptr->getTracer()->traceEnabled()) {
+    g_system_ptr->getTracer()->traceRequest(m_name, line_addr, Address(request.pc),
+                                            request.type, g_eventQueue_ptr->getTime());
+  }
+
+  Time latency = 0;  // initialzed to an null value
+
+  if (request.type == RubyRequestType_IFETCH)
+    latency = m_instCache_ptr->getLatency();
+  else
+    latency = m_dataCache_ptr->getLatency();
+
+  // Send the message to the cache controller
+  assert(latency > 0);
+
+
+  m_mandatory_q_ptr->enqueue(msg, latency);
 }
-
+/*
 bool Sequencer::tryCacheAccess(const Address& addr, CacheRequestType type,
-                               const Address& pc, AccessModeType access_mode,
+                               AccessModeType access_mode,
                                int size, DataBlock*& data_ptr) {
   if (type == CacheRequestType_IFETCH) {
-    if (Protocol::m_TwoLevelCache) {
-      return m_chip_ptr->m_L1Cache_L1IcacheMemory_vec[m_version]->tryCacheAccess(line_address(addr), type, data_ptr);
-    }
-    else {
-      return m_chip_ptr->m_L1Cache_cacheMemory_vec[m_version]->tryCacheAccess(line_address(addr), type, data_ptr);
-    }
+    return m_instCache_ptr->tryCacheAccess(line_address(addr), type, data_ptr);
   } else {
-    if (Protocol::m_TwoLevelCache) {
-      return m_chip_ptr->m_L1Cache_L1DcacheMemory_vec[m_version]->tryCacheAccess(line_address(addr), type, data_ptr);
-    }
-    else {
-      return m_chip_ptr->m_L1Cache_cacheMemory_vec[m_version]->tryCacheAccess(line_address(addr), type, data_ptr);
-    }
-  }
-}
-
-void Sequencer::resetRequestTime(const Address& addr, int thread){
-  assert(thread >= 0);
-  //reset both load and store requests, if they exist
-  if(m_readRequestTable_ptr[thread]->exist(line_address(addr))){
-    CacheMsg& request = m_readRequestTable_ptr[thread]->lookup(addr);
-    if( request.m_AccessMode != AccessModeType_UserMode){
-      cout << "resetRequestType ERROR read request addr = " << addr << " thread = "<< thread << " is SUPERVISOR MODE" << endl;
-      printProgress(cout);
-    }
-    //ASSERT(request.m_AccessMode == AccessModeType_UserMode);
-    request.setTime(g_eventQueue_ptr->getTime());
+    return m_dataCache_ptr->tryCacheAccess(line_address(addr), type, data_ptr);
   }
-  if(m_writeRequestTable_ptr[thread]->exist(line_address(addr))){
-    CacheMsg& request = m_writeRequestTable_ptr[thread]->lookup(addr);
-    if( request.m_AccessMode != AccessModeType_UserMode){
-      cout << "resetRequestType ERROR write request addr = " << addr << " thread = "<< thread << " is SUPERVISOR MODE" << endl;
-      printProgress(cout);
-    }
-    //ASSERT(request.m_AccessMode == AccessModeType_UserMode);
-    request.setTime(g_eventQueue_ptr->getTime());
-  }
-}
-
-// removes load request from queue
-void Sequencer::removeLoadRequest(const Address & addr, int thread){
-  removeRequest(getReadRequest(addr, thread));
-}
-
-void Sequencer::removeStoreRequest(const Address & addr, int thread){
-  removeRequest(getWriteRequest(addr, thread));
-}
-
-// returns the read CacheMsg
-CacheMsg & Sequencer::getReadRequest( const Address & addr, int thread ){
-  Address temp = addr;
-  assert(thread >= 0);
-  assert(temp == line_address(temp));
-  assert(m_readRequestTable_ptr[thread]->exist(addr));
-  return m_readRequestTable_ptr[thread]->lookup(addr);
-}
-
-CacheMsg & Sequencer::getWriteRequest( const Address & addr, int thread){
-  Address temp = addr;
-  assert(thread >= 0);
-  assert(temp == line_address(temp));
-  assert(m_writeRequestTable_ptr[thread]->exist(addr));
-  return m_writeRequestTable_ptr[thread]->lookup(addr);
 }
+*/
 
 void Sequencer::print(ostream& out) const {
-  out << "[Sequencer: " << m_chip_ptr->getID()
+  out << "[Sequencer: " << m_version
       << ", outstanding requests: " << m_outstanding_count;
 
-  int smt_threads = RubyConfig::numberofSMTThreads();
-  for(int p=0; p < smt_threads; ++p){
-    out << ", read request table[ " << p << " ]: " << *m_readRequestTable_ptr[p]
-        << ", write request table[ " << p << " ]: " << *m_writeRequestTable_ptr[p];
-  }
+  out << ", read request table: " << m_readRequestTable
+      << ", write request table: " << m_writeRequestTable;
   out << "]";
 }
 
 #endif
 }
 
+/*
 bool Sequencer::getRubyMemoryValue(const Address& addr, char* value,
-                                   unsigned int size_in_bytes ) {
-  for(unsigned int i=0; i < size_in_bytes; i++) {
-    std::cerr << __FILE__ << "(" << __LINE__ << "): Not implemented. " << std::endl;
-    value[i] = 0; // _read_physical_memory( m_chip_ptr->getID()*RubyConfig::numberOfProcsPerChip()+m_version,
-                  //                          addr.getAddress() + i, 1 );
-  }
-  return false; // Do nothing?
+                                   unsigned int size_in_bytes )
+{
+    bool found = false;
+    const Address lineAddr = line_address(addr);
+    DataBlock data;
+    PhysAddress paddr(addr);
+    DataBlock* dataPtr = &data;
+
+    MachineID l2_mach = map_L2ChipId_to_L2Cache(addr, m_chip_ptr->getID() );
+    int l2_ver = l2_mach.num%RubyConfig::numberOfL2CachePerChip();
+
+    if (Protocol::m_TwoLevelCache) {
+      if(Protocol::m_CMP){
+        assert(n->m_L2Cache_L2cacheMemory_vec[l2_ver] != NULL);
+      }
+      else{
+        assert(n->m_L1Cache_cacheMemory_vec[m_version] != NULL);
+      }
+    }
+
+    if (n->m_L1Cache_L1IcacheMemory_vec[m_version]->tryCacheAccess(lineAddr, CacheRequestType_IFETCH, dataPtr)){
+      n->m_L1Cache_L1IcacheMemory_vec[m_version]->getMemoryValue(addr, value, size_in_bytes);
+      found = true;
+    } else if (n->m_L1Cache_L1DcacheMemory_vec[m_version]->tryCacheAccess(lineAddr, CacheRequestType_LD, dataPtr)){
+      n->m_L1Cache_L1DcacheMemory_vec[m_version]->getMemoryValue(addr, value, size_in_bytes);
+      found = true;
+    } else if (Protocol::m_CMP && n->m_L2Cache_L2cacheMemory_vec[l2_ver]->tryCacheAccess(lineAddr, CacheRequestType_LD, dataPtr)){
+      n->m_L2Cache_L2cacheMemory_vec[l2_ver]->getMemoryValue(addr, value, size_in_bytes);
+      found = true;
+    // } else if (n->TBE_TABLE_MEMBER_VARIABLE->isPresent(lineAddr)){
+//       ASSERT(n->TBE_TABLE_MEMBER_VARIABLE->isPresent(lineAddr));
+//       L1Cache_TBE tbeEntry = n->TBE_TABLE_MEMBER_VARIABLE->lookup(lineAddr);
+
+//       int offset = addr.getOffset();
+//       for(int i=0; i<size_in_bytes; ++i){
+//         value[i] = tbeEntry.getDataBlk().getByte(offset + i);
+//       }
+
+//       found = true;
+    } else {
+      // Address not found
+      //cout << "  " << m_chip_ptr->getID() << " NOT IN CACHE, Value at Directory is: " << (int) value[0] << endl;
+      n = dynamic_cast<Chip*>(g_system_ptr->getChip(map_Address_to_DirectoryNode(addr)/RubyConfig::numberOfDirectoryPerChip()));
+      int dir_version = map_Address_to_DirectoryNode(addr)%RubyConfig::numberOfDirectoryPerChip();
+      for(unsigned int i=0; i<size_in_bytes; ++i){
+        int offset = addr.getOffset();
+        value[i] = n->m_Directory_directory_vec[dir_version]->lookup(lineAddr).m_DataBlk.getByte(offset + i);
+      }
+      // Address not found
+      //WARN_MSG("Couldn't find address");
+      //WARN_EXPR(addr);
+      found = false;
+    }
+    return true;
 }
 
 bool Sequencer::setRubyMemoryValue(const Address& addr, char *value,
                                    unsigned int size_in_bytes) {
   char test_buffer[64];
 
-  return false; // Do nothing?
+  // idea here is that coherent cache should find the
+  // latest data, the update it
+  bool found = false;
+  const Address lineAddr = line_address(addr);
+  PhysAddress paddr(addr);
+  DataBlock data;
+  DataBlock* dataPtr = &data;
+  Chip* n = dynamic_cast<Chip*>(m_chip_ptr);
+
+  MachineID l2_mach = map_L2ChipId_to_L2Cache(addr, m_chip_ptr->getID() );
+  int l2_ver = l2_mach.num%RubyConfig::numberOfL2CachePerChip();
+
+  assert(n->m_L1Cache_L1IcacheMemory_vec[m_version] != NULL);
+  assert(n->m_L1Cache_L1DcacheMemory_vec[m_version] != NULL);
+  if (Protocol::m_TwoLevelCache) {
+    if(Protocol::m_CMP){
+      assert(n->m_L2Cache_L2cacheMemory_vec[l2_ver] != NULL);
+    }
+    else{
+      assert(n->m_L1Cache_cacheMemory_vec[m_version] != NULL);
+    }
+  }
+
+  if (n->m_L1Cache_L1IcacheMemory_vec[m_version]->tryCacheAccess(lineAddr, CacheRequestType_IFETCH, dataPtr)){
+    n->m_L1Cache_L1IcacheMemory_vec[m_version]->setMemoryValue(addr, value, size_in_bytes);
+    found = true;
+  } else if (n->m_L1Cache_L1DcacheMemory_vec[m_version]->tryCacheAccess(lineAddr, CacheRequestType_LD, dataPtr)){
+    n->m_L1Cache_L1DcacheMemory_vec[m_version]->setMemoryValue(addr, value, size_in_bytes);
+    found = true;
+  } else if (Protocol::m_CMP && n->m_L2Cache_L2cacheMemory_vec[l2_ver]->tryCacheAccess(lineAddr, CacheRequestType_LD, dataPtr)){
+    n->m_L2Cache_L2cacheMemory_vec[l2_ver]->setMemoryValue(addr, value, size_in_bytes);
+    found = true;
+  } else {
+    // Address not found
+    n = dynamic_cast<Chip*>(g_system_ptr->getChip(map_Address_to_DirectoryNode(addr)/RubyConfig::numberOfDirectoryPerChip()));
+    int dir_version = map_Address_to_DirectoryNode(addr)%RubyConfig::numberOfDirectoryPerChip();
+    for(unsigned int i=0; i<size_in_bytes; ++i){
+      int offset = addr.getOffset();
+      n->m_Directory_directory_vec[dir_version]->lookup(lineAddr).m_DataBlk.setByte(offset + i, value[i]);
+    }
+    found = false;
+  }
+
+  if (found){
+    found = getRubyMemoryValue(addr, test_buffer, size_in_bytes);
+    assert(found);
+    if(value[0] != test_buffer[0]){
+      WARN_EXPR((int) value[0]);
+      WARN_EXPR((int) test_buffer[0]);
+      ERROR_MSG("setRubyMemoryValue failed to set value.");
+    }
+  }
+
+  return true;
+}
+*/
+/*
+
+void
+Sequencer::rubyMemAccess(const uint64 paddr, char* data, const int len, const AccessType type)
+{
+  if ( type == AccessType_Read || type == AccessType_Write ) {
+    // need to break up the packet data
+    uint64 guest_ptr = paddr;
+    Vector<DataBlock*> datablocks;
+    while (paddr + len != guest_ptr) {
+      Address addr(guest_ptr);
+      Address line_addr = line_address(addr);
+
+      int bytes_copied;
+      if (addr.getOffset() == 0) {
+        bytes_copied = (guest_ptr + RubyConfig::dataBlockBytes() > paddr + len)?
+          (paddr + len - guest_ptr):
+          RubyConfig::dataBlockBytes();
+      } else {
+        bytes_copied = RubyConfig::dataBlockBytes() - addr.getOffset();
+        if (guest_ptr + bytes_copied > paddr + len)
+          bytes_copied = paddr + len - guest_ptr;
+      }
+
+      // first we need to find all data blocks that have to be updated for a write
+      // and the highest block for a read
+     for(int i=0;i<RubyConfig::numberOfProcessors();i++) {
+        if (Protocol::m_TwoLevelCache){
+          if(m_chip_ptr->m_L1Cache_L1IcacheMemory_vec[i]->isTagPresent(line_address(addr)))
+            datablocks.insertAtBottom(&m_chip_ptr->m_L1Cache_L1IcacheMemory_vec[i]->lookup(line_addr).getDataBlk());
+          if(m_chip_ptr->m_L1Cache_L1DcacheMemory_vec[i]->isTagPresent(line_address(addr)))
+            datablocks.insertAtBottom(&m_chip_ptr->m_L1Cache_L1DcacheMemory_vec[i]->lookup(line_addr).getDataBlk());
+        } else {
+          if(m_chip_ptr->m_L1Cache_cacheMemory_vec[i]->isTagPresent(line_address(addr)))
+            datablocks.insertAtBottom(&m_chip_ptr->m_L1Cache_cacheMemory_vec[i]->lookup(line_addr).getDataBlk());
+        }
+      }
+      if (Protocol::m_TwoLevelCache){
+        int l2_bank = map_L2ChipId_to_L2Cache(addr, 0).num; // TODO: ONLY WORKS WITH CMP!!!
+        if (m_chip_ptr->m_L2Cache_L2cacheMemory_vec[l2_bank]->isTagPresent(line_address(Address(paddr)))) {
+          datablocks.insertAtBottom(&m_chip_ptr->m_L2Cache_L2cacheMemory_vec[l2_bank]->lookup(addr).getDataBlk());
+        }
+      }
+      assert(dynamic_cast<Chip*>(m_chip_ptr)->m_Directory_directory_vec.size() > map_Address_to_DirectoryNode(addr));
+      DirectoryMemory* dir = dynamic_cast<Chip*>(m_chip_ptr)->m_Directory_directory_vec[map_Address_to_DirectoryNode(addr)];
+      Directory_Entry& entry = dir->lookup(line_addr);
+      datablocks.insertAtBottom(&entry.getDataBlk());
+
+      if (pkt->isRead()){
+        datablocks[0]->copyData(pkt_data, addr.getOffset(), bytes_copied);
+      } else {// pkt->isWrite() {
+        for (int i=0;i<datablocks.size();i++)
+          datablocks[i]->setData(pkt_data, addr.getOffset(), bytes_copied);
+      }
+
+      guest_ptr += bytes_copied;
+      pkt_data += bytes_copied;
+      datablocks.clear();
+    }
 }
 
+*/
 
 #include "mem/protocol/AccessModeType.hh"
 #include "mem/protocol/GenericMachineType.hh"
 #include "mem/protocol/PrefetchBit.hh"
+#include "mem/ruby/system/RubyPort.hh"
 #include "mem/gems_common/Map.hh"
+#include "mem/ruby/common/Address.hh"
 
 class DataBlock;
-class AbstractChip;
 class CacheMsg;
-class Address;
 class MachineID;
-class Packet;
+class CacheMemory;
+class AbstractController;
 
-class Sequencer : public Consumer {
+struct SequencerRequest {
+  RubyRequest ruby_request;
+  int64_t id;
+  Time issue_time;
+
+  SequencerRequest(const RubyRequest & _ruby_request, int64_t _id, Time _issue_time)
+    : ruby_request(_ruby_request), id(_id), issue_time(_issue_time)
+  {}
+};
+
+class Sequencer : public Consumer, public RubyPort {
 public:
   // Constructors
-  Sequencer(AbstractChip* chip_ptr, int version);
+  Sequencer(const string & name);
+  void init(const vector<string> & argv);
 
   // Destructor
   ~Sequencer();
   // Public Methods
   void wakeup(); // Used only for deadlock detection
 
-  static void printConfig(ostream& out);
-
-  // returns total number of outstanding request (includes prefetches)
-  int getNumberOutstanding();
-  // return only total number of outstanding demand requests
-  int getNumberOutstandingDemand();
-  // return only total number of outstanding prefetch requests
-  int getNumberOutstandingPrefetch();
-
-  // remove load/store request from queue
-  void removeLoadRequest(const Address & addr, int thread);
-  void removeStoreRequest(const Address & addr, int thread);
+  void printConfig(ostream& out) const;
 
   void printProgress(ostream& out) const;
 
-  // returns a pointer to the request in the request tables
-  CacheMsg & getReadRequest( const Address & addr, int thread );
-  CacheMsg & getWriteRequest( const Address & addr, int thread );
-
   void writeCallback(const Address& address, DataBlock& data);
   void readCallback(const Address& address, DataBlock& data);
-  void writeCallback(const Address& address);
-  void readCallback(const Address& address);
-  void writeCallback(const Address& address, DataBlock& data, GenericMachineType respondingMach, PrefetchBit pf, int thread);
-  void readCallback(const Address& address, DataBlock& data, GenericMachineType respondingMach, PrefetchBit pf, int thread);
-  void writeCallback(const Address& address, DataBlock& data, GenericMachineType respondingMach, int thread);
-  void readCallback(const Address& address, DataBlock& data, GenericMachineType respondingMach, int thread);
-
-  // returns the thread ID of the request
-  int getRequestThreadID(const Address & addr);
-  // returns the physical address of the request
-  Address getRequestPhysicalAddress(const Address & lineaddr);
-  // returns whether a request is a prefetch request
-  bool isPrefetchRequest(const Address & lineaddr);
-
-  //notifies driver of debug print
-  void printDebug();
 
   // called by Tester or Simics
-  void makeRequest(Packet* pkt);
-  bool doRequest(const CacheMsg& request);
-  void issueRequest(const CacheMsg& request);
-  bool isReady(const Packet* pkt) const;
-  bool isReady(const CacheMsg& request) const; // depricate this function
+  int64_t makeRequest(const RubyRequest & request);
+  bool isReady(const RubyRequest& request) const;
   bool empty() const;
-  void resetRequestTime(const Address& addr, int thread);
-  Address getLogicalAddressOfRequest(Address address, int thread);
-  AccessModeType getAccessModeOfRequest(Address address, int thread);
-  //uint64 getSequenceNumberOfRequest(Address addr, int thread);
 
   void print(ostream& out) const;
   void checkCoherence(const Address& address);
 
-  bool getRubyMemoryValue(const Address& addr, char* value, unsigned int size_in_bytes);
-  bool setRubyMemoryValue(const Address& addr, char *value, unsigned int size_in_bytes);
+  //  bool getRubyMemoryValue(const Address& addr, char* value, unsigned int size_in_bytes);
+  //  bool setRubyMemoryValue(const Address& addr, char *value, unsigned int size_in_bytes);
 
-  void removeRequest(const CacheMsg& request);
+  void removeRequest(SequencerRequest* request);
 private:
   // Private Methods
   bool tryCacheAccess(const Address& addr, CacheRequestType type, const Address& pc, AccessModeType access_mode, int size, DataBlock*& data_ptr);
-  //  void conflictCallback(const CacheMsg& request, GenericMachineType respondingMach, int thread);
-  void hitCallback(const CacheMsg& request, DataBlock& data, GenericMachineType respondingMach, int thread);
-  bool insertRequest(const CacheMsg& request);
+  void issueRequest(const RubyRequest& request);
+
+  void hitCallback(SequencerRequest* request, DataBlock& data);
+  bool insertRequest(SequencerRequest* request);
 
 
   // Private copy constructor and assignment operator
   Sequencer(const Sequencer& obj);
   Sequencer& operator=(const Sequencer& obj);
 
-  // Data Members (m_ prefix)
-  AbstractChip* m_chip_ptr;
+private:
+  int m_max_outstanding_requests;
+  int m_deadlock_threshold;
+
+  AbstractController* m_controller;
+  MessageBuffer* m_mandatory_q_ptr;
+  CacheMemory* m_dataCache_ptr;
+  CacheMemory* m_instCache_ptr;
 
   // indicates what processor on the chip this sequencer is associated with
   int m_version;
+  int m_controller_type;
 
-  // One request table per SMT thread
-  Map<Address, CacheMsg>** m_writeRequestTable_ptr;
-  Map<Address, CacheMsg>** m_readRequestTable_ptr;
-
-  Map<Address, Packet*>* m_packetTable_ptr;
-
+  Map<Address, SequencerRequest*> m_writeRequestTable;
+  Map<Address, SequencerRequest*> m_readRequestTable;
   // Global outstanding request count, across all request tables
   int m_outstanding_count;
   bool m_deadlock_check_scheduled;
 
+++ /dev/null
-
-/*
- * 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.
- */
-
-/*
- * $Id$
- *
- */
-
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/config/RubyConfig.hh"
-#include "mem/ruby/system/StoreBuffer.hh"
-#include "mem/ruby/slicc_interface/AbstractChip.hh"
-#include "mem/ruby/system/System.hh"
-#include "mem/ruby/common/Driver.hh"
-#include "mem/gems_common/Vector.hh"
-#include "mem/ruby/eventqueue/RubyEventQueue.hh"
-#include "mem/ruby/profiler/AddressProfiler.hh"
-#include "mem/ruby/system/Sequencer.hh"
-#include "mem/ruby/common/SubBlock.hh"
-#include "mem/ruby/profiler/Profiler.hh"
-#include "mem/packet.hh"
-
-// *** Begin Helper class ***
-struct StoreBufferEntry {
-  StoreBufferEntry() {} // So we can allocate a vector of StoreBufferEntries
-  StoreBufferEntry(const SubBlock& block, CacheRequestType type, const Address& pc, AccessModeType access_mode, int size, int thread) : m_subblock(block) {
-    m_type = type;
-    m_pc = pc;
-    m_access_mode = access_mode;
-    m_size = size;
-    m_thread = thread;
-    m_time = g_eventQueue_ptr->getTime();
-  }
-
-  void print(ostream& out) const
-  {
-    out << "[StoreBufferEntry: "
-        << "SubBlock: " << m_subblock
-        << ", Type: " << m_type
-        << ", PC: " << m_pc
-        << ", AccessMode: " << m_access_mode
-        << ", Size: " << m_size
-        << ", Thread: " << m_thread
-        << ", Time: " << m_time
-        << "]";
-  }
-
-  SubBlock m_subblock;
-  CacheRequestType m_type;
-  Address m_pc;
-  AccessModeType m_access_mode;
-  int m_size;
-  int m_thread;
-  Time m_time;
-};
-
-extern inline
-ostream& operator<<(ostream& out, const StoreBufferEntry& obj)
-{
-  obj.print(out);
-  out << flush;
-  return out;
-}
-
-// *** End Helper class ***
-
-const int MAX_ENTRIES = 128;
-
-static void inc_index(int& index)
-{
-  index++;
-  if (index >= MAX_ENTRIES) {
-    index = 0;
-  }
-}
-
-StoreBuffer::StoreBuffer(AbstractChip* chip_ptr, int version) :
-  m_store_cache()
-{
-  m_chip_ptr = chip_ptr;
-  m_version = version;
-  m_queue_ptr = new Vector<StoreBufferEntry>(MAX_ENTRIES);
-  m_queue_ptr->setSize(MAX_ENTRIES);
-  m_pending = false;
-  m_seen_atomic = false;
-  m_head = 0;
-  m_tail = 0;
-  m_size = 0;
-  m_deadlock_check_scheduled = false;
-}
-
-StoreBuffer::~StoreBuffer()
-{
-  delete m_queue_ptr;
-}
-
-// Used only to check for deadlock
-void StoreBuffer::wakeup()
-{
-  // Check for deadlock of any of the requests
-  Time current_time = g_eventQueue_ptr->getTime();
-
-  int queue_pointer = m_head;
-  for (int i=0; i<m_size; i++) {
-    if (current_time - (getEntry(queue_pointer).m_time) >= g_DEADLOCK_THRESHOLD) {
-      WARN_EXPR(getEntry(queue_pointer));
-      WARN_EXPR(m_chip_ptr->getID());
-      WARN_EXPR(current_time);
-      ERROR_MSG("Possible Deadlock detected");
-    }
-    inc_index(queue_pointer);
-  }
-
-  if (m_size > 0) { // If there are still outstanding requests, keep checking
-    g_eventQueue_ptr->scheduleEvent(this, g_DEADLOCK_THRESHOLD);
-  } else {
-    m_deadlock_check_scheduled = false;
-  }
-}
-
-void StoreBuffer::printConfig(ostream& out)
-{
-  out << "Store buffer entries: " << MAX_ENTRIES << " (Only valid if TSO is enabled)" << endl;
-}
-
-// Handle an incoming store request, this method is responsible for
-// calling hitCallback as needed
-void
-StoreBuffer::insertStore(Packet* pkt, const CacheMsg& request)
-{
-  Address addr = request.getAddress();
-  CacheRequestType type = request.getType();
-  Address pc = request.getProgramCounter();
-  AccessModeType access_mode = request.getAccessMode();
-  int size = request.getSize();
-  int threadID = request.getThreadID();
-
-  DEBUG_MSG(STOREBUFFER_COMP, MedPrio, "insertStore");
-  DEBUG_EXPR(STOREBUFFER_COMP, MedPrio, g_eventQueue_ptr->getTime());
-  assert((type == CacheRequestType_ST) || (type == CacheRequestType_ATOMIC));
-  assert(isReady());
-
-  // See if we should schedule a deadlock check
-  if (m_deadlock_check_scheduled == false) {
-    g_eventQueue_ptr->scheduleEvent(this, g_DEADLOCK_THRESHOLD);
-    m_deadlock_check_scheduled = true;
-  }
-
-  // Perform the hit-callback for the store
-  SubBlock subblock(addr, size);
-  if(type == CacheRequestType_ST) {
-    g_system_ptr->getDriver()->hitCallback(pkt);
-    assert(subblock.getSize() != 0);
-  } else {
-    // wait to perform the hitCallback until later for Atomics
-  }
-
-  // Perform possible pre-fetch
-  if(!isEmpty()) {
-    Packet new_pkt(pkt);
-    pkt->req->setFlags(Request::PREFETCH);
-    m_chip_ptr->getSequencer(m_version)->makeRequest(&new_pkt);
-  }
-
-  // Update the StoreCache
-  m_store_cache.add(subblock);
-
-  // Enqueue the entry
-  StoreBufferEntry entry(subblock, type, pc, access_mode, size, threadID); // FIXME
-  enqueue(entry);
-
-  if(type == CacheRequestType_ATOMIC) {
-    m_seen_atomic = true;
-  }
-
-  processHeadOfQueue();
-}
-
-void StoreBuffer::callBack(const Address& addr, DataBlock& data, Packet* pkt)
-{
-  DEBUG_MSG(STOREBUFFER_COMP, MedPrio, "callBack");
-  DEBUG_EXPR(STOREBUFFER_COMP, MedPrio, g_eventQueue_ptr->getTime());
-  assert(!isEmpty());
-  assert(m_pending == true);
-  assert(line_address(addr) == addr);
-  assert(line_address(m_pending_address) == addr);
-  assert(line_address(peek().m_subblock.getAddress()) == addr);
-  CacheRequestType type = peek().m_type;
-  //int threadID = peek().m_thread;
-  assert((type == CacheRequestType_ST) || (type == CacheRequestType_ATOMIC));
-  m_pending = false;
-
-  // If oldest entry was ATOMIC, perform the callback
-  if(type == CacheRequestType_ST) {
-    // We already performed the call back for the store at insert time
-  } else {
-    // We waited to perform the hitCallback until now for Atomics
-    peek().m_subblock.mergeFrom(data);  // copy the correct bytes from DataBlock into the SubBlock for the Load part of the atomic Load/Store
-    g_system_ptr->getDriver()->hitCallback(pkt);
-    m_seen_atomic = false;
-
-    /// FIXME - record the time spent in the store buffer - split out ST vs ATOMIC
-  }
-  assert(peek().m_subblock.getSize() != 0);
-
-  // Apply the head entry to the datablock
-  peek().m_subblock.mergeTo(data);  // For both the Store and Atomic cases
-
-  // Update the StoreCache
-  m_store_cache.remove(peek().m_subblock);
-
-  // Dequeue the entry from the store buffer
-  dequeue();
-
-  if (isEmpty()) {
-    assert(m_store_cache.isEmpty());
-  }
-
-  if(type == CacheRequestType_ATOMIC) {
-    assert(isEmpty());
-  }
-
-  // See if we can remove any more entries
-  processHeadOfQueue();
-}
-
-void StoreBuffer::processHeadOfQueue()
-{
-  if(!isEmpty() && !m_pending) {
-    StoreBufferEntry& entry = peek();
-    assert(m_pending == false);
-    m_pending = true;
-    m_pending_address = entry.m_subblock.getAddress();
-    CacheMsg request(entry.m_subblock.getAddress(), entry.m_subblock.getAddress(), entry.m_type, entry.m_pc, entry.m_access_mode, entry.m_size, PrefetchBit_No, 0, Address(0), entry.m_thread);
-    m_chip_ptr->getSequencer(m_version)->doRequest(request);
-  }
-}
-
-bool StoreBuffer::isReady() const
-{
-  return ((m_size < MAX_ENTRIES) && (!m_seen_atomic));
-}
-
-// Queue implementation methods
-
-StoreBufferEntry& StoreBuffer::peek()
-{
-  return getEntry(m_head);
-}
-
-void StoreBuffer::dequeue()
-{
-  assert(m_size > 0);
-  m_size--;
-  inc_index(m_head);
-}
-
-void StoreBuffer::enqueue(const StoreBufferEntry& entry)
-{
-  //  assert(isReady());
-  (*m_queue_ptr)[m_tail] = entry;
-  m_size++;
-  g_system_ptr->getProfiler()->storeBuffer(m_size, m_store_cache.size());
-  inc_index(m_tail);
-}
-
-StoreBufferEntry& StoreBuffer::getEntry(int index)
-{
-  return (*m_queue_ptr)[index];
-}
-
-void StoreBuffer::print(ostream& out) const
-{
-  out << "[StoreBuffer]";
-}
-
 
+++ /dev/null
-
-/*
- * 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.
- */
-
-/*
- * $Id$
- *
- * Description:
- *
- */
-
-#ifndef StoreBuffer_H
-#define StoreBuffer_H
-
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/common/Consumer.hh"
-#include "mem/ruby/common/Address.hh"
-#include "mem/protocol/AccessModeType.hh"
-#include "mem/protocol/CacheRequestType.hh"
-#include "mem/ruby/system/StoreCache.hh"
-
-class CacheMsg;
-class DataBlock;
-class SubBlock;
-class StoreBufferEntry;
-class AbstractChip;
-class Packet;
-
-template <class TYPE> class Vector;
-
-class StoreBuffer : public Consumer {
-public:
-  // Constructors
-  StoreBuffer(AbstractChip* chip_ptr, int version);
-
-  // Destructor
-  ~StoreBuffer();
-
-  // Public Methods
-  void wakeup(); // Used only for deadlock detection
-  void callBack(const Address& addr, DataBlock& data, Packet* pkt);
-  void insertStore(Packet* pkt, const CacheMsg& request);
-  void updateSubBlock(SubBlock& sub_block) const { m_store_cache.update(sub_block); }
-  bool trySubBlock(const SubBlock& sub_block) const { assert(isReady()); return m_store_cache.check(sub_block); }
-  void print(ostream& out) const;
-  bool isEmpty() const { return (m_size == 0); }
-  bool isReady() const;
-
-  // Class methods
-  static void printConfig(ostream& out);
-
-private:
-  // Private Methods
-  void processHeadOfQueue();
-
-  StoreBufferEntry& peek();
-  void dequeue();
-  void enqueue(const StoreBufferEntry& entry);
-  StoreBufferEntry& getEntry(int index);
-
-  // Private copy constructor and assignment operator
-  StoreBuffer(const StoreBuffer& obj);
-  StoreBuffer& operator=(const StoreBuffer& obj);
-
-  // Data Members (m_ prefix)
-  int m_version;
-
-  Vector<StoreBufferEntry>* m_queue_ptr;
-  int m_head;
-  int m_tail;
-  int m_size;
-
-  StoreCache m_store_cache;
-
-  AbstractChip* m_chip_ptr;
-  bool m_pending;
-  Address m_pending_address;
-  bool m_seen_atomic;
-  bool m_deadlock_check_scheduled;
-};
-
-// Output operator declaration
-ostream& operator<<(ostream& out, const StoreBuffer& obj);
-
-// ******************* Definitions *******************
-
-// Output operator definition
-extern inline
-ostream& operator<<(ostream& out, const StoreBuffer& obj)
-{
-  obj.print(out);
-  out << flush;
-  return out;
-}
-
-#endif //StoreBuffer_H
 
+++ /dev/null
-
-/*
- * 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.
- */
-
-/*
- * $Id$
- *
- */
-
-#include "mem/ruby/system/StoreCache.hh"
-#include "mem/ruby/system/System.hh"
-#include "mem/ruby/common/Driver.hh"
-#include "mem/gems_common/Vector.hh"
-#include "mem/ruby/common/DataBlock.hh"
-#include "mem/ruby/common/SubBlock.hh"
-#include "mem/gems_common/Map.hh"
-
-// Helper class
-struct StoreCacheEntry {
-  StoreCacheEntry() {
-    m_byte_counters.setSize(RubyConfig::dataBlockBytes());
-    for(int i=0; i<m_byte_counters.size(); i++) {
-      m_byte_counters[i] = 0;
-    }
-    m_line_counter = 0;
-
-  }
-  Address m_addr;
-  DataBlock m_datablock;
-  Vector<int> m_byte_counters;
-  int m_line_counter;
-};
-
-StoreCache::StoreCache()
-{
-  m_internal_cache_ptr = new Map<Address, StoreCacheEntry>;
-}
-
-StoreCache::~StoreCache()
-{
-  delete m_internal_cache_ptr;
-}
-
-bool StoreCache::isEmpty() const
-{
-  return m_internal_cache_ptr->size() == 0;
-}
-
-int StoreCache::size() const { return m_internal_cache_ptr->size(); }
-
-void StoreCache::add(const SubBlock& block)
-{
-  if (m_internal_cache_ptr->exist(line_address(block.getAddress())) == false) {
-    m_internal_cache_ptr->allocate(line_address(block.getAddress()));
-  }
-
-  StoreCacheEntry& entry = m_internal_cache_ptr->lookup(line_address(block.getAddress()));
-
-  // For each byte in entry change the bytes and inc. the counters
-  int starting_offset = block.getAddress().getOffset();
-  int size = block.getSize();
-  for (int index=0; index < size; index++) {
-    // Update counter
-    entry.m_byte_counters[starting_offset+index]++;
-
-    // Record data
-    entry.m_datablock.setByte(starting_offset+index, block.getByte(index));
-
-    DEBUG_EXPR(SEQUENCER_COMP, LowPrio, block.getAddress());
-    DEBUG_EXPR(SEQUENCER_COMP, LowPrio, int(block.getByte(index)));
-    DEBUG_EXPR(SEQUENCER_COMP, LowPrio, starting_offset+index);
-  }
-
-  // Increment the counter
-  entry.m_line_counter++;
-}
-
-void StoreCache::remove(const SubBlock& block)
-{
-  assert(m_internal_cache_ptr->exist(line_address(block.getAddress())));
-
-  StoreCacheEntry& entry = m_internal_cache_ptr->lookup(line_address(block.getAddress()));
-
-  // Decrement the byte counters
-  int starting_offset = block.getAddress().getOffset();
-  int size = block.getSize();
-  for (int index=0; index < size; index++) {
-    // Update counter
-    entry.m_byte_counters[starting_offset+index]--;
-  }
-
-  // Decrement the line counter
-  entry.m_line_counter--;
-  assert(entry.m_line_counter >= 0);
-
-  // Check to see if we should de-allocate this entry
-  if (entry.m_line_counter == 0) {
-    m_internal_cache_ptr->deallocate(line_address(block.getAddress()));
-  }
-}
-
-bool StoreCache::check(const SubBlock& block) const
-{
-  if (m_internal_cache_ptr->exist(line_address(block.getAddress())) == false) {
-    return false;
-  } else {
-    // Lookup the entry
-    StoreCacheEntry& entry = m_internal_cache_ptr->lookup(line_address(block.getAddress()));
-
-    // See if all the bytes are valid
-    int starting_offset = block.getAddress().getOffset();
-    int size = block.getSize();
-    for (int index=0; index < size; index++) {
-      if (entry.m_byte_counters[starting_offset+index] > 0) {
-        // So far so good
-      } else {
-        // not all the bytes were valid
-        return false;
-      }
-    }
-  }
-  return true;
-}
-
-void StoreCache::update(SubBlock& block) const
-{
-  if (m_internal_cache_ptr->exist(line_address(block.getAddress()))) {
-    // Lookup the entry
-    StoreCacheEntry& entry = m_internal_cache_ptr->lookup(line_address(block.getAddress()));
-
-    // Copy all appropriate and valid bytes from the store cache to
-    // the SubBlock
-    int starting_offset = block.getAddress().getOffset();
-    int size = block.getSize();
-    for (int index=0; index < size; index++) {
-
-      DEBUG_EXPR(SEQUENCER_COMP, LowPrio, block.getAddress());
-      DEBUG_EXPR(SEQUENCER_COMP, LowPrio, int(entry.m_datablock.getByte(starting_offset+index)));
-      DEBUG_EXPR(SEQUENCER_COMP, LowPrio, starting_offset+index);
-
-      // If this byte is valid, copy the data into the sub-block
-      if (entry.m_byte_counters[starting_offset+index] > 0) {
-        block.setByte(index, entry.m_datablock.getByte(starting_offset+index));
-      }
-    }
-  }
-}
-
-void StoreCache::print(ostream& out) const
-{
-  out << "[StoreCache]";
-}
-
 
+++ /dev/null
-
-/*
- * 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.
- */
-
-/*
- * $Id$
- *
- * Description:
- *
- */
-
-#ifndef StoreCache_H
-#define StoreCache_H
-
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/common/Address.hh"
-
-
-class DataBlock;
-class SubBlock;
-class StoreCacheEntry;
-
-template <class KEY_TYPE, class VALUE_TYPE> class Map;
-
-class StoreCache {
-public:
-  // Constructors
-  StoreCache();
-
-  // Destructor
-  ~StoreCache();
-
-  // Public Methods
-  void add(const SubBlock& block);
-  void remove(const SubBlock& block);
-  bool check(const SubBlock& block) const;
-  void update(SubBlock& block) const;
-  bool isEmpty() const;
-  int size() const;
-  void print(ostream& out) const;
-
-private:
-  Map<Address, StoreCacheEntry>* m_internal_cache_ptr;
-};
-
-// Output operator declaration
-ostream& operator<<(ostream& out, const StoreCache& obj);
-
-// ******************* Definitions *******************
-
-// Output operator definition
-extern inline
-ostream& operator<<(ostream& out, const StoreCache& obj)
-{
-  obj.print(out);
-  out << flush;
-  return out;
-}
-
-#endif //StoreCache_H
 
 
 
 #include "mem/ruby/system/System.hh"
+#include "mem/ruby/common/Address.hh"
 #include "mem/ruby/profiler/Profiler.hh"
 #include "mem/ruby/network/Network.hh"
-#include "mem/ruby/tester/Tester.hh"
-#include "mem/ruby/tester/SyntheticDriver.hh"
-#include "mem/ruby/tester/DeterministicDriver.hh"
-#include "mem/protocol/Chip.hh"
-//#include "mem/ruby/recorder/Tracer.hh"
+#include "mem/ruby/recorder/Tracer.hh"
 #include "mem/protocol/Protocol.hh"
-
-RubySystem::RubySystem()
+#include "mem/ruby/buffers/MessageBuffer.hh"
+#include "mem/ruby/system/Sequencer.hh"
+#include "mem/ruby/system/DMASequencer.hh"
+#include "mem/ruby/system/MemoryVector.hh"
+#include "mem/protocol/ControllerFactory.hh"
+#include "mem/ruby/slicc_interface/AbstractController.hh"
+#include "mem/ruby/system/CacheMemory.hh"
+#include "mem/ruby/system/DirectoryMemory.hh"
+#include "mem/ruby/network/simple/Topology.hh"
+#include "mem/ruby/network/simple/SimpleNetwork.hh"
+#include "mem/ruby/system/RubyPort.hh"
+#include "mem/ruby/network/garnet-flexible-pipeline/GarnetNetwork.hh"
+#include "mem/ruby/network/garnet-fixed-pipeline/GarnetNetwork_d.hh"
+#include "mem/ruby/system/MemoryControl.hh"
+
+int RubySystem::m_random_seed;
+bool RubySystem::m_randomization;
+int RubySystem::m_tech_nm;
+int RubySystem::m_freq_mhz;
+int RubySystem::m_block_size_bytes;
+int RubySystem::m_block_size_bits;
+uint64 RubySystem::m_memory_size_bytes;
+int RubySystem::m_memory_size_bits;
+
+map< string, RubyPort* > RubySystem::m_ports;
+map< string, CacheMemory* > RubySystem::m_caches;
+map< string, DirectoryMemory* > RubySystem::m_directories;
+map< string, Sequencer* > RubySystem::m_sequencers;
+map< string, DMASequencer* > RubySystem::m_dma_sequencers;
+map< string, AbstractController* > RubySystem::m_controllers;
+map< string, MemoryControl* > RubySystem::m_memorycontrols;
+
+
+Network* RubySystem::m_network_ptr;
+map< string, Topology*> RubySystem::m_topologies;
+Profiler* RubySystem::m_profiler_ptr;
+Tracer* RubySystem::m_tracer_ptr;
+
+MemoryVector* RubySystem::m_mem_vec_ptr;
+
+
+RubySystem* RubySystem::create(const vector <RubyObjConf> & sys_conf)
 {
-  init();
-  m_preinitialized_driver = false;
-  createDriver();
-
- /*  gem5:Binkert for decomissiong of tracer
-     m_tracer_ptr = new Tracer;
- */
-
- /*  gem5:Arka for decomissiong of log_tm
-  if (XACT_MEMORY) {
-    m_xact_isolation_checker = new XactIsolationChecker;
-    m_xact_commit_arbiter    = new XactCommitArbiter;
-    m_xact_visualizer        = new XactVisualizer;
-  }
-*/
+  if (g_system_ptr == NULL)
+    return new RubySystem(sys_conf);
+  return g_system_ptr;
 }
 
-RubySystem::RubySystem(Driver* _driver)
+void RubySystem::init(const vector<string> & argv)
 {
-  init();
-  m_preinitialized_driver = true;
-  m_driver_ptr = _driver;
-}
+  for (size_t i=0; i < argv.size(); i+=2) {
+    if (argv[i] == "random_seed") {
+      m_random_seed = atoi(argv[i+1].c_str());
+      srandom(m_random_seed);
+    } else if (argv[i] == "randomization") {
+      m_randomization = string_to_bool(argv[i+1]);
+    } else if (argv[i] == "tech_nm") {
+      m_tech_nm = atoi(argv[i+1].c_str());
+    } else if (argv[i] == "freq_mhz") {
+      m_freq_mhz = atoi(argv[i+1].c_str());
+    } else if (argv[i] == "block_size_bytes") {
+      m_block_size_bytes = atoi(argv[i+1].c_str());
+      assert(is_power_of_2(m_block_size_bytes));
+      m_block_size_bits = log_int(m_block_size_bytes);
+    } else if (argv[i] == "debug") {
+
+    } else if (argv[i] == "tracer") {
+
+    } else if (argv[i] == "profiler") {
+
+  //  } else if (argv[i] == "MI_example") {
 
-RubySystem::~RubySystem()
-{
-  for (int i = 0; i < m_chip_vector.size(); i++) {
-    delete m_chip_vector[i];
+    } else {
+      cerr << "Error: Unknown RubySystem config parameter -- " << argv[i] << endl;
+     assert(0);
+    }
   }
-  if (!m_preinitialized_driver)
-    delete m_driver_ptr;
-  delete m_network_ptr;
-  delete m_profiler_ptr;
- /*  gem5:Binkert for decomissiong of tracer
-     delete m_tracer_ptr;
- */
 }
 
-void RubySystem::init()
+RubySystem::RubySystem(const vector <RubyObjConf> & sys_conf)
 {
-  DEBUG_MSG(SYSTEM_COMP, MedPrio,"initializing");
-
-  m_driver_ptr = NULL;
-  m_profiler_ptr = new Profiler;
+  //  DEBUG_MSG(SYSTEM_COMP, MedPrio,"initializing");
+
+  for (size_t i=0;i<sys_conf.size(); i++) {
+    const string & type = sys_conf[i].type;
+    const string & name = sys_conf[i].name;
+    const vector<string> & argv = sys_conf[i].argv;
+    if (type == "RubySystem") {
+      init(argv);  // initialize system-wide variables before doing anything else!
+    } else if (type == "Debug") {
+      g_debug_ptr = new Debug(name, argv);
+    }
+  }
 
-  // NETWORK INITIALIZATION
-  // create the network by calling a function that calls new
-  m_network_ptr = Network::createNetwork(RubyConfig::numberOfChips());
+  assert( g_debug_ptr != NULL);
+  g_eventQueue_ptr = new RubyEventQueue;
+  g_system_ptr = this;
+  m_mem_vec_ptr = new MemoryVector;
+
+  /* object contruction is broken into two steps (Constructor and init) to avoid cyclic dependencies
+   *  e.g. a sequencer needs a pointer to a controller and a controller needs a pointer to a sequencer
+   */
+
+  vector<string> memory_control_names;
+
+  for (size_t i=0;i<sys_conf.size(); i++) {
+    const string & type = sys_conf[i].type;
+    const string & name = sys_conf[i].name;
+    const vector<string> & argv = sys_conf[i].argv;
+    if (type == "RubySystem" || type == "Debug")
+      continue;
+    else if (type == "SetAssociativeCache")
+      m_caches[name] = new CacheMemory(name);
+    else if (type == "DirectoryMemory")
+      m_directories[name] = new DirectoryMemory(name);
+    else if (type == "Sequencer") {
+      m_sequencers[name] = new Sequencer(name);
+      m_ports[name] = m_sequencers[name];
+    } else if (type == "DMASequencer") {
+      m_dma_sequencers[name] = new DMASequencer(name);
+      m_ports[name] = m_dma_sequencers[name];
+    } else if (type == "Topology") {
+      assert(m_topologies.size() == 0); // only one toplogy at a time is supported right now
+      m_topologies[name] = new Topology(name);
+    } else if (type == "SimpleNetwork") {
+      assert(m_network_ptr == NULL); // only one network at a time is supported right now
+      m_network_ptr = new SimpleNetwork(name);
+    } else if (type.find("generated") == 0) {
+      string controller_type = type.substr(10);
+      m_controllers[name] = ControllerFactory::createController(controller_type, name);
+//      printf ("ss: generated %s \n", controller_type);
+//added by SS
+    } else if (type == "Tracer") {
+      //m_tracers[name] = new Tracer(name);
+      m_tracer_ptr = new Tracer(name);
+    } else if (type == "Profiler") {
+      m_profiler_ptr = new Profiler(name);
+    } else if (type == "GarnetNetwork") {
+      assert(m_network_ptr == NULL); // only one network at a time is supported right now
+      m_network_ptr = new GarnetNetwork(name);
+    } else if (type == "GarnetNetwork_d") {
+      assert(m_network_ptr == NULL); // only one network at a time is supported right now
+      m_network_ptr = new GarnetNetwork_d(name);
+    } else if (type == "MemoryControl") {
+      m_memorycontrols[name] = new MemoryControl(name);
+      memory_control_names.push_back (name);
+    } else {
+      cerr << "Error: Unknown object type -- " << type << endl;
+      assert(0);
+    }
+  }
 
-  DEBUG_MSG(SYSTEM_COMP, MedPrio,"Constructed network");
+  for (size_t i=0;i<sys_conf.size(); i++) {
+    string type = sys_conf[i].type;
+    string name = sys_conf[i].name;
+    const vector<string> & argv = sys_conf[i].argv;
+    if (type == "Topology")
+      m_topologies[name]->init(argv);
+  }
 
-  // CHIP INITIALIZATION
-  m_chip_vector.setSize(RubyConfig::numberOfChips());// create the vector of pointers to processors
-  for(int i=0; i<RubyConfig::numberOfChips(); i++) { // for each chip
-    // create the chip
-    m_chip_vector[i] = new Chip(i, m_network_ptr);
-    DEBUG_MSG(SYSTEM_COMP, MedPrio,"Constructed a chip");
+  for (size_t i=0;i<sys_conf.size(); i++) {
+    string type = sys_conf[i].type;
+    string name = sys_conf[i].name;
+    const vector<string> & argv = sys_conf[i].argv;
+    if (type == "SimpleNetwork" || type == "GarnetNetwork" || type == "GarnetNetwork_d"){
+      m_network_ptr->init(argv);
+    }
   }
 
-  // These must be after the chips are constructed
+  for (size_t i=0;i<sys_conf.size(); i++) {
+    string type = sys_conf[i].type;
+    string name = sys_conf[i].name;
+    const vector<string> & argv = sys_conf[i].argv;
+    if (type == "MemoryControl" ){
+      m_memorycontrols[name]->init(argv);
+    }
+  }
 
-#if 0
-  if (!g_SIMICS) {
-    if (g_SYNTHETIC_DRIVER && !g_DETERMINISTIC_DRIVER) {
-      m_driver_ptr = new SyntheticDriver(this);
-    } else if (!g_SYNTHETIC_DRIVER && g_DETERMINISTIC_DRIVER) {
-      m_driver_ptr = new DeterministicDriver(this);
-    } else if (g_SYNTHETIC_DRIVER && g_DETERMINISTIC_DRIVER) {
-      ERROR_MSG("SYNTHETIC and DETERMINISTIC DRIVERS are exclusive and cannot be both enabled");
-    } else {
-      // normally make tester object, otherwise make an opal interface object.
-      if (!OpalInterface::isOpalLoaded()) {
-        m_driver_ptr = new Tester(this);
-      } else {
-        m_driver_ptr = new OpalInterface(this);
-      }
+  for (size_t i=0;i<sys_conf.size(); i++) {
+    string type = sys_conf[i].type;
+    string name = sys_conf[i].name;
+    const vector<string> & argv = sys_conf[i].argv;
+    if (type == "RubySystem" || type == "Debug")
+      continue;
+    else if (type == "SetAssociativeCache")
+      m_caches[name]->init(argv);
+    else if (type == "DirectoryMemory")
+      m_directories[name]->init(argv);
+    else if (type == "MemoryControl")
+      continue;
+    else if (type == "Sequencer")
+      m_sequencers[name]->init(argv);
+    else if (type == "DMASequencer")
+      m_dma_sequencers[name]->init(argv);
+    else if (type == "Topology")
+      continue;
+    else if (type == "SimpleNetwork" || type == "GarnetNetwork" || type == "GarnetNetwork_d")
+      continue;
+    else if (type.find("generated") == 0) {
+      string controller_type = type.substr(11);
+      m_controllers[name]->init(m_network_ptr, argv);
     }
-  } else {
-    // detect if opal is loaded or not
-    if (OpalInterface::isOpalLoaded()) {
-      m_driver_ptr = new OpalInterface(this);
-    } else {
+//added by SS
+    else if (type == "Tracer")
+      //m_tracers[name]->init(argv);
+      m_tracer_ptr->init(argv);
+    else if (type == "Profiler")
+      m_profiler_ptr->init(argv, memory_control_names);
+//    else if (type == "MI_example"){
+//    }
+    else
       assert(0);
-      /* Need to allocate a driver here */
-      // m_driver_ptr = new SimicsDriver(this);
-    }
   }
-#endif
+
+//  m_profiler_ptr = new Profiler;
+
+  // calculate system-wide parameters
+  m_memory_size_bytes = 0;
+  DirectoryMemory* prev = NULL;
+  for (map< string, DirectoryMemory*>::const_iterator it = m_directories.begin();
+       it != m_directories.end(); it++) {
+    if (prev != NULL)
+      assert((*it).second->getSize() == prev->getSize()); // must be equal for proper address mapping
+    m_memory_size_bytes += (*it).second->getSize();
+    prev = (*it).second;
+  }
+  m_mem_vec_ptr->setSize(m_memory_size_bytes);
+  m_memory_size_bits = log_int(m_memory_size_bytes);
+
+//  m_tracer_ptr = new Tracer;
   DEBUG_MSG(SYSTEM_COMP, MedPrio,"finished initializing");
   DEBUG_NEWLINE(SYSTEM_COMP, MedPrio);
 }
 
-void RubySystem::createDriver()
+RubySystem::~RubySystem()
 {
-    if (g_SYNTHETIC_DRIVER && !g_DETERMINISTIC_DRIVER) {
-      cerr << "Creating Synthetic Driver" << endl;
-      m_driver_ptr = new SyntheticDriver(this);
-    } else if (!g_SYNTHETIC_DRIVER && g_DETERMINISTIC_DRIVER) {
-      cerr << "Creating Deterministic Driver" << endl;
-      m_driver_ptr = new DeterministicDriver(this);
+  /*
+  for (int i=0; i < MachineType_base_level(MachineType_NUM); i++) {
+    for (int j=0; j < RubyConfig::getNumberOfControllersPerType(i); j++ ) {
+      delete m_controllers[i][j];
     }
+  }
+  delete m_network_ptr;
+  delete m_profiler_ptr;
+  delete m_tracer_ptr;
+  */
+}
+
+void RubySystem::printSystemConfig(ostream & out)
+{
+  out << "RubySystem config:" << endl;
+  out << "  random_seed: " << m_random_seed << endl;
+  out << "  randomization: " << m_randomization << endl;
+  out << "  tech_nm: " << m_tech_nm << endl;
+  out << "  freq_mhz: " << m_freq_mhz << endl;
+  out << "  block_size_bytes: " << m_block_size_bytes << endl;
+  out << "  block_size_bits: " << m_block_size_bits << endl;
+  out << "  memory_size_bytes: " << m_memory_size_bytes << endl;
+  out << "  memory_size_bits: " << m_memory_size_bits << endl;
+
 }
 
-void RubySystem::printConfig(ostream& out) const
+void RubySystem::printConfig(ostream& out)
 {
   out << "\n================ Begin RubySystem Configuration Print ================\n\n";
-  RubyConfig::printConfiguration(out);
-  out << endl;
-  getChip(0)->printConfig(out);
+  //  RubyConfig::printConfiguration(out);
+  //  out << endl;
+  printSystemConfig(out);
+  for (map<string, AbstractController*>::const_iterator it = m_controllers.begin();
+       it != m_controllers.end(); it++) {
+    (*it).second->printConfig(out);
+  }
+  for (map<string, CacheMemory*>::const_iterator it = m_caches.begin();
+       it != m_caches.end(); it++) {
+    (*it).second->printConfig(out);
+  }
+  DirectoryMemory::printGlobalConfig(out);
+  for (map<string, DirectoryMemory*>::const_iterator it = m_directories.begin();
+       it != m_directories.end(); it++) {
+    (*it).second->printConfig(out);
+  }
+  for (map<string, Sequencer*>::const_iterator it = m_sequencers.begin();
+       it != m_sequencers.end(); it++) {
+    (*it).second->printConfig(out);
+  }
+
   m_network_ptr->printConfig(out);
-  m_driver_ptr->printConfig(out);
   m_profiler_ptr->printConfig(out);
+
   out << "\n================ End RubySystem Configuration Print ================\n\n";
 }
 
 void RubySystem::printStats(ostream& out)
 {
+
   const time_t T = time(NULL);
   tm *localTime = localtime(&T);
   char buf[100];
   out << "Real time: " << buf << endl;
 
   m_profiler_ptr->printStats(out);
-  for(int i=0; i<RubyConfig::numberOfChips(); i++) { // for each chip
-    for(int p=0; p<RubyConfig::numberOfProcsPerChip(); p++) {
-      m_chip_vector[i]->m_L1Cache_mandatoryQueue_vec[p]->printStats(out);
-    }
-  }
   m_network_ptr->printStats(out);
-  m_driver_ptr->printStats(out);
-  Chip::printStats(out);
+  for (map<string, AbstractController*>::const_iterator it = m_controllers.begin();
+       it != m_controllers.end(); it++) {
+    (*it).second->printStats(out);
+  }
 }
 
 void RubySystem::clearStats() const
 {
+  /*
   m_profiler_ptr->clearStats();
+  for (int i=0; i<m_rubyRequestQueues.size(); i++)
+    for (int j=0;j<m_rubyRequestQueues[i].size(); j++)
+      m_rubyRequestQueues[i][j]->clearStats();
   m_network_ptr->clearStats();
-  m_driver_ptr->clearStats();
-  Chip::clearStats();
-  for(int i=0; i<RubyConfig::numberOfChips(); i++) { // for each chip
-    for(int p=0; p<RubyConfig::numberOfProcsPerChip(); p++) {
-      m_chip_vector[i]->m_L1Cache_mandatoryQueue_vec[p]->clearStats();
-    }
-  }
+  for (int i=0; i < MachineType_base_level(MachineType_NUM); i++)
+    m_controllers[i][0]->clearStats();
+  */
 }
 
 void RubySystem::recordCacheContents(CacheRecorder& tr) const
 {
-  for (int i = 0; i < m_chip_vector.size(); i++) {
+  /*
+    for (int i = 0; i < m_chip_vector.size(); i++) {
     for (int m_version = 0; m_version < RubyConfig::numberOfProcsPerChip(); m_version++) {
       if (Protocol::m_TwoLevelCache) {
         m_chip_vector[i]->m_L1Cache_L1IcacheMemory_vec[m_version]->setAsInstructionCache(true);
     }
     m_chip_vector[i]->recordCacheContents(tr);
   }
+  */
 }
 
 #ifdef CHECK_COHERENCE
 // and "isBlockExclusive" that are specific to that protocol
 //
 void RubySystem::checkGlobalCoherenceInvariant(const Address& addr  )  {
-
+  /*
   NodeID exclusive = -1;
   bool sharedDetected = false;
   NodeID lastShared = -1;
       }
     }
   }
+  */
 }
 #endif
 
 
 #ifndef SYSTEM_H
 #define SYSTEM_H
 
+#include "mem/ruby/system/RubyPort.hh"
 #include "mem/ruby/common/Global.hh"
 #include "mem/gems_common/Vector.hh"
-#include "mem/ruby/common/Address.hh"
-#include "mem/ruby/config/RubyConfig.hh"
-#include "mem/protocol/MachineType.hh"
-#include "mem/ruby/slicc_interface/AbstractChip.hh"
+#include "mem/ruby/eventqueue/RubyEventQueue.hh"
+#include <map>
 
 class Profiler;
 class Network;
-class Driver;
 class CacheRecorder;
 class Tracer;
 class Sequencer;
-class XactIsolationChecker;
-class XactCommitArbiter;
-class XactVisualizer;
-class TransactionInterfaceManager;
+class DMASequencer;
+class MemoryVector;
+class AbstractController;
+class MessageBuffer;
+class CacheMemory;
+class DirectoryMemory;
+class Topology;
+class MemoryControl;
+
+struct RubyObjConf {
+  string type;
+  string name;
+  vector<string> argv;
+  RubyObjConf(string _type, string _name, vector<string> _argv)
+    : type(_type), name(_name), argv(_argv)
+  {}
+};
 
 class RubySystem {
 public:
-  // Constructors
-  RubySystem();
-  RubySystem(Driver* _driver); // used when driver is already instantiated (e.g. M5's RubyMem)
-
+  static RubySystem* create(const vector <RubyObjConf> & sys_conf);
   // Destructor
   ~RubySystem();
 
+  // config accessors
+  static int getRandomSeed() { return m_random_seed; }
+  static int getRandomization() { return m_randomization; }
+  static int getTechNm() { return m_tech_nm; }
+  static int getFreqMhz() { return m_freq_mhz; }
+  static int getBlockSizeBytes() { return m_block_size_bytes; }
+  static int getBlockSizeBits() { return m_block_size_bits; }
+  static uint64 getMemorySizeBytes() { return m_memory_size_bytes; }
+  static int getMemorySizeBits() { return m_memory_size_bits; }
+
   // Public Methods
-  int getNumProcessors() { return RubyConfig::numberOfProcessors(); }
-  int getNumMemories() { return RubyConfig::numberOfMemories(); }
-  Profiler* getProfiler() { return m_profiler_ptr; }
-  Driver* getDriver() { assert(m_driver_ptr != NULL); return m_driver_ptr; }
+  static RubyPort* getPortOnly(const string & name) {
+    assert(m_ports.count(name) == 1); return m_ports[name]; }
+  static RubyPort* getPort(const string & name, void (*hit_callback)(int64_t)) {
+    assert(m_ports.count(name) == 1); m_ports[name]->registerHitCallback(hit_callback); return m_ports[name]; }
+  static Network* getNetwork() { assert(m_network_ptr != NULL); return m_network_ptr; }
+  static Topology* getTopology(const string & name) { assert(m_topologies.count(name) == 1); return m_topologies[name]; }
+  static CacheMemory* getCache(const string & name) { assert(m_caches.count(name) == 1); return m_caches[name]; }
+  static DirectoryMemory* getDirectory(const string & name) { assert(m_directories.count(name) == 1); return m_directories[name]; }
+  static MemoryControl* getMemoryControl(const string & name) { assert(m_memorycontrols.count(name) == 1); return m_memorycontrols[name]; }
+  static Sequencer* getSequencer(const string & name) { assert(m_sequencers.count(name) == 1); return m_sequencers[name]; }
+  static DMASequencer* getDMASequencer(const string & name) { assert(m_dma_sequencers.count(name) == 1); return m_dma_sequencers[name]; }
+  static AbstractController* getController(const string & name) { assert(m_controllers.count(name) == 1); return m_controllers[name]; }
+
+  static RubyEventQueue* getEventQueue() { return g_eventQueue_ptr; }
+
+  static int getNumberOfDirectories() { return m_directories.size(); }
+  static int getNumberOfSequencers() { return m_sequencers.size(); }
+
+  Profiler* getProfiler() {assert(m_profiler_ptr != NULL); return m_profiler_ptr; }
   Tracer* getTracer() { assert(m_tracer_ptr != NULL); return m_tracer_ptr; }
-  Network* getNetwork() { assert(m_network_ptr != NULL); return m_network_ptr; }
-  XactIsolationChecker* getXactIsolationChecker() { assert(m_xact_isolation_checker!= NULL); return m_xact_isolation_checker;}
-  XactCommitArbiter* getXactCommitArbiter() { assert(m_xact_commit_arbiter!= NULL); return m_xact_commit_arbiter;}
-  XactVisualizer*    getXactVisualizer() { assert(m_xact_visualizer!= NULL); return m_xact_visualizer;}
-
-  AbstractChip* getChip(int chipNumber) const { assert(m_chip_vector[chipNumber] != NULL); return m_chip_vector[chipNumber];}
-  Sequencer* getSequencer(int procNumber) const {
-    assert(procNumber < RubyConfig::numberOfProcessors());
-    return m_chip_vector[procNumber/RubyConfig::numberOfProcsPerChip()]->getSequencer(procNumber%RubyConfig::numberOfProcsPerChip());
-  }
-  TransactionInterfaceManager* getTransactionInterfaceManager(int procNumber) const {
-    return m_chip_vector[procNumber/RubyConfig::numberOfProcsPerChip()]->getTransactionInterfaceManager(procNumber%RubyConfig::numberOfProcsPerChip());
-  }
+  static MemoryVector* getMemoryVector() { assert(m_mem_vec_ptr != NULL); return m_mem_vec_ptr;}
+
   void recordCacheContents(CacheRecorder& tr) const;
-  void printConfig(ostream& out) const;
-  void printStats(ostream& out);
+  static void printConfig(ostream& out);
+  static void printStats(ostream& out);
   void clearStats() const;
 
+  uint64 getInstructionCount(int thread) { return 1; }
+  static uint64 getCycleCount(int thread) { return g_eventQueue_ptr->getTime(); }
+
   void print(ostream& out) const;
+  /*
 #ifdef CHECK_COHERENCE
   void checkGlobalCoherenceInvariant(const Address& addr);
 #endif
+  */
 
 private:
-  // Private Methods
-  void init();
-  void createDriver();
+  // Constructors
+  RubySystem(const vector <RubyObjConf> & cfg_file);
 
   // Private copy constructor and assignment operator
   RubySystem(const RubySystem& obj);
   RubySystem& operator=(const RubySystem& obj);
 
+  void init(const vector<string> & argv);
+
+  static void printSystemConfig(ostream& out);
+
+private:
+  // configuration parameters
+  static int m_random_seed;
+  static bool m_randomization;
+  static int m_tech_nm;
+  static int m_freq_mhz;
+  static int m_block_size_bytes;
+  static int m_block_size_bits;
+  static uint64 m_memory_size_bytes;
+  static int m_memory_size_bits;
+
   // Data Members (m_ prefix)
-  Network* m_network_ptr;
-  Vector<AbstractChip*> m_chip_vector;
-  Profiler* m_profiler_ptr;
-  bool m_preinitialized_driver;
-  Driver* m_driver_ptr;
-  Tracer* m_tracer_ptr;
-  XactIsolationChecker *m_xact_isolation_checker;
-  XactCommitArbiter    *m_xact_commit_arbiter;
-  XactVisualizer       *m_xact_visualizer;
+  static Network* m_network_ptr;
+  static map< string, Topology* > m_topologies;
+  static map< string, RubyPort* > m_ports;
+  static map< string, CacheMemory* > m_caches;
+  static map< string, DirectoryMemory* > m_directories;
+  static map< string, Sequencer* > m_sequencers;
+  static map< string, DMASequencer* > m_dma_sequencers;
+  static map< string, AbstractController* > m_controllers;
+  static map< string, MemoryControl* > m_memorycontrols;
+
+  //added by SS
+  //static map< string, Tracer* > m_tracers;
+
+  static Profiler* m_profiler_ptr;
+  static Tracer* m_tracer_ptr;
+  static MemoryVector* m_mem_vec_ptr;
 };
 
 // Output operator declaration
 
 #include "mem/gems_common/Map.hh"
 #include "mem/ruby/common/Address.hh"
 #include "mem/ruby/profiler/Profiler.hh"
-#include "mem/ruby/slicc_interface/AbstractChip.hh"
 #include "mem/ruby/system/System.hh"
 
 template<class ENTRY>
 public:
 
   // Constructors
-  TBETable(AbstractChip* chip_ptr);
+  TBETable(int number_of_TBEs);
+
 
   // Destructor
   //~TBETable();
 
   // Public Methods
 
-  static void printConfig(ostream& out) { out << "TBEs_per_TBETable: " << NUMBER_OF_TBES << endl; }
+  void printConfig(ostream& out) { out << "TBEs_per_TBETable: " << m_number_of_TBEs << endl; }
 
   bool isPresent(const Address& address) const;
   void allocate(const Address& address);
   void deallocate(const Address& address);
-  bool areNSlotsAvailable(int n) const { return (NUMBER_OF_TBES - m_map.size()) >= n; }
+  bool areNSlotsAvailable(int n) const { return (m_number_of_TBEs - m_map.size()) >= n; }
 
   ENTRY& lookup(const Address& address);
   const ENTRY& lookup(const Address& address) const;
 
   // Data Members (m_prefix)
   Map<Address, ENTRY> m_map;
-  AbstractChip* m_chip_ptr;
+
+private:
+  int m_number_of_TBEs;
 };
 
 // Output operator declaration
 
 // ****************************************************************
 
+
 template<class ENTRY>
 extern inline
-TBETable<ENTRY>::TBETable(AbstractChip* chip_ptr)
+TBETable<ENTRY>::TBETable(int number_of_TBEs)
 {
-  m_chip_ptr = chip_ptr;
+  m_number_of_TBEs = number_of_TBEs;
 }
 
 // PUBLIC METHODS
 bool TBETable<ENTRY>::isPresent(const Address& address) const
 {
   assert(address == line_address(address));
-  assert(m_map.size() <= NUMBER_OF_TBES);
+  assert(m_map.size() <= m_number_of_TBEs);
   return m_map.exist(address);
 }
 
 void TBETable<ENTRY>::allocate(const Address& address)
 {
   assert(isPresent(address) == false);
-  assert(m_map.size() < NUMBER_OF_TBES);
+  assert(m_map.size() < m_number_of_TBEs);
   g_system_ptr->getProfiler()->L2tbeUsageSample(m_map.size());
   m_map.add(address, ENTRY());
 }
 
+++ /dev/null
-
-/*
- * 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.
- */
-
-/*
- * $Id: BarrierGenerator.C 1.3 2005/01/19 13:12:35-06:00 mikem@maya.cs.wisc.edu $
- *
- */
-
-#include "mem/ruby/tester/BarrierGenerator.hh"
-#include "mem/ruby/system/Sequencer.hh"
-#include "mem/ruby/system/System.hh"
-#include "mem/ruby/config/RubyConfig.hh"
-#include "mem/ruby/common/SubBlock.hh"
-#include "mem/ruby/tester/SyntheticDriver.hh"
-#include "mem/protocol/Chip.hh"
-
-BarrierGenerator::BarrierGenerator(NodeID node, SyntheticDriver& driver) :
-  m_driver(driver)
-{
-  m_status = BarrierGeneratorStatus_Thinking;
-  m_last_transition = 0;
-  m_node = node;
-  m_counter = 0;
-  proc_counter = 0;
-  m_local_sense = false;
-
-  m_total_think = 0;
-  m_think_periods = 0;
-
-  g_eventQueue_ptr->scheduleEvent(this, 1+(random() % 200));
-}
-
-BarrierGenerator::~BarrierGenerator()
-{
-}
-
-void BarrierGenerator::wakeup()
-{
-  DEBUG_EXPR(TESTER_COMP, MedPrio, m_node);
-  DEBUG_EXPR(TESTER_COMP, MedPrio, m_status);
-
-  if (m_status == BarrierGeneratorStatus_Thinking) {
-    m_barrier_done = false;
-    m_local_sense = !m_local_sense;
-    m_status = BarrierGeneratorStatus_Test_Pending;
-    m_last_transition = g_eventQueue_ptr->getTime();
-    initiateTest();  // Test
-  } else if (m_status == BarrierGeneratorStatus_Test_Waiting) {
-    m_status = BarrierGeneratorStatus_Test_Pending;
-    m_last_transition = g_eventQueue_ptr->getTime();
-    initiateTest();  // Test
-  } else if (m_status == BarrierGeneratorStatus_Release_Waiting) {
-    m_status = BarrierGeneratorStatus_Release_Pending;
-    m_last_transition = g_eventQueue_ptr->getTime();
-    initiateRelease();  // Test
-  } else if (m_status == BarrierGeneratorStatus_StoreBarrierCounter_Waiting) {
-    m_status = BarrierGeneratorStatus_StoreBarrierCounter_Pending;
-    m_last_transition = g_eventQueue_ptr->getTime();
-    initiateStoreCtr();
-  } else if (m_status == BarrierGeneratorStatus_StoreFlag_Waiting) {
-    m_status = BarrierGeneratorStatus_StoreFlag_Pending;
-    m_last_transition = g_eventQueue_ptr->getTime();
-    initiateStoreFlag();
-  } else if (m_status == BarrierGeneratorStatus_Holding) {
-    m_status = BarrierGeneratorStatus_Release_Pending;
-    m_last_transition = g_eventQueue_ptr->getTime();
-    initiateRelease();  // Release
-  } else if (m_status == BarrierGeneratorStatus_Before_Swap) {
-    m_status = BarrierGeneratorStatus_Swap_Pending;
-    m_last_transition = g_eventQueue_ptr->getTime();
-    initiateSwap();
-  } else if (m_status == BarrierGeneratorStatus_SpinFlag_Ready) {
-    m_status = BarrierGeneratorStatus_SpinFlag_Pending;
-    m_last_transition = g_eventQueue_ptr->getTime();
-    initiateLoadFlag();
-  } else {
-    WARN_EXPR(m_status);
-    ERROR_MSG("Invalid status");
-  }
-}
-
-void BarrierGenerator::performCallback(NodeID proc, SubBlock& data)
-{
-  Address address = data.getAddress();
-  assert(proc == m_node);
-
-  DEBUG_EXPR(TESTER_COMP, LowPrio, proc);
-  DEBUG_EXPR(TESTER_COMP, LowPrio, m_status);
-  DEBUG_EXPR(TESTER_COMP, LowPrio, address);
-  DEBUG_EXPR(TESTER_COMP, LowPrio, data);
-
-  if (m_status == BarrierGeneratorStatus_Test_Pending) {
-    uint8 dat = data.readByte();
-    uint8 lock = dat >> 7;
-    if (lock == 1) {
-      // Locked - keep spinning
-      m_status = BarrierGeneratorStatus_Test_Waiting;
-      m_last_transition = g_eventQueue_ptr->getTime();
-      g_eventQueue_ptr->scheduleEvent(this, waitTime());
-    } else {
-      // Unlocked - try the swap
-      m_driver.recordTestLatency(g_eventQueue_ptr->getTime() - m_last_transition);
-      m_status = BarrierGeneratorStatus_Before_Swap;
-      m_last_transition = g_eventQueue_ptr->getTime();
-      g_eventQueue_ptr->scheduleEvent(this, waitTime());
-    }
-  } else if (m_status == BarrierGeneratorStatus_Swap_Pending) {
-    m_driver.recordSwapLatency(g_eventQueue_ptr->getTime() - m_last_transition);
-    uint8 dat = data.readByte();
-    uint8 lock = dat >> 7;
-    if (lock == 1) {
-      // We failed to aquire the lock
-      m_status = BarrierGeneratorStatus_Test_Waiting;
-      m_last_transition = g_eventQueue_ptr->getTime();
-      g_eventQueue_ptr->scheduleEvent(this, waitTime());
-    } else {
-      // We acquired the lock
-      dat = dat | 0x80;
-      data.writeByte(dat);
-      m_status = BarrierGeneratorStatus_StoreBarrierCounter_Waiting;
-      m_last_transition = g_eventQueue_ptr->getTime();
-      DEBUG_MSG(TESTER_COMP, HighPrio, "Acquired");
-      DEBUG_EXPR(TESTER_COMP, HighPrio, proc);
-      DEBUG_EXPR(TESTER_COMP, HighPrio, g_eventQueue_ptr->getTime());
-      // g_eventQueue_ptr->scheduleEvent(this, holdTime());
-
-      g_eventQueue_ptr->scheduleEvent(this, 1);
-
-      // initiateLoadCtr();
-    }
-  } else if (m_status == BarrierGeneratorStatus_StoreBarrierCounter_Pending) {
-
-    // if value == p, reset counter and set local sense flag
-    uint8 ctr = data.readByte();
-    //uint8 sense = ctr >> 4;
-    ctr = ctr & 0x0F;
-
-    ctr++;
-    data.writeByte( ctr | 0x80);  // store counter and lock
-
-    //cout << m_node << " incremented Barrier_ctr to " << (int)ctr << ", " << data << "\n";
-
-    if (ctr == (uint8) 16) {
-
-       data.writeByte( 0x0 );
-       m_status = BarrierGeneratorStatus_StoreFlag_Waiting;
-       m_barrier_done = true;
-
-       g_eventQueue_ptr->scheduleEvent(this, 1);
-    }
-    else {
-
-       m_status = BarrierGeneratorStatus_Release_Waiting;
-       g_eventQueue_ptr->scheduleEvent(this, 1);
-    }
-  } else if (m_status == BarrierGeneratorStatus_StoreFlag_Pending) {
-
-     // write flag
-     if (m_local_sense) {
-         data.writeByte( 0x01 );
-     }
-     else {
-         data.writeByte( 0x00 );
-     }
-
-     m_status = BarrierGeneratorStatus_Release_Waiting;
-     g_eventQueue_ptr->scheduleEvent(this, 1);
-
-  } else if (m_status == BarrierGeneratorStatus_Release_Pending) {
-    m_driver.recordReleaseLatency(g_eventQueue_ptr->getTime() - m_last_transition);
-    // We're releasing the lock
-    uint8 dat = data.readByte();
-    dat = dat & 0x7F;
-    data.writeByte(dat);
-
-    if (m_barrier_done) {
-      m_counter++;
-      proc_counter++;
-      if (m_counter < g_tester_length) {
-        m_status = BarrierGeneratorStatus_Thinking;
-        m_last_transition = g_eventQueue_ptr->getTime();
-        g_eventQueue_ptr->scheduleEvent(this, thinkTime());
-      } else {
-
-        m_driver.reportDone(proc_counter, m_node);
-        m_last_transition = g_eventQueue_ptr->getTime();
-      }
-    }
-    else {
-      m_status = BarrierGeneratorStatus_SpinFlag_Ready;
-      m_last_transition = g_eventQueue_ptr->getTime();
-      g_eventQueue_ptr->scheduleEvent(this, waitTime());
-    }
-  } else if (m_status == BarrierGeneratorStatus_SpinFlag_Pending) {
-
-    uint8 sense = data.readByte();
-
-
-    if (sense != m_local_sense) {
-      m_status = BarrierGeneratorStatus_SpinFlag_Ready;
-      m_last_transition = g_eventQueue_ptr->getTime();
-      g_eventQueue_ptr->scheduleEvent(this, waitTime());
-    }
-    else {
-      m_counter++;
-      proc_counter++;
-      if (m_counter < g_tester_length) {
-        m_status = BarrierGeneratorStatus_Thinking;
-        m_last_transition = g_eventQueue_ptr->getTime();
-        g_eventQueue_ptr->scheduleEvent(this, thinkTime());
-      } else {
-        m_driver.reportDone(proc_counter, m_node);
-        m_status = BarrierGeneratorStatus_Done;
-        m_last_transition = g_eventQueue_ptr->getTime();
-      }
-    }
-
-  } else {
-    WARN_EXPR(m_status);
-    ERROR_MSG("Invalid status");
-  }
-}
-
-int BarrierGenerator::thinkTime()
-{
-  int ret;
-  float ratio = g_think_fudge_factor;
-
-  // return 400;
-
-  if (ratio == 0) {
-    return g_think_time;
-  }
-
-  int r = random();
-  int x = (int) ( (float)g_think_time*ratio*2.0);
-  int mod = r % x;
-
-
-  int rand = ( mod+1 -  ((float)g_think_time*ratio) );
-
-  ret = (g_think_time + rand);
-
-  m_total_think += ret;
-  m_think_periods++;
-
-  return ret;
-}
-
-int BarrierGenerator::waitTime() const
-{
-  return g_wait_time;
-}
-
-
-void BarrierGenerator::initiateTest()
-{
-  DEBUG_MSG(TESTER_COMP, MedPrio, "initiating Test");
-  sequencer()->makeRequest(CacheMsg(Address(0x40), CacheRequestType_LD, Address(1), AccessModeType_UserMode, 1, PrefetchBit_No, 0, false));
-}
-
-void BarrierGenerator::initiateSwap()
-{
-  DEBUG_MSG(TESTER_COMP, MedPrio, "initiating Swap");
-  sequencer()->makeRequest(CacheMsg(Address(0x40), CacheRequestType_ATOMIC, Address(2), AccessModeType_UserMode, 1, PrefetchBit_No, 0, false));
-}
-
-void BarrierGenerator::initiateRelease()
-{
-  DEBUG_MSG(TESTER_COMP, MedPrio, "initiating Release");
-  sequencer()->makeRequest(CacheMsg(Address(0x40), CacheRequestType_ST, Address(3), AccessModeType_UserMode, 1, PrefetchBit_No, 0, false));
-}
-
-void BarrierGenerator::initiateLoadCtr()
-{
-  DEBUG_MSG(TESTER_COMP, MedPrio, "initiating load of barrier counter");
-  sequencer()->makeRequest(CacheMsg(Address(0x40), CacheRequestType_LD, Address(3), AccessModeType_UserMode, 1, PrefetchBit_No, 0, false));
-}
-
-void BarrierGenerator::initiateStoreCtr()
-{
-  DEBUG_MSG(TESTER_COMP, MedPrio, "initiating load of barrier counter");
-  sequencer()->makeRequest(CacheMsg(Address(0x40), CacheRequestType_ST, Address(3), AccessModeType_UserMode, 1, PrefetchBit_No, 0, false));
-}
-
-void BarrierGenerator::initiateStoreFlag()
-{
-  DEBUG_MSG(TESTER_COMP, MedPrio, "initiating load of barrier counter");
-  sequencer()->makeRequest(CacheMsg(Address(0x00), CacheRequestType_ST, Address(3), AccessModeType_UserMode, 1, PrefetchBit_No, 0, false));
-}
-
-void BarrierGenerator::initiateLoadFlag()
-{
-  DEBUG_MSG(TESTER_COMP, MedPrio, "initiating load of barrier counter");
-  sequencer()->makeRequest(CacheMsg(Address(0x00), CacheRequestType_LD, Address(3), AccessModeType_UserMode, 1, PrefetchBit_No, 0, false));
-}
-
-
-Sequencer* BarrierGenerator::sequencer() const
-{
-  return g_system_ptr->getChip(m_node/RubyConfig::numberOfProcsPerChip())->getSequencer(m_node%RubyConfig::numberOfProcsPerChip());
-}
-
-void BarrierGenerator::print(ostream& out) const
-{
-}
-
 
+++ /dev/null
-
-/*
- * 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.
- */
-
-/*
- * $Id$
- *
- * Description:
- *
- */
-
-#ifndef BARRIERGENERATOR_H
-#define BARRIERGENERATOR_H
-
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/common/Consumer.hh"
-#include "mem/ruby/system/NodeID.hh"
-#include "mem/ruby/common/Address.hh"
-
-class Sequencer;
-class SubBlock;
-class SyntheticDriver;
-
-
-enum BarrierGeneratorStatus {
-  BarrierGeneratorStatus_FIRST,
-  BarrierGeneratorStatus_Thinking = BarrierGeneratorStatus_FIRST,
-  BarrierGeneratorStatus_Test_Pending,
-  BarrierGeneratorStatus_Test_Waiting,
-  BarrierGeneratorStatus_Before_Swap,
-  BarrierGeneratorStatus_Swap_Pending,
-  BarrierGeneratorStatus_Holding,
-  BarrierGeneratorStatus_Release_Pending,
-  BarrierGeneratorStatus_Release_Waiting,
-  BarrierGeneratorStatus_StoreFlag_Waiting,
-  BarrierGeneratorStatus_StoreFlag_Pending,
-  BarrierGeneratorStatus_Done,
-  BarrierGeneratorStatus_SpinFlag_Ready,
-  BarrierGeneratorStatus_SpinFlag_Pending,
-  BarrierGeneratorStatus_LoadBarrierCounter_Pending,
-  BarrierGeneratorStatus_StoreBarrierCounter_Pending,
-  BarrierGeneratorStatus_StoreBarrierCounter_Waiting,
-  BarrierGeneratorStatus_NUM
-};
-
-
-// UNCOMMENT THIS FOR A SINGLE WORK QUEUE
-// static int m_counter;
-
-class BarrierGenerator : public Consumer {
-public:
-  // Constructors
-  BarrierGenerator(NodeID node, SyntheticDriver& driver);
-
-  // Destructor
-  ~BarrierGenerator();
-
-  // Public Methods
-  void wakeup();
-  void performCallback(NodeID proc, SubBlock& data);
-
-  void print(ostream& out) const;
-private:
-  // Private Methods
-  int thinkTime() ;
-  int waitTime() const;
-  void initiateTest();
-  void initiateSwap();
-  void initiateRelease();
-  void initiateLoadCtr();
-  void initiateStoreCtr();
-  void initiateLoadFlag();
-  void initiateStoreFlag();
-  Sequencer* sequencer() const;
-
-  // Private copy constructor and assignment operator
-  BarrierGenerator(const BarrierGenerator& obj);
-  BarrierGenerator& operator=(const BarrierGenerator& obj);
-
-  // Data Members (m_ prefix)
-  SyntheticDriver& m_driver;
-  NodeID m_node;
-  BarrierGeneratorStatus m_status;
-  int proc_counter;
-
-  int m_counter;
-
-  bool m_local_sense;
-  bool m_barrier_done;
-
-  Time m_last_transition;
-  Address m_address;
-
-  int m_total_think;
-  int m_think_periods;
-};
-
-// Output operator declaration
-ostream& operator<<(ostream& out, const BarrierGenerator& obj);
-
-// ******************* Definitions *******************
-
-// Output operator definition
-extern inline
-ostream& operator<<(ostream& out, const BarrierGenerator& obj)
-{
-  obj.print(out);
-  out << flush;
-  return out;
-}
-
-#endif //REQUESTGENERATOR_H
-
 
+++ /dev/null
-
-/*
- * 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.
- */
-
-/*
- * $Id$
- *
- */
-
-#include "mem/ruby/tester/Check.hh"
-#include "mem/ruby/system/Sequencer.hh"
-#include "mem/ruby/system/System.hh"
-#include "mem/ruby/common/SubBlock.hh"
-#include "mem/protocol/Chip.hh"
-#include "mem/packet.hh"
-
-Check::Check(const Address& address, const Address& pc)
-{
-  m_status = TesterStatus_Idle;
-
-  pickValue();
-  pickInitiatingNode();
-  changeAddress(address);
-  m_pc = pc;
-  m_access_mode = AccessModeType(random() % AccessModeType_NUM);
-  m_store_count = 0;
-}
-
-void Check::initiate()
-{
-  DEBUG_MSG(TESTER_COMP, MedPrio, "initiating");
-  DEBUG_EXPR(TESTER_COMP, MedPrio, *this);
-
-  // current CMP protocol doesn't support prefetches
-  if (!Protocol::m_CMP && (random() & 0xf) == 0) { // 1 in 16 chance
-    initiatePrefetch(); // Prefetch from random processor
-  }
-
-  if(m_status == TesterStatus_Idle) {
-    initiateAction();
-  } else if(m_status == TesterStatus_Ready) {
-    initiateCheck();
-  } else {
-    // Pending - do nothing
-    DEBUG_MSG(TESTER_COMP, MedPrio, "initiating action/check - failed: action/check is pending\n");
-  }
-}
-
-void Check::initiatePrefetch(Sequencer* targetSequencer_ptr)
-{
-  DEBUG_MSG(TESTER_COMP, MedPrio, "initiating prefetch");
-
-  CacheRequestType type;
-  if ((random() & 0x7) != 0) { // 1 in 8 chance
-    if ((random() & 0x1) == 0) { // 50% chance
-      type = CacheRequestType_LD;
-    } else {
-      type = CacheRequestType_IFETCH;
-    }
-  } else {
-    type = CacheRequestType_ST;
-  }
-
-  Addr data_addr = m_address.getAddress();
-  Addr pc_addr = m_pc.getAddress();
-  Request request(0, data_addr, 0, Flags<unsigned int>(Request::PREFETCH), pc_addr, 0, 0);
-  MemCmd::Command command;
-  if (type == CacheRequestType_IFETCH) {
-    command = MemCmd::ReadReq;
-    request.setFlags(Request::INST_FETCH);
-  } else if (type == CacheRequestType_LD || type == CacheRequestType_IFETCH) {
-    command = MemCmd::ReadReq;
-  } else if (type == CacheRequestType_ST) {
-    command = MemCmd::WriteReq;
-  } else if (type == CacheRequestType_ATOMIC) {
-    command = MemCmd::SwapReq; // TODO -- differentiate between atomic types
-  } else {
-    panic("Cannot convert request to packet");
-  }
-
-  Packet pkt(&request, command, 0); // TODO -- make dest a real NodeID
-
-  assert(targetSequencer_ptr != NULL);
-  if (targetSequencer_ptr->isReady(&pkt)) {
-    targetSequencer_ptr->makeRequest(&pkt);
-  }
-}
-
-void Check::initiatePrefetch()
-{
-  // Any sequencer can issue a prefetch for this address
-  Sequencer* targetSequencer_ptr = g_system_ptr->getChip(random() % RubyConfig::numberOfChips())->getSequencer(random() % RubyConfig::numberOfProcsPerChip());
-  assert(targetSequencer_ptr != NULL);
-  initiatePrefetch(targetSequencer_ptr);
-}
-
-void Check::initiateAction()
-{
-  DEBUG_MSG(TESTER_COMP, MedPrio, "initiating Action");
-  assert(m_status == TesterStatus_Idle);
-
-  CacheRequestType type = CacheRequestType_ST;
-  if ((random() & 0x1) == 0) { // 50% chance
-    type = CacheRequestType_ATOMIC;
-  }
-
-  Addr data_addr = m_address.getAddress()+m_store_count;
-  Addr pc_addr = m_pc.getAddress();
-  Request request(0, data_addr, 1, Flags<unsigned int>(), pc_addr, 0, 0);
-  MemCmd::Command command;
-  if (type == CacheRequestType_IFETCH) {
-    command = MemCmd::ReadReq;
-    request.setFlags(Request::INST_FETCH);
-  } else if (type == CacheRequestType_LD || type == CacheRequestType_IFETCH) {
-    command = MemCmd::ReadReq;
-  } else if (type == CacheRequestType_ST) {
-    command = MemCmd::WriteReq;
-  } else if (type == CacheRequestType_ATOMIC) {
-    command = MemCmd::SwapReq; // TODO -- differentiate between atomic types
-  } else {
-    panic("Cannot convert request to packet");
-  }
-
-  Packet pkt(&request, command, 0); // TODO -- make dest a real NodeID
-
-  Sequencer* sequencer_ptr = initiatingSequencer();
-  if (sequencer_ptr->isReady(&pkt) == false) {
-    DEBUG_MSG(TESTER_COMP, MedPrio, "failed to initiate action - sequencer not ready\n");
-  } else {
-    DEBUG_MSG(TESTER_COMP, MedPrio, "initiating action - successful\n");
-    DEBUG_EXPR(TESTER_COMP, MedPrio, m_status);
-    m_status = TesterStatus_Action_Pending;
-
-    sequencer_ptr->makeRequest(&pkt);
-  }
-  DEBUG_EXPR(TESTER_COMP, MedPrio, m_status);
-}
-
-void Check::initiateCheck()
-{
-  DEBUG_MSG(TESTER_COMP, MedPrio, "initiating Check");
-  assert(m_status == TesterStatus_Ready);
-
-  CacheRequestType type = CacheRequestType_LD;
-  if ((random() & 0x1) == 0) { // 50% chance
-    type = CacheRequestType_IFETCH;
-  }
-
-
-  Addr data_addr = m_address.getAddress()+m_store_count;
-  Addr pc_addr = m_pc.getAddress();
-  Request request(0, data_addr, CHECK_SIZE, Flags<unsigned int>(), pc_addr, 0, 0);
-  MemCmd::Command command;
-  if (type == CacheRequestType_IFETCH) {
-    command = MemCmd::ReadReq;
-    request.setFlags(Request::INST_FETCH);
-  } else if (type == CacheRequestType_LD || type == CacheRequestType_IFETCH) {
-    command = MemCmd::ReadReq;
-  } else if (type == CacheRequestType_ST) {
-    command = MemCmd::WriteReq;
-  } else if (type == CacheRequestType_ATOMIC) {
-    command = MemCmd::SwapReq; // TODO -- differentiate between atomic types
-  } else {
-    panic("Cannot convert request to packet");
-  }
-
-  Packet pkt(&request, command, 0); // TODO -- make dest a real NodeID
-
-  Sequencer* sequencer_ptr = initiatingSequencer();
-  if (sequencer_ptr->isReady(&pkt) == false) {
-    DEBUG_MSG(TESTER_COMP, MedPrio, "failed to initiate check - sequencer not ready\n");
-  } else {
-    DEBUG_MSG(TESTER_COMP, MedPrio, "initiating check - successful\n");
-    DEBUG_MSG(TESTER_COMP, MedPrio, m_status);
-    m_status = TesterStatus_Check_Pending;
-
-    sequencer_ptr->makeRequest(&pkt);
-  }
-  DEBUG_MSG(TESTER_COMP, MedPrio, m_status);
-}
-
-void Check::performCallback(NodeID proc, SubBlock& data)
-{
-  Address address = data.getAddress();
-  //  assert(getAddress() == address);  // This isn't exactly right since we now have multi-byte checks
-  assert(getAddress().getLineAddress() == address.getLineAddress());
-
-  DEBUG_MSG(TESTER_COMP, MedPrio, "Callback");
-  DEBUG_EXPR(TESTER_COMP, MedPrio, *this);
-
-  if (m_status == TesterStatus_Action_Pending) {
-    DEBUG_MSG(TESTER_COMP, MedPrio, "Action callback");
-    // Perform store
-    data.setByte(0, m_value+m_store_count); // We store one byte at a time
-    m_store_count++;
-
-    if (m_store_count == CHECK_SIZE) {
-      m_status = TesterStatus_Ready;
-    } else {
-      m_status = TesterStatus_Idle;
-    }
-  } else if (m_status == TesterStatus_Check_Pending) {
-    DEBUG_MSG(TESTER_COMP, MedPrio, "Check callback");
-    // Perform load/check
-    for(int byte_number=0; byte_number<CHECK_SIZE; byte_number++) {
-      if (uint8(m_value+byte_number) != data.getByte(byte_number) && (DATA_BLOCK == true)) {
-        WARN_EXPR(proc);
-        WARN_EXPR(address);
-        WARN_EXPR(data);
-        WARN_EXPR(byte_number);
-        WARN_EXPR((int)m_value+byte_number);
-        WARN_EXPR((int)data.getByte(byte_number));
-        WARN_EXPR(*this);
-        WARN_EXPR(g_eventQueue_ptr->getTime());
-        ERROR_MSG("Action/check failure");
-      }
-    }
-    DEBUG_MSG(TESTER_COMP, HighPrio, "Action/check success:");
-    DEBUG_EXPR(TESTER_COMP, HighPrio, *this);
-    DEBUG_EXPR(TESTER_COMP, MedPrio, data);
-
-    m_status = TesterStatus_Idle;
-    pickValue();
-
-  } else {
-    WARN_EXPR(*this);
-    WARN_EXPR(proc);
-    WARN_EXPR(data);
-    WARN_EXPR(m_status);
-    WARN_EXPR(g_eventQueue_ptr->getTime());
-    ERROR_MSG("Unexpected TesterStatus");
-  }
-
-  DEBUG_EXPR(TESTER_COMP, MedPrio, proc);
-  DEBUG_EXPR(TESTER_COMP, MedPrio, data);
-  DEBUG_EXPR(TESTER_COMP, MedPrio, getAddress().getLineAddress());
-  DEBUG_MSG(TESTER_COMP, MedPrio, "Callback done");
-  DEBUG_EXPR(TESTER_COMP, MedPrio, *this);
-}
-
-void Check::changeAddress(const Address& address)
-{
-  assert((m_status == TesterStatus_Idle) || (m_status == TesterStatus_Ready));
-  m_status = TesterStatus_Idle;
-  m_address = address;
-  m_store_count = 0;
-}
-
-Sequencer* Check::initiatingSequencer() const
-{
-  return g_system_ptr->getChip(m_initiatingNode/RubyConfig::numberOfProcsPerChip())->getSequencer(m_initiatingNode%RubyConfig::numberOfProcsPerChip());
-}
-
-void Check::pickValue()
-{
-  assert(m_status == TesterStatus_Idle);
-  m_status = TesterStatus_Idle;
-  //  DEBUG_MSG(TESTER_COMP, MedPrio, m_status);
-  DEBUG_MSG(TESTER_COMP, MedPrio, *this);
-  m_value = random() & 0xff; // One byte
-  //  DEBUG_MSG(TESTER_COMP, MedPrio, m_value);
-  DEBUG_MSG(TESTER_COMP, MedPrio, *this);
-  m_store_count = 0;
-}
-
-void Check::pickInitiatingNode()
-{
-  assert((m_status == TesterStatus_Idle) || (m_status == TesterStatus_Ready));
-  m_status = TesterStatus_Idle;
-  DEBUG_MSG(TESTER_COMP, MedPrio, m_status);
-  m_initiatingNode = (random() % RubyConfig::numberOfProcessors());
-  DEBUG_MSG(TESTER_COMP, MedPrio, m_initiatingNode);
-  m_store_count = 0;
-}
-
-void Check::print(ostream& out) const
-{
-  out << "["
-      << m_address << ", value: "
-      << (int) m_value << ", status: "
-      << m_status << ", initiating node: "
-      << m_initiatingNode << ", store_count: "
-      << m_store_count
-      << "]" << flush;
-}
 
+++ /dev/null
-
-/*
- * 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.
- */
-
-/*
- * $Id$
- *
- * Description:
- *
- */
-
-#ifndef CHECK_H
-#define CHECK_H
-
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/common/Address.hh"
-#include "mem/ruby/system/NodeID.hh"
-#include "mem/protocol/TesterStatus.hh"
-#include "mem/protocol/AccessModeType.hh"
-class Sequencer;
-class SubBlock;
-
-const int CHECK_SIZE_BITS = 2;
-const int CHECK_SIZE = (1<<CHECK_SIZE_BITS);
-
-class Check {
-public:
-  // Constructors
-  Check(const Address& address, const Address& pc);
-
-  // Default Destructor
-  //~Check();
-
-  // Public Methods
-
-  void initiate(); // Does Action or Check or nether
-  void performCallback(NodeID proc, SubBlock& data);
-  const Address& getAddress() { return m_address; }
-  void changeAddress(const Address& address);
-
-  void print(ostream& out) const;
-private:
-  // Private Methods
-  void initiatePrefetch(Sequencer* targetSequencer_ptr);
-  void initiatePrefetch();
-  void initiateAction();
-  void initiateCheck();
-
-  Sequencer* initiatingSequencer() const;
-
-  void pickValue();
-  void pickInitiatingNode();
-
-  // Using default copy constructor and assignment operator
-  //  Check(const Check& obj);
-  //  Check& operator=(const Check& obj);
-
-  // Data Members (m_ prefix)
-  TesterStatus m_status;
-  uint8 m_value;
-  int m_store_count;
-  NodeID m_initiatingNode;
-  Address m_address;
-  Address m_pc;
-  AccessModeType m_access_mode;
-};
-
-// Output operator declaration
-ostream& operator<<(ostream& out, const Check& obj);
-
-// ******************* Definitions *******************
-
-// Output operator definition
-extern inline
-ostream& operator<<(ostream& out, const Check& obj)
-{
-  obj.print(out);
-  out << flush;
-  return out;
-}
-
-#endif //CHECK_H
 
+++ /dev/null
-
-/*
- * 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.
- */
-
-/*
- * $Id$
- *
- */
-
-#include "mem/ruby/tester/CheckTable.hh"
-#include "mem/ruby/tester/Check.hh"
-#include "mem/gems_common/Map.hh"
-
-CheckTable::CheckTable()
-{
-  m_lookup_map_ptr = new Map<Address, Check*>;
-  physical_address_t physical = 0;
-  Address address;
-
-  const int size1 = 32;
-  const int size2 = 100;
-
-  // The first set is to get some false sharing
-  physical = 1000;
-  for (int i=0; i<size1; i++) {
-    // Setup linear addresses
-    address.setAddress(physical);
-    addCheck(address);
-    physical += CHECK_SIZE;
-  }
-
-  // The next two sets are to get some limited false sharing and cache conflicts
-  physical = 1000;
-  for (int i=0; i<size2; i++) {
-    // Setup linear addresses
-    address.setAddress(physical);
-    addCheck(address);
-    physical += 256;
-  }
-
-  physical = 1000 + CHECK_SIZE;
-  for (int i=0; i<size2; i++) {
-    // Setup linear addresses
-    address.setAddress(physical);
-    addCheck(address);
-    physical += 256;
-  }
-}
-
-CheckTable::~CheckTable()
-{
-  int size = m_check_vector.size();
-  for (int i=0; i<size; i++) {
-    delete m_check_vector[i];
-  }
-  delete m_lookup_map_ptr;
-}
-
-void CheckTable::addCheck(const Address& address)
-{
-  if (log_int(CHECK_SIZE) != 0) {
-    if (address.bitSelect(0,CHECK_SIZE_BITS-1) != 0) {
-      ERROR_MSG("Check not aligned");
-    }
-  }
-
-  for (int i=0; i<CHECK_SIZE; i++) {
-    if (m_lookup_map_ptr->exist(Address(address.getAddress()+i))) {
-      // A mapping for this byte already existed, discard the entire check
-      return;
-    }
-  }
-
-  Check* check_ptr = new Check(address, Address(100+m_check_vector.size()));
-  for (int i=0; i<CHECK_SIZE; i++) {
-    // Insert it once per byte
-    m_lookup_map_ptr->add(Address(address.getAddress()+i), check_ptr);
-  }
-  m_check_vector.insertAtBottom(check_ptr);
-}
-
-Check* CheckTable::getRandomCheck()
-{
-  return m_check_vector[random() % m_check_vector.size()];
-}
-
-Check* CheckTable::getCheck(const Address& address)
-{
-  DEBUG_MSG(TESTER_COMP, MedPrio, "Looking for check by address");
-  DEBUG_EXPR(TESTER_COMP, MedPrio, address);
-
-  if (m_lookup_map_ptr->exist(address)) {
-    Check* check = m_lookup_map_ptr->lookup(address);
-    assert(check != NULL);
-    return check;
-  } else {
-    return NULL;
-  }
-}
-
-void CheckTable::print(ostream& out) const
-{
-}
 
+++ /dev/null
-
-/*
- * 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.
- */
-
-/*
- * $Id$
- *
- * Description:
- *
- */
-
-#ifndef CHECKTABLE_H
-#define CHECKTABLE_H
-
-#include "mem/ruby/common/Global.hh"
-#include "mem/gems_common/Vector.hh"
-
-class Address;
-class Check;
-template <class KEY_TYPE, class VALUE_TYPE> class Map;
-
-class CheckTable {
-public:
-  // Constructors
-  CheckTable();
-
-  // Destructor
-  ~CheckTable();
-
-  // Public Methods
-
-  Check* getRandomCheck();
-  Check* getCheck(const Address& address);
-
-  //  bool isPresent(const Address& address) const;
-  //  void removeCheckFromTable(const Address& address);
-  //  bool isTableFull() const;
-  // Need a method to select a check or retrieve a check
-
-  void print(ostream& out) const;
-private:
-  // Private Methods
-  void addCheck(const Address& address);
-
-  // Private copy constructor and assignment operator
-  CheckTable(const CheckTable& obj);
-  CheckTable& operator=(const CheckTable& obj);
-
-  // Data Members (m_ prefix)
-  Vector<Check*> m_check_vector;
-  Map<Address, Check*>* m_lookup_map_ptr;
-};
-
-// Output operator declaration
-ostream& operator<<(ostream& out, const CheckTable& obj);
-
-// ******************* Definitions *******************
-
-// Output operator definition
-extern inline
-ostream& operator<<(ostream& out, const CheckTable& obj)
-{
-  obj.print(out);
-  out << flush;
-  return out;
-}
-
-#endif //CHECKTABLE_H
 
 
 #include "mem/ruby/tester/DetermGETXGenerator.hh"
 #include "mem/protocol/DetermGETXGeneratorStatus.hh"
-#include "mem/protocol/LockStatus.hh"
-#include "mem/ruby/system/Sequencer.hh"
-#include "mem/ruby/system/System.hh"
-#include "mem/ruby/config/RubyConfig.hh"
-#include "mem/ruby/common/SubBlock.hh"
 #include "mem/ruby/tester/DeterministicDriver.hh"
-#include "mem/protocol/Chip.hh"
-#include "mem/packet.hh"
+#include "mem/ruby/tester/Global_Tester.hh"
+#include "mem/ruby/tester/SpecifiedGenerator.hh"
+//#include "DMAController.hh"
+#include "mem/ruby/libruby.hh"
 
-DetermGETXGenerator::DetermGETXGenerator(NodeID node, DeterministicDriver& driver) :
-  m_driver(driver)
+
+DetermGETXGenerator::DetermGETXGenerator(NodeID node, DeterministicDriver * driver)
 {
   m_status = DetermGETXGeneratorStatus_Thinking;
   m_last_transition = 0;
   m_node = node;
   m_address = Address(9999);  // initialize to null value
   m_counter = 0;
-
+  parent_driver = driver;
   // don't know exactly when this node needs to request so just guess randomly
-  g_eventQueue_ptr->scheduleEvent(this, 1+(random() % 200));
+  parent_driver->eventQueue->scheduleEvent(this, 1+(random() % 200));
 }
 
 DetermGETXGenerator::~DetermGETXGenerator()
 
   // determine if this node is next for the GETX round robin request
   if (m_status == DetermGETXGeneratorStatus_Thinking) {
-    if (m_driver.isStoreReady(m_node)) {
+    if (parent_driver->isStoreReady(m_node)) {
       pickAddress();
       m_status = DetermGETXGeneratorStatus_Store_Pending;  // Store Pending
-      m_last_transition = g_eventQueue_ptr->getTime();
+      m_last_transition = parent_driver->eventQueue->getTime();
       initiateStore();  // GETX
     } else { // I'll check again later
-      g_eventQueue_ptr->scheduleEvent(this, thinkTime());
+      parent_driver->eventQueue->scheduleEvent(this, thinkTime());
     }
   } else {
     WARN_EXPR(m_status);
 
 }
 
-void DetermGETXGenerator::performCallback(NodeID proc, SubBlock& data)
+void DetermGETXGenerator::performCallback(NodeID proc, Address address)
 {
-  Address address = data.getAddress();
   assert(proc == m_node);
   assert(address == m_address);
 
   DEBUG_EXPR(TESTER_COMP, LowPrio, proc);
   DEBUG_EXPR(TESTER_COMP, LowPrio, m_status);
   DEBUG_EXPR(TESTER_COMP, LowPrio, address);
-  DEBUG_EXPR(TESTER_COMP, LowPrio, data);
 
   if (m_status == DetermGETXGeneratorStatus_Store_Pending) {
-    m_driver.recordStoreLatency(g_eventQueue_ptr->getTime() - m_last_transition);
-    data.writeByte(m_node);
-    m_driver.storeCompleted(m_node, data.getAddress());  // advance the store queue
+    parent_driver->recordStoreLatency(parent_driver->eventQueue->getTime() - m_last_transition);
+    parent_driver->storeCompleted(m_node, address);  // advance the store queue
 
     m_counter++;
-    if (m_counter < g_tester_length) {
+    if (m_counter < parent_driver->m_tester_length) {
       m_status = DetermGETXGeneratorStatus_Thinking;
-      m_last_transition = g_eventQueue_ptr->getTime();
-      g_eventQueue_ptr->scheduleEvent(this, waitTime());
+      m_last_transition = parent_driver->eventQueue->getTime();
+      parent_driver->eventQueue->scheduleEvent(this, waitTime());
     } else {
-      m_driver.reportDone();
+      parent_driver->reportDone();
       m_status = DetermGETXGeneratorStatus_Done;
-      m_last_transition = g_eventQueue_ptr->getTime();
+      m_last_transition = parent_driver->eventQueue->getTime();
     }
 
   } else {
 
 int DetermGETXGenerator::thinkTime() const
 {
-  return g_think_time;
+  return parent_driver->m_think_time;
 }
 
 int DetermGETXGenerator::waitTime() const
 {
-  return g_wait_time;
+  return parent_driver->m_wait_time;
 }
 
 void DetermGETXGenerator::pickAddress()
 {
   assert(m_status == DetermGETXGeneratorStatus_Thinking);
 
-  m_address = m_driver.getNextStoreAddr(m_node);
+  m_address = parent_driver->getNextStoreAddr(m_node);
 }
 
 void DetermGETXGenerator::initiateStore()
 {
   DEBUG_MSG(TESTER_COMP, MedPrio, "initiating Store");
 
-  Addr data_addr = m_address.getAddress();
-  Request request(0, data_addr, 1, Flags<unsigned int>(), 3, 0, 0);
-  MemCmd::Command command;
-  command = MemCmd::WriteReq;
+  uint8_t *write_data = new uint8_t[64];
+  for(int i=0; i < 64; i++) {
+      write_data[i] = m_node;
+  }
+
+  char name [] = "Sequencer_";
+  char port_name [13];
+  sprintf(port_name, "%s%d", name, m_node);
 
-  Packet pkt(&request, command, 0); // TODO -- make dest a real NodeID
+  int64_t request_id = libruby_issue_request(libruby_get_port_by_name(port_name), RubyRequest(m_address.getAddress(), write_data, 64, 0, RubyRequestType_ST, RubyAccessMode_Supervisor));
 
-  sequencer()->makeRequest(&pkt);
-}
+  // delete [] write_data;
 
-Sequencer* DetermGETXGenerator::sequencer() const
-{
-  return g_system_ptr->getChip(m_node/RubyConfig::numberOfProcsPerChip())->getSequencer(m_node%RubyConfig::numberOfProcsPerChip());
+  ASSERT(parent_driver->requests.find(request_id) == parent_driver->requests.end());
+  parent_driver->requests.insert(make_pair(request_id, make_pair(m_node, m_address)));
 }
 
 void DetermGETXGenerator::print(ostream& out) const
 
 #ifndef DETERMGETXGENERATOR_H
 #define DETERMGETXGENERATOR_H
 
-#include "mem/ruby/common/Global.hh"
+#include "mem/ruby/tester/Global_Tester.hh"
 #include "mem/ruby/common/Consumer.hh"
 #include "mem/protocol/DetermGETXGeneratorStatus.hh"
-#include "mem/ruby/system/NodeID.hh"
-#include "mem/ruby/common/Address.hh"
+#include "Address_Tester.hh"
 #include "mem/ruby/tester/SpecifiedGenerator.hh"
 
-class Sequencer;
-class SubBlock;
 class DeterministicDriver;
+class DMAController;
 
 class DetermGETXGenerator : public SpecifiedGenerator {
 public:
   // Constructors
-  DetermGETXGenerator(NodeID node, DeterministicDriver& driver);
+  DetermGETXGenerator(NodeID node, DeterministicDriver * driver);
 
   // Destructor
   ~DetermGETXGenerator();
 
   // Public Methods
   void wakeup();
-  void performCallback(NodeID proc, SubBlock& data);
+  void performCallback(NodeID proc, Address address);
 
   void print(ostream& out) const;
 private:
   int thinkTime() const;
   int waitTime() const;
   void initiateStore();
+  void initiateDMA();
   void pickAddress();
 
-  Sequencer* sequencer() const;
+  DMAController* dma() const;
 
   // copy constructor and assignment operator
   DetermGETXGenerator(const DetermGETXGenerator& obj);
   DetermGETXGenerator& operator=(const DetermGETXGenerator& obj);
 
+  DeterministicDriver * parent_driver;
   // Data Members (m_ prefix)
   DetermGETXGeneratorStatus m_status;
   int m_counter;
   Address m_address;
   NodeID m_node;
-  DeterministicDriver& m_driver;
   Time m_last_transition;
 };
 
 
 
 #include "mem/ruby/tester/DetermInvGenerator.hh"
 #include "mem/protocol/DetermInvGeneratorStatus.hh"
-#include "mem/protocol/LockStatus.hh"
-#include "mem/ruby/system/Sequencer.hh"
-#include "mem/ruby/system/System.hh"
-#include "mem/ruby/config/RubyConfig.hh"
-#include "mem/ruby/common/SubBlock.hh"
 #include "mem/ruby/tester/DeterministicDriver.hh"
-#include "mem/protocol/Chip.hh"
+#include "mem/ruby/tester/Global_Tester.hh"
+//#include "DMAController.hh"
+#include "mem/ruby/libruby.hh"
 
 DetermInvGenerator::DetermInvGenerator(NodeID node, DeterministicDriver& driver) :
   m_driver(driver)
   m_node = node;
   m_address = Address(9999);  // initiate to a NULL value
   m_counter = 0;
-
   // don't know exactly when this node needs to request so just guess randomly
-  g_eventQueue_ptr->scheduleEvent(this, 1+(random() % 200));
+  m_driver.eventQueue->scheduleEvent(this, 1+(random() % 200));
 }
 
 DetermInvGenerator::~DetermInvGenerator()
     if (m_driver.isLoadReady(m_node) && m_counter == m_driver.getStoresCompleted()) {
       pickLoadAddress();
       m_status = DetermInvGeneratorStatus_Load_Pending;  // Load Pending
-      m_last_transition = g_eventQueue_ptr->getTime();
+      m_last_transition = m_driver.eventQueue->getTime();
       initiateLoad();  // GETS
     } else { // I'll check again later
-      g_eventQueue_ptr->scheduleEvent(this, thinkTime());
+      m_driver.eventQueue->scheduleEvent(this, thinkTime());
     }
   } else if (m_status == DetermInvGeneratorStatus_Load_Complete) {
     if (m_driver.isStoreReady(m_node, m_address))   {  // do a store in this transaction or start the next one
       if (m_driver.isLoadReady((0), m_address)) {  // everyone is in S for this address i.e. back to node 0
         m_status = DetermInvGeneratorStatus_Store_Pending;
-        m_last_transition = g_eventQueue_ptr->getTime();
+        m_last_transition = m_driver.eventQueue->getTime();
         initiateStore();  // GETX
       } else {  // I'm next, I just have to wait for all loads to complete
-        g_eventQueue_ptr->scheduleEvent(this, thinkTime());
+        m_driver.eventQueue->scheduleEvent(this, thinkTime());
       }
     } else {  // I'm not next to store, go back to thinking
       m_status = DetermInvGeneratorStatus_Thinking;
-      g_eventQueue_ptr->scheduleEvent(this, thinkTime());
+      m_driver.eventQueue->scheduleEvent(this, thinkTime());
     }
   } else {
     WARN_EXPR(m_status);
 
 }
 
-void DetermInvGenerator::performCallback(NodeID proc, SubBlock& data)
+void DetermInvGenerator::performCallback(NodeID proc, Address address)
 {
-  Address address = data.getAddress();
   assert(proc == m_node);
   assert(address == m_address);
 
   DEBUG_EXPR(TESTER_COMP, LowPrio, proc);
   DEBUG_EXPR(TESTER_COMP, LowPrio, m_status);
   DEBUG_EXPR(TESTER_COMP, LowPrio, address);
-  DEBUG_EXPR(TESTER_COMP, LowPrio, data);
 
   if (m_status == DetermInvGeneratorStatus_Load_Pending) {
-    m_driver.recordLoadLatency(g_eventQueue_ptr->getTime() - m_last_transition);
-    m_driver.loadCompleted(m_node, data.getAddress());
+    m_driver.recordLoadLatency(m_driver.eventQueue->getTime() - m_last_transition);
+    //NodeID firstByte = data.readByte();  // dummy read
+
+    m_driver.loadCompleted(m_node, address);
 
     if (!m_driver.isStoreReady(m_node, m_address))  {  // if we don't have to store, we are done for this transaction
       m_counter++;
     }
-    if (m_counter < g_tester_length) {
+    if (m_counter < m_driver.m_tester_length) {
       m_status = DetermInvGeneratorStatus_Load_Complete;
-      m_last_transition = g_eventQueue_ptr->getTime();
-      g_eventQueue_ptr->scheduleEvent(this, waitTime());
+      m_last_transition = m_driver.eventQueue->getTime();
+      m_driver.eventQueue->scheduleEvent(this, waitTime());
     } else {
       m_driver.reportDone();
       m_status = DetermInvGeneratorStatus_Done;
-      m_last_transition = g_eventQueue_ptr->getTime();
+      m_last_transition = m_driver.eventQueue->getTime();
     }
 
   } else if (m_status == DetermInvGeneratorStatus_Store_Pending) {
-    m_driver.recordStoreLatency(g_eventQueue_ptr->getTime() - m_last_transition);
-    data.writeByte(m_node);
-    m_driver.storeCompleted(m_node, data.getAddress());  // advance the store queue
+    m_driver.recordStoreLatency(m_driver.eventQueue->getTime() - m_last_transition);
+    //data.writeByte(m_node);
+    m_driver.storeCompleted(m_node, address);  // advance the store queue
 
     m_counter++;
-    if (m_counter < g_tester_length) {
+    if (m_counter < m_driver.m_tester_length) {
       m_status = DetermInvGeneratorStatus_Thinking;
-      m_last_transition = g_eventQueue_ptr->getTime();
-      g_eventQueue_ptr->scheduleEvent(this, waitTime());
+      m_last_transition = m_driver.eventQueue->getTime();
+      m_driver.eventQueue->scheduleEvent(this, waitTime());
     } else {
       m_driver.reportDone();
       m_status = DetermInvGeneratorStatus_Done;
-      m_last_transition = g_eventQueue_ptr->getTime();
+      m_last_transition = m_driver.eventQueue->getTime();
     }
   } else {
     WARN_EXPR(m_status);
   DEBUG_EXPR(TESTER_COMP, LowPrio, proc);
   DEBUG_EXPR(TESTER_COMP, LowPrio, m_status);
   DEBUG_EXPR(TESTER_COMP, LowPrio, address);
-  DEBUG_EXPR(TESTER_COMP, LowPrio, data);
 
 }
 
 int DetermInvGenerator::thinkTime() const
 {
-  return g_think_time;
+  return m_driver.m_think_time;
 }
 
 int DetermInvGenerator::waitTime() const
 {
-  return g_wait_time;
+  return m_driver.m_wait_time;
 }
 
 int DetermInvGenerator::holdTime() const
 {
-  return g_hold_time;
+  assert(0);
 }
 
 void DetermInvGenerator::pickLoadAddress()
 void DetermInvGenerator::initiateLoad()
 {
   DEBUG_MSG(TESTER_COMP, MedPrio, "initiating Load");
+  // sequencer()->makeRequest(CacheMsg(m_address, m_address, CacheRequestType_LD, Address(1), AccessModeType_UserMode, 1, PrefetchBit_No, Address(0), 0 /* only 1 SMT thread */));
+  uint8_t * read_data = new uint8_t[64];
 
-  Addr data_addr = m_address.getAddress();
-  Request request(0, data_addr, 1, Flags<unsigned int>(), 1, 0, 0);
-  MemCmd::Command command;
-  command = MemCmd::ReadReq;
+  char name [] = "Sequencer_";
+  char port_name [13];
+  sprintf(port_name, "%s%d", name, m_node);
 
-  Packet pkt(&request, command, 0); // TODO -- make dest a real NodeID
+  int64_t request_id = libruby_issue_request(libruby_get_port_by_name(port_name), RubyRequest(m_address.getAddress(), read_data, 64, 0, RubyRequestType_LD, RubyAccessMode_Supervisor));
 
-  sequencer()->makeRequest(&pkt);
+  //delete [] read_data;
+
+  ASSERT(m_driver.requests.find(request_id) == m_driver.requests.end());
+  m_driver.requests.insert(make_pair(request_id, make_pair(m_node, m_address)));
 
 }
 
 void DetermInvGenerator::initiateStore()
 {
   DEBUG_MSG(TESTER_COMP, MedPrio, "initiating Store");
+  // sequencer()->makeRequest(CacheMsg(m_address, m_address, CacheRequestType_ST, Address(3), AccessModeType_UserMode, 1, PrefetchBit_No, Address(0), 0 /* only 1 SMT thread */));
+  uint8_t *write_data = new uint8_t[64];
+  for(int i=0; i < 64; i++) {
+      write_data[i] = m_node;
+  }
 
-  Addr data_addr = m_address.getAddress();
-  Request request(0, data_addr, 1, Flags<unsigned int>(), 3, 0, 0);
-  MemCmd::Command command;
-  command = MemCmd::WriteReq;
+  char name [] = "Sequencer_";
+  char port_name [13];
+  sprintf(port_name, "%s%d", name, m_node);
 
-  Packet pkt(&request, command, 0); // TODO -- make dest a real NodeID
+  int64_t request_id = libruby_issue_request(libruby_get_port_by_name(port_name), RubyRequest(m_address.getAddress(), write_data, 64, 0, RubyRequestType_ST, RubyAccessMode_Supervisor));
 
-  sequencer()->makeRequest(&pkt);
-}
+  //delete [] write_data;
+
+  ASSERT(m_driver.requests.find(request_id) == m_driver.requests.end());
+  m_driver.requests.insert(make_pair(request_id, make_pair(m_node, m_address)));
 
-Sequencer* DetermInvGenerator::sequencer() const
-{
-  return g_system_ptr->getChip(m_node/RubyConfig::numberOfProcsPerChip())->getSequencer(m_node%RubyConfig::numberOfProcsPerChip());
 }
 
 void DetermInvGenerator::print(ostream& out) const
 
 #ifndef DETERMINVGENERATOR_H
 #define DETERMINVGENERATOR_H
 
-#include "mem/ruby/common/Global.hh"
+#include "mem/ruby/tester/Global_Tester.hh"
 #include "mem/ruby/common/Consumer.hh"
 #include "mem/protocol/DetermInvGeneratorStatus.hh"
-#include "mem/ruby/system/NodeID.hh"
-#include "mem/ruby/common/Address.hh"
+#include "Address_Tester.hh"
 #include "mem/ruby/tester/SpecifiedGenerator.hh"
 
-class Sequencer;
-class SubBlock;
 class DeterministicDriver;
 
 class DetermInvGenerator : public SpecifiedGenerator {
 
   // Public Methods
   void wakeup();
-  void performCallback(NodeID proc, SubBlock& data);
+  void performCallback(NodeID proc, Address address);
 
   void print(ostream& out) const;
 private:
   void pickLoadAddress();
   void pickStoreAddress();
 
-  Sequencer* sequencer() const;
-
   // copy constructor and assignment operator
   DetermInvGenerator(const DetermInvGenerator& obj);
   DetermInvGenerator& operator=(const DetermInvGenerator& obj);
 
 
 #include "mem/ruby/tester/DetermSeriesGETSGenerator.hh"
 #include "mem/protocol/DetermSeriesGETSGeneratorStatus.hh"
-#include "mem/protocol/LockStatus.hh"
-#include "mem/ruby/system/Sequencer.hh"
-#include "mem/ruby/system/System.hh"
-#include "mem/ruby/config/RubyConfig.hh"
-#include "mem/ruby/common/SubBlock.hh"
 #include "mem/ruby/tester/DeterministicDriver.hh"
-#include "mem/protocol/Chip.hh"
 
 DetermSeriesGETSGenerator::DetermSeriesGETSGenerator(NodeID node, DeterministicDriver& driver) :
   m_driver(driver)
   m_address = Address(9999);  // initialize to null value
   m_counter = 0;
 
+
   // don't know exactly when this node needs to request so just guess randomly
-  g_eventQueue_ptr->scheduleEvent(this, 1+(random() % 200));
+  m_driver.eventQueue->scheduleEvent(this, 1+(random() % 200));
 }
 
 DetermSeriesGETSGenerator::~DetermSeriesGETSGenerator()
     if (m_driver.isLoadReady(m_node)) {
       pickAddress();
       m_status = DetermSeriesGETSGeneratorStatus_Load_Pending;  // Load Pending
-      m_last_transition = g_eventQueue_ptr->getTime();
+      m_last_transition = m_driver.eventQueue->getTime();
       initiateLoad();  // SeriesGETS
     } else { // I'll check again later
-      g_eventQueue_ptr->scheduleEvent(this, thinkTime());
+      m_driver.eventQueue->scheduleEvent(this, thinkTime());
     }
   } else {
     WARN_EXPR(m_status);
 
 }
 
-void DetermSeriesGETSGenerator::performCallback(NodeID proc, SubBlock& data)
+void DetermSeriesGETSGenerator::performCallback(NodeID proc, Address address)
 {
-  Address address = data.getAddress();
   assert(proc == m_node);
   assert(address == m_address);
 
   DEBUG_EXPR(TESTER_COMP, LowPrio, proc);
   DEBUG_EXPR(TESTER_COMP, LowPrio, m_status);
   DEBUG_EXPR(TESTER_COMP, LowPrio, address);
-  DEBUG_EXPR(TESTER_COMP, LowPrio, data);
 
   if (m_status == DetermSeriesGETSGeneratorStatus_Load_Pending) {
-    m_driver.recordLoadLatency(g_eventQueue_ptr->getTime() - m_last_transition);
-    data.writeByte(m_node);
-    m_driver.loadCompleted(m_node, data.getAddress());  // advance the load queue
+    m_driver.recordLoadLatency(m_driver.eventQueue->getTime() - m_last_transition);
+    //data.writeByte(m_node);
+    m_driver.loadCompleted(m_node, address);  // advance the load queue
 
     m_counter++;
     // do we still have more requests to complete before the next proc starts?
-    if (m_counter < g_tester_length*g_NUM_COMPLETIONS_BEFORE_PASS) {
+    if (m_counter < m_driver.m_tester_length*m_driver.m_numCompletionsPerNode) {
       m_status = DetermSeriesGETSGeneratorStatus_Thinking;
-      m_last_transition = g_eventQueue_ptr->getTime();
-      g_eventQueue_ptr->scheduleEvent(this, waitTime());
+      m_last_transition = m_driver.eventQueue->getTime();
+      m_driver.eventQueue->scheduleEvent(this, waitTime());
     } else {
       m_driver.reportDone();
       m_status = DetermSeriesGETSGeneratorStatus_Done;
-      m_last_transition = g_eventQueue_ptr->getTime();
+      m_last_transition = m_driver.eventQueue->getTime();
     }
 
   } else {
 
 int DetermSeriesGETSGenerator::thinkTime() const
 {
-  return g_think_time;
+  return m_driver.m_think_time;
 }
 
 int DetermSeriesGETSGenerator::waitTime() const
 {
-  return g_wait_time;
+  return m_driver.m_wait_time;
 }
 
 void DetermSeriesGETSGenerator::pickAddress()
 void DetermSeriesGETSGenerator::initiateLoad()
 {
   DEBUG_MSG(TESTER_COMP, MedPrio, "initiating Load");
+  //sequencer()->makeRequest(CacheMsg(m_address, m_address, CacheRequestType_IFETCH, Address(3), AccessModeType_UserMode, 1, PrefetchBit_No, Address(0), 0 /* only 1 SMT thread */));
 
-  Addr data_addr = m_address.getAddress();
-  Request request(0, data_addr, 1, Flags<unsigned int>(), 3, 0, 0);
-  MemCmd::Command command;
-  command = MemCmd::ReadReq;
-  request.setFlags(Request::INST_FETCH);
+  uint8_t *read_data = new uint8_t[64];
 
-  Packet pkt(&request, command, 0); // TODO -- make dest a real NodeID
+  char name [] = "Sequencer_";
+  char port_name [13];
+  sprintf(port_name, "%s%d", name, m_node);
 
-  sequencer()->makeRequest(&pkt);
-}
+  int64_t request_id = libruby_issue_request(libruby_get_port_by_name(port_name), RubyRequest(m_address.getAddress(), read_data, 64, 0, RubyRequestType_LD, RubyAccessMode_Supervisor));
 
-Sequencer* DetermSeriesGETSGenerator::sequencer() const
-{
-  return g_system_ptr->getChip(m_node/RubyConfig::numberOfProcsPerChip())->getSequencer(m_node%RubyConfig::numberOfProcsPerChip());
+  //delete [] read_data;
+
+  ASSERT(m_driver.requests.find(request_id) == m_driver.requests.end());
+  m_driver.requests.insert(make_pair(request_id, make_pair(m_node, m_address)));
 }
 
 void DetermSeriesGETSGenerator::print(ostream& out) const
 
 #ifndef DETERMSERIESGETSGENERATOR_H
 #define DETERMSERIESGETSGENERATOR_H
 
-#include "mem/ruby/common/Global.hh"
+#include "mem/ruby/tester/Global_Tester.hh"
 #include "mem/ruby/common/Consumer.hh"
 #include "mem/protocol/DetermSeriesGETSGeneratorStatus.hh"
-#include "mem/ruby/system/NodeID.hh"
-#include "mem/ruby/common/Address.hh"
+#include "Address_Tester.hh"
 #include "mem/ruby/tester/SpecifiedGenerator.hh"
 
-class Sequencer;
-class SubBlock;
 class DeterministicDriver;
 
 class DetermSeriesGETSGenerator : public SpecifiedGenerator {
 
   // Public Methods
   void wakeup();
-  void performCallback(NodeID proc, SubBlock& data);
+  void performCallback(NodeID proc, Address address);
 
   void print(ostream& out) const;
 private:
   void initiateLoad();
   void pickAddress();
 
-  Sequencer* sequencer() const;
-
   // copy constructor and assignment operator
   DetermSeriesGETSGenerator(const DetermSeriesGETSGenerator& obj);
   DetermSeriesGETSGenerator& operator=(const DetermSeriesGETSGenerator& obj);
 
  *
  */
 
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/system/System.hh"
+#include "mem/ruby/tester/Global_Tester.hh"
 #include "mem/ruby/tester/DeterministicDriver.hh"
-#include "mem/ruby/eventqueue/RubyEventQueue.hh"
-#include "mem/ruby/tester/SpecifiedGenerator.hh"
+#include "mem/ruby/tester/EventQueue_Tester.hh"
+//#include "DMAGenerator.hh"
 #include "mem/ruby/tester/DetermGETXGenerator.hh"
-#include "mem/ruby/tester/DetermInvGenerator.hh"
-#include "mem/ruby/tester/DetermSeriesGETSGenerator.hh"
-#include "mem/ruby/common/SubBlock.hh"
-#include "mem/protocol/Chip.hh"
-#include "mem/packet.hh"
 
-DeterministicDriver::DeterministicDriver(RubySystem* sys_ptr)
+#define DATA_BLOCK_BYTES 64
+
+DeterministicDriver::DeterministicDriver(string generator_type, int num_completions, int num_procs, Time g_think_time, Time g_wait_time, int g_tester_length)
 {
+  eventQueue = new RubyEventQueue;
   m_finish_time = 0;
   m_last_issue = -11;
   m_done_counter = 0;
   m_loads_completed = 0;
   m_stores_completed = 0;
 
-  m_numCompletionsPerNode = g_NUM_COMPLETIONS_BEFORE_PASS;
+  m_numCompletionsPerNode = num_completions;
+  m_num_procs = num_procs;
+  m_think_time = g_think_time;
+  m_wait_time = g_wait_time;
+  m_tester_length = g_tester_length;
+
 
-  m_last_progress_vector.setSize(RubyConfig::numberOfProcessors());
+  m_last_progress_vector.setSize(num_procs);
   for (int i=0; i<m_last_progress_vector.size(); i++) {
     m_last_progress_vector[i] = 0;
   }
 
-  m_load_vector.setSize(g_deterministic_addrs);
+  m_load_vector.setSize(10);
   for (int i=0; i<m_load_vector.size(); i++) {
     m_load_vector[i] = -1;  // No processor last held it
   }
 
-  m_store_vector.setSize(g_deterministic_addrs);
+  m_store_vector.setSize(10);
   for (int i=0; i<m_store_vector.size(); i++) {
     m_store_vector[i] = -1;  // No processor last held it
   }
 
-  m_generator_vector.setSize(RubyConfig::numberOfProcessors());
+  m_generator_vector.setSize(num_procs);
 
-  SpecifiedGeneratorType generator = string_to_SpecifiedGeneratorType(g_SpecifiedGenerator);
+  int generator = string_to_SpecifiedGeneratorType(generator_type);
 
   for (int i=0; i<m_generator_vector.size(); i++) {
     switch (generator) {
     case SpecifiedGeneratorType_DetermGETXGenerator:
-      m_generator_vector[i] = new DetermGETXGenerator(i, *this);
-      break;
-    case SpecifiedGeneratorType_DetermSeriesGETSGenerator:
-      m_generator_vector[i] = new DetermSeriesGETSGenerator(i, *this);
+      m_generator_vector[i] = new DetermGETXGenerator(i, this);
       break;
     case SpecifiedGeneratorType_DetermInvGenerator:
       m_generator_vector[i] = new DetermInvGenerator(i, *this);
       break;
+    case SpecifiedGeneratorType_DetermSeriesGETSGenerator:
+      m_generator_vector[i] = new DetermSeriesGETSGenerator(i, *this);
+      break;
     default:
       ERROR_MSG("Unexpected specified generator type");
     }
   }
 
-  // add the tester consumer to the global event queue
-  g_eventQueue_ptr->scheduleEvent(this, 1);
+  //m_dma_generator = new DMAGenerator(0, this);
 }
 
+
+void DeterministicDriver::go()
+{
+  // tick both queues until everyone is done
+  while (m_done_counter != m_num_procs) {
+    libruby_tick(1);
+    eventQueue->triggerEvents(eventQueue->getTime() + 1);
+  }
+}
+
+
 DeterministicDriver::~DeterministicDriver()
 {
   for (int i=0; i<m_last_progress_vector.size(); i++) {
   }
 }
 
-void
-DeterministicDriver::hitCallback(Packet * pkt)
+//void DeterministicDriver::dmaHitCallback()
+//{
+//  m_dma_generator->performCallback();
+//}
+
+void DeterministicDriver::wakeup() {
+  assert(0);
+  // this shouldn't be called as we are not scheduling the driver ever
+}
+
+void DeterministicDriver::hitCallback(int64_t request_id)
 {
-  NodeID proc = pkt->req->contextId();
-  SubBlock data(Address(pkt->getAddr()), pkt->req->getSize());
-  if (pkt->hasData()) {
-    for (int i = 0; i < pkt->req->getSize(); i++) {
-      data.setByte(i, *(pkt->getPtr<uint8>()+i));
-    }
-  }
-  m_generator_vector[proc]->performCallback(proc, data);
-  m_last_progress_vector[proc] = g_eventQueue_ptr->getTime();
+  ASSERT(requests.find(request_id) != requests.end());
+  int proc = requests[request_id].first;
+  Address address = requests[request_id].second;
+
+  m_generator_vector[proc]->performCallback(proc, address);
+
+  m_last_progress_vector[proc] = eventQueue->getTime();
+
+  requests.erase(request_id);
 }
 
 bool DeterministicDriver::isStoreReady(NodeID node)
 
 bool DeterministicDriver::isStoreReady(NodeID node, Address addr)
 {
+  int addr_number = addr.getAddress()/DATA_BLOCK_BYTES;
+
   return isAddrReady(node, m_store_vector, addr);
 }
 
 bool DeterministicDriver::isAddrReady(NodeID node, Vector<NodeID> addr_vector)
 {
   for (int i=0; i<addr_vector.size(); i++) {
-    if (((addr_vector[i]+1)%RubyConfig::numberOfProcessors() == node) &&
+    if (((addr_vector[i]+1)%m_num_procs == node) &&
         (m_loads_completed+m_stores_completed >= m_numCompletionsPerNode*node) && // is this node next
-        (g_eventQueue_ptr->getTime() >= m_last_issue + 10)) { // controll rate of requests
+        (eventQueue->getTime() >= m_last_issue + 10)) { // controll rate of requests
       return true;
     }
   }
+
   return false;
 }
 
 // test for a particular addr
 bool DeterministicDriver::isAddrReady(NodeID node, Vector<NodeID> addr_vector, Address addr)
 {
-  int addr_number = addr.getAddress()/RubyConfig::dataBlockBytes();
+  int addr_number = addr.getAddress()/DATA_BLOCK_BYTES;
 
   ASSERT ((addr_number >= 0) && (addr_number < addr_vector.size()));
 
-  if (((addr_vector[addr_number]+1)%RubyConfig::numberOfProcessors() == node) &&
+  if (((addr_vector[addr_number]+1)%m_num_procs == node) &&
       (m_loads_completed+m_stores_completed >= m_numCompletionsPerNode*node) && // is this node next
-      (g_eventQueue_ptr->getTime() >= m_last_issue + 10)) { // controll rate of requests
+      (eventQueue->getTime() >= m_last_issue + 10)) { // controll rate of requests
     return true;
   } else {
     return false;
 void DeterministicDriver::setNextAddr(NodeID node, Address addr, Vector<NodeID>& addr_vector)
 {
   // mark the addr vector that this proc was the last to use the particular address
-  int addr_number = addr.getAddress()/RubyConfig::dataBlockBytes();
+  int addr_number = addr.getAddress()/DATA_BLOCK_BYTES;
   addr_vector[addr_number] = node;
 }
 
   ASSERT(isAddrReady(node, addr_vector));
 
   for (int addr_number=0; addr_number<addr_vector.size(); addr_number++) {
-  //for (int addr_number=addr_vector.size()-1; addr_number>0; addr_number--) {
 
     // is this node next in line for the addr
-    if (((addr_vector[addr_number]+1)%RubyConfig::numberOfProcessors()) == node) {
+    if ((addr_vector[addr_number] != 1) && ((addr_vector[addr_number]+1)%m_num_procs) == node) {
 
       // One addr per cache line
-      addr.setAddress(addr_number * RubyConfig::dataBlockBytes());
+      addr.setAddress(addr_number * DATA_BLOCK_BYTES);
     }
   }
 
-  m_last_issue = g_eventQueue_ptr->getTime();
+  m_last_issue = eventQueue->getTime();
 
   return addr;
 }
 void DeterministicDriver::reportDone()
 {
   m_done_counter++;
-  if ((m_done_counter == RubyConfig::numberOfProcessors())) {
-      //|| (m_done_counter == g_tester_length)) {
-    m_finish_time = g_eventQueue_ptr->getTime();
+  if ((m_done_counter == m_num_procs)) {
+    m_finish_time = eventQueue->getTime();
+    //m_dma_generator->stop();
   }
 }
 
   m_store_latency.add(time);
 }
 
-void DeterministicDriver::wakeup()
-{
-  //  checkForDeadlock();
-  if (m_done_counter < RubyConfig::numberOfProcessors()) {
-    g_eventQueue_ptr->scheduleEvent(this, g_DEADLOCK_THRESHOLD);
-  }
-}
-
-void DeterministicDriver::checkForDeadlock()
-{
-  int size = m_last_progress_vector.size();
-  Time current_time = g_eventQueue_ptr->getTime();
-  for (int processor=0; processor<size; processor++) {
-    if ((current_time - m_last_progress_vector[processor]) > g_DEADLOCK_THRESHOLD) {
-      WARN_EXPR(processor);
-#ifndef NDEBUG
-      Sequencer* seq_ptr = g_system_ptr->getChip(processor/RubyConfig::numberOfProcsPerChip())->getSequencer(processor%RubyConfig::numberOfProcsPerChip());
-#endif
-      assert(seq_ptr != NULL);
-      //     if (seq_ptr->isRequestPending()) {
-      //       WARN_EXPR(seq_ptr->pendingAddress());
-      //      }
-      WARN_EXPR(current_time);
-      WARN_EXPR(m_last_progress_vector[processor]);
-      WARN_EXPR(current_time - m_last_progress_vector[processor]);
-      ERROR_MSG("Deadlock detected.");
-    }
-  }
-}
-
 void DeterministicDriver::printStats(ostream& out) const
 {
   out << endl;
 
 
 #ifndef DETERMINISTICDRIVER_H
 #define DETERMINISTICDRIVER_H
-
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/common/Driver.hh"
-#include "mem/ruby/common/Histogram.hh"
-#include "mem/protocol/CacheRequestType.hh"
-
-class RubySystem;
-class SpecifiedGenerator;
-class Packet;
-
-class DeterministicDriver : public Driver, public Consumer {
+#include <map>
+#include "mem/ruby/tester/Global_Tester.hh"
+#include "mem/ruby/common/Histogram.hh"            // includes global, but doesn't use anything, so it should be fine
+#include "mem/protocol/CacheRequestType.hh"     // includes global, but doesn't use anything, so it should be fine
+#include "Address_Tester.hh"       // we redefined the address
+#include "mem/ruby/tester/DetermGETXGenerator.hh"  // this is our file
+#include "mem/ruby/tester/DetermSeriesGETSGenerator.hh"  // this is our file
+#include "mem/ruby/tester/DetermInvGenerator.hh"  // this is our file
+#include "mem/ruby/libruby.hh"
+#include "mem/ruby/tester/Driver_Tester.hh"
+#include "mem/ruby/common/Consumer.hh"
+#include "mem/ruby/tester/EventQueue_Tester.hh"
+#include "mem/protocol/SpecifiedGeneratorType.hh"
+
+//class DMAGenerator;
+
+class DeterministicDriver : public Driver_Tester, public Consumer {
 public:
+  friend class DetermGETXGenerator;
+  friend class DetermSeriesGETSGenerator;
+  friend class DetermInvGenerator;
   // Constructors
-  DeterministicDriver(RubySystem* sys_ptr);
+  DeterministicDriver(string generator_type, int num_completions, int num_procs, Time g_think_time, Time g_wait_time, int g_tester_length);
 
   // Destructor
   ~DeterministicDriver();
 
   // Public Methods
+  void go();
   bool isStoreReady(NodeID node);
   bool isLoadReady(NodeID node);
   bool isStoreReady(NodeID node, Address addr);
   void recordLoadLatency(Time time);
   void recordStoreLatency(Time time);
 
-  void hitCallback(Packet* pkt);
+//  void dmaHitCallback();
+  void hitCallback(int64_t request_id);
   void wakeup();
   void printStats(ostream& out) const;
   void clearStats() {}
   void printConfig(ostream& out) const {}
 
   void print(ostream& out) const;
+  // Public copy constructor and assignment operator
+  DeterministicDriver(const DeterministicDriver& obj);
+  DeterministicDriver& operator=(const DeterministicDriver& obj);
+
 private:
   // Private Methods
-  void checkForDeadlock();
 
   Address getNextAddr(NodeID node, Vector<NodeID> addr_vector);
   bool isAddrReady(NodeID node, Vector<NodeID> addr_vector);
   bool isAddrReady(NodeID node, Vector<NodeID> addr_vector, Address addr);
   void setNextAddr(NodeID node, Address addr, Vector<NodeID>& addr_vector);
 
-  // Private copy constructor and assignment operator
-  DeterministicDriver(const DeterministicDriver& obj);
-  DeterministicDriver& operator=(const DeterministicDriver& obj);
 
   // Data Members (m_ prefix)
   Vector<Time> m_last_progress_vector;
   Vector<SpecifiedGenerator*> m_generator_vector;
+  //DMAGenerator* m_dma_generator;
   Vector<NodeID> m_load_vector;  // Processor last to load the addr
   Vector<NodeID> m_store_vector;  // Processor last to store the addr
 
+  int last_proc;
   int m_done_counter;
   int m_loads_completed;
   int m_stores_completed;
   // enforces the previous node to have a certain # of completions
   // before next node starts
+
+  map <int64_t, pair <int, Address> > requests;
+  Time m_think_time;
+  Time m_wait_time;
+  int m_tester_length;
+  int m_num_procs;
+  RubyEventQueue * eventQueue;
   int m_numCompletionsPerNode;
 
   Histogram m_load_latency;
 
--- /dev/null
+
+/*
+ * 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.
+ */
+
+/*
+ * $Id$
+ *
+ * Description: See Driver_Tester.hh
+ *
+ */
+
+#include "mem/ruby/tester/Driver_Tester.hh"
+
+Driver_Tester::Driver_Tester() {
+}
+
+// still need to be defined for subclasses
+Driver_Tester::~Driver_Tester() {
+}
 
--- /dev/null
+
+/*
+ * 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.
+ */
+
+/*
+ * $Id$
+ *
+ * Description:
+ *
+ */
+
+#ifndef Driver_Tester_H
+#define Driver_Tester_H
+
+#include "mem/ruby/tester/Global_Tester.hh"
+#include "mem/ruby/common/Consumer.hh"
+#include "mem/ruby/system/NodeID.hh"
+#include "Address_Tester.hh"
+
+class Driver_Tester {
+public:
+  // Constructors
+  Driver_Tester();
+
+  // Destructor
+  virtual ~Driver_Tester() = 0;
+
+  // Public Methods
+  virtual void get_network_config() {}
+  virtual void dmaHitCallback() {};
+  virtual void hitCallback(int64_t id) = 0;
+  virtual void go() = 0;
+  virtual integer_t getInstructionCount(int procID) const { return 1; }
+  virtual integer_t getCycleCount(int procID) const { return 1; }
+  virtual void addThreadDependency(int procID, int requestor_thread, int conflict_thread) const { assert(0);}
+  virtual void printDebug(){}
+
+  virtual void printStats(ostream& out) const = 0;
+  virtual void clearStats() = 0;
+
+  virtual void printConfig(ostream& out) const = 0;
+
+  virtual integer_t readPhysicalMemory(int procID, physical_address_t address,
+                                       int len ){ ASSERT(0); return 0; }
+
+  virtual void writePhysicalMemory( int procID, physical_address_t address,
+                                    integer_t value, int len ){ ASSERT(0); }
+
+protected:
+  // accessible by subclasses
+
+private:
+  // inaccessible by subclasses
+
+};
+
+#endif //Driver_Tester_H
 
--- /dev/null
+
+/*
+ * 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.
+ */
+
+/*
+ * $Id$
+ *
+ * Description: The RubyEventQueue class implements an event queue which
+ * can be trigger events, allowing our simulation to be event driven.
+ *
+ * Currently, the only event we support is a Consumer being signaled
+ * by calling the consumer's wakeup() routine.  Adding the event to
+ * the queue does not require a virtual function call, though calling
+ * wakeup() is a virtual function call.
+ *
+ * The method triggerEvents() is called with a global time.  All
+ * events which are before or at this time are triggered in timestamp
+ * order.  No ordering is enforced for events scheduled to occur at
+ * the same time.  Events scheduled to wakeup the same consumer at the
+ * same time are combined into a single event.
+ *
+ * The method scheduleConsumerWakeup() is called with a global time
+ * and a consumer pointer.  The event queue will call the wakeup()
+ * method of the consumer at the appropriate time.
+ *
+ * This implementation of RubyEventQueue uses a dynamically sized array
+ * managed as a heap.  The algorithms used has O(lg n) for insert and
+ * O(lg n) for extract minimum element. (Based on chapter 7 of Cormen,
+ * Leiserson, and Rivest.)  The array is dynamically sized and is
+ * automatically doubled in size when necessary.
+ *
+ */
+
+#ifndef EVENTQUEUE_H
+#define EVENTQUEUE_H
+
+#include "mem/ruby/tester/Global_Tester.hh"
+#include "mem/gems_common/Vector.hh"
+
+class Consumer;
+template <class TYPE> class PrioHeap;
+class RubyEventQueueNode;
+
+class RubyEventQueue {
+public:
+  // Constructors
+  RubyEventQueue();
+
+  // Destructor
+  ~RubyEventQueue();
+
+  // Public Methods
+
+  Time getTime() const { return m_globalTime; }
+  void scheduleEvent(Consumer* consumer, Time timeDelta) { scheduleEventAbsolute(consumer, timeDelta + m_globalTime); }
+  void scheduleEventAbsolute(Consumer* consumer, Time timeAbs);
+  void triggerEvents(Time t); // called to handle all events <= time t
+  void triggerAllEvents();
+  void print(ostream& out) const;
+  bool isEmpty() const;
+
+  Time getTimeOfLastRecovery() {return m_timeOfLastRecovery;}
+  void setTimeOfLastRecovery(Time t) {m_timeOfLastRecovery = t;}
+
+  // Private Methods
+private:
+  // Private copy constructor and assignment operator
+  void init();
+  RubyEventQueue(const RubyEventQueue& obj);
+  RubyEventQueue& operator=(const RubyEventQueue& obj);
+
+  // Data Members (m_ prefix)
+  PrioHeap<RubyEventQueueNode>* m_prio_heap_ptr;
+  Time m_globalTime;
+  Time m_timeOfLastRecovery;
+};
+
+// Output operator declaration
+inline extern
+ostream& operator<<(ostream& out, const RubyEventQueue& obj);
+
+// ******************* Definitions *******************
+
+// Output operator definition
+inline extern
+ostream& operator<<(ostream& out, const RubyEventQueue& obj)
+{
+  obj.print(out);
+  out << flush;
+  return out;
+}
+
+#endif //EVENTQUEUE_H
 
--- /dev/null
+
+/*
+ * 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.
+ */
+
+/*
+ * $Id$
+ *
+ * */
+
+#ifndef GLOBAL_H
+#define GLOBAL_H
+
+typedef unsigned char uint8;
+typedef unsigned int uint32;
+typedef unsigned long long uint64;
+
+typedef signed char int8;
+typedef int int32;
+typedef long long int64;
+
+typedef long long integer_t;
+typedef unsigned long long uinteger_t;
+
+typedef int64 Time;
+typedef uint64 physical_address_t;
+typedef uint64 la_t;
+typedef uint64 pa_t;
+typedef integer_t simtime_t;
+typedef int NodeID;
+
+#include "mem/ruby/common/TypeDefines.hh"
+#include "mem/gems_common/std-includes.hh"
+#include "Debug_Tester.hh"
+
+// simple type declarations
+typedef Time LogicalTime;
+typedef int64 Index;            // what the address bit ripper returns
+typedef int word;               // one word of a cache line
+typedef unsigned int uint;
+typedef int SwitchID;
+typedef int LinkID;
+
+
+class Debug;
+extern Debug * debug_ptr;
+class RubyEventQueue;
+extern RubyEventQueue * eventQueue;
+#endif //GLOBAL_H
+
 
+++ /dev/null
-/*
- * Copyright (c) 1999 by Mark Hill and David Wood for the Wisconsin
- * Multifacet Project.  ALL RIGHTS RESERVED.
- *
- * ##HEADER##
- *
- * This software is furnished under a license and may be used and
- * copied only in accordance with the terms of such license and the
- * inclusion of the above copyright notice.  This software or any
- * other copies thereof or any derivative works may not be provided or
- * otherwise made available to any other persons.  Title to and
- * ownership of the software is retained by Mark Hill and David Wood.
- * Any use of this software must include the above copyright notice.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS".  THE LICENSOR MAKES NO
- * WARRANTIES ABOUT ITS CORRECTNESS OR PERFORMANCE.
- * */
-
-/*
- * $Id: Instruction.C 1.2 05/08/26 00:54:48-05:00 xu@s0-32.cs.wisc.edu $
- *
- * Description:
- *
- */
-
-#include "mem/ruby/tester/Instruction.hh"
-
-Instruction::Instruction(){
-  m_opcode = Opcode_NUM_OPCODES;
-  m_address = Address(physical_address_t(0));
-}
-
-Instruction::Instruction(Opcode op, Address addr){
-  m_opcode = op;
-  m_address = addr;
-  assert(addr.getAddress() == 0);
-}
-
-void Instruction::init(Opcode op, Address addr){
-  m_opcode = op;
-  m_address = addr;
-  //cout << "Instruction(" << op << ", " << m_address << ")" << endl;
-}
-
-Opcode Instruction::getOpcode(){
-  return m_opcode;
-}
-
-Address Instruction::getAddress(){
-  return m_address;
-}
 
+++ /dev/null
-/*
- * Copyright (c) 1999 by Mark Hill and David Wood for the Wisconsin
- * Multifacet Project.  ALL RIGHTS RESERVED.
- *
- * ##HEADER##
- *
- * This software is furnished under a license and may be used and
- * copied only in accordance with the terms of such license and the
- * inclusion of the above copyright notice.  This software or any
- * other copies thereof or any derivative works may not be provided or
- * otherwise made available to any other persons.  Title to and
- * ownership of the software is retained by Mark Hill and David Wood.
- * Any use of this software must include the above copyright notice.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS".  THE LICENSOR MAKES NO
- * WARRANTIES ABOUT ITS CORRECTNESS OR PERFORMANCE.
- * */
-
-/*
- * $Id: Instruction.hh 1.2 05/05/24 12:15:47-05:00 kmoore@balder.cs.wisc.edu $
- *
- * Description:
- *
- */
-
-#ifndef INSTRUCTION_H
-#define INSTRUCTION_H
-
-#include "mem/ruby/common/Address.hh"
-
-
-enum Opcode {
-  Opcode_BEGIN,
-  Opcode_LD,
-  Opcode_ST,
-  Opcode_INC,
-  Opcode_COMMIT,
-  Opcode_DONE,
-  Opcode_NUM_OPCODES
-};
-
-class Instruction {
- public:
-  Instruction();
-  Instruction(Opcode op, Address addr);
-
-  void init(Opcode op, Address addr);
-  Opcode getOpcode();
-  Address getAddress();
-
- private:
-  Opcode m_opcode;
-  Address m_address;
-
-};
-
-#endif
 
 
 /*
- * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
+ * Copyright (c) 1999-2005 Mark D. Hill and David A. Wood
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  *
  */
 
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/system/System.hh"
+#include "mem/ruby/tester/Global_Tester.hh"
 #include "mem/ruby/tester/RaceyDriver.hh"
-#include "mem/ruby/eventqueue/RubyEventQueue.hh"
-#include "RaceyPseudoThread.hh"
-#include "mem/ruby/common/SubBlock.hh"
+#include "mem/ruby/tester/EventQueue_Tester.hh"
+#include "mem/ruby/tester/RaceyPseudoThread.hh"
 
-RaceyDriver::RaceyDriver()
+RaceyDriver::RaceyDriver(int num_procs, int tester_length)
 {
-  // debug transition?
-  if(false) {
-    assert(g_debug_ptr);
-    g_debug_ptr->setDebugTime(1);
-  }
-
   m_finish_time = 0;
   m_done_counter = 0;
   m_wakeup_thread0 = false;
+  m_num_procs = num_procs;
+  m_tester_length = tester_length;
+  eventQueue = new RubyEventQueue;
 
   // racey at least need two processors
-  assert(RubyConfig::numberOfProcessors() >= 2);
+  assert(m_num_procs >= 2);
 
   // init all racey pseudo threads
-  m_racey_pseudo_threads.setSize(RubyConfig::numberOfProcessors());
+  m_racey_pseudo_threads.setSize(m_num_procs);
   for (int i=0; i<m_racey_pseudo_threads.size(); i++) {
     m_racey_pseudo_threads[i] = new RaceyPseudoThread(i, *this);
   }
 
   // add this driver to the global event queue, for deadlock detection
-  g_eventQueue_ptr->scheduleEvent(this, g_DEADLOCK_THRESHOLD);
+  eventQueue->scheduleEvent(this, g_DEADLOCK_THRESHOLD);
 }
 
 RaceyDriver::~RaceyDriver()
   }
 }
 
-void RaceyDriver::hitCallback(NodeID proc, SubBlock& data, CacheRequestType type, int thread)
+void RaceyDriver::go() {
+  // tick both queues until everyone is done
+  while (m_done_counter != m_num_procs) {
+    libruby_tick(1);
+    eventQueue->triggerEvents(eventQueue->getTime() + 1);
+  }
+}
+
+
+void RaceyDriver::hitCallback(int64_t request_id)
 {
-  DEBUG_EXPR(TESTER_COMP, MedPrio, data);
-  m_racey_pseudo_threads[proc]->performCallback(proc, data);
+  ASSERT(requests.find(request_id) != requests.end());
+  int proc = requests[request_id].first;
+  Address address = requests[request_id].second.address;
+  uint8_t * data = new uint8_t[4];
+  for (int i = 0; i < 4; i++) {
+    data[i] = requests[request_id].second.data[i];
+  }
+  requests[request_id].second.data;
+  m_racey_pseudo_threads[proc]->performCallback(proc, address, data);
+  requests.erase(request_id);
 }
 
 integer_t RaceyDriver::getInstructionCount(int procID) const
 {
-  return m_racey_pseudo_threads[procID]->getInstructionCounter();
+ // return m_racey_pseudo_threads[procID]->getInstructionCounter();
+ assert(0);
 }
 
 int RaceyDriver::runningThreads()
 {
-  return RubyConfig::numberOfProcessors() - m_done_counter;
+  return m_num_procs - m_done_counter;
 }
 
 // used to wake up thread 0 whenever other thread finishes
 void RaceyDriver::joinThread()
 {
   m_done_counter++;
-  if (m_done_counter == RubyConfig::numberOfProcessors()) {
-    m_finish_time = g_eventQueue_ptr->getTime();
+  if (m_done_counter == m_num_procs) {
+   m_finish_time = eventQueue->getTime();
   }
 
   if(m_wakeup_thread0) {
-    g_eventQueue_ptr->scheduleEvent(m_racey_pseudo_threads[0], 1);
+    eventQueue->scheduleEvent(m_racey_pseudo_threads[0], 1);
     m_wakeup_thread0 = false;
   }
 }
   }
 
   // schedule next wakeup
-  if (m_done_counter < RubyConfig::numberOfProcessors()) {
-    g_eventQueue_ptr->scheduleEvent(this, g_DEADLOCK_THRESHOLD);
+  if (m_done_counter < m_num_procs) {
+    eventQueue->scheduleEvent(this, g_DEADLOCK_THRESHOLD);
   }
 }
 
 void RaceyDriver::printStats(ostream& out) const
 {
-  assert(m_done_counter == RubyConfig::numberOfProcessors());
+  assert(m_done_counter == m_num_procs);
   out << endl;
   out << "RaceyDriver Stats" << endl;
   out << "---------------------" << endl;
 
 
 /*
- * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
+ * Copyright (c) 1999-2005 Mark D. Hill and David A. Wood
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 #ifndef RACEYDRIVER_H
 #define RACEYDRIVER_H
 
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/common/Driver.hh"
+#include "mem/ruby/tester/Global_Tester.hh"
+#include "mem/ruby/tester/Driver_Tester.hh"
+#include "mem/ruby/tester/RaceyPseudoThread.hh"
+#include <map>
+#include "mem/ruby/libruby.hh"
 
-class RaceyPseudoThread;
+#define g_DEADLOCK_THRESHOLD 5000
 
-class RaceyDriver : public Driver, public Consumer {
+
+struct address_data {
+  Address address;
+  uint8_t * data;
+};
+
+class RaceyDriver : public Driver_Tester, public Consumer {
 public:
+  friend class RaceyPseudoThread;
   // Constructors
-  RaceyDriver();
+  RaceyDriver(int num_procs, int tester_length);
 
   // Destructor
   ~RaceyDriver();
     return m_racey_pseudo_threads[0]->getInitializedState();
   };
 
-  void hitCallback(NodeID proc, SubBlock& data, CacheRequestType type, int thread);
+  void hitCallback(int64_t request_id);
   void wakeup();
   void printStats(ostream& out) const;
   void clearStats() {}
   void printConfig(ostream& out) const {}
+  void go();
 
   integer_t getInstructionCount(int procID) const;
 
   }
 
   void print(ostream& out) const;
+
 private:
 
   // Private copy constructor and assignment operator
   Vector<RaceyPseudoThread*> m_racey_pseudo_threads;
   int m_done_counter;
   bool m_wakeup_thread0;
-
   Time m_finish_time;
+  map <int64_t, pair <int, struct address_data> > requests;
+  RubyEventQueue * eventQueue;
+  int m_num_procs;
+  int m_tester_length;
 };
 
 // Output operator declaration
 }
 
 #endif //RACEYDRIVER_H
+
 
--- /dev/null
+/*
+ * Copyright (c) 1999 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.
+ */
+
+/*
+ * Description: see RaceyPseudoThread.hh
+ */
+
+#include "mem/ruby/tester/RaceyPseudoThread.hh"
+#include "mem/ruby/config/RubyConfig.hh"
+#include "mem/ruby/tester/RaceyDriver.hh"
+#include "gzstream.hh"
+
+RaceyPseudoThread::RaceyPseudoThread(NodeID id, RaceyDriver& driver)
+  : m_driver(driver), m_proc_id(id) {
+
+  resetIC(); // IC contains the committed instruction number
+  m_last_progress = 0;
+  m_done = false;
+  m_stop = 0;
+  m_driver.eventQueue->scheduleEvent(this, 1);
+}
+
+RaceyPseudoThread::~RaceyPseudoThread() {
+}
+
+void RaceyPseudoThread::checkForDeadlock() {
+  Time current_time = m_driver.eventQueue->getTime();
+  if(!m_done && (current_time - m_last_progress) > g_DEADLOCK_THRESHOLD) {
+    WARN_EXPR(m_proc_id);
+    WARN_EXPR(m_ic_counter);
+    WARN_EXPR(m_last_progress);
+    ERROR_MSG("Deadlock detected.");
+  }
+}
+
+void RaceyPseudoThread::performCallback(int proc, Address address, uint8_t * data ) {
+  assert(proc == m_proc_id);
+
+  DEBUG_EXPR(TESTER_COMP, LowPrio, proc);
+  DEBUG_EXPR(TESTER_COMP, LowPrio, address);
+
+
+  m_last_progress = m_driver.eventQueue->getTime();
+
+  if(m_read) {
+    int b0, b1, b2, b3;
+    b0 = data[0]; b0 <<= 0;
+    b1 = data[1]; b1 <<= 8;
+    b2 = data[2]; b2 <<= 16;
+    b3 = data[3]; b3 <<= 24;
+    m_value = b0 | b1 | b2 | b3;
+  } else {
+    char b0, b1, b2, b3;
+    b0 = (m_value>>0)&0xFF; data[0] = b0;
+    b1 = (m_value>>8)&0xFF; data[1] = b1;
+    b2 = (m_value>>16)&0xFF; data[2] = b2;
+    b3 = (m_value>>24)&0xFF; data[3] = b3;
+  }
+
+  // schedule wakeup for next requests in next cycle
+  m_driver.eventQueue->scheduleEvent(this, 1);
+
+  // new instruction
+  m_ic_counter++;
+
+}
+
+void RaceyPseudoThread::wakeup() {
+  // for debug
+  if(m_stop != 0) {
+    cout << m_proc_id << " " << m_stop << ((m_read)?  " read ":" written ") << m_value;
+    if(0) cout << " [" << m_driver.eventQueue->getTime() << "]";
+    cout << endl;
+  }
+
+  assert(!m_done);
+
+  // Note, this function can not have ANY local variable!
+
+  switch(m_stop) {
+  case 0:
+    break;
+  case 1:
+    goto L1;
+  case 2:
+    goto L2;
+  case 3:
+    goto L3;
+  case 4:
+    goto L4;
+  case 5:
+    goto L5;
+  case 6:
+    goto L6;
+  case 7:
+    goto L7;
+  case 8:
+    goto L8;
+  case 9:
+    goto L9;
+  case 10:
+    goto L10;
+  default:
+    WARN_EXPR(m_stop);
+    ERROR_MSG("RaceyPseudoThread: Bad context point!");
+  }
+
+  //
+  // initialization
+  //
+  if(m_proc_id == 0) {
+    for(m_looper = 0; m_looper < m_driver.m_num_procs; m_looper++) {
+      store_sig(m_looper, m_looper+1);
+      m_stop = 6; return;
+L6:   {};
+    }
+    for(m_looper = 0; m_looper < M_ELEM; m_looper++) {
+      store_m(m_looper, M_ELEM-m_looper);
+      m_stop = 7; return;
+L7:   {};
+    }
+
+    // init done
+    m_initialized = true;
+  } else {
+    // other processors
+    if(!m_driver.Thread0Initialized()) {
+      // wait for processors 0
+      m_driver.eventQueue->scheduleEvent(this, 1);
+      return;
+    }
+  }
+
+  cout << "Thread " << m_proc_id << " started in parallel phase" << endl;
+
+  //
+  // main thread body
+  //
+  for(m_looper = 0 ; m_looper < m_driver.m_tester_length; m_looper++) {
+    /* m_value = */ load_sig(m_proc_id);
+    m_stop = 1; return;
+L1: {};
+    m_num = m_value;
+    m_index1 = m_num%M_ELEM;
+    /* m_value = */ load_m(m_index1);
+    m_stop = 2; return;
+L2: {};
+    m_num = mix(m_num, m_value);
+    m_index2 = m_num%M_ELEM;
+    /* m_value = */ load_m(m_index2);
+    m_stop = 3; return;
+L3: {};
+    m_num = mix(m_num, m_value);
+    store_m(m_index2, m_num);
+    m_stop = 4; return;
+L4: {};
+    store_sig(m_proc_id, m_num);
+    m_stop = 5; return;
+L5: {};
+  } // end for
+
+  //
+  // compute final sig
+  //
+  if(m_proc_id == 0) {
+    // wait for other threads
+    while (m_driver.runningThreads() > 1) {
+      m_driver.registerThread0Wakeup();
+      m_stop = 10; return;
+L10: {};
+    }
+
+    /* m_value = */ load_sig(0);
+    m_stop = 8; return;
+L8: {};
+    m_final_sig = m_value;
+    for(m_looper = 1; m_looper < m_driver.m_num_procs; m_looper++) {
+      /* m_value = */ load_sig(m_looper);
+      m_stop = 9; return;
+L9:   {};
+      m_final_sig = mix(m_value, m_final_sig);
+    }
+  } // processors 0
+
+  // done
+  m_driver.joinThread();
+  m_done = true;
+}
+
+void RaceyPseudoThread::load_sig(unsigned index) {
+  cout << m_proc_id << " : load_sig " << index << endl;
+
+  m_read = true;
+  // timestamp, threadid, action, and logical address are used only by transactional memory, should be augmented
+  uint8_t * read_data = new uint8_t[4];
+
+  char name [] = "Sequencer_";
+  char port_name [13];
+  sprintf(port_name, "%s%d", name, m_proc_id);
+
+  // pc is zero, problem?
+  int64_t request_id = libruby_issue_request(libruby_get_port_by_name(port_name), RubyRequest(sig(index), read_data, 4, 0, RubyRequestType_LD, RubyAccessMode_User));
+
+  ASSERT(m_driver.requests.find(request_id) == m_driver.requests.end());
+
+  struct address_data request_data;
+  request_data.address = Address(sig(index));
+  request_data.data = read_data;
+  m_driver.requests.insert(make_pair(request_id, make_pair(m_proc_id, request_data)));
+
+  /*sequencer()->makeRequest(CacheMsg(Address(sig(index)), Address(sig(index)), CacheRequestType_LD,
+                                    Address(physical_address_t(1)),
+                                    AccessModeType_UserMode, 4,
+                                    PrefetchBit_No, 0, Address(0),
+                                    0, 0 , false)); */
+}
+
+void RaceyPseudoThread::load_m(unsigned index) {
+  // cout << m_proc_id << " : load_m " << index << endl;
+
+  m_read = true;
+  uint8_t * read_data = new uint8_t[4];
+
+  char name [] = "Sequencer_";
+  char port_name [13];
+  sprintf(port_name, "%s%d", name, m_proc_id);
+
+  // pc is zero, problem?
+  int64_t request_id = libruby_issue_request(libruby_get_port_by_name(port_name), RubyRequest(m(index), read_data, 4, 0, RubyRequestType_LD, RubyAccessMode_User));
+
+  ASSERT(m_driver.requests.find(request_id) == m_driver.requests.end());
+
+  struct address_data request_data;
+  request_data.address = Address(m(index));
+  request_data.data = read_data;
+  m_driver.requests.insert(make_pair(request_id, make_pair(m_proc_id, request_data)));
+
+  /*sequencer()->makeRequest(CacheMsg(Address(m(index)), Address(m(index)), CacheRequestType_LD,
+                                    Address(physical_address_t(1)),
+                                    AccessModeType_UserMode, 4,
+                                    PrefetchBit_No, 0, Address(0),
+                                    0, 0, false)); */
+}
+
+void RaceyPseudoThread::store_sig(unsigned index, unsigned value) {
+  cout << m_proc_id << " : store_sig " << index << " " << value << endl;
+
+  m_read = false;
+  m_value = value;
+  uint8_t * write_data = new uint8_t[4];
+
+  memcpy(write_data, &value, 4);
+
+  char name [] = "Sequencer_";
+  char port_name [13];
+  sprintf(port_name, "%s%d", name, m_proc_id);
+
+  // pc is zero, problem?
+  int64_t request_id = libruby_issue_request(libruby_get_port_by_name(port_name), RubyRequest(sig(index), write_data, 4, 0, RubyRequestType_ST, RubyAccessMode_User));
+
+  ASSERT(m_driver.requests.find(request_id) == m_driver.requests.end());
+
+  struct address_data request_data;
+  request_data.address = Address(sig(index));
+  request_data.data = write_data;
+  m_driver.requests.insert(make_pair(request_id, make_pair(m_proc_id, request_data)));
+
+  /*sequencer()->makeRequest(CacheMsg(Address(sig(index)), Address(sig(index)), CacheRequestType_ST,
+                                    Address(physical_address_t(1)),
+                                    AccessModeType_UserMode, 4,
+                                    PrefetchBit_No, 0, Address(0),
+                                    0, 0, false)); */
+}
+
+void RaceyPseudoThread::store_m(unsigned index, unsigned value) {
+  //cout << m_proc_id << " : store_m " << index << endl;
+
+  m_read = false;
+  m_value = value;
+  uint8_t * write_data = new uint8_t[4];
+  memcpy(write_data, &value, 4);
+
+  char name [] = "Sequencer_";
+  char port_name [13];
+  sprintf(port_name, "%s%d", name, m_proc_id);
+
+  // pc is zero, problem?
+  int64_t request_id = libruby_issue_request(libruby_get_port_by_name(port_name), RubyRequest(m(index), write_data, 4, 0, RubyRequestType_ST, RubyAccessMode_User));
+
+  ASSERT(m_driver.requests.find(request_id) == m_driver.requests.end());
+
+  struct address_data request_data;
+  request_data.address = Address(m(index));
+  request_data.data = write_data;
+  m_driver.requests.insert(make_pair(request_id, make_pair(m_proc_id, request_data)));
+
+  /*sequencer()->makeRequest(CacheMsg(Address(m(index)), Address(m(index)), CacheRequestType_ST,
+                                    Address(physical_address_t(1)),
+                                    AccessModeType_UserMode, 4,
+                                    PrefetchBit_No, 0, Address(0),
+                                    0, 0, false)); */
+}
+
+// Save and Load context of a thread
+void RaceyPseudoThread::saveCPUStates(string filename) {
+  ogzstream out(filename.c_str());
+  out.write((char*)&m_looper, sizeof(int));
+  out.write((char*)&m_num, sizeof(unsigned));
+  out.write((char*)&m_index1, sizeof(unsigned));
+  out.write((char*)&m_index2, sizeof(unsigned));
+  out.write((char*)&m_stop, sizeof(unsigned));
+  out.close();
+}
+
+void RaceyPseudoThread::loadCPUStates(string filename) {
+  igzstream out(filename.c_str());
+  out.read((char*)&m_looper, sizeof(int));
+  out.read((char*)&m_num, sizeof(unsigned));
+  out.read((char*)&m_index1, sizeof(unsigned));
+  out.read((char*)&m_index2, sizeof(unsigned));
+  out.read((char*)&m_stop, sizeof(unsigned));
+  out.close();
+}
+
+void RaceyPseudoThread::print(ostream& out) const {
+  out << "[Racey Pseudo Thread: " << m_proc_id << "]" << endl;
+}
+
 
--- /dev/null
+/*
+ * Copyright (c) 1999 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.
+ */
+
+/*
+ * Description: This implements a pseudo racey thread which drives ruby timing
+ *              simulator with access to two shared arrays.
+ *
+ */
+
+#ifndef RACEYPSEUDOTHREAD_H
+#define RACEYPSEUDOTHREAD_H
+
+#include "mem/ruby/tester/Global_Tester.hh"
+#include "mem/ruby/common/Consumer.hh"
+#include "mem/ruby/system/NodeID.hh"
+#include "Address_Tester.hh"
+#include "mem/ruby/libruby.hh"
+
+class RaceyDriver;
+
+class RaceyPseudoThread : public Consumer {
+private:
+  // constants
+  static const int PRIME1     = 103072243;
+  static const int PRIME2     = 103995407;
+  static const int M_ELEM     = 64;
+
+  // m and sig array's starting address,
+  // each signature should occupy a cacheline
+  static const int SIG_ARR    = 0;
+  static const int M_ARR      = 0x10000;
+  static const int LINESIZE   = 64;
+
+  // get address of a element from the m and sig arrays
+  physical_address_t sig(unsigned index) {
+    assert(index < M_ARR/64);
+    return SIG_ARR + (index*64);
+  };
+  physical_address_t m(unsigned index) { return M_ARR + (index*64); };
+
+public:
+  // Constructors
+  RaceyPseudoThread(NodeID node, RaceyDriver& driver);
+
+  // Destructor
+  ~RaceyPseudoThread();
+
+  // Public Methods
+  void performCallback(int proc, Address address, uint8_t * data);
+
+  void wakeup();
+
+  integer_t getInstructionCount() { return m_ic_counter; };
+
+  unsigned getSignature() { assert(m_proc_id == 0); return m_final_sig; };
+
+  void checkForDeadlock();
+
+  // save and restore the thread state
+  void saveCPUStates(string filename);
+  void loadCPUStates(string filename);
+
+  // reset IC to zero for next checkpoint
+  void resetIC() { m_ic_counter = 0; };
+
+  bool getInitializedState() { return m_initialized; };
+
+  void print(ostream& out) const;
+private:
+  // Private Methods
+
+  // mix two numbers
+  unsigned mix (unsigned i, unsigned j) { return (i + j * PRIME2) % PRIME1; };
+
+  // load or store the array
+  void load_sig(unsigned index);
+  void load_m(unsigned index);
+  void store_sig(unsigned index, unsigned value);
+  void store_m(unsigned index, unsigned value);
+
+  // Private copy constructor and assignment operator
+  RaceyPseudoThread(const RaceyPseudoThread& obj);
+  RaceyPseudoThread& operator=(const RaceyPseudoThread& obj);
+
+  // Data Members (m_ prefix)
+  RaceyDriver& m_driver;
+  NodeID m_proc_id;
+
+  // are we done?
+  bool m_done;
+
+  // [committed] instruction counter
+  int m_ic_counter;
+
+  // last time we made progress
+  Time m_last_progress;
+
+  // value of the callback block
+  bool     m_read;
+  unsigned m_value;
+
+  // final signature
+  unsigned m_final_sig;
+
+  // local variables for the pseudo thread
+  int m_looper;
+  unsigned m_num, m_index1, m_index2, m_stop;
+  bool m_initialized;
+};
+
+// Output operator declaration
+ostream& operator<<(ostream& out, const RaceyPseudoThread& obj);
+
+// ******************* Definitions *******************
+
+// Output operator definition
+extern inline
+ostream& operator<<(ostream& out, const RaceyPseudoThread& obj)
+{
+  obj.print(out);
+  out << flush;
+  return out;
+}
+
+#endif //RACEYPSEUDOTHREAD_H
+
 
+++ /dev/null
-
-/*
- * 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.
- */
-
-/*
- * $Id$
- *
- */
-
-#include "mem/ruby/tester/RequestGenerator.hh"
-#include "mem/protocol/RequestGeneratorStatus.hh"
-#include "mem/protocol/LockStatus.hh"
-#include "mem/ruby/system/Sequencer.hh"
-#include "mem/ruby/system/System.hh"
-#include "mem/ruby/config/RubyConfig.hh"
-#include "mem/ruby/common/SubBlock.hh"
-#include "mem/ruby/tester/SyntheticDriver.hh"
-#include "mem/protocol/Chip.hh"
-
-RequestGenerator::RequestGenerator(NodeID node, SyntheticDriver& driver) :
-  m_driver(driver)
-{
-  m_status = RequestGeneratorStatus_Thinking;
-  m_last_transition = 0;
-  m_node = node;
-  pickAddress();
-  m_counter = 0;
-
-  //g_eventQueue_ptr->scheduleEvent(this, 1+(random() % 200));
-}
-
-RequestGenerator::~RequestGenerator()
-{
-}
-
-void RequestGenerator::wakeup()
-{
-  DEBUG_EXPR(TESTER_COMP, MedPrio, m_node);
-  DEBUG_EXPR(TESTER_COMP, MedPrio, m_status);
-
-  if (m_status == RequestGeneratorStatus_Thinking) {
-    m_status = RequestGeneratorStatus_Test_Pending;
-    m_last_transition = g_eventQueue_ptr->getTime();
-    initiateTest();  // Test
-  } else if (m_status == RequestGeneratorStatus_Holding) {
-    m_status = RequestGeneratorStatus_Release_Pending;
-    m_last_transition = g_eventQueue_ptr->getTime();
-    initiateRelease();  // Release
-  } else if (m_status == RequestGeneratorStatus_Before_Swap) {
-    m_status = RequestGeneratorStatus_Swap_Pending;
-    m_last_transition = g_eventQueue_ptr->getTime();
-    initiateSwap();
-  } else {
-    WARN_EXPR(m_status);
-    ERROR_MSG("Invalid status");
-  }
-}
-
-void RequestGenerator::performCallback(NodeID proc, SubBlock& data)
-{
-  Address address = data.getAddress();
-  assert(proc == m_node);
-  assert(address == m_address);
-
-  DEBUG_EXPR(TESTER_COMP, LowPrio, proc);
-  DEBUG_EXPR(TESTER_COMP, LowPrio, m_status);
-  DEBUG_EXPR(TESTER_COMP, LowPrio, address);
-  DEBUG_EXPR(TESTER_COMP, LowPrio, data);
-
-  if (m_status == RequestGeneratorStatus_Test_Pending) {
-    //    m_driver.recordTestLatency(g_eventQueue_ptr->getTime() - m_last_transition);
-    if (data.readByte() == LockStatus_Locked) {
-      // Locked - keep spinning
-      m_status = RequestGeneratorStatus_Thinking;
-      m_last_transition = g_eventQueue_ptr->getTime();
-      g_eventQueue_ptr->scheduleEvent(this, waitTime());
-    } else {
-      // Unlocked - try the swap
-      m_driver.recordTestLatency(g_eventQueue_ptr->getTime() - m_last_transition);
-      m_status = RequestGeneratorStatus_Before_Swap;
-      m_last_transition = g_eventQueue_ptr->getTime();
-      g_eventQueue_ptr->scheduleEvent(this, waitTime());
-    }
-  } else if (m_status == RequestGeneratorStatus_Swap_Pending) {
-    m_driver.recordSwapLatency(g_eventQueue_ptr->getTime() - m_last_transition);
-    if (data.readByte() == LockStatus_Locked) {
-      // We failed to aquire the lock
-      m_status = RequestGeneratorStatus_Thinking;
-      m_last_transition = g_eventQueue_ptr->getTime();
-      g_eventQueue_ptr->scheduleEvent(this, waitTime());
-    } else {
-      // We acquired the lock
-      data.writeByte(LockStatus_Locked);
-      m_status = RequestGeneratorStatus_Holding;
-      m_last_transition = g_eventQueue_ptr->getTime();
-      DEBUG_MSG(TESTER_COMP, HighPrio, "Acquired");
-      DEBUG_EXPR(TESTER_COMP, HighPrio, proc);
-      DEBUG_EXPR(TESTER_COMP, HighPrio, g_eventQueue_ptr->getTime());
-      g_eventQueue_ptr->scheduleEvent(this, holdTime());
-    }
-  } else if (m_status == RequestGeneratorStatus_Release_Pending) {
-    m_driver.recordReleaseLatency(g_eventQueue_ptr->getTime() - m_last_transition);
-    // We're releasing the lock
-    data.writeByte(LockStatus_Unlocked);
-
-    m_counter++;
-    if (m_counter < g_tester_length) {
-      m_status = RequestGeneratorStatus_Thinking;
-      m_last_transition = g_eventQueue_ptr->getTime();
-      pickAddress();
-      g_eventQueue_ptr->scheduleEvent(this, thinkTime());
-    } else {
-      m_driver.reportDone();
-      m_status = RequestGeneratorStatus_Done;
-      m_last_transition = g_eventQueue_ptr->getTime();
-    }
-  } else {
-    WARN_EXPR(m_status);
-    ERROR_MSG("Invalid status");
-  }
-}
-
-int RequestGenerator::thinkTime() const
-{
-  return g_think_time;
-}
-
-int RequestGenerator::waitTime() const
-{
-  return g_wait_time;
-}
-
-int RequestGenerator::holdTime() const
-{
-  return g_hold_time;
-}
-
-void RequestGenerator::pickAddress()
-{
-  assert(m_status == RequestGeneratorStatus_Thinking);
-  m_address = m_driver.pickAddress(m_node);
-}
-
-void RequestGenerator::initiateTest()
-{
-  DEBUG_MSG(TESTER_COMP, MedPrio, "initiating Test");
-
-  Addr data_addr = m_address.getAddress();
-  Request request(0, data_addr, 1, Flags<unsigned int>(), 1, 0, 0);
-  MemCmd::Command command;
-  command = MemCmd::ReadReq;
-
-  Packet pkt(&request, command, 0); // TODO -- make dest a real NodeID
-
-  sequencer()->makeRequest(&pkt);
-}
-
-void RequestGenerator::initiateSwap()
-{
-  DEBUG_MSG(TESTER_COMP, MedPrio, "initiating Swap");
-
-  Addr data_addr = m_address.getAddress();
-  Request request(0, data_addr, 1, Flags<unsigned int>(), 2, 0, 0);
-  MemCmd::Command command;
-  command = MemCmd::SwapReq;
-
-  Packet pkt(&request, command, 0); // TODO -- make dest a real NodeID
-
-  sequencer()->makeRequest(&pkt);
-}
-
-void RequestGenerator::initiateRelease()
-{
-  DEBUG_MSG(TESTER_COMP, MedPrio, "initiating Release");
-
-  Addr data_addr = m_address.getAddress();
-  Request request(0, data_addr, 1, Flags<unsigned int>(), 3, 0, 0);
-  MemCmd::Command command;
-  command = MemCmd::WriteReq;
-
-  Packet pkt(&request, command, 0); // TODO -- make dest a real NodeID
-
-  sequencer()->makeRequest(&pkt);
-}
-
-Sequencer* RequestGenerator::sequencer() const
-{
-  return g_system_ptr->getChip(m_node/RubyConfig::numberOfProcsPerChip())->getSequencer(m_node%RubyConfig::numberOfProcsPerChip());
-}
-
-void RequestGenerator::print(ostream& out) const
-{
-  out << "[RequestGenerator]" << endl;
-}
-
 
+++ /dev/null
-
-/*
- * 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.
- */
-
-/*
- * $Id$
- *
- * Description:
- *
- */
-
-#ifndef REQUESTGENERATOR_H
-#define REQUESTGENERATOR_H
-
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/common/Consumer.hh"
-#include "mem/protocol/RequestGeneratorStatus.hh"
-#include "mem/ruby/system/NodeID.hh"
-#include "mem/ruby/common/Address.hh"
-
-class Sequencer;
-class SubBlock;
-class SyntheticDriver;
-
-class RequestGenerator : public Consumer {
-public:
-  // Constructors
-  RequestGenerator(NodeID node, SyntheticDriver& driver);
-
-  // Destructor
-  ~RequestGenerator();
-
-  // Public Methods
-  void wakeup();
-  void performCallback(NodeID proc, SubBlock& data);
-
-  void print(ostream& out) const;
-private:
-  // Private Methods
-  int thinkTime() const;
-  int waitTime() const;
-  int holdTime() const;
-  void initiateTest();
-  void initiateSwap();
-  void initiateRelease();
-  void pickAddress();
-  Sequencer* sequencer() const;
-
-  // Private copy constructor and assignment operator
-  RequestGenerator(const RequestGenerator& obj);
-  RequestGenerator& operator=(const RequestGenerator& obj);
-
-  // Data Members (m_ prefix)
-  SyntheticDriver& m_driver;
-  NodeID m_node;
-  RequestGeneratorStatus m_status;
-  int m_counter;
-  Time m_last_transition;
-  Address m_address;
-};
-
-// Output operator declaration
-ostream& operator<<(ostream& out, const RequestGenerator& obj);
-
-// ******************* Definitions *******************
-
-// Output operator definition
-extern inline
-ostream& operator<<(ostream& out, const RequestGenerator& obj)
-{
-  obj.print(out);
-  out << flush;
-  return out;
-}
-
-#endif //REQUESTGENERATOR_H
-
 
  */
 
 #include "mem/ruby/tester/SpecifiedGenerator.hh"
-#include "mem/ruby/system/Sequencer.hh"
-#include "mem/ruby/system/System.hh"
-#include "mem/ruby/common/SubBlock.hh"
-#include "mem/ruby/tester/SyntheticDriver.hh"
 
 SpecifiedGenerator::SpecifiedGenerator()
 {
 
 #ifndef SPECIFIEDGENERATOR_H
 #define SPECIFIEDGENERATOR_H
 
-#include "mem/ruby/common/Global.hh"
+#include "mem/ruby/tester/Global_Tester.hh"
 #include "mem/ruby/common/Consumer.hh"
 #include "mem/ruby/system/NodeID.hh"
-
-class Sequencer;
-class SubBlock;
+#include "Address_Tester.hh"
 
 class SpecifiedGenerator : public Consumer {
 public:
 
   // Public Methods
   virtual void wakeup() = 0;
-  virtual void performCallback(NodeID proc, SubBlock& data) = 0;
+  virtual void performCallback(NodeID proc, Address address) = 0;
 
   virtual void print(ostream& out) const = 0;
 protected:
 
+++ /dev/null
-
-/*
- * 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.
- */
-
-/*
- * $Id$
- *
- */
-
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/system/System.hh"
-#include "mem/ruby/tester/SyntheticDriver.hh"
-#include "mem/ruby/eventqueue/RubyEventQueue.hh"
-#include "mem/ruby/tester/RequestGenerator.hh"
-#include "mem/ruby/common/SubBlock.hh"
-#include "mem/protocol/Chip.hh"
-
-SyntheticDriver::SyntheticDriver(RubySystem* sys_ptr)
-{
-  m_finish_time = 0;
-  m_done_counter = 0;
-
-  m_last_progress_vector.setSize(RubyConfig::numberOfProcessors());
-  for (int i=0; i<m_last_progress_vector.size(); i++) {
-    m_last_progress_vector[i] = 0;
-  }
-
-  m_lock_vector.setSize(g_synthetic_locks);
-  for (int i=0; i<m_lock_vector.size(); i++) {
-    m_lock_vector[i] = -1;  // No processor last held it
-  }
-
-  m_request_generator_vector.setSize(RubyConfig::numberOfProcessors());
-  for (int i=0; i<m_request_generator_vector.size(); i++) {
-    if(XACT_MEMORY){
-      //m_request_generator_vector[i] = new XactRequestGenerator(i, *this);
-    } else {
-      m_request_generator_vector[i] = new RequestGenerator(i, *this);
-    }
-  }
-
-  // add the tester consumer to the global event queue
-  g_eventQueue_ptr->scheduleEvent(this, 1);
-}
-
-SyntheticDriver::~SyntheticDriver()
-{
-  for (int i=0; i<m_last_progress_vector.size(); i++) {
-    delete m_request_generator_vector[i];
-  }
-}
-
-void
-SyntheticDriver::hitCallback(Packet * pkt)
-{
-  NodeID proc = pkt->req->contextId();
-  SubBlock data(Address(pkt->getAddr()), pkt->req->getSize());
-  if (pkt->hasData()) {
-    for (int i = 0; i < pkt->req->getSize(); i++) {
-      data.setByte(i, *(pkt->getPtr<uint8>()+i));
-    }
-  }
-  m_request_generator_vector[proc]->performCallback(proc, data);
-  m_last_progress_vector[proc] = g_eventQueue_ptr->getTime();
-}
-
-void SyntheticDriver::abortCallback(NodeID proc, SubBlock& data, CacheRequestType type, int thread)
-{
-  //cout << "SyntheticDriver::abortCallback" << endl;
-  DEBUG_EXPR(TESTER_COMP, MedPrio, data);
-
-  if(XACT_MEMORY){
-    //XactRequestGenerator* reqGen = static_cast<XactRequestGenerator*>(m_request_generator_vector[proc]);
-    //reqGen->abortTransaction();
-    //reqGen->performCallback(proc, data);
-  } else {
-    m_request_generator_vector[proc]->performCallback(proc, data);
-  }
-
-  // Mark that we made progress
-  m_last_progress_vector[proc] = g_eventQueue_ptr->getTime();
-}
-
-// For Transactional Memory
-/*
-// called whenever we send a nack
-void SyntheticDriver::notifySendNack( int proc, const Address & addr, uint64 remote_timestamp, const MachineID & remote_id ){
-  if(XACT_MEMORY){
-    //XactRequestGenerator* reqGen = static_cast<XactRequestGenerator*>(m_request_generator_vector[proc]);
-    //reqGen->notifySendNack(addr, remote_timestamp, remote_id);
-  }
-  else{
-    cout << "notifySendNack NOT USING TM" << endl;
-    ASSERT(0);
-  }
-}
-
-// called whenever we receive a NACK
-//  Either for a demand request or log store
-void SyntheticDriver::notifyReceiveNack( int proc, const Address & addr, uint64 remote_timestamp, const MachineID & remote_id ){
-  if(XACT_MEMORY){
-    //XactRequestGenerator* reqGen = static_cast<XactRequestGenerator*>(m_request_generator_vector[proc]);
-    //reqGen->notifyReceiveNack(addr, remote_timestamp, remote_id);
-  }
-  else{
-    cout << "notifyReceiveNack NOT USING TM" << endl;
-    ASSERT(0);
-  }
-}
-
-// called whenever we received ALL the NACKs. Take abort or retry action here
-void SyntheticDriver::notifyReceiveNackFinal(int proc, const Address & addr){
-  if(XACT_MEMORY){
-    //XactRequestGenerator* reqGen = static_cast<XactRequestGenerator*>(m_request_generator_vector[proc]);
-    //reqGen->notifyReceiveNackFinal(addr);
-  }
-  else{
-    ASSERT(0);
-  }
-}
-
-// called during abort handling
-// void SyntheticDriver::notifyAbortStart( const Address & handlerPC ){
-
-// }
-
-// void SyntheticDriver::notifyAbortComplete( const Address & newPC ){
-
-// }
-*/
-
-Address SyntheticDriver::pickAddress(NodeID node)
-{
-  // This methods picks a random lock that we were NOT that last
-  // processor to acquire.  Why?  Without this change 2 and 4
-  // processor runs, the odds of having the lock in your cache in
-  // read/write state is 50% or 25%, respectively.  This effect can
-  // make our 'throughput per processor' results look too strange.
-
-  Address addr;
-  // FIXME - make this a parameter of the workload
-  int lock_number = 0;
-  int counter = 0;
-  while (1) {
-    // Pick a random lock
-    lock_number = random() % m_lock_vector.size();
-
-    // Were we the last to acquire the lock?
-    if (m_lock_vector[lock_number] != node) {
-      break;
-    }
-
-    // Don't keep trying forever, since if there is only one lock, we're always the last to try to obtain the lock
-    counter++;
-    if (counter > 10) {
-      break;
-    }
-  }
-
-  // We're going to acquire it soon, so we can update the last
-  // processor to hold the lock at this time
-  m_lock_vector[lock_number] = node;
-
-  // One lock per cache line
-  addr.setAddress(lock_number * RubyConfig::dataBlockBytes());
-  return addr;
-}
-
-void SyntheticDriver::reportDone()
-{
-  m_done_counter++;
-  if (m_done_counter == RubyConfig::numberOfProcessors()) {
-    m_finish_time = g_eventQueue_ptr->getTime();
-  }
-}
-
-void SyntheticDriver::recordTestLatency(Time time)
-{
-  m_test_latency.add(time);
-}
-
-void SyntheticDriver::recordSwapLatency(Time time)
-{
-  m_swap_latency.add(time);
-}
-
-void SyntheticDriver::recordReleaseLatency(Time time)
-{
-  m_release_latency.add(time);
-}
-
-void SyntheticDriver::wakeup()
-{
-  //  checkForDeadlock();
-  if (m_done_counter < RubyConfig::numberOfProcessors()) {
-    g_eventQueue_ptr->scheduleEvent(this, g_DEADLOCK_THRESHOLD);
-  }
-}
-
-void SyntheticDriver::checkForDeadlock()
-{
-  int size = m_last_progress_vector.size();
-  Time current_time = g_eventQueue_ptr->getTime();
-  for (int processor=0; processor<size; processor++) {
-    if ((current_time - m_last_progress_vector[processor]) > g_DEADLOCK_THRESHOLD) {
-      WARN_EXPR(processor);
-#ifndef NDEBUG
-      Sequencer* seq_ptr = g_system_ptr->getChip(processor/RubyConfig::numberOfProcsPerChip())->getSequencer(processor%RubyConfig::numberOfProcsPerChip());
-#endif
-      assert(seq_ptr != NULL);
-      //     if (seq_ptr->isRequestPending()) {
-      //       WARN_EXPR(seq_ptr->pendingAddress());
-      //      }
-      WARN_EXPR(current_time);
-      WARN_EXPR(m_last_progress_vector[processor]);
-      WARN_EXPR(current_time - m_last_progress_vector[processor]);
-      ERROR_MSG("Deadlock detected.");
-    }
-  }
-}
-
-integer_t  SyntheticDriver::readPhysicalMemory(int procID, physical_address_t address,
-                                               int len ){
-  char buffer[8];
-  ASSERT(len <= 8);
-  Sequencer* seq = g_system_ptr->getChip(procID/RubyConfig::numberOfProcsPerChip())->getSequencer(procID%RubyConfig::numberOfProcsPerChip());
-  assert(seq != NULL);
-  bool found = seq->getRubyMemoryValue(Address(address), buffer, len );
-  ASSERT(found);
-  return *((integer_t *) buffer);
-}
-
-void  SyntheticDriver::writePhysicalMemory( int procID, physical_address_t address,
-                                            integer_t value, int len ){
-  char buffer[8];
-  ASSERT(len <= 8);
-
-  memcpy(buffer, (const void*) &value, len);
-  DEBUG_EXPR(TESTER_COMP, MedPrio, "");
-  Sequencer* seq = g_system_ptr->getChip(procID/RubyConfig::numberOfProcsPerChip())->getSequencer(procID%RubyConfig::numberOfProcsPerChip());
-  assert(seq != NULL);
-  bool found = seq->setRubyMemoryValue(Address(address), buffer, len );
-  ASSERT(found);
-  //return found;
-}
-
-void SyntheticDriver::printStats(ostream& out) const
-{
-  out << endl;
-  out << "SyntheticDriver Stats" << endl;
-  out << "---------------------" << endl;
-
-  out << "synthetic_finish_time: " << m_finish_time << endl;
-  out << "test_latency: " << m_test_latency << endl;
-  out << "swap_latency: " << m_swap_latency << endl;
-  out << "release_latency: " << m_release_latency << endl;
-}
-
-void SyntheticDriver::print(ostream& out) const
-{
-}
 
+++ /dev/null
-
-/*
- * 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.
- */
-
-/*
- * $Id$
- *
- * Description:
- *
- */
-
-#ifndef SYNTHETICDRIVER_H
-#define SYNTHETICDRIVER_H
-
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/common/Driver.hh"
-#include "mem/ruby/common/Histogram.hh"
-#include "mem/protocol/CacheRequestType.hh"
-
-class RubySystem;
-class RequestGenerator;
-
-class SyntheticDriver : public Driver, public Consumer {
-public:
-  // Constructors
-  SyntheticDriver(RubySystem* sys_ptr);
-
-  // Destructor
-  ~SyntheticDriver();
-
-  // Public Methods
-  Address pickAddress(NodeID node);
-  void reportDone();
-  void recordTestLatency(Time time);
-  void recordSwapLatency(Time time);
-  void recordReleaseLatency(Time time);
-
-  void hitCallback(Packet* pkt);
-  void conflictCallback(NodeID proc, SubBlock& data, CacheRequestType type, int thread) {assert(0);}
-  void abortCallback(NodeID proc, SubBlock& data, CacheRequestType type, int thread);
-  void wakeup();
-  void printStats(ostream& out) const;
-  void clearStats() {}
-  void printConfig(ostream& out) const {}
-
-  integer_t readPhysicalMemory(int procID, physical_address_t address,
-                               int len );
-
-  void writePhysicalMemory( int procID, physical_address_t address,
-                            integer_t value, int len );
-
-  void print(ostream& out) const;
-
-  // For handling NACKs/retries
-  //void notifySendNack( int procID, const Address & addr, uint64 remote_timestamp, const MachineID & remote_id);
-  //void notifyReceiveNack( int procID, const Address & addr, uint64 remote_timestamp, const MachineID & remote_id);
-  //void notifyReceiveNackFinal( int procID, const Address & addr);
-
-private:
-  // Private Methods
-  void checkForDeadlock();
-
-  // Private copy constructor and assignment operator
-  SyntheticDriver(const SyntheticDriver& obj);
-  SyntheticDriver& operator=(const SyntheticDriver& obj);
-
-  // Data Members (m_ prefix)
-  Vector<Time> m_last_progress_vector;
-  Vector<RequestGenerator*> m_request_generator_vector;
-  Vector<NodeID> m_lock_vector;  // Processor last to hold the lock
-  int m_done_counter;
-
-  Histogram m_test_latency;
-  Histogram m_swap_latency;
-  Histogram m_release_latency;
-  Time m_finish_time;
-};
-
-// Output operator declaration
-ostream& operator<<(ostream& out, const SyntheticDriver& obj);
-
-// ******************* Definitions *******************
-
-// Output operator definition
-extern inline
-ostream& operator<<(ostream& out, const SyntheticDriver& obj)
-{
-  obj.print(out);
-  out << flush;
-  return out;
-}
-
-#endif //SYNTHETICDRIVER_H
 
+++ /dev/null
-
-/*
- * 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.
- */
-
-/*
- * $Id$
- *
- */
-
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/system/System.hh"
-#include "mem/ruby/tester/Tester.hh"
-#include "mem/ruby/eventqueue/RubyEventQueue.hh"
-#include "mem/ruby/common/SubBlock.hh"
-#include "mem/ruby/tester/Check.hh"
-#include "mem/protocol/Chip.hh"
-
-Tester::Tester(RubySystem* sys_ptr)
-{
-  g_callback_counter = 0;
-
-  // add the tester consumer to the global event queue
-  g_eventQueue_ptr->scheduleEvent(this, 1);
-
-  m_last_progress_vector.setSize(RubyConfig::numberOfProcessors());
-  for (int i=0; i<m_last_progress_vector.size(); i++) {
-    m_last_progress_vector[i] = 0;
-  }
-}
-
-Tester::~Tester()
-{
-}
-
-void Tester::hitCallback(NodeID proc, SubBlock& data, CacheRequestType type, int thread)
-{
-  // Mark that we made progress
-  m_last_progress_vector[proc] = g_eventQueue_ptr->getTime();
-  g_callback_counter++;
-
-  // This tells us our store has 'completed' or for a load gives us
-  // back the data to make the check
-  DEBUG_EXPR(TESTER_COMP, MedPrio, proc);
-  DEBUG_EXPR(TESTER_COMP, MedPrio, data);
-  Check* check_ptr = m_checkTable.getCheck(data.getAddress());
-  assert(check_ptr != NULL);
-  check_ptr->performCallback(proc, data);
-
-}
-
-void Tester::wakeup()
-{
-  if (g_callback_counter < g_tester_length) {
-    // Try to perform an action or check
-    Check* check_ptr = m_checkTable.getRandomCheck();
-    assert(check_ptr != NULL);
-    check_ptr->initiate();
-
-    checkForDeadlock();
-
-    g_eventQueue_ptr->scheduleEvent(this, 2);
-  }
-}
-
-void Tester::checkForDeadlock()
-{
-  int size = m_last_progress_vector.size();
-  Time current_time = g_eventQueue_ptr->getTime();
-  for (int processor=0; processor<size; processor++) {
-    if ((current_time - m_last_progress_vector[processor]) > g_DEADLOCK_THRESHOLD) {
-      WARN_EXPR(current_time);
-      WARN_EXPR(m_last_progress_vector[processor]);
-      WARN_EXPR(current_time - m_last_progress_vector[processor]);
-      WARN_EXPR(processor);
-      Sequencer* seq_ptr = g_system_ptr->getChip(processor/RubyConfig::numberOfProcsPerChip())->getSequencer(processor%RubyConfig::numberOfProcsPerChip());
-      assert(seq_ptr != NULL);
-      WARN_EXPR(*seq_ptr);
-      ERROR_MSG("Deadlock detected.");
-    }
-  }
-}
-
-void Tester::print(ostream& out) const
-{
-  out << "[Tester]" << endl;
-}
-
 
+++ /dev/null
-
-/*
- * 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.
- */
-
-/*
- * $Id$
- *
- * Description:
- *
- */
-
-#ifndef TESTER_H
-#define TESTER_H
-
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/common/Driver.hh"
-#include "mem/ruby/tester/CheckTable.hh"
-#include "mem/protocol/CacheRequestType.hh"
-
-class RubySystem;
-
-class Tester : public Driver, public Consumer {
-public:
-  // Constructors
-  Tester(RubySystem* sys_ptr);
-
-  // Destructor
-  ~Tester();
-
-  // Public Methods
-
-  void hitCallback(NodeID proc, SubBlock& data, CacheRequestType type, int thread);
-  void wakeup();
-  void printStats(ostream& out) const {}
-  void clearStats() {}
-  void printConfig(ostream& out) const {}
-
-  void print(ostream& out) const;
-private:
-  // Private Methods
-
-  void checkForDeadlock();
-
-  // Private copy constructor and assignment operator
-  Tester(const Tester& obj);
-  Tester& operator=(const Tester& obj);
-
-  // Data Members (m_ prefix)
-
-  CheckTable m_checkTable;
-  Vector<Time> m_last_progress_vector;
-};
-
-// Output operator declaration
-ostream& operator<<(ostream& out, const Tester& obj);
-
-// ******************* Definitions *******************
-
-// Output operator definition
-extern inline
-ostream& operator<<(ostream& out, const Tester& obj)
-{
-  obj.print(out);
-  out << flush;
-  return out;
-}
-
-#endif //TESTER_H
 
  *
  */
 
-#include "mem/ruby/tester/main.hh"
-#include "mem/ruby/eventqueue/RubyEventQueue.hh"
-#include "mem/ruby/config/RubyConfig.hh"
-//#include "mem/ruby/tester/test_framework.hh"
+#include "mem/slicc/main.hh"
+#include "mem/ruby/tester/test_framework.hh"
 
 // *******************
 // *** tester main ***
 
 int main(int argc, char *argv[])
 {
-    //dsm: PRUNED
-    //tester_main(argc, argv);
+  tester_main(argc, argv);
 }
 
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+/*
+ * $Id$
+ *
+ * Description:
+ *
+ */
+
 #ifndef MAIN_H
 #define MAIN_H
 
-#include "mem/ruby/common/Global.hh"
+#include "Global_Tester.hh"
 
 #endif //MAIN_H
 
  *
  */
 
-#include "mem/protocol/protocol_name.hh"
+using namespace std;
+
 #include "mem/ruby/tester/test_framework.hh"
-#include "mem/ruby/system/System.hh"
-#include "mem/ruby/init.hh"
-#include "mem/ruby/tester/Tester.hh"
-#include "mem/ruby/eventqueue/RubyEventQueue.hh"
+#include "mem/protocol/protocol_name.hh"
 #include "getopt.hh"
-#include "mem/ruby/network/Network.hh"
-#include "mem/ruby/recorder/CacheRecorder.hh"
-#include "mem/ruby/recorder/Tracer.hh"
+#include "mem/ruby/tester/DeterministicDriver.hh"
+#include "mem/ruby/tester/RaceyDriver.hh"
+#include "mem/ruby/tester/Driver_Tester.hh"
 
-using namespace std;
 #include <string>
 #include <map>
+#include <iostream>
+#include <assert.h>
+#include <vector>
+#include <string>
+#include <sstream>
+#include <sys/wait.h>
 
-// Maurice
-// extern "C" {
-// #include "simics/api.hh"
-// };
+#include "mem/ruby/libruby.hh"
 
-#include "mem/gems_common/ioutil/confio.hh"
-#include "mem/gems_common/ioutil/initvar.hh"
+// FIXME: should really make this a class if can't figure out how to make a function to get the ruby parameter
 
-// A generated file containing the default tester parameters in string form
-// The defaults are stored in the variables
-// global_default_param and global_default_tester_param
-#include "mem/ruby/default_param.hh"
-#include "mem/ruby/tester_param.hh"
 
+static void set_defaults();
 static void parseOptions(int argc, char **argv);
 static void usageInstructions();
 static void checkArg(char ch);
-static void tester_record_cache();
-static void tester_playback_trace();
 static void tester_initialize(int argc, char **argv);
 static void tester_destroy();
+static void hit_callback(int64_t request_id);
+
+// Tester variables
+string driver_type;
+string generator_type;
+Driver_Tester * m_driver_ptr;
+int g_tester_length;
+int num_completions;
+Time g_think_time;
+Time g_wait_time;
+int num_procs;
+
+// Debugger variables
+Debug * debug_ptr;
+string g_debug_verbosity_string;
+string g_debug_filter_string;
+string g_debug_output_filename;
+Time g_debug_start_time;
 
-static string trace_filename;
-char * my_default_param;
-initvar_t * my_initvar;
 
 void tester_main(int argc, char **argv)
 {
   tester_initialize(argc, argv);
 
-  if (trace_filename != "") {
-    // playback a trace (for multicast-mask prediction)
-    tester_playback_trace();
-  } else {
-    // test code to create a trace
-    if (!(g_SYNTHETIC_DRIVER || g_DETERMINISTIC_DRIVER) && trace_filename == "") {
-      g_system_ptr->getTracer()->startTrace("ruby.trace.gz");
-      g_eventQueue_ptr->triggerEvents(g_eventQueue_ptr->getTime() + 10000);
-      g_system_ptr->getTracer()->stopTrace();
-    }
-
-    g_eventQueue_ptr->triggerAllEvents();
-
-    // This call is placed here to make sure the cache dump code doesn't fall victim to code rot
-    if (!(g_SYNTHETIC_DRIVER || g_DETERMINISTIC_DRIVER)) {
-      tester_record_cache();
-    }
-  }
   tester_destroy();
 }
 
-static void tester_allocate( void )
+vector<string> tokenizeMyString(string str, string delims)
 {
-  init_simulator();
+  vector<string> tokens;
+  char* pch;
+  char* tmp;
+  const char* c_delims = delims.c_str();
+  tmp = new char[str.length()+1];
+  strcpy(tmp, str.c_str());
+  pch = strtok(tmp, c_delims);
+  while (pch != NULL) {
+    tokens.push_back(string(pch));
+    pch = strtok(NULL, c_delims);
+  }
+  delete [] tmp;
+  return tokens;
 }
 
-static void tester_generate_values( void )
+
+vector<string> getPorts(const char* cfg_script, int cfg_script_argc, char* cfg_script_argv[])
 {
+  stringstream cfg_output;
+
+  // first we execute the Ruby-lang configuration script
+  int fd[2];
+  int pid;
+  if (pipe(fd) == -1) {
+    perror("Error Creating Pipe");
+    exit(EXIT_FAILURE);
+  }
+
+  pid = fork();
+  if (pid == -1){
+    perror("Error forking");
+    exit(EXIT_FAILURE);
+  }
+
+  if (!pid) {
+    // child
+    close(fd[0]); // close the read end of the pipe
+    // replace stdout with the write pipe
+    if (dup2(fd[1], STDOUT_FILENO) == -1) {
+      perror("Error redirecting stdout");
+      exit(EXIT_FAILURE);
+    }
+#define QUOTE_MACRO(x, y) QUOTE_TXT(x,y)
+#define QUOTE_TXT(x, y) #x y
+    if (execlp("ruby", "ruby", "-I", QUOTE_MACRO(GEMS_ROOT, "/ruby/config"), QUOTE_MACRO(GEMS_ROOT, "/tests/list_ports.rb"), cfg_script, NULL)) {
+      perror("execlp");
+      exit(EXIT_FAILURE);
+    }
+  } else {
+    close(fd[1]);
+
+    int child_status;
+    if (wait(&child_status) == -1) {
+      perror("wait");
+      exit(EXIT_FAILURE);
+    }
+    if (child_status != EXIT_SUCCESS) {
+      exit(EXIT_FAILURE);
+    }
+
+    char buf[100];
+    int bytes_read;
+    while( (bytes_read = read(fd[0], buf, 100)) > 0 ) {
+      for (int i=0;i<bytes_read;i++) {
+        cfg_output << buf[i];
+      }
+    }
+    assert(bytes_read == 0);
+    close(fd[0]);
+  }
+  string line;
+  getline(cfg_output, line);
+
+  return tokenizeMyString(line, " ");
 }
 
+
+
 void tester_initialize(int argc, char **argv)
 {
-  int   param_len = strlen( global_default_param ) + strlen( global_default_tester_param ) + 1;
-  char *default_param = (char *) malloc( sizeof(char) * param_len );
-  my_default_param = default_param;
-  strcpy( default_param, global_default_param );
-  strcat( default_param, global_default_tester_param );
-
-  // when the initvar object is created, it reads the configuration default
-  //   -for the tester, the configuration defaults in config/tester.defaults
-
-  /** note: default_param is included twice in the tester:
-   *       -once in init.C
-   *       -again in this file
-   */
-  initvar_t *ruby_initvar = new initvar_t( "ruby", "../../../ruby/",
-                                           default_param,
-                                           &tester_allocate,
-                                           &tester_generate_values,
-                                           NULL,
-                                           NULL );
-  my_initvar = ruby_initvar;
-  ruby_initvar->checkInitialization();
+  const char* cfg_file = argv[1];
+
+  set_defaults();
   parseOptions(argc, argv);
 
-  ruby_initvar->allocate();
+  libruby_init(cfg_file);
+  libruby_print_config(std::cout);
 
-  g_system_ptr->printConfig(cout);
-  cout << "Testing clear stats...";
-  g_system_ptr->clearStats();
-  cout << "Done." << endl;
-  //free( default_param );
-  //delete ruby_initvar;
-}
+  vector<string> port_names = getPorts(cfg_file, 0, NULL);
+  vector<RubyPortHandle> ports;
 
-void tester_destroy()
-{
-  g_system_ptr->printStats(cout);
-  g_debug_ptr->closeDebugOutputFile();
+  for (vector<string>::const_iterator it = port_names.begin(); it != port_names.end(); it++)
+    ports.push_back(libruby_get_port((*it).c_str(), hit_callback));
 
-  free(my_default_param);
-  delete my_initvar;
-  // Clean up
-  destroy_simulator();
-  cerr << "Success: " << CURRENT_PROTOCOL << endl;
-}
+  debug_ptr = new Debug(   g_debug_filter_string.c_str(),
+                           g_debug_verbosity_string.c_str(),
+                           g_debug_start_time,
+                           g_debug_output_filename.c_str() );
 
-void tester_install_opal(mf_opal_api_t* opal_api, mf_ruby_api_t* ruby_api)
-{
-  std::cout << __FILE__ << "(" << __LINE__ << "): Not implemented" << std::endl;
+  if (driver_type == "Deterministic") {
+    m_driver_ptr = new DeterministicDriver(generator_type, num_completions, num_procs, g_think_time, g_wait_time, g_tester_length);
+  }
+  else if (driver_type == "Racey") {
+    m_driver_ptr = new RaceyDriver(num_procs, g_tester_length);
+  }
+ /* else if (driver_type == "Synthetic") {
+    m_driver_ptr = new SyntheticDriver();
+  }
+  }*/
+
+  m_driver_ptr->go();
 }
 
-void tester_record_cache()
+void tester_destroy()
 {
-  cout << "Testing recording of cache contents" << endl;
-  CacheRecorder recorder;
-  g_system_ptr->recordCacheContents(recorder);
-  int written = recorder.dumpRecords("ruby.caches.gz");
-  int read = Tracer::playbackTrace("ruby.caches.gz");
-  assert(read == written);
-  cout << "Testing recording of cache contents completed" << endl;
+  m_driver_ptr->printStats(cout);
+  libruby_destroy();
+  cerr << "Success: " << CURRENT_PROTOCOL << endl;
 }
 
-void tester_playback_trace()
+
+void hit_callback(int64_t request_id)
 {
-  assert(trace_filename != "");
-  cout << "Reading trace from file '" << trace_filename << "'..." << endl;
-  int read = Tracer::playbackTrace(trace_filename);
-  cout << "(" << read << " requests read)" << endl;
-  if (read == 0) {
-    ERROR_MSG("Zero items read from tracefile.");
-  }
+  m_driver_ptr->hitCallback(request_id);
 }
 
 // ************************************************************************
 // *** Functions for parsing the command line parameters for the tester ***
 // ************************************************************************
 
+
+
 static struct option const long_options[] =
 {
   {"help", no_argument, NULL, 'h'},
-  {"processors", required_argument, NULL, 'p'},
-  {"length", required_argument, NULL, 'l'},
-  {"random", required_argument, NULL, 'r'},
-  {"trace_input", required_argument, NULL, 'z'},
-  {"component", required_argument, NULL, 'c'},
-  {"verbosity", required_argument, NULL, 'v'},
-  {"debug_output_file", required_argument, NULL, 'o'},
-  {"start", required_argument, NULL, 's'},
-  {"bandwidth", required_argument, NULL, 'b'},
-  {"threshold", required_argument, NULL, 't'},
-  {"think_time", required_argument, NULL, 'k'},
-  {"locks", required_argument, NULL, 'q'},
-  {"network", required_argument, NULL, 'n'},
-  {"procs_per_chip", required_argument, NULL, 'a'},
-  {"l2_caches", required_argument, NULL, 'e'},
-  {"memories", required_argument, NULL, 'm'},
+  {"number of processors", required_argument, NULL, 'p'},
+  {"test run length", required_argument, NULL, 'l'},
+  {"debugger verbosity", required_argument, NULL, 'v'},
+  {"debugger filter component", required_argument, NULL, 'c'},
+  {"debugger output file", required_argument, NULL, 'o'},
+  {"debugger start time", required_argument, NULL, 's'},
+  {"generator think time", required_argument, NULL, 'k'},
+  {"generator wait time", required_argument, NULL, 'w'},
+  {"driver type", required_argument, NULL, 'd'},
+  {"generator type", required_argument, NULL, 'g'},
+  {"num completions before pass", required_argument, NULL, 'n'},
   {NULL, 0, NULL, 0}
 };
 
+
+// This is awkward and temporary, need the defaults config, and also need functions to
+// just lookup a parameter in the configuration file
+// Ideally the default values are set by libruby_init and then a function is provided to
+// set values at run-time
+static void set_defaults() {
+  g_tester_length = 0;
+  g_think_time = 5;
+  g_wait_time = 20;
+
+  num_procs = 1;
+  num_completions = 1;
+  driver_type = "Deterministic";
+  generator_type = "DetermInvGenerator";
+  g_debug_verbosity_string = "none";
+  g_debug_filter_string = "none";
+  g_debug_output_filename = "none";
+  g_debug_start_time = 0;
+}
+
 static void parseOptions(int argc, char **argv)
 {
   cout << "Parsing command line arguments:" << endl;
     switch (c) {
     case 0:
       break;
-
-    case 'c':
-      checkArg(c);
-      cout << "  component filter string = " << optarg << endl;
-      error = Debug::checkFilterString( optarg );
-      if (error) {
-        usageInstructions();
-      }
-      DEBUG_FILTER_STRING = strdup( optarg );
-      break;
-
     case 'h':
       usageInstructions();
       break;
-
+    case 'p':
+      checkArg(c);
+      cout << "  number of processors = " << optarg << endl;
+      num_procs = atoi( optarg );
+      break;
     case 'v':
       checkArg(c);
       cout << "  verbosity string = " << optarg << endl;
       if (error) {
         usageInstructions();
       }
-      DEBUG_VERBOSITY_STRING = strdup( optarg );
-      break;
-
-    case 'r': {
-      checkArg(c);
-      if (string(optarg) == "random") {
-        g_RANDOM_SEED = time(NULL);
-      } else {
-        g_RANDOM_SEED = atoi(optarg);
-        if (g_RANDOM_SEED == 0) {
-          usageInstructions();
-        }
-      }
+      g_debug_verbosity_string = strdup( optarg );
       break;
-    }
-
     case 'l': {
       checkArg(c);
       g_tester_length = atoi(optarg);
       }
       break;
     }
-
-    case 'q': {
+      case 'c':
       checkArg(c);
-      g_synthetic_locks = atoi(optarg);
-      cout << "  locks in synthetic workload = " << g_synthetic_locks << endl;
-      if (g_synthetic_locks == 0) {
+      cout << "  component filter string = " << optarg << endl;
+      error = Debug::checkFilterString( optarg );
+      if (error) {
         usageInstructions();
       }
+      g_debug_filter_string = strdup( optarg );
       break;
-    }
-
-    case 'p': {
-      checkArg(c);
-      g_NUM_PROCESSORS = atoi(optarg);
-      break;
-    }
-
-    case 'a': {
-      checkArg(c);
-      g_PROCS_PER_CHIP = atoi(optarg);
-      cout << "  g_PROCS_PER_CHIP: " << g_PROCS_PER_CHIP << endl;
-      break;
-    }
-
-    case 'e': {
-      checkArg(c);
-      g_NUM_L2_BANKS = atoi(optarg);
-      cout << "  g_NUM_L2_BANKS: " << g_NUM_L2_BANKS << endl;
-      break;
-    }
-
-    case 'm': {
-      checkArg(c);
-      g_NUM_MEMORIES = atoi(optarg);
-      cout << "  g_NUM_MEMORIES: " << g_NUM_MEMORIES << endl;
-      break;
-    }
-
     case 's': {
       checkArg(c);
       long long start_time = atoll(optarg);
       if (start_time == 0) {
         usageInstructions();
       }
-      DEBUG_START_TIME = start_time;
-      break;
-    }
-
-    case 'b': {
-      checkArg(c);
-      int bandwidth = atoi(optarg);
-      cout << "  bandwidth per link (MB/sec) = " << bandwidth << endl;
-      g_endpoint_bandwidth = bandwidth;
-      if (bandwidth == 0) {
-        usageInstructions();
-      }
+      g_debug_start_time = start_time;
       break;
     }
-
-    case 't': {
+    case 'k': {
       checkArg(c);
-      g_bash_bandwidth_adaptive_threshold = atof(optarg);
-      if ((g_bash_bandwidth_adaptive_threshold > 1.1) || (g_bash_bandwidth_adaptive_threshold < -0.1)) {
-        cerr << "Error: Bandwidth adaptive threshold must be between 0.0 and 1.0" << endl;
-        usageInstructions();
-      }
-
+      g_think_time = atoi(optarg);
       break;
     }
-
-    case 'k': {
+    case 'w': {
       checkArg(c);
-      g_think_time = atoi(optarg);
+      g_wait_time = atoi(optarg);
       break;
     }
-
     case 'o':
       checkArg(c);
       cout << "  output file = " << optarg << endl;
-      DEBUG_OUTPUT_FILENAME = strdup( optarg );
+      g_debug_output_filename = strdup( optarg );
       break;
-
-    case 'z':
+    case 'd':
       checkArg(c);
-      trace_filename = string(optarg);
-      cout << "  tracefile = " << trace_filename << endl;
+      cout << "  driver type = " << optarg << endl;
+      driver_type = strdup( optarg );
+      break;
+    case 'g':
+      checkArg(c);
+      cout << "  generator type = " << optarg << endl;
+      generator_type = strdup( optarg );
+      break;
+    case 'n':
+      checkArg(c);
+      cout << "  num completions before pass = " << optarg << endl;
+      num_completions = atoi( optarg );
       break;
-
-      case 'n':
-        checkArg(c);
-        cout << "  topology = " << string(optarg) << endl;
-        g_NETWORK_TOPOLOGY = strdup(optarg);
-        break;
-
     default:
       cerr << "parameter '" << c << "' unknown" << endl;
       usageInstructions();
     }
   }
-
-  if ((trace_filename != "") || (g_tester_length != 0)) {
-    if ((trace_filename != "") && (g_tester_length != 0)) {
-      cerr << "Error: both a run length (-l) and a trace file (-z) have been specified." << endl;
-      usageInstructions();
-    }
-  } else {
-    cerr << "Error: either run length (-l) must be > 0 or a trace file (-z) must be specified." << endl;
-    usageInstructions();
-  }
 }
 
 static void usageInstructions()
     counter++;
   }
 
-  cerr << "Option --processors (-p) is required." << endl;
-  cerr << "Either option --length (-l) or --trace_input (-z) must be specified." << endl;
   cerr << endl;
-  g_debug_ptr->usageInstructions();
+  debug_ptr->usageInstructions();
   cerr << endl;
 
   exit(1);
 
 #ifndef TESTFRAMEWORK_H
 #define TESTFRAMEWORK_H
 
-#include "mem/ruby/common/Global.hh"
-#include "mem/ruby/interfaces/mf_api.hh"
+#include "mem/ruby/tester/Global_Tester.hh"
 
 void tester_main(int argc, char **argv);
-void tester_install_opal( mf_opal_api_t  *opal_api, mf_ruby_api_t *ruby_api );
 
 #endif //TESTFRAMEWORK_H
 
 #include "mem/slicc/ast/InfixOperatorExprAST.hh"
 #include "mem/slicc/ast/FuncCallExprAST.hh"
 #include "mem/slicc/ast/MethodCallExprAST.hh"
+#include "mem/slicc/ast/NewExprAST.hh"
 
 #include "mem/slicc/ast/ChipComponentAccessAST.hh"
 
 
   code += ".enqueue(out_msg";
 
   if (getPairs().exist("latency")) {
-    code += ", " + getPairs().lookup("latency");
+    code += ", RubyConfig::get" + getPairs().lookup("latency") + "()";
   }
 
   code += ");\n";
 
 
 MachineAST::MachineAST(string* ident_ptr,
                        PairListAST* pairs_ptr,
+                       Vector<TypeFieldAST*>* config_params_ptr,
+                       std::vector<std::string*>* latency_vector,
                        DeclListAST* decl_list_ptr)
 
   : DeclAST(pairs_ptr)
 {
   m_ident_ptr = ident_ptr;
   m_pairs_ptr = pairs_ptr;
+  m_config_params_ptr = config_params_ptr;
   m_decl_list_ptr = decl_list_ptr;
+  m_latency_vector = latency_vector;
 }
 
 MachineAST::~MachineAST()
   g_sym_table.pushFrame();
 
   // Create a new machine
-  machine_ptr = new StateMachine(*m_ident_ptr, getLocation(), getPairs());
+  machine_ptr = new StateMachine(*m_ident_ptr, getLocation(), getPairs(), m_latency_vector);
   g_sym_table.newCurrentMachine(machine_ptr);
 
   // Generate code for all the internal decls
 
 #include "mem/slicc/slicc_global.hh"
 #include "mem/slicc/ast/DeclAST.hh"
 #include "mem/slicc/ast/DeclListAST.hh"
+#include "mem/slicc/ast/TypeFieldAST.hh"
 #include "mem/slicc/symbols/StateMachine.hh"
 
 class MachineAST : public DeclAST {
   // Constructors
   MachineAST(string* ident_ptr,
              PairListAST* pairs_ptr,
+             Vector<TypeFieldAST*>* config_params_ptr,
+             std::vector<std::string*>* latency_vector,
              DeclListAST* decl_list_ptr);
 
   // Destructor
   MachineAST& operator=(const MachineAST& obj);
 
   // Data Members (m_ prefix)
+  std::vector<std::string*>* m_latency_vector;
   string* m_ident_ptr;
   DeclListAST* m_decl_list_ptr;
+  Vector<TypeFieldAST*>* m_config_params_ptr;
   PairListAST* m_pairs_ptr;
 };
 
 
 {
   Type* obj_type_ptr = NULL;
 
+  string methodId;
+  Vector <Type*> paramTypes;
+
+  int actual_size = m_expr_vec_ptr->size();
+  for(int i=0; i<actual_size; i++) {
+    string tmp;
+    Type* actual_type_ptr = (*m_expr_vec_ptr)[i]->generate(tmp);
+    paramTypes.insertAtBottom(actual_type_ptr);
+  }
+
   if(m_obj_expr_ptr) {
     // member method call
+    string tmp;
+    obj_type_ptr = m_obj_expr_ptr->generate(tmp);
+    methodId = obj_type_ptr->methodId(*m_proc_name_ptr, paramTypes);
+    if (obj_type_ptr->methodReturnType(methodId)->isInterface())
+      code += "static_cast<" + obj_type_ptr->methodReturnType(methodId)->cIdent() + "&>";
     code += "((";
-    obj_type_ptr = m_obj_expr_ptr->generate(code);
-
+    code += tmp;
     code += ").";
   } else if (m_type_ptr) {
     // class method call
     code += "(" + m_type_ptr->toString() + "::";
     obj_type_ptr = m_type_ptr->lookupType();
+    methodId = obj_type_ptr->methodId(*m_proc_name_ptr, paramTypes);
   } else {
     // impossible
     assert(0);
   }
 
-  Vector <Type*> paramTypes;
-
   // generate code
-  int actual_size = m_expr_vec_ptr->size();
+  actual_size = m_expr_vec_ptr->size();
   code += (*m_proc_name_ptr) + "(";
   for(int i=0; i<actual_size; i++) {
     if (i != 0) {
     }
     // Check the types of the parameter
     Type* actual_type_ptr = (*m_expr_vec_ptr)[i]->generate(code);
-    paramTypes.insertAtBottom(actual_type_ptr);
   }
   code += "))";
 
-  string methodId = obj_type_ptr->methodId(*m_proc_name_ptr, paramTypes);
-
   // Verify that this is a method of the object
   if (!obj_type_ptr->methodExist(methodId)) {
     error("Invalid method call: Type '" + obj_type_ptr->toString() + "' does not have a method '" + methodId + "'");
 
--- /dev/null
+
+#include "mem/slicc/ast/NewExprAST.hh"
+
+Type* NewExprAST::generate(string & code) const
+{
+  Type* type = m_type_ptr->lookupType();
+  code += "new " + type->cIdent();
+  return type;
+}
 
--- /dev/null
+#ifndef NEWEXPRAST_H
+#define NEWEXPRAST_H
+
+#include "mem/slicc/ast/ExprAST.hh"
+#include "mem/slicc/ast/TypeAST.hh"
+#include "mem/slicc/symbols/Type.hh"
+
+class NewExprAST : public ExprAST
+{
+public:
+  NewExprAST(TypeAST* type_ptr) : ExprAST() { m_type_ptr = type_ptr; }
+  Type* generate(string & code) const;
+  void print(ostream & out) const { out << "[NewExprAST: " << *m_type_ptr << "]"; }
+  string getName() const { return m_type_ptr->toString(); }
+
+private:
+  TypeAST* m_type_ptr;
+};
+
+#endif
 
     c_code = "m_version";
   } else if (*m_ident_ptr == "machineID") {
     c_code = "m_machineID";
-  } else if (*m_ident_ptr == "sequencer") {
-    c_code = "*(dynamic_cast<"+m_type_ptr->toString()+"*>(m_chip_ptr->getSequencer(m_version)))";
-    machineComponentSym = true;
-  } /*else if (*m_ident_ptr == "xfdr_record_mgr") {
-    c_code = "*(dynamic_cast<"+m_type_ptr->toString()+"*>(m_chip_ptr->getXfdrManager(m_version)))";
-    machineComponentSym = true;
-    } */else if (// getPairs().exist("network") || (m_type_ptr->lookupType()->existPair("cache"))
-//              || (m_type_ptr->lookupType()->existPair("tbe")) ||
-//              (m_type_ptr->lookupType()->existPair("newtbe")) ||
-//              (m_type_ptr->lookupType()->existPair("timer")) ||
-//              (m_type_ptr->lookupType()->existPair("dir")) ||
-//              (m_type_ptr->lookupType()->existPair("persistent")) ||
-//              (m_type_ptr->lookupType()->existPair("filter")) ||
-//              (getPairs().exist("trigger_queue"))
-             getPairs().exist("no_vector")) {
-    c_code = "(*(m_chip_ptr->m_" + machine + *m_ident_ptr + "_ptr))";
-    machineComponentSym = true;
   } else {
-    c_code = "(*(m_chip_ptr->m_" + machine + *m_ident_ptr + "_vec[m_version]))";
-    machineComponentSym = true;
+    c_code = "(*m_" + machine + *m_ident_ptr + "_ptr)";
+    //    c_code = "(*(m_chip_ptr->m_" + machine + *m_ident_ptr + "_ptr))";
+      //    machineComponentSym = true;
   }
 
   Var* v = new Var(*m_ident_ptr, getLocation(), type_ptr, c_code,
                              getPairs(), g_sym_table.getStateMachine());
 
-  g_sym_table.newSym(v);
+  StateMachine* machine_ptr = g_sym_table.getStateMachine();
+  if (machine_ptr != NULL) {
+    machine_ptr->addObj(v);
+  }// else {
+    g_sym_table.newSym(v);
+    //}
 
   // used to cheat-- that is, access components in other machines
   if (machineComponentSym) {
 
+
 /*
  * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
  * All rights reserved.
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+/*
+ * $Id$
+ */
+
 %{
 
 #include <assert.h>
 #include "mem/slicc/ast/ASTs.hh"
-#include "mem/slicc/parser/parser.hh"
+#include "parser.hh"
 #include <string>
 
 extern "C" int yylex();
 THIS       { return THIS; }
 CHIP       { return CHIP; }
 void       { yylval.str_ptr = new string(yytext); return VOID; }
+new        { return NEW; }
 
 ==        { yylval.str_ptr = new string(yytext); return EQ; }
 !=        { yylval.str_ptr = new string(yytext); return NE; }
 
 [0-9]*[.][0-9]*     { yylval.str_ptr = new string(yytext); return FLOATNUMBER; }
 [0-9]*     { yylval.str_ptr = new string(yytext); return NUMBER; }
+
 [a-zA-Z_][a-zA-Z_0-9]{0,50}    { yylval.str_ptr = new string(yytext); return IDENT; }
 \"[^"\n]*\"  { yytext[strlen(yytext)-1] = '\0';  yylval.str_ptr = new string(yytext+1); return STRING; }
 \'[^'\n]*\'  { yytext[strlen(yytext)-1] = '\0';  yylval.str_ptr = new string(yytext+1); return STRING; }
 
+
 /*
  * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
  * All rights reserved.
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+/*
+ * $Id$
+ *
+ * */
+
 %{
 #include <string>
 #include <stdio.h>
 #include <assert.h>
 #include "mem/slicc/ast/ASTs.hh"
+#include <vector>
 
 #define YYMAXDEPTH 100000
 #define YYERROR_VERBOSE
 %union {
   string* str_ptr;
   Vector<string>* string_vector_ptr;
+  std::vector<string*>* stdstring_vector_ptr;
 
   // Decls
   DeclAST* decl_ptr;
 %type <expr_ptr> expr literal enumeration
 %type <expr_vector_ptr> expr_list
 
+%type <stdstring_vector_ptr> myrule
+
 %type <pair_ptr> pair
 %type <pair_list_ptr> pair_list pairs
 
 //%token DEQUEUE REMOVE_EARLY SKIP_EARLY PEEK_EARLY
 %token DEBUG_EXPR_TOKEN DEBUG_MSG_TOKEN
 %token ACTION_DECL TRANSITION_DECL TYPE_DECL STRUCT_DECL EXTERN_TYPE_DECL ENUM_DECL
-%token TYPE_FIELD OTHER IF ELSE RETURN
+%token TYPE_FIELD OTHER IF ELSE RETURN NEW
 
 %token <str_ptr> EQ NE '<' '>' LE GE NOT AND OR PLUS DASH STAR SLASH RIGHTSHIFT LEFTSHIFT
 
      | { $$ = new Vector<DeclAST*>; }
      ;
 
-decl:  MACHINE_DECL     '(' ident pair_list ')' '{' decl_list '}' { $$ = new MachineAST($3, $4, $7); }
+decl:  MACHINE_DECL     '(' ident pair_list ')' ':' myrule '{' decl_list '}' { $$ = new MachineAST($3, $4, NULL, $7, $9); }
+//    |  MACHINE_DECL     '(' ident pair_list ')' ':' type_members '{' decl_list '}' { $$ = new MachineAST($3, $4, $7, string_vector, $9); }
+    |  MACHINE_DECL     '(' ident pair_list ')' '{' decl_list '}' { $$ = new MachineAST($3, $4, NULL, new vector<string*>(), $7); }
     |  ACTION_DECL      '(' ident pair_list ')' statement_list { $$ = new ActionDeclAST($3, $4, $6); }
     |  IN_PORT_DECL     '(' ident ',' type ',' var pair_list ')' statement_list { $$ = new InPortDeclAST($3, $5, $7, $8, $10); }
     |  OUT_PORT_DECL    '(' ident ',' type ',' var pair_list ')' SEMICOLON { $$ = new OutPortDeclAST($3, $5, $7, $8); }
              ;
 
 // Idents and lists
-ident: IDENT { $$ = $1; } ;
+ident: IDENT { $$ = $1; };
 
 ident_list: '{' idents '}' { $$ = $2; }
           | ident { $$ = new Vector<string>; $$->insertAtTop(*($1)); delete $1; }
     |  literal { $$ = $1; }
     |  enumeration { $$ = $1; }
     |  ident '(' expr_list ')' { $$ = new FuncCallExprAST($1, $3); }
-
+    |  NEW type { $$ = new NewExprAST($2); }
 
 // globally access a local chip component and call a method
     |  THIS DOT var '[' expr ']' DOT var DOT ident '(' expr_list ')' { $$ = new ChipComponentAccessAST($3, $5, $8, $10, $12 ); }
 field: ident { $$ = $1; }
      ;
 
+myrule: myrule IDENT { $1->push_back($2); }
+      | IDENT { $$ = new vector<string*>(1, $1); }
+      ;
+
 %%
 
 extern FILE *yyin;
     exit(1);
   }
   g_line_number = 1;
-  g_file_name() = filename;
+  g_file_name = filename;
   yyin = file;
   g_decl_list_ptr = NULL;
   yyparse();
 
 extern "C" void yyerror(char* s)
 {
-  fprintf(stderr, "%s:%d: %s at %s\n", g_file_name().c_str(), g_line_number, s, yytext);
+  fprintf(stderr, "%s:%d: %s at %s\n", g_file_name.c_str(), g_line_number, s, yytext);
   exit(1);
 }
 
 
 }
 
 // This write a function of object Chip
-void Func::writeCFiles(string path) const
+void Func::writeCFiles(string path)
 {
   if (isExternal()) {
     // Do nothing
     out << "/** Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< " */" << endl;
     out << endl;
     out << "#include \"mem/protocol/Types.hh\"" << endl;
-    out << "#include \"mem/protocol/Chip.hh\"" << endl;
     if (m_isInternalMachineFunc) {
-      out << "#include \"" << m_machineStr << "_Controller.hh\"" << endl;
+      out << "#include \"mem/protocol/" << m_machineStr << "_Controller.hh\"" << endl;
     }
     out << endl;
 
 
   string cIdent() const { return m_c_ident; }
   const Vector<Type*>& getParamTypes() const { return m_param_type_vec; }
   Type* getReturnType() const { return m_type_ptr; }
-  void writeCFiles(string path) const;
+  void writeCFiles(string path) ;
   void funcPrototype(string& code) const;
   bool isExternal() const { return existPair("external"); }
   bool isInternalMachineFunc() const { return m_isInternalMachineFunc; }
 
 #include "mem/gems_common/util.hh"
 #include "mem/gems_common/Vector.hh"
 
-StateMachine::StateMachine(string ident, const Location& location, const Map<string, string>& pairs)
+#include <set>
+
+StateMachine::StateMachine(string ident, const Location& location, const Map<string, string>& pairs,  std::vector<std::string*>* latency_vector)
   : Symbol(ident, location, pairs)
 {
   m_table_built = false;
+  m_latency_vector = *latency_vector;
 }
 
 StateMachine::~StateMachine()
 // ******* C Files ******* //
 // *********************** //
 
-void StateMachine::writeCFiles(string path) const
+void StateMachine::writeCFiles(string path)
 {
   string comp = getIdent();
   string filename;
 
+  // Output the method declarations for the class declaration
+  {
+    ostringstream sstr;
+    printControllerH(sstr, comp);
+    conditionally_write_file(path + comp + "_Controller.hh", sstr);
+  }
+
   // Output switch statement for transition table
   {
     ostringstream sstr;
     conditionally_write_file(path + comp + "_Controller.cc", sstr);
   }
 
-  // Output the method declarations for the class declaration
-  {
-    ostringstream sstr;
-    printControllerH(sstr, comp);
-    conditionally_write_file(path + comp + "_Controller.hh", sstr);
-  }
-
   // Output the wakeup loop for the events
   {
     ostringstream sstr;
 
 }
 
-void StateMachine::printControllerH(ostream& out, string component) const
+void StateMachine::printControllerH(ostream& out, string component)
 {
+
+  m_message_buffer_names.clear();
+
   out << "/** \\file " << getIdent() << ".hh" << endl;
   out << "  * " << endl;
   out << "  * Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< endl;
   out << endl;
   out << "#include \"mem/ruby/common/Global.hh\"" << endl;
   out << "#include \"mem/ruby/common/Consumer.hh\"" << endl;
+  out << "#include \"mem/ruby/slicc_interface/AbstractController.hh\"" << endl;
   out << "#include \"mem/protocol/TransitionResult.hh\"" << endl;
   out << "#include \"mem/protocol/Types.hh\"" << endl;
   out << "#include \"mem/protocol/" << component << "_Profiler.hh\"" << endl;
+
+  // include object classes
+  std::set<string> seen_types;
+  for(int i=0; i<numObjects(); i++) {
+    Var* var = m_objs[i];
+    if (seen_types.count(var->getType()->cIdent()) == 0) {
+      out << "#include \"mem/protocol/" << var->getType()->cIdent() << ".hh\"" << endl;
+      //      out << "class " << var->getType()->cIdent() << ";" << endl;
+      seen_types.insert(var->getType()->cIdent());
+    }
+  }
+
   out << endl;
 
   // for adding information to the protocol debug trace
   out << "extern stringstream " << component << "_" << "transitionComment;" << endl;
 
-  out << "class " << component << "_Controller : public Consumer {" << endl;
+  out << "class " << component << "_Controller : public AbstractController {" << endl;
 
   /* the coherence checker needs to call isBlockExclusive() and isBlockShared()
      making the Chip a friend class is an easy way to do this for now */
   out << "#ifdef CHECK_COHERENCE" << endl;
-  out << "  friend class Chip;" << endl;
   out << "#endif /* CHECK_COHERENCE */" << endl;
 
   out << "public:" << endl;
-  out << "  " << component << "_Controller(Chip* chip_ptr, int version);" << endl;
+  //  out << "  " << component << "_Controller(int version, Network* net_ptr);" << endl;
+  out << "  " << component << "_Controller(const string & name);" << endl;
+  out << "  static int getNumControllers();" << endl;
+  out << "  void init(Network* net_ptr, const vector<string> & argv);" << endl;
+  out << "  MessageBuffer* getMandatoryQueue() const;" << endl;
+  out << "  const int & getVersion() const;" << endl;
+  out << "  const string toString() const;" << endl;
+  out << "  const string getName() const;" << endl;
+  out << "  const MachineType getMachineType() const;" << endl;
   out << "  void print(ostream& out) const;" << endl;
+  out << "  void printConfig(ostream& out) const;" << endl;
   out << "  void wakeup();" << endl;
-  out << "  static void dumpStats(ostream& out) { s_profiler.dumpStats(out); }" << endl;
-  out << "  static void clearStats() { s_profiler.clearStats(); }" << endl;
+  out << "  void printStats(ostream& out) const { s_profiler.dumpStats(out); }" << endl;
+  out << "  void clearStats() { s_profiler.clearStats(); }" << endl;
   out << "private:" << endl;
+
+//added by SS
+//  found_to_mem = 0;
+  std::vector<std::string*>::const_iterator it;
+  for(it=m_latency_vector.begin();it!=m_latency_vector.end();it++){
+        out << "  int m_" << (*it)->c_str() << ";" << endl;
+  }
+  out << "  int m_number_of_TBEs;" << endl;
+
   out << "  TransitionResult doTransition(" << component << "_Event event, " << component
       << "_State state, const Address& addr";
   if(CHECK_INVALID_RESOURCE_STALLS) {
     out << ", int priority";
   }
   out << ");  // in " << component << "_Transitions.cc" << endl;
-  out << "  Chip* m_chip_ptr;" << endl;
-  out << "  NodeID m_id;" << endl;
+  out << "  string m_name;" << endl;
+  out << "  int m_transitions_per_cycle;" << endl;
+  out << "  int m_buffer_size;" << endl;
+  out << "  int m_recycle_latency;" << endl;
+  out << "  map< string, string > m_cfg;" << endl;
   out << "  NodeID m_version;" << endl;
+  out << "  Network* m_net_ptr;" << endl;
   out << "  MachineID m_machineID;" << endl;
   out << "  static " << component << "_Profiler s_profiler;" << endl;
+  out << "  static int m_num_controllers;" << endl;
 
   // internal function protypes
   out << "  // Internal functions" << endl;
     out << "/** \\brief " << action.getDescription() << "*/" << endl;
     out << "  void " << action.getIdent() << "(const Address& addr);" << endl;
   }
+
+  // the controller internal variables
+  out << "  // Object" << endl;
+  for(int i=0; i < numObjects(); i++) {
+    const Var* var = m_objs[i];
+    string template_hack = "";
+    if (var->existPair("template_hack")) {
+      template_hack = var->lookupPair("template_hack");
+    }
+    out << "  " << var->getType()->cIdent() << template_hack << "* m_"
+        << var->cIdent() << "_ptr;" << endl;
+
+    string str = "m_"+ var->cIdent() + "_ptr";
+    if (var->getType()->cIdent() == "MessageBuffer")
+        m_message_buffer_names.push_back(str);
+
+  }
+
+
   out << "};" << endl;
   out << "#endif // " << component << "_CONTROLLER_H" << endl;
 }
 
-void StateMachine::printControllerC(ostream& out, string component) const
+void StateMachine::printControllerC(ostream& out, string component)
 {
   out << "/** \\file " << getIdent() << ".cc" << endl;
   out << "  * " << endl;
   out << "#include \"mem/protocol/" << component << "_Event.hh\"" << endl;
   out << "#include \"mem/protocol/Types.hh\"" << endl;
   out << "#include \"mem/ruby/system/System.hh\"" << endl;
-  out << "#include \"mem/protocol/Chip.hh\"" << endl;
+
+  // include object classes
+  std::set<string> seen_types;
+  for(int i=0; i<numObjects(); i++) {
+    Var* var = m_objs[i];
+    if (seen_types.count(var->getType()->cIdent()) == 0) {
+      out << "#include \"mem/protocol/" << var->getType()->cIdent() << ".hh\"" << endl;
+      seen_types.insert(var->getType()->cIdent());
+    }
+
+  }
+
   out << endl;
 
+  out << "int " << component << "_Controller::m_num_controllers = 0;" << endl;
+
   // for adding information to the protocol debug trace
   out << "stringstream " << component << "_" << "transitionComment;" << endl;
   out << "#define APPEND_TRANSITION_COMMENT(str) (" << component << "_" << "transitionComment << str)" << endl;
 
   out << "/** \\brief constructor */" << endl;
   out << component << "_Controller::" << component
-      << "_Controller(Chip* chip_ptr, int version)" << endl;
+    //      << "_Controller(int version, Network* net_ptr)" << endl;
+      << "_Controller(const string & name)" << endl;
+  out << " : m_name(name)" << endl;
+  out << "{ " << endl;
+  out << "   m_num_controllers++; " << endl;
+  for(int i=0; i < numObjects(); i++) {
+    const Var* var = m_objs[i];
+    if ( var->cIdent().find("mandatoryQueue") != string::npos)
+      out << "  m_" << var->cIdent() << "_ptr = new " << var->getType()->cIdent() << "();" << endl;
+  }
+  out << "}" << endl << endl;
+
+  out << "void " << component << "_Controller::init(Network * net_ptr, const vector<string> & argv)" << endl;
   out << "{" << endl;
-  out << "  m_chip_ptr = chip_ptr;" << endl;
-  out << "  m_id = m_chip_ptr->getID();" << endl;
-  out << "  m_version = version;" << endl;
+  out << "  for (size_t i=0; i < argv.size(); i+=2) {" << endl;
+//  out << "    printf (\"ARG: %s = %s \\n \", argv[i].c_str(), argv[i+1].c_str());"<< endl;
+
+  out << "    if (argv[i] == \"version\") " << endl;
+  out << "      m_version = atoi(argv[i+1].c_str());" << endl;
+  out << "    else if (argv[i] == \"transitions_per_cycle\") " << endl;
+  out << "      m_transitions_per_cycle = atoi(argv[i+1].c_str());" << endl;
+  out << "    else if (argv[i] == \"buffer_size\") " << endl;
+  out << "      m_buffer_size = atoi(argv[i+1].c_str());" << endl;
+//added by SS
+  out << "    else if (argv[i] == \"recycle_latency\") " << endl;
+  out << "      m_recycle_latency = atoi(argv[i+1].c_str());" << endl;
+//added by SS --> for latency
+//for loop on latency_vector to check with argv[i] and assign the value to the related m_latency ...
+  out << "    else if (argv[i] == \"number_of_TBEs\") " << endl;
+  out << "      m_number_of_TBEs = atoi(argv[i+1].c_str());" << endl;
+
+  if (m_latency_vector.size()) {
+  out << "    else { " << endl;
+    std::vector<std::string*>::const_iterator it;
+    for(it=m_latency_vector.begin();it!=m_latency_vector.end();it++) {
+      string str = (*it)->c_str();
+      str.erase(0,8);
+//convert to lowercase
+      size_t i;
+      char* strc = (char*) malloc (str.length()+1);
+      strc[str.length()]=0;
+      for(i=0; i < str.length(); i++) {
+        strc[i] = str.at(i);
+        strc[i] = tolower(strc[i]);
+      }
+      str = strc;
+      delete strc;
+      out << "      if (argv[i] == \"" << str << "\"){" << endl;
+      if (str == "to_mem_ctrl_latency")
+        out << "        m_" << (*it)->c_str() << "=" << "atoi(argv[i+1].c_str())+(random() % 5);" << endl;
+      else
+        out << "        m_" << (*it)->c_str() << "=" << "atoi(argv[i+1].c_str());" << endl;
+//      out << "        printf (\"SET m_" << it->c_str() << "= %i \\n \", m_" << it->c_str() << ");" << endl;
+      out << "      }" << endl;
+    }
+  out << "    }" << endl;
+  }
+  out << "  }" << endl;
+
+  out << "  m_net_ptr = net_ptr;" << endl;
   out << "  m_machineID.type = MachineType_" << component << ";" << endl;
-  out << "  m_machineID.num = m_id*RubyConfig::numberOf"<< component << "PerChip()+m_version;" << endl;
+  out << "  m_machineID.num = m_version;" << endl;
+
+//  out << "  printf (\"I set m_LATENCY_ISSUE_LATENCY to %i \\n \", m_LATENCY_ISSUE_LATENCY);" << endl;
+//  out << "  printf (\"I set m_LATENCY_CACHE_RESPONSE_LATENCY to %i \\n \", m_LATENCY_CACHE_RESPONSE_LATENCY);" << endl;
+
+  // make configuration array
+  out << "  for (size_t i=0; i < argv.size(); i+=2) {" << endl;
+  out << "    if (argv[i] != \"version\") " << endl;
+  out << "      m_cfg[argv[i]] = argv[i+1];" << endl;
+  out << "  }" << endl;
+
+  out << endl;
+
+  // initialize objects
+  out << "  // Objects" << endl;
+  for(int i=0; i < numObjects(); i++) {
+    const Var* var = m_objs[i];
+    if (!var->existPair("network")) {
+      // Not a network port object
+      if (var->getType()->existPair("primitive")) {
+        out << "    m_" << var->cIdent() << "_ptr = new " << var->getType()->cIdent() << ";\n";
+        if (var->existPair("default")) {
+          out << "    (*m_" << var->cIdent() << "_ptr) = " << var->lookupPair("default") << ";\n";
+        }
+        out << "  }\n";
+
+      } else {
+        // Normal Object
+        string template_hack = "";
+        if (var->existPair("template_hack")) {
+          template_hack = var->lookupPair("template_hack");
+        }
+//added by SS
+        string str = "";
+        int found = 0;
+        if (var->existPair("factory")) {
+          out << "  m_" << var->cIdent() << "_ptr = " << var->lookupPair("factory");
+        } else {
+          if ( var->cIdent().find("mandatoryQueue") == string::npos) {
+
+            str = "  m_" + var->cIdent() + "_ptr = new " + var->getType()->cIdent() + template_hack;
+            out << str;
+            if (str.find("TBETable")!=string::npos){
+              found = 1;
+            }
+
+            if (!var->getType()->existPair("non_obj") && (!var->getType()->isEnumeration())) {
+              str = "";
+              if (var->existPair("constructor_hack")) {
+                string constructor_hack = var->lookupPair("constructor_hack");
+                str = "(" + constructor_hack + ")";
+              } else {
+                str = "()";
+              }
+              if (found)
+                str = "(m_number_of_TBEs)";
+              out << str;
+            }
+          }
+        }
+
+        out << ";\n";
+        out << "  assert(m_" << var->cIdent() << "_ptr != NULL);" << endl;
+
+        if (var->existPair("default")) {
+          out << "  (*m_" << var->cIdent() << "_ptr) = " << var->lookupPair("default")
+              << "; // Object default" << endl;
+        } else if (var->getType()->hasDefault()) {
+            out << "  (*m_" << var->cIdent() << "_ptr) = " << var->getType()->getDefault()
+                << "; // Type " << var->getType()->getIdent() << " default" << endl;
+        }
+
+        // Set ordering
+        if (var->existPair("ordered") && !var->existPair("trigger_queue")) {
+          // A buffer
+          string ordered =  var->lookupPair("ordered");
+          out << "  m_" << var->cIdent() << "_ptr->setOrdering(" << ordered << ");\n";
+        }
+
+        // Set randomization
+        if (var->existPair("random")) {
+          // A buffer
+          string value =  var->lookupPair("random");
+          out << "  m_" << var->cIdent() << "_ptr->setRandomization(" << value << ");\n";
+        }
+
+        // Set Priority
+        if (var->getType()->isBuffer() && var->existPair("rank") && !var->existPair("trigger_queue")) {
+          string rank =  var->lookupPair("rank");
+          out << "  m_" << var->cIdent() << "_ptr->setPriority(" << rank << ");\n";
+        }
+      }
+    } else {
+      // Network port object
+      string network = var->lookupPair("network");
+      string ordered =  var->lookupPair("ordered");
+      string vnet =  var->lookupPair("virtual_network");
+
+      assert (var->getMachine() != NULL);
+      out << "  m_" << var->cIdent() << "_ptr = m_net_ptr->get"
+          << network << "NetQueue(m_version+MachineType_base_number(string_to_MachineType(\""
+          << var->getMachine()->getIdent() << "\")), "
+          << ordered << ", " << vnet << ");\n";
+      out << "  assert(m_" << var->cIdent() << "_ptr != NULL);" << endl;
+
+      // Set ordering
+      if (var->existPair("ordered")) {
+        // A buffer
+        string ordered =  var->lookupPair("ordered");
+        out << "  m_" << var->cIdent() << "_ptr->setOrdering(" << ordered << ");\n";
+      }
+
+      // Set randomization
+      if (var->existPair("random")) {
+        // A buffer
+        string value =  var->lookupPair("random");
+        out << "  m_" << var->cIdent() << "_ptr->setRandomization(" << value << ");\n";
+      }
+
+      // Set Priority
+      if (var->existPair("rank")) {
+        string rank =  var->lookupPair("rank");
+        out << "  m_" << var->cIdent() << "_ptr->setPriority(" << rank << ");\n";
+      }
+
+      // Set buffer size
+      if (var->getType()->isBuffer()) {
+        out << "  if (m_buffer_size > 0) {\n";
+        out << "    m_" << var->cIdent() << "_ptr->setSize(m_buffer_size);\n";
+        out << "  }\n";
+      }
+
+      // set description (may be overriden later by port def)
+      out << "  m_" << var->cIdent()
+          << "_ptr->setDescription(\"[Version \" + int_to_string(m_version) + \", "
+          << component << ", name=" << var->cIdent() << "]\");" << endl;
+      out << endl;
+    }
+  }
 
   // Set the queue consumers
+  out << endl;
   for(int i=0; i < m_in_ports.size(); i++) {
     const Var* port = m_in_ports[i];
     out << "  " << port->getCode() << ".setConsumer(this);" << endl;
   }
 
-  out << endl;
   // Set the queue descriptions
+  out << endl;
   for(int i=0; i < m_in_ports.size(); i++) {
     const Var* port = m_in_ports[i];
     out << "  " << port->getCode()
-        << ".setDescription(\"[Chip \" + int_to_string(m_chip_ptr->getID()) + \" \" + int_to_string(m_version) + \", "
+        << ".setDescription(\"[Version \" + int_to_string(m_version) + \", "
         << component << ", " << port->toString() << "]\");" << endl;
   }
 
     }
   }
 
+  //added by SS to initialize recycle_latency of message buffers
+  std::vector<std::string>::const_iterator it;
+  for ( it=m_message_buffer_names.begin() ; it != m_message_buffer_names.end(); it++ ){
+    out << "  "<< (*it).c_str() << "->setRecycleLatency(m_recycle_latency);" << endl;
+  }
+
+
+  out << "}" << endl;
+
+  out << endl;
+
+  bool has_mandatory_q = false;
+  for(int i=0; i < m_in_ports.size(); i++) {
+    if (m_in_ports[i]->getCode().find("mandatoryQueue_ptr")!= string::npos)
+      has_mandatory_q = true;
+  }
+
+  out << "int " << component << "_Controller::getNumControllers() {" << endl;
+  out << "  return m_num_controllers;" << endl;
   out << "}" << endl;
 
   out << endl;
 
+  out << "MessageBuffer* " << component << "_Controller::getMandatoryQueue() const {" << endl;
+  if (has_mandatory_q)
+    out << "  return m_" << component << "_mandatoryQueue_ptr;" << endl;
+  else
+    out << "  return NULL;" << endl;
+  out << "}" << endl;
+
+  out << endl;
+
+  out << "const int & "<<component<<"_Controller::getVersion() const{" << endl;
+  out << "  return m_version;" << endl;
+  out << "}";
+
+  out << endl;
+
+  out << "const string "<<component<<"_Controller::toString() const{" << endl;
+  out << "  return \"" << component<< "_Controller\";" << endl;
+  out << "}";
+
+  out << endl;
+
+  out << "const string "<<component<<"_Controller::getName() const{" << endl;
+  out << "  return m_name;" << endl;
+  out << "}";
+
+  out << endl;
+
+  out << "const MachineType "<<component<<"_Controller::getMachineType() const{" << endl;
+  out << "  return MachineType_" << component<< ";" << endl;
+  out << "}";
+
+  out << endl;
+
   out << "void " << component << "_Controller::print(ostream& out) const { out << \"[" << component
-      << "_Controller \" << m_chip_ptr->getID() << \" \" << m_version << \"]\"; }" << endl;
+      << "_Controller \" << m_version << \"]\"; }" << endl;
+
+  out << "void " << component << "_Controller::printConfig(ostream& out) const {" << endl;
+  out << "  out << \"" << component << "_Controller config: \" << m_name << endl;" << endl;
+  out << "  out << \"  version: \" << m_version << endl;" << endl;
+  out << "  for(map< string, string >::const_iterator it = m_cfg.begin(); it != m_cfg.end(); it++) {" << endl;
+  out << "    out << \"  \" << (*it).first << \": \" << (*it).second << endl;" << endl;
+  out << "  }" << endl;
+  out << "}" << endl;
 
   out << endl;
   out << "// Actions" << endl;
           << action.getIdent() << "(const Address& addr)" << endl;
       out << "{" << endl;
       out << "  DEBUG_MSG(GENERATED_COMP, HighPrio,\"executing\");" << endl;
-      out << action.lookupPair("c_code");
+//added by SS
+//instead of rubyconfig:: --> it should point to m_latency...
+//so I should change the string output of this lookup
+
+      string c_code_string = action.lookupPair("c_code");
+
+      size_t found = c_code_string.find("RubyConfig::get");
+
+      if (found!=string::npos){ //found --> replace it with local access
+        //if it is related to latency --> replace it
+        std::vector<std::string*>::const_iterator it;
+        for(it=m_latency_vector.begin();it!=m_latency_vector.end();it++){
+          string str = (*it)->c_str();
+          str.erase(0,8);
+          size_t fd = c_code_string.find(str, found);
+          if (fd!=string::npos && (fd == found+15)){
+            string rstr = "m_";
+            rstr += (*it)->c_str();
+            c_code_string.replace(found,15+str.size()+2,rstr);
+            break;
+          }
+        }
+      }
+
+      out << c_code_string;
+
       out << "}" << endl;
     }
     out << endl;
   }
 }
 
-void StateMachine::printCWakeup(ostream& out, string component) const
+void StateMachine::printCWakeup(ostream& out, string component)
 {
   out << "// Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< endl;
   out << "// " << getIdent() << ": " << getShorthand() << endl;
   out << "#include \"mem/protocol/" << component << "_Event.hh\"" << endl;
   out << "#include \"mem/protocol/Types.hh\"" << endl;
   out << "#include \"mem/ruby/system/System.hh\"" << endl;
-  out << "#include \"mem/protocol/Chip.hh\"" << endl;
   out << endl;
   out << "void " << component << "_Controller::wakeup()" << endl;
   out << "{" << endl;
   out << "int counter = 0;" << endl;
   out << "  while (true) {" << endl;
   out << "    // Some cases will put us into an infinite loop without this limit" << endl;
-  out << "    assert(counter <= RubyConfig::" << getIdent() << "TransitionsPerCycle());" << endl;
-  out << "    if (counter == RubyConfig::" << getIdent() << "TransitionsPerCycle()) {" << endl;
+  out << "    assert(counter <= m_transitions_per_cycle);" << endl;
+  out << "    if (counter == m_transitions_per_cycle) {" << endl;
   out << "      g_system_ptr->getProfiler()->controllerBusy(m_machineID); // Count how often we're fully utilized" << endl;
   out << "      g_eventQueue_ptr->scheduleEvent(this, 1); // Wakeup in another cycle and try again" << endl;
   out << "      break;" << endl;
   out << endl;
 }
 
-void StateMachine::printCSwitch(ostream& out, string component) const
+void StateMachine::printCSwitch(ostream& out, string component)
 {
   out << "// Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< endl;
   out << "// " << getIdent() << ": " << getShorthand() << endl;
   out << "#include \"mem/protocol/" << component << "_Event.hh\"" << endl;
   out << "#include \"mem/protocol/Types.hh\"" << endl;
   out << "#include \"mem/ruby/system/System.hh\"" << endl;
-  out << "#include \"mem/protocol/Chip.hh\"" << endl;
   out << endl;
   out << "#define HASH_FUN(state, event)  ((int(state)*" << component
       << "_Event_NUM)+int(event))" << endl;
   out << "    DEBUG_EXPR(GENERATED_COMP, MedPrio, next_state);" << endl;
   out << "    DEBUG_NEWLINE(GENERATED_COMP, MedPrio);" << endl;
   out << "    s_profiler.countTransition(state, event);" << endl;
-  out << "    if (PROTOCOL_DEBUG_TRACE) {" << endl
+  out << "    if (Debug::getProtocolTrace()) {" << endl
       << "      g_system_ptr->getProfiler()->profileTransition(\"" << component
-      << "\", m_chip_ptr->getID(), m_version, addr, " << endl
+      << "\", m_version, addr, " << endl
       << "        " << component << "_State_to_string(state), " << endl
       << "        " << component << "_Event_to_string(event), " << endl
       << "        " << component << "_State_to_string(next_state), GET_TRANSITION_COMMENT());" << endl
   out << "    " << component << "_setState(addr, next_state);" << endl;
   out << "    " << endl;
   out << "  } else if (result == TransitionResult_ResourceStall) {" << endl;
-  out << "    if (PROTOCOL_DEBUG_TRACE) {" << endl
+  out << "    if (Debug::getProtocolTrace()) {" << endl
       << "      g_system_ptr->getProfiler()->profileTransition(\"" << component
-      << "\", m_chip_ptr->getID(), m_version, addr, " << endl
+      << "\", m_version, addr, " << endl
       << "        " << component << "_State_to_string(state), " << endl
       << "        " << component << "_Event_to_string(event), " << endl
       << "        " << component << "_State_to_string(next_state), " << endl
   out << "  } else if (result == TransitionResult_ProtocolStall) {" << endl;
   out << "    DEBUG_MSG(GENERATED_COMP,HighPrio,\"stalling\");" << endl
       << "    DEBUG_NEWLINE(GENERATED_COMP, MedPrio);" << endl;
-  out << "    if (PROTOCOL_DEBUG_TRACE) {" << endl
+  out << "    if (Debug::getProtocolTrace()) {" << endl
       << "      g_system_ptr->getProfiler()->profileTransition(\"" << component
-      << "\", m_chip_ptr->getID(), m_version, addr, " << endl
+      << "\", m_version, addr, " << endl
       << "        " << component << "_State_to_string(state), " << endl
       << "        " << component << "_Event_to_string(event), " << endl
       << "        " << component << "_State_to_string(next_state), " << endl
   }
 
   out << "  default:" << endl;
-  out << "    WARN_EXPR(m_id);" << endl;
   out << "    WARN_EXPR(m_version);" << endl;
   out << "    WARN_EXPR(g_eventQueue_ptr->getTime());" << endl;
   out << "    WARN_EXPR(addr);" << endl;
   out << "}" << endl;
 }
 
-void StateMachine::printProfilerH(ostream& out, string component) const
+void StateMachine::printProfilerH(ostream& out, string component)
 {
   out << "// Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< endl;
   out << "// " << getIdent() << ": " << getShorthand() << endl;
   out << "#endif // " << component << "_PROFILER_H" << endl;
 }
 
-void StateMachine::printProfilerC(ostream& out, string component) const
+void StateMachine::printProfilerC(ostream& out, string component)
 {
   out << "// Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< endl;
   out << "// " << getIdent() << ": " << getShorthand() << endl;
 }
 
 
-void StateMachine::writeHTMLFiles(string path) const
+void StateMachine::writeHTMLFiles(string path)
 {
   string filename;
   string component = getIdent();
   }
 }
 
-void StateMachine::printHTMLTransitions(ostream& out, int active_state) const
+void StateMachine::printHTMLTransitions(ostream& out, int active_state)
 {
   // -- Prolog
   out << "<HTML><BODY link=\"blue\" vlink=\"blue\">" << endl;
 
 #include "mem/gems_common/Vector.hh"
 #include "mem/gems_common/Map.hh"
 #include "mem/slicc/symbols/Symbol.hh"
+#include <list>
+
+using namespace std;
 
 class Transition;
 class Event;
 class StateMachine : public Symbol {
 public:
   // Constructors
-  StateMachine(string ident, const Location& location, const Map<string, string>& pairs);
+  StateMachine(string ident, const Location& location, const Map<string, string>& pairs,  std::vector<std::string*>* latency_vector);
 
   // Destructor
   ~StateMachine();
   void addTransition(Transition* trans_ptr);
   void addInPort(Var* var) { m_in_ports.insertAtBottom(var); }
   void addFunc(Func* func);
+  void addObj(Var* obj) { m_objs.insertAtBottom(obj); }
 
   // Accessors to vectors
   const State& getState(int index) const { return *m_states[index]; }
   const Action& getAction(int index) const { return *m_actions[index]; }
   const Transition& getTransition(int index) const { return *m_transitions[index]; }
   const Transition* getTransPtr(int stateIndex, int eventIndex) const;
+  const Var& getObject(int index) const { return *m_objs[index]; }
 
   // Accessors for size of vectors
   int numStates() const { return m_states.size(); }
   int numEvents() const { return m_events.size(); }
   int numActions() const { return m_actions.size(); }
   int numTransitions() const { return m_transitions.size(); }
+  int numObjects() const { return m_objs.size(); }
 
   void buildTable();  // Needs to be called before accessing the table
 
   // Code generator methods
-  void writeCFiles(string path) const;
-  void writeHTMLFiles(string path) const;
+  void writeCFiles(string path) ;
+  void writeHTMLFiles(string path) ;
 
   void print(ostream& out) const { out << "[StateMachine: " << toString() << "]" << endl; }
 private:
+
+  std::vector<std::string*> m_latency_vector;
+
   // Private Methods
   void checkForDuplicate(const Symbol& sym) const;
 
   //  StateMachine(const StateMachine& obj);
   //  StateMachine& operator=(const StateMachine& obj);
 
-  void printControllerH(ostream& out, string component) const;
-  void printControllerC(ostream& out, string component) const;
-  void printCWakeup(ostream& out, string component) const;
-  void printCSwitch(ostream& out, string component) const;
-  void printProfilerH(ostream& out, string component) const;
-  void printProfilerC(ostream& out, string component) const;
+  void printControllerH(ostream& out, string component) ;
+  void printControllerC(ostream& out, string component) ;
+  void printCWakeup(ostream& out, string component) ;
+  void printCSwitch(ostream& out, string component) ;
+  void printProfilerH(ostream& out, string component) ;
+  void printProfilerC(ostream& out, string component) ;
 
-  void printHTMLTransitions(ostream& out, int active_state) const;
+  void printHTMLTransitions(ostream& out, int active_state) ;
 
   // Data Members (m_ prefix)
   Vector<State*> m_states;
 
   Vector<Var*> m_in_ports;
 
+  Vector<Var*> m_objs;
+
   // Table variables
   bool m_table_built;
   Vector<Vector<Transition*> > m_table;
 
+  //added by SS
+  std::vector<std::string> m_message_buffer_names;
+
 };
 
 // Output operator declaration
 
   void addPair(const string& key, const string& value);
 
   //  virtual string getCode() const = 0;
-  virtual void writeCFiles(string path) const {}
-  virtual void writeHTMLFiles(string path) const {}
+  virtual void writeCFiles(string path)  {}
+  virtual void writeHTMLFiles(string path)  {}
   virtual void print(ostream& out) const { out << "[Symbol: " << getIdent() << "]"; }
 
 private:
 
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+/*
+ * SymbolTable.cc
+ *
+ * Description: See SymbolTable.hh
+ *
+ * $Id$
+ *
+ * */
+
 #include "mem/slicc/symbols/SymbolTable.hh"
 #include "mem/slicc/generator/fileio.hh"
 #include "mem/slicc/generator/html_gen.hh"
 {
   int size = m_sym_vec.size();
   {
-    // Write the mem/protocol/Types.hh include file for the types
+    // Write the Types.hh include file for the types
     ostringstream sstr;
     sstr << "/** Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<< " */" << endl;
     sstr << endl;
     m_sym_vec[i]->writeCFiles(path + '/');
   }
 
-  writeChipFiles(path);
+  writeControllerFactory(path);
 }
 
-void SymbolTable::writeChipFiles(string path) const
+void SymbolTable::writeControllerFactory(string path) const
 {
-  // Create Chip.cc and mem/protocol/Chip.hh
-
-  // FIXME - Note: this method is _really_ ugly.  Most of this
-  // functionality should be pushed into each type of symbol and use
-  // virtual methods to get the right behavior for each type of
-  // symbol.  This is also more flexible, and much cleaner.
-
+  ostringstream sstr;
   int size = m_sym_vec.size();
 
-  // Create Chip.h
-  {
-    ostringstream sstr;
-    sstr << "/** \\file Chip.h " << endl;
-    sstr << "  * Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<<endl;
-    sstr << "  */ " <<endl<<endl;
-
-    sstr << "#ifndef CHIP_H" << endl;
-    sstr << "#define CHIP_H" << endl;
-    sstr << endl;
+  sstr << "/** \\file ControllerFactory.hh " << endl;
+  sstr << "  * Auto generatred C++ code started by " << __FILE__ << ":" << __LINE__ << endl;
+  sstr << "  */" << endl << endl;
 
-    // Includes
-    sstr << "#include \"mem/ruby/common/Global.hh\"" << endl;
-    sstr << "#include \"mem/protocol/Types.hh\"" << endl;
-    sstr << "#include \"mem/ruby/slicc_interface/AbstractChip.hh\"" << endl;
-    sstr << "class Network;" << endl;
-    sstr << endl;
-
-    // Class declarations for all Machines/Controllers
-    for(int i=0; i<size; i++) {
-      StateMachine* machine = dynamic_cast<StateMachine*>(m_sym_vec[i]);
-      if (machine != NULL) {
-        sstr << "class " << machine->getIdent() << "_Controller;" << endl;
-      }
-    }
+  sstr << "#ifndef CONTROLLERFACTORY_H" << endl;
+  sstr << "#define CONTROLLERFACTORY_H" << endl;
+  sstr << endl;
 
-    sstr << "class Chip : public AbstractChip {" << endl;
-    sstr << "public:" << endl;
-    sstr << endl;
-    sstr << "  // Constructors" << endl;
-    sstr << "  Chip(NodeID chip_number, Network* net_ptr);" << endl;
-    sstr << endl;
-    sstr << "  // Destructor" << endl;
-    sstr << "  ~Chip();" << endl;
-    sstr << endl;
-    sstr << "  // Public Methods" << endl;
-    sstr << "  void recordCacheContents(CacheRecorder& tr) const;" << endl;
-    sstr << "  void dumpCaches(ostream& out) const;" << endl;
-    sstr << "  void dumpCacheData(ostream& out) const;" << endl;
-    sstr << "  static void printStats(ostream& out);" << endl;
-    sstr << "  static void clearStats();" << endl;
-    sstr << "  void printConfig(ostream& out);" << endl;
-    sstr << "  void print(ostream& out) const;" << endl;
-
-    // Used by coherence checker
-    sstr << "#ifdef CHECK_COHERENCE" << endl;
-    sstr << "  bool isBlockShared(const Address& addr) const;" << endl;
-    sstr << "  bool isBlockExclusive(const Address& addr) const;" << endl;
-    sstr << "#endif /* CHECK_COHERENCE */" << endl;
+  Vector< string > controller_types;
 
-    sstr << endl;
-    sstr << "private:" << endl;
-    sstr << "  // Private copy constructor and assignment operator" << endl;
-    sstr << "  Chip(const Chip& obj);" << endl;
-    sstr << "  Chip& operator=(const Chip& obj);" << endl;
-    sstr << endl;
-    sstr << "public: // FIXME - these should not be public" << endl;
-    sstr << "  // Data Members (m_ prefix)" << endl;
-    sstr << endl;
-    sstr << "  Chip* m_chip_ptr;" << endl;
-    sstr << endl;
-    sstr << "  // SLICC object variables" << endl;
-    sstr << endl;
+  // includes
+  sstr << "#include <string>" << endl;
+  sstr << "class Network;" << endl;
+  sstr << "class AbstractController;" << endl;
+  sstr << endl;
 
-    // Look at all 'Vars'
-    for(int i=0; i<size; i++) {
-      Var* var = dynamic_cast<Var*>(m_sym_vec[i]);
-      if (var != NULL) {
-        if (var->existPair("chip_object")) {
-          if (var->existPair("no_chip_object")) {
-            // Do nothing
-          } else {
-            string template_hack = "";
-            if (var->existPair("template_hack")) {
-              template_hack = var->lookupPair("template_hack");
-            }
-            if (// var->existPair("network") || var->getType()->existPair("cache") ||
-//                 var->getType()->existPair("tbe") || var->getType()->existPair("newtbe") ||
-//                 var->getType()->existPair("dir") || var->getType()->existPair("persistent") ||
-//                 var->getType()->existPair("filter") || var->getType()->existPair("timer") ||
-//                 var->existPair("trigger_queue")
-                var->existPair("no_vector")
-                ) {
-              sstr << "  " << var->getType()->cIdent() << template_hack << "* m_"
-                   << var->cIdent() << "_ptr;" << endl;
-            } else {
-              // create pointer except those created in AbstractChip
-              if (!(var->existPair("abstract_chip_ptr"))) {
-                sstr << "  Vector < " << var->getType()->cIdent() << template_hack
-                     << "* >  m_" << var->cIdent() << "_vec;" << endl;
-              }
-            }
-          }
-        }
-      }
-    }
+  sstr << "class ControllerFactory {" << endl;
+  sstr << "public:" << endl;
+  sstr << "  static AbstractController* createController(const std::string & controller_type, const std::string & name);" << endl;
+  sstr << "};" << endl;
+  sstr << endl;
 
-    sstr << endl;
-    sstr << "  // SLICC machine/controller variables" << endl;
+  sstr << "#endif // CONTROLLERFACTORY_H" << endl;
+  conditionally_write_file(path + "/ControllerFactory.hh", sstr);
 
-    // Look at all 'Machines'
-    for(int i=0; i<size; i++) {
-      StateMachine* machine = dynamic_cast<StateMachine*>(m_sym_vec[i]);
-      if (machine != NULL) {
-        string ident = machine->getIdent() + "_Controller";
-        sstr << "  Vector < " << ident << "* > m_" << ident << "_vec;\n";
-      }
-    }
+  // ControllerFactory.cc file
 
-    sstr << endl;
+  sstr.str("");
 
-    sstr << "  // machine external SLICC function decls\n";
+  sstr << "/** \\file ControllerFactory.cc " << endl;
+  sstr << "  * Auto generatred C++ code started by " << __FILE__ << ":" << __LINE__ << endl;
+  sstr << "  */" << endl << endl;
 
-    // Look at all 'Functions'
-    for(int i=0; i<size; i++) {
-      Func* func = dynamic_cast<Func*>(m_sym_vec[i]);
-      if (func != NULL) {
-        string proto;
-        func->funcPrototype(proto);
-        if (proto != "") {
-          sstr << "  " << proto;
-        }
-      }
+  // includes
+  sstr << "#include \"mem/protocol/ControllerFactory.hh\"" << endl;
+  sstr << "#include \"mem/ruby/slicc_interface/AbstractController.hh\"" << endl;
+  sstr << "#include \"mem/protocol/MachineType.hh\"" << endl;
+  for(int i=0; i<size; i++) {
+    StateMachine* machine = dynamic_cast<StateMachine*>(m_sym_vec[i]);
+    if (machine != NULL) {
+      sstr << "#include \"mem/protocol/" << machine->getIdent() << "_Controller.hh\"" << endl;
+      controller_types.insertAtBottom(machine->getIdent());
     }
-
-    sstr << "};" << endl;
-    sstr << endl;
-    sstr << "#endif // CHIP_H" << endl;
-
-    conditionally_write_file(path + "/Chip.hh", sstr);
   }
-  // Create Chip.cc
-  {
-    ostringstream sstr;
-    sstr << "// Auto generated C++ code started by "<<__FILE__<<":"<<__LINE__<<endl<<endl;
-    sstr << "#include \"mem/protocol/Chip.hh\"" << endl;
-    sstr << "#include \"mem/ruby/network/Network.hh\"" << endl;
-    sstr << "#include \"mem/ruby/recorder/CacheRecorder.hh\"" << endl;
-    sstr << "" << endl;
-
-    sstr << "// Includes for controllers" << endl;
-    for(int i=0; i<size; i++) {
-      StateMachine* machine = dynamic_cast<StateMachine*>(m_sym_vec[i]);
-      if (machine != NULL) {
-        sstr << "#include \"mem/protocol/" << machine->getIdent() << "_Controller.hh\"" << endl;
-      }
-    }
-
-    sstr << "" << endl;
-    sstr << "Chip::Chip(NodeID id, Network* net_ptr):AbstractChip(id, net_ptr)" << endl;
-    sstr << "{" << endl;
-    sstr << "  m_chip_ptr = this;" << endl;
-
-    // FIXME - WHY IS THIS LOOP HERE?
-    // WE SEEM TO BE CREATING A SEQUENCER HERE THEN OVERWRITTING THAT INSTANITATION
-    // IN THE NEXT LOOP
-//     // find sequencer's type
-//     for(int i=0; i<size; i++) {
-//       Var* var = dynamic_cast<Var*>(m_sym_vec[i]);
-//       if(var && var->cIdent() == "sequencer")
-//         sstr << "  m_sequencer_ptr = new " << var->getType()->cIdent() << "(this);\n";
-//     }
-
-    // Look at all 'Vars'
-    for(int i=0; i<size; i++) {
-      Var* var = dynamic_cast<Var*>(m_sym_vec[i]);
-      if (var != NULL && var->existPair("chip_object") && !var->existPair("no_chip_object")) {
-
-        sstr << "  // " << var->cIdent() << endl;
-        if (!var->existPair("network")) {
-          // Not a network port object
-          if (var->getType()->existPair("primitive")) {
-            // Normal non-object
-            // sstr << "  m_" << var->cIdent() << "_ptr = new " << var->getType()->cIdent() << ";\n";
-
-              sstr << "  m_" << var->cIdent();
-              sstr << "_vec.setSize(RubyConfig::numberOf";
-              sstr << var->getMachine()->getIdent() << "PerChip(m_id));" << endl;
-              sstr << "  for (int i = 0; i < RubyConfig::numberOf" << var->getMachine()->getIdent()
-                   << "PerChip(m_id); i++)  {" << endl;
-              sstr << "    m_" << var->cIdent() << "_vec[i] = new " << var->getType()->cIdent() << ";\n";
-              if (var->existPair("default")) {
-                sstr << "    *(m_" << var->cIdent() << "_vec[i]) = " << var->lookupPair("default") << ";\n";
-              }
-              sstr << "  }\n";
-
-          } else {
-
-            // Normal Object
-            string template_hack = "";
-            if (var->existPair("template_hack")) {
-              template_hack = var->lookupPair("template_hack");
-            }
-            if (// var->getType()->existPair("cache") || var->getType()->existPair("tbe") ||
-//                 var->getType()->existPair("newtbe") || var->getType()->existPair("timer") ||
-//                 var->getType()->existPair("dir") || var->getType()->existPair("persistent") ||
-//                 var->getType()->existPair("filter") || var->existPair("trigger_queue")
-                var->existPair("no_vector")) {
-              sstr << "  m_" << var->cIdent() << "_ptr = new " << var->getType()->cIdent() << template_hack;
-              if (!var->getType()->existPair("non_obj") && (!var->getType()->isEnumeration())) {
-                if (var->existPair("constructor_hack")) {
-                  string constructor_hack = var->lookupPair("constructor_hack");
-                  sstr << "(this, " << constructor_hack << ")";
-                } else {
-                  sstr << "(this)";
-                }
-              }
-              sstr << ";\n";
-              sstr << "  assert(m_" << var->cIdent() << "_ptr != NULL);" << endl;
-
-              if (var->existPair("default")) {
-                sstr << "  (*m_" << var->cIdent() << "_ptr) = " << var->lookupPair("default")
-                     << "; // Object default" << endl;
-              } else if (var->getType()->hasDefault()) {
-                sstr << "  (*m_" << var->cIdent() << "_ptr) = " << var->getType()->getDefault()
-                     << "; // Type " << var->getType()->getIdent() << " default" << endl;
-              }
-
-              // Set ordering
-              if (var->existPair("ordered") && !var->existPair("trigger_queue")) {
-                // A buffer
-                string ordered =  var->lookupPair("ordered");
-                sstr << "  m_" << var->cIdent() << "_ptr->setOrdering(" << ordered << ");\n";
-              }
-
-              // Set randomization
-              if (var->existPair("random")) {
-                // A buffer
-                string value =  var->lookupPair("random");
-                sstr << "  m_" << var->cIdent() << "_ptr->setRandomization(" << value << ");\n";
-              }
-
-              // Set Priority
-              if (var->getType()->isBuffer() && var->existPair("rank") && !var->existPair("trigger_queue")) {
-                string rank =  var->lookupPair("rank");
-                sstr << "  m_" << var->cIdent() << "_ptr->setPriority(" << rank << ");\n";
-              }
-            } else if ((var->getType()->existPair("mover")) && (var->getMachine()->getIdent() == "L2Cache")) {
-              // FIXME - dnuca mover is a special case
-              sstr << "  m_" << var->cIdent() << "_ptr = NULL;" << endl;
-              sstr << "  if (RubyConfig::isL2CacheDNUCAMoverChip(m_id))  {" << endl;
-              sstr << "    m_" << var->cIdent() << "_ptr = new " << var->getType()->cIdent() << template_hack;
-              if (!var->getType()->existPair("non_obj") && (!var->getType()->isEnumeration())) {
-                if (var->existPair("constructor_hack")) {
-                  string constructor_hack = var->lookupPair("constructor_hack");
-                  sstr << "(this, " << constructor_hack << ")";
-                } else {
-                  sstr << "(this)";
-                }
-              }
-              sstr << ";\n";
-              sstr << "  }\n";
-            } else if (var->getType()->existPair("mover") && ((var->getMachine()->getIdent() == "L1Cache") || (var->getMachine()->getIdent() == "Collector"))) {
-              sstr << "  m_" << var->cIdent() << "_ptr = NULL;" << endl;
-              sstr << "  \n";
-            } else {
-              sstr << "  m_" << var->cIdent();
-              sstr << "_vec.setSize(RubyConfig::numberOf";
-              sstr << var->getMachine()->getIdent() << "PerChip(m_id));" << endl;
-              sstr << "  for (int i = 0; i < RubyConfig::numberOf" << var->getMachine()->getIdent()
-                   << "PerChip(m_id); i++)  {" << endl;
-
-
-              ostringstream tail;
-              tail << template_hack;
-              if (!var->getType()->existPair("non_obj") && (!var->getType()->isEnumeration())) {
-                if (var->existPair("constructor_hack")) {
-                  string constructor_hack = var->lookupPair("constructor_hack");
-                  tail << "(this, " << constructor_hack << ")";
-                } else {
-                  tail << "(this)";
-                }
-              }
-              tail << ";\n";
-
-
-              if(var->existPair("child_selector")){
-                string child_selector = var->lookupPair("child_selector");
-                string child_types = var->lookupPair("child_types");
-                string::iterator it = child_types.begin();
-
-                unsigned num_types = 0;
-                for(unsigned t=0;t<child_types.size();t++){
-                  if(child_types.at(t) == '<'){
-                    num_types++;
-                  }
-                }
-
-                string* types = new string[num_types];
-                string* ids = new string[num_types];
-                int type_idx = 0;
-                bool id_done = false;
-                for(unsigned t=0;t<child_types.size();t++){
-                  if(child_types[t] == '<'){
-                    id_done = false;
-                    unsigned r;
-                    for(r=t+1;child_types.at(r)!='>';r++){
-                      if(r == child_types.size()){
-                        cerr << "Parse error in child_types" << endl;
-                        exit(EXIT_FAILURE);
-                      }
-                      if(child_types.at(r) == ' ') continue;  //ignore whitespace
-                      if(child_types.at(r) == ',') {id_done = true;continue;}
-                      if(id_done == true)
-                        types[type_idx].push_back(child_types.at(r));
-                      else
-                        ids[type_idx].push_back(child_types.at(r));
-                    }
-                    type_idx++;
-                    t = r;
-                  }
-                }
-
-                for(unsigned t=0;t<num_types;t++){
-                  if(t==0)
-                    sstr << "    if(strcmp(" << child_selector << ", \"" << ids[t] << "\") == 0)" << endl;
-                  else
-                    sstr << "    else if(strcmp(" << child_selector << ", \"" << ids[t] << "\") == 0)" << endl;
-                  sstr << "      m_" << var->cIdent() << "_vec[i] = new " << types[t] << tail.str() << endl;
-                }
-              }
-              else {
-                sstr << "    m_" << var->cIdent() << "_vec[i] = new " << var->getType()->cIdent() << tail.str() << endl;
-              }
-
-              sstr << "    assert(m_" << var->cIdent() << "_vec[i] != NULL);" << endl;
-              if (var->existPair("ordered")) {
-                string ordered =  var->lookupPair("ordered");
-                sstr << "    m_" << var->cIdent() << "_vec[i]->setOrdering(" << ordered << ");\n";
-              }
-              if (var->existPair("rank")) {
-                string rank =  var->lookupPair("rank");
-                sstr << "    m_" << var->cIdent() << "_vec[i]->setPriority(" << rank << ");\n";
-              }
-
-              // Set buffer size
-              if (var->getType()->isBuffer() && !var->existPair("infinite")) {
-                sstr << "    if (FINITE_BUFFERING) {\n";
-                sstr << "      m_" << var->cIdent() << "_vec[i]->setSize(PROCESSOR_BUFFER_SIZE);\n";
-                sstr << "    }\n";
-              }
-
-              sstr << "  }\n";
-            }
-          }
-
-          sstr << endl;
-
-        } else {
-          // Network port object
-          string network = var->lookupPair("network");
-          string ordered =  var->lookupPair("ordered");
-          string vnet =  var->lookupPair("virtual_network");
-
-          if (var->getMachine() != NULL) {
-            sstr << "  m_" << var->cIdent() << "_vec.setSize(RubyConfig::numberOf"
-                 << var->getMachine()->getIdent() << "PerChip(m_id));" << endl;
-            sstr << "  for (int i = 0; i < RubyConfig::numberOf" << var->getMachine()->getIdent()
-                 << "PerChip(m_id); i++)  {" << endl;
-            sstr << "    m_" << var->cIdent() << "_vec[i] = m_net_ptr->get"
-                 << network << "NetQueue(i+m_id*RubyConfig::numberOf" <<var->getMachine()->getIdent()
-                 << "PerChip()+MachineType_base_number(string_to_MachineType(\""
-                 << var->getMachine()->getIdent() << "\")), "
-                 << ordered << ", " << vnet << ");\n";
-            sstr << "    assert(m_" << var->cIdent() << "_vec[i] != NULL);" << endl;
-          } else { // old protocol
-            sstr << "  m_" << var->cIdent() << "_vec.setSize(1);" << endl;
-            sstr << "  for (int i = 0; i < 1; i++)  {" << endl;
-            sstr << "    m_" << var->cIdent() << "_vec[i] = m_net_ptr->get"
-                 << network << "NetQueue(m_id, "
-                 << ordered << ", " << vnet << ");\n";
-            sstr << "    assert(m_" << var->cIdent() << "_vec[i] != NULL);" << endl;
-          }
-
-          // Set ordering
-          if (var->existPair("ordered")) {
-            // A buffer
-            string ordered =  var->lookupPair("ordered");
-            sstr << "    m_" << var->cIdent() << "_vec[i]->setOrdering(" << ordered << ");\n";
-          }
-
-          // Set randomization
-          if (var->existPair("random")) {
-            // A buffer
-            string value =  var->lookupPair("random");
-            sstr << "    m_" << var->cIdent() << "_vec[i]->setRandomization(" << value << ");\n";
-          }
-
-          // Set Priority
-          if (var->existPair("rank")) {
-            string rank =  var->lookupPair("rank");
-            sstr << "    m_" << var->cIdent() << "_vec[i]->setPriority(" << rank << ");\n";
-          }
-
-          // Set buffer size
-          if (var->getType()->isBuffer()) {
-            sstr << "    if (FINITE_BUFFERING) {\n";
-            sstr << "      m_" << var->cIdent() << "_vec[i]->setSize(PROTOCOL_BUFFER_SIZE);\n";
-            sstr << "    }\n";
-          }
-
-          sstr << "  }\n";
-        }
-      }
-    }
-    // Look at all 'Machines'
-    for(int i=0; i<size; i++) {
-      StateMachine* machine = dynamic_cast<StateMachine*>(m_sym_vec[i]);
-      if (machine != NULL) {
-        string ident = machine->getIdent() + "_Controller";
-        sstr << "  m_" << ident << "_vec.setSize(RubyConfig::numberOf" << machine->getIdent()
-             << "PerChip(m_id));" << endl;
-        sstr << "  for (int i = 0; i < RubyConfig::numberOf" << machine->getIdent()
-             << "PerChip(m_id); i++)  {" << endl;
-        sstr << "    m_" << ident << "_vec[i] = new " << ident << "(this, i);\n";
-        sstr << "    assert(m_" << ident << "_vec[i] != NULL);" << endl;
-        sstr << "  }\n";
-        sstr << endl;
-      }
-    }
-
-    sstr << "}" << endl;
-    sstr << endl;
-    sstr << "Chip::~Chip()\n";
-    sstr << "{\n";
-
-//     // FIXME: sequencer shouldn' be manually handled
-//     sstr << "  delete m_sequencer_ptr;" << endl;
-
-    // Look at all 'Vars'
-    for(int i=0; i<size; i++) {
-      Var* var = dynamic_cast<Var*>(m_sym_vec[i]);
-      if (var != NULL) {
-        if (var->existPair("chip_object")) {
-          if (var->existPair("no_chip_object")) {
-            // Do nothing
-          } else {
-            string template_hack = "";
-            if (var->existPair("template_hack")) {
-              template_hack = var->lookupPair("template_hack");
-            }
-            if (// var->getType()->existPair("cache") || var->getType()->existPair("tbe") ||
-//                 var->getType()->existPair("newtbe") || var->getType()->existPair("timer") ||
-//                 var->getType()->existPair("dir") || var->getType()->existPair("persistent") ||
-//                 var->getType()->existPair("filter") || var->existPair("trigger_queue")
-                var->existPair("no_vector")) {
-              sstr << "  delete m_" << var->cIdent() << "_ptr;\n";
-            } else if ((var->getType()->existPair("mover")) && (var->getMachine()->getIdent() == "L2Cache")) {
-              sstr << "  if (RubyConfig::isL2CacheDNUCAMoverChip(m_id))  {" << endl;
-              sstr << "    delete m_" << var->cIdent() << "_ptr;\n";
-              sstr << "  }\n";
-            } else if (var->getType()->existPair("mover") && ((var->getMachine()->getIdent() == "L1Cache") || (var->getMachine()->getIdent() == "Collector"))) {
-              sstr << "  m_" << var->cIdent() << "_ptr = NULL;" << endl;
-            } else if (!var->existPair("network")) {
-              // Normal Object
-              sstr << "  for (int i = 0; i < RubyConfig::numberOf" << var->getMachine()->getIdent()
-                   << "PerChip(m_id); i++)  {" << endl;
-              sstr << "    delete m_" << var->cIdent() << "_vec[i];\n";
-              sstr << "  }\n";
-            }
-          }
-        }
-      }
-    }
-
-    // Look at all 'Machines'
-    for(int i=0; i<size; i++) {
-      StateMachine* machine = dynamic_cast<StateMachine*>(m_sym_vec[i]);
-      if (machine != NULL) {
-        string ident = machine->getIdent() + "_Controller";
-        sstr << "  for (int i = 0; i < RubyConfig::numberOf" << machine->getIdent()
-             << "PerChip(m_id); i++)  {" << endl;
-        sstr << "    delete m_" << ident << "_vec[i];\n";
-        sstr << "  }\n";
-      }
-    }
-    sstr << "}\n";
-
-    sstr << "\n";
-    sstr << "void Chip::clearStats()\n";
-    sstr << "{\n";
-
-
-    // Look at all 'Machines'
-    for(int i=0; i<size; i++) {
-      StateMachine* machine = dynamic_cast<StateMachine*>(m_sym_vec[i]);
-      if (machine != NULL) {
-        string ident = machine->getIdent() + "_Controller";
-        sstr << "  " << ident << "::clearStats();\n";
-      }
-    }
-
-    sstr << "}\n";
-
-    sstr << "\n";
-    sstr << "void Chip::printStats(ostream& out)\n";
-    sstr << "{\n";
-    sstr << "  out << endl;\n";
-    sstr << "  out << \"Chip Stats\" << endl;\n";
-    sstr << "  out << \"----------\" << endl << endl;\n";
-
-    // Look at all 'Machines'
-    for(int i=0; i<size; i++) {
-      StateMachine* machine = dynamic_cast<StateMachine*>(m_sym_vec[i]);
-      if (machine != NULL) {
-        string ident = machine->getIdent() + "_Controller";
-        sstr << "  " << ident << "::dumpStats(out);\n";
-      }
-    }
-
-    sstr << "}" << endl;
-    sstr << endl;
-    sstr << "void Chip::printConfig(ostream& out)\n";
-    sstr << "{\n";
-    sstr << "  out << \"Chip Config\" << endl;\n";
-    sstr << "  out << \"-----------\" << endl;\n";
-    sstr << "  out << \"Total_Chips: \" << RubyConfig::numberOfChips() << endl;\n";
-
-    // Look at all 'Vars'
-    for(int i=0; i<size; i++) {
-      Var* var = dynamic_cast<Var*>(m_sym_vec[i]);
-      if (var != NULL) {
-        if (var->existPair("chip_object")) {
-          if (var->existPair("no_chip_object")) {
-            // Do nothing
-          } else {
-            string template_hack = "";
-            if (var->existPair("template_hack")) {
-              template_hack = var->lookupPair("template_hack");
-            }
-
-            if (!var->existPair("network") && (!var->getType()->existPair("primitive"))) {
-              // Normal Object
-              if (!var->getType()->existPair("non_obj") && (!var->getType()->isEnumeration())) {
-                if (var->existPair("no_vector")) {
-                  sstr << "  m_" << var->cIdent() << "_ptr->printConfig(out);\n";
-                } else {
-                  sstr << "  out << \"\\n" << var->cIdent() << " numberPerChip: \" << RubyConfig::numberOf" << var->getMachine()->getIdent()
-                       << "PerChip() << endl;\n";
-                  sstr << "  m_" << var->cIdent() << "_vec[0]->printConfig(out);\n";
-//                   sstr << "  for (int i = 0; i < RubyConfig::numberOf" << var->getMachine()->getIdent()
-//                        << "PerChip(m_id); i++)  {" << endl;
-//                   sstr << "    m_" << var->cIdent() << "_vec[i]->printConfig(out);\n";
-//                   sstr << "  }\n";
-                }
-              }
-            }
-          }
-        }
-      }
-    }
-
-    sstr << "  out << endl;\n";
-    sstr << "}" << endl;
-
-    sstr << endl;
-    sstr << "void Chip::print(ostream& out) const\n";
-    sstr << "{\n";
-    sstr << "  out << \"Ruby Chip\" << endl;\n";
-    sstr << "}" << endl;
-
-    sstr << "#ifdef CHECK_COHERENCE" << endl;
-    sstr << endl;
-    sstr << "bool Chip::isBlockShared(const Address& addr) const" << endl;
-    sstr << "{" << endl;
-
-    // Look at all 'Machines'
-    for(int i=0; i<size; i++) {
-      StateMachine* machine = dynamic_cast<StateMachine*>(m_sym_vec[i]);
-      if (machine != NULL) {
-        string ident = machine->getIdent() + "_Controller";
-        sstr << "  for (int i = 0; i < RubyConfig::numberOf" << machine->getIdent()
-             << "PerChip(m_id); i++)  {" << endl;
-        sstr << "    if (m_" << ident << "_vec[i]->" << machine->getIdent() << "_isBlockShared(addr)) {\n";
-        sstr << "      return true; \n";
-        sstr << "    }\n";
-        sstr << "  }\n";
-      }
-    }
-    sstr << "  return false;" << endl;
-    sstr << "}" << endl;
-    sstr << endl;
-
-    sstr << endl;
-    sstr << "bool Chip::isBlockExclusive(const Address& addr) const" << endl;
-    sstr << "{" << endl;
-
-    // Look at all 'Machines'
-    for(int i=0; i<size; i++) {
-      StateMachine* machine = dynamic_cast<StateMachine*>(m_sym_vec[i]);
-      if (machine != NULL) {
-        string ident = machine->getIdent() + "_Controller";
-        sstr << "  for (int i = 0; i < RubyConfig::numberOf" << machine->getIdent()
-             << "PerChip(m_id); i++)  {" << endl;
-        sstr << "    if (m_" << ident << "_vec[i]->" << machine->getIdent() << "_isBlockExclusive(addr)) {\n";
-        sstr << "      return true; \n";
-        sstr << "    }\n";
-        sstr << "  }\n";
-      }
-    }
-
-    sstr << "  return false;" << endl;
-    sstr << "}" << endl;
-    sstr << endl;
-
-    sstr << "#endif /* CHECK_COHERENCE */ " << endl;
-
-
-    sstr << endl;
-    sstr << "void Chip::dumpCaches(ostream& out) const" << endl;
-    sstr << "{" << endl;
-
-    // Look at all 'Vars'
-    for(int i=0; i<size; i++) {
-      Var* var = dynamic_cast<Var*>(m_sym_vec[i]);
-      if (var != NULL) {
-        if (var->getType()->existPair("cache")){  // caches are partitioned one per controller instaniation
-          sstr << "  for (int i = 0; i < RubyConfig::numberOf" << var->getMachine()->getIdent()
-               << "PerChip(m_id); i++)  {" << endl;
-          sstr << "    m_" << var->cIdent() << "_vec[i]->print(out);\n";
-          sstr << "  }\n";
-        }
-      }
-    }
-    sstr << "}" << endl;
-    sstr << endl;
-
-    // Function to dump cache tag and data information
-    sstr << "void Chip::dumpCacheData(ostream& out) const" << endl;
-    sstr << "{" << endl;
-
-    // Look at all 'Vars'
-    for(int i=0; i<size; i++) {
-      Var* var = dynamic_cast<Var*>(m_sym_vec[i]);
-      if (var != NULL) {
-        if (var->getType()->existPair("cache")){  // caches are partitioned one per controller instaniation
-          sstr << "  for (int i = 0; i < RubyConfig::numberOf" << var->getMachine()->getIdent()
-               << "PerChip(m_id); i++)  {" << endl;
-          sstr << "    m_" << var->cIdent() << "_vec[i]->printData(out);\n";
-          sstr << "  }\n";
-        }
-      }
-    }
-    sstr << "}" << endl;
-    sstr << endl;
-
-    sstr << "void Chip::recordCacheContents(CacheRecorder& tr) const" << endl;
-    sstr << "{" << endl;
-
-    // Look at all 'Vars'
-    for(int i=0; i<size; i++) {
-      Var* var = dynamic_cast<Var*>(m_sym_vec[i]);
-      if (var != NULL) {
-        if (var->getType()->existPair("cache")){  // caches are partitioned one per controller instaniation
-          sstr << "  for (int i = 0; i < RubyConfig::numberOf" << var->getMachine()->getIdent()
-               << "PerChip(m_id); i++)  {" << endl;
-          sstr << "    m_" << var->cIdent() << "_vec[i]->recordCacheContents(tr);\n";
-          sstr << "  }\n";
-        }
-      }
-    }
-    sstr << "}" << endl;
+  sstr << endl;
 
-    conditionally_write_file(path + "/Chip.cc", sstr);
+  sstr << "AbstractController* ControllerFactory::createController(const std::string & controller_type, const std::string & name) {" << endl;
+  for (int i=0;i<controller_types.size();i++) {
+    sstr << "    if (controller_type == \"" << controller_types[i] << "\")" << endl;
+    sstr << "      return new " << controller_types[i] << "_Controller(name);" << endl;
   }
+  sstr << "  assert(0); // invalid controller type" << endl;
+  sstr << "  return NULL;" << endl;
+  sstr << "}" << endl;
+  conditionally_write_file(path + "/ControllerFactory.cc", sstr);
 }
 
 Vector<StateMachine*> SymbolTable::getStateMachines() const
 
 private:
   // Private Methods
   void registerGlobalSym(string id, Symbol* sym_ptr);
-  void writeChipFiles(string path) const;
+  void writeControllerFactory(string path) const;
 
   // Private copy constructor and assignment operator
   SymbolTable(const SymbolTable& obj);
 
   }
 }
 
-void Type::writeCFiles(string path) const
+void Type::writeCFiles(string path)
 {
   if (isExternal()) {
     // Do nothing
     out << "  }" << endl;
   } // end of if(!isGlobal())
 
+  // create a static factory method
+  if (interface != "") {
+    out << "  static " << interface << "* create() {" << endl;
+    out << "    return new " << type_name << "(); " << endl;
+    out << "  }" << endl;
+  }
+
   // bobba -
   //******** Partial init constructor ********
   //**  Constructor needs only the first n-1 data members for init
   out << endl;
   // Include all of the #includes needed
   out << "#include \"mem/ruby/common/Global.hh\"" << endl;
-  if (m_isMachineType) {
-    out << "#include \"mem/ruby/config/RubyConfig.hh\"" << endl << endl;
-  }
   out << endl;
 
   // Class definition
   // MachineType hack used to set the base component id for each Machine
   if (m_isMachineType) {
     out << "int " << type_name << "_base_level(const " << type_name << "& obj);" << endl;
+    out << "MachineType " << type_name << "_from_base_level(int);" << endl;
     out << "int " << type_name << "_base_number(const " << type_name << "& obj);" << endl;
     out << "int " << type_name << "_base_count(const " << type_name << "& obj);" << endl;
-    out << "int " << type_name << "_chip_count(const " << type_name << "& obj, NodeID chipID);" << endl;
+    //    out << "int " << type_name << "_chip_count(const " << type_name << "& obj, int chipID);" << endl;
 
     for(int i = 0; i < size; i++ ) {
       string id = m_enum_vec[i];
 
   out << endl;
   out << "#include \"mem/protocol/" << type_name << ".hh\"" << endl;
+  if (m_isMachineType) {
+    out << "#include \"mem/ruby/config/RubyConfig.hh\"" << endl;
+    out << "#include \"mem/protocol/ControllerFactory.hh\"" << endl;
+    for( int i = 0; i<size; i++ ) {
+      out << "#include \"mem/protocol/" << m_enum_vec[i] << "_Controller.hh\"" << endl;
+    }
+    out << endl;
+  }
   out << endl;
 
   // Code for output operator
     out << "/** \\brief returns the base vector index for each machine type to be used by NetDest " << endl;
     out << "  * " << endl;
     out << "  * \\return the base vector index for each machine type to be used by NetDest" << endl;
-    out << "  * \\see mem/ruby/common/NetDest.hh" << endl;
+    out << "  * \\see NetDest.hh" << endl;
     out << "  */" << endl;
     out << "int " << type_name << "_base_level(const " << type_name << "& obj)" << endl;
     out << "{" << endl;
     out << "  }" << endl;
     out << "}" << endl;
 
+    out << "/** \\brief returns the machine type for each base vector index used by NetDest and RubyConfig" << endl;
+    out << "  * " << endl;
+    out << "  * \\return the MachineTYpe" << endl;
+    out << "  */" << endl;
+    out << "MachineType " << type_name << "_from_base_level(int type)" << endl;
+    out << "{" << endl;
+    out << "  switch(type) {" << endl;
+
+    // For each field
+    MachineNames.clear();
+    for( int i = 0; i<size; i++ ) {
+      out << "  case " << MachineNames.size() << ":" << endl;
+      out << "    return " << type_name << "_" << m_enum_vec[i] << ";" << endl;
+      MachineNames.insertAtBottom(m_enum_vec[i]);
+    }
+
+    // Trailer
+    out << "  default:" << endl;
+    out << "    ERROR_MSG(\"Invalid range for type " << type_name << "\");" << endl;
+    out << "    return MachineType_NUM;" << endl;
+    out << "  }" << endl;
+    out << "}" << endl;
+
+
     out << endl;
     out << "/** \\brief The return value indicates the number of components created" << endl;
     out << "  * before a particular machine's components" << endl;
       out << "  case " << type_name << "_" << m_enum_vec[i] << ":" << endl;
       out << "    return 0";
       for ( int m = 0; m<MachineNames.size(); m++) {
-        out << "+RubyConfig::numberOf" << MachineNames[m] << "()";
+        out << "+ " << MachineNames[m] << "_Controller::getNumControllers()";
       }
       out << ";" << endl;
       MachineNames.insertAtBottom(m_enum_vec[i]);
     out << "  case " << type_name << "_NUM:" << endl;
     out << "    return 0";
     for ( int m = 0; m<MachineNames.size(); m++) {
-      out << "+RubyConfig::numberOf" << MachineNames[m] << "()";
+      out << "+ " << MachineNames[m] << "_Controller::getNumControllers()";
     }
     out << ";" << endl;
 
     // For each field
     for( int i = 0; i<size; i++ ) {
       out << "  case " << type_name << "_" << m_enum_vec[i] << ":" << endl;
-      out << "    return RubyConfig::numberOf" << m_enum_vec[i] << "();" << endl;
+      out << "    return " << m_enum_vec[i] << "_Controller::getNumControllers();" << endl;
     }
 
     // total num
     out << "}" << endl;
 
     out << endl;
-    out << "/** \\brief returns the total number of components for each machine" << endl;
-    out << "  * \\return the total number of components for each machine" << endl;
-    out << "  */" << endl;
-    out << "int " << type_name << "_chip_count(const " << type_name << "& obj, NodeID chipID)" << endl;
-    out << "{" << endl;
-    out << "  switch(obj) {" << endl;
 
-    // For each field
-    for( int i = 0; i<size; i++ ) {
-      out << "  case " << type_name << "_" << m_enum_vec[i] << ":" << endl;
-      out << "    return RubyConfig::numberOf" << m_enum_vec[i] << "PerChip(chipID);" << endl;
-    }
+//     out << "/** \\brief returns the total number of components for each machine" << endl;
+//     out << "  * \\return the total number of components for each machine" << endl;
+//     out << "  */" << endl;
+//     out << "int " << type_name << "_chip_count(const " << type_name << "& obj, int chip_id)" << endl;
+//     out << "{" << endl;
+//     out << "  switch(obj) {" << endl;
+
+//     // For each field
+//     for( int i = 0; i<size; i++ ) {
+//       out << "  case " << type_name << "_" << m_enum_vec[i] << ":" << endl;
+//       out << "    return RubyConfig::getNumberOfControllersPerTypePerChip(MachineType_base_level(MachineType_" << m_enum_vec[i] << "), chip_id);" << endl;
+//     }
 
-    // total num
-    out << "  case " << type_name << "_NUM:" << endl;
-    // Trailer
-    out << "  default:" << endl;
-    out << "    ERROR_MSG(\"Invalid range for type " << type_name << "\");" << endl;
-    out << "    return -1;" << endl;
-    out << "  }" << endl;
-    out << "}" << endl;
+//     // total num
+//     out << "  case " << type_name << "_NUM:" << endl;
+//     // Trailer
+//     out << "  default:" << endl;
+//     out << "    ERROR_MSG(\"Invalid range for type " << type_name << "\");" << endl;
+//     out << "    return -1;" << endl;
+//     out << "  }" << endl;
+//     out << "}" << endl;
 
 
   }
 
   bool isEnumeration() const { return existPair("enumeration"); }
   bool isExternal() const { return existPair("external"); }
   bool isGlobal() const { return existPair("global"); }
+  bool isInterface() const { return existPair("interface"); }
 
   // The data members of this type - only valid for messages and SLICC
   // declared structures
   bool enumExist(string id) const { return m_enum_map.exist(id); }
 
   // Write the C output files
-  void writeCFiles(string path) const;
+  void writeCFiles(string path) ;
 
   bool hasDefault() const { return existPair("default"); }
   string getDefault() const { return lookupPair("default"); }
 
 
   // Public Methods
   string cIdent() const { return m_c_id; }
-  void writeCFiles(string path) const {}
+  void writeCFiles(string path)  {}
   string getCode() const { return m_code; }
   Type* getType() const { return m_type_ptr; }
   StateMachine* getMachine() const { return m_machine_ptr; }