From a1b5a6320f8aed2596969195d4955284c2dd04e8 Mon Sep 17 00:00:00 2001
From: Derek Hower <drh5@cs.wisc.edu>
Date: Thu, 6 Aug 2009 01:15:23 -0500
Subject: ruby: better configuration assert message

---
 src/mem/ruby/config/cfg.rb | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'src')

diff --git a/src/mem/ruby/config/cfg.rb b/src/mem/ruby/config/cfg.rb
index ffc36dd67..82f0d2776 100644
--- a/src/mem/ruby/config/cfg.rb
+++ b/src/mem/ruby/config/cfg.rb
@@ -11,7 +11,7 @@ end
 
 def assert(condition,message)
   unless condition
-    raise AssertionFailure, "Assertion failed: #{message}"
+    raise AssertionFailure, "\n\nAssertion failed: \n\n   #{message}\n\n"
   end
 end
 
-- 
cgit v1.2.3


From f5e0c56da24ad1b6ee51592d19a9babb7b59da05 Mon Sep 17 00:00:00 2001
From: Derek Hower <drh5@cs.wisc.edu>
Date: Thu, 6 Aug 2009 01:15:55 -0500
Subject: protocol: fixed MOESI_CMP_directory bug

---
 src/mem/protocol/MOESI_CMP_directory-dma.sm | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'src')

diff --git a/src/mem/protocol/MOESI_CMP_directory-dma.sm b/src/mem/protocol/MOESI_CMP_directory-dma.sm
index 74246c730..da10695d0 100644
--- a/src/mem/protocol/MOESI_CMP_directory-dma.sm
+++ b/src/mem/protocol/MOESI_CMP_directory-dma.sm
@@ -98,7 +98,8 @@ machine(DMA, "DMA Controller")
       peek( dmaResponseQueue_in, ResponseMsg) {
         if (in_msg.Type == CoherenceResponseType:DMA_ACK) {
           trigger(Event:DMA_Ack, in_msg.Address);
-        } else if (in_msg.Type == CoherenceResponseType:DATA_EXCLUSIVE) {
+        } else if (in_msg.Type == CoherenceResponseType:DATA_EXCLUSIVE ||
+		   in_msg.Type == CoherenceResponseType:DATA) {
           trigger(Event:Data, in_msg.Address);
         } else if (in_msg.Type == CoherenceResponseType:ACK) {
           trigger(Event:Inv_Ack, in_msg.Address);
-- 
cgit v1.2.3


From cbc52ef6c564837060a64ca33780af9152d8d38e Mon Sep 17 00:00:00 2001
From: Derek Hower <drh5@cs.wisc.edu>
Date: Thu, 6 Aug 2009 03:41:28 -0500
Subject: fixed MOESI_CMP_directory bug

---
 src/mem/protocol/MOESI_CMP_directory-dir.sm | 11 +++++++----
 src/mem/protocol/MOESI_CMP_directory-dma.sm | 14 +++++++-------
 2 files changed, 14 insertions(+), 11 deletions(-)

(limited to 'src')

diff --git a/src/mem/protocol/MOESI_CMP_directory-dir.sm b/src/mem/protocol/MOESI_CMP_directory-dir.sm
index edd67707e..bafbc404e 100644
--- a/src/mem/protocol/MOESI_CMP_directory-dir.sm
+++ b/src/mem/protocol/MOESI_CMP_directory-dir.sm
@@ -101,7 +101,7 @@ machine(Directory, "Directory protocol")
   }
 
   structure(TBE, desc="...") {
-    Address address,   desc="Address for this entry";
+    Address PhysicalAddress,   desc="Physical address for this entry";
     int Len,           desc="Length of request";
     DataBlock DataBlk, desc="DataBlk";
     MachineID Requestor, desc="original requestor";
@@ -245,9 +245,9 @@ machine(Directory, "Directory protocol")
         } else if (in_msg.Type == CoherenceRequestType:PUTO_SHARERS) {
           trigger(Event:PUTO_SHARERS, in_msg.Address);
         } else if (in_msg.Type == CoherenceRequestType:DMA_READ) {
-          trigger(Event:DMA_READ, in_msg.Address);
+          trigger(Event:DMA_READ, makeLineAddress(in_msg.Address));
         } else if (in_msg.Type == CoherenceRequestType:DMA_WRITE) {
-          trigger(Event:DMA_WRITE, in_msg.Address);
+          trigger(Event:DMA_WRITE, makeLineAddress(in_msg.Address));
         } else {
           error("Invalid message");
         }
@@ -527,12 +527,15 @@ machine(Directory, "Directory protocol")
   }
 
   action(l_writeDMADataToMemoryFromTBE, "\ll", desc="Write data from a DMA_WRITE to memory") {
-    directory[address].DataBlk.copyPartial(TBEs[address].DataBlk, addressOffset(address), TBEs[address].Len);
+    directory[address].DataBlk.copyPartial(TBEs[address].DataBlk, 
+					   addressOffset(TBEs[address].PhysicalAddress), 
+					   TBEs[address].Len);
   }
 
   action(v_allocateTBE, "v", desc="Allocate TBE entry") {
     peek (requestQueue_in, RequestMsg) {
       TBEs.allocate(address);
+      TBEs[address].PhysicalAddress := in_msg.Address;
       TBEs[address].Len := in_msg.Len;
       TBEs[address].DataBlk := in_msg.DataBlk;
       TBEs[address].Requestor := in_msg.Requestor;
diff --git a/src/mem/protocol/MOESI_CMP_directory-dma.sm b/src/mem/protocol/MOESI_CMP_directory-dma.sm
index da10695d0..ae86e24da 100644
--- a/src/mem/protocol/MOESI_CMP_directory-dma.sm
+++ b/src/mem/protocol/MOESI_CMP_directory-dma.sm
@@ -83,9 +83,9 @@ machine(DMA, "DMA Controller")
     if (dmaRequestQueue_in.isReady()) {
       peek(dmaRequestQueue_in, SequencerMsg) {
         if (in_msg.Type == SequencerRequestType:LD ) {
-          trigger(Event:ReadRequest, in_msg.PhysicalAddress);
+          trigger(Event:ReadRequest, in_msg.LineAddress);
         } else if (in_msg.Type == SequencerRequestType:ST) {
-          trigger(Event:WriteRequest, in_msg.PhysicalAddress);
+          trigger(Event:WriteRequest, in_msg.LineAddress);
         } else {
           error("Invalid request type");
         }
@@ -97,12 +97,12 @@ machine(DMA, "DMA Controller")
     if (dmaResponseQueue_in.isReady()) {
       peek( dmaResponseQueue_in, ResponseMsg) {
         if (in_msg.Type == CoherenceResponseType:DMA_ACK) {
-          trigger(Event:DMA_Ack, in_msg.Address);
+          trigger(Event:DMA_Ack, makeLineAddress(in_msg.Address));
         } else if (in_msg.Type == CoherenceResponseType:DATA_EXCLUSIVE ||
 		   in_msg.Type == CoherenceResponseType:DATA) {
-          trigger(Event:Data, in_msg.Address);
+          trigger(Event:Data, makeLineAddress(in_msg.Address));
         } else if (in_msg.Type == CoherenceResponseType:ACK) {
-          trigger(Event:Inv_Ack, in_msg.Address);
+          trigger(Event:Inv_Ack, makeLineAddress(in_msg.Address));
         } else {
           error("Invalid response type");
         }
@@ -126,7 +126,7 @@ machine(DMA, "DMA Controller")
   action(s_sendReadRequest, "s", desc="Send a DMA read request to memory") {
     peek(dmaRequestQueue_in, SequencerMsg) {
       enqueue(reqToDirectory_out, RequestMsg, latency=request_latency) {
-        out_msg.Address := address;
+        out_msg.Address := in_msg.PhysicalAddress;
         out_msg.Type := CoherenceRequestType:DMA_READ;
         out_msg.DataBlk := in_msg.DataBlk;
         out_msg.Len := in_msg.Len;
@@ -140,7 +140,7 @@ machine(DMA, "DMA Controller")
   action(s_sendWriteRequest, "\s", desc="Send a DMA write request to memory") {
     peek(dmaRequestQueue_in, SequencerMsg) {
       enqueue(reqToDirectory_out, RequestMsg, latency=request_latency) {
-          out_msg.Address := address;
+          out_msg.Address := in_msg.PhysicalAddress;
           out_msg.Type := CoherenceRequestType:DMA_WRITE;
           out_msg.DataBlk := in_msg.DataBlk;
           out_msg.Len := in_msg.Len;
-- 
cgit v1.2.3


From b952eb19c18bffcd4519bac19f79979fab477ff6 Mon Sep 17 00:00:00 2001
From: Tushar Krishna <Tushar.Krishna@amd.com>
Date: Fri, 7 Aug 2009 13:59:40 -0700
Subject: bug fix for data_msg_size in network/Network.cc

---
 src/mem/protocol/MOESI_CMP_directory-L2cache.sm    |  2 +-
 src/mem/protocol/MOESI_CMP_token-L2cache.sm        |  2 +-
 src/mem/protocol/MSI_MOSI_CMP_directory-L2cache.sm |  2 +-
 src/mem/protocol/RubySlicc_Util.sm                 |  1 -
 src/mem/ruby/config/cfg.rb                         |  2 +-
 src/mem/ruby/config/defaults.rb                    |  2 ++
 src/mem/ruby/network/Network.cc                    | 39 ++++++++++++++++++--
 src/mem/ruby/network/Network.hh                    | 41 +++-------------------
 .../garnet-fixed-pipeline/NetworkInterface_d.cc    |  2 +-
 .../garnet-flexible-pipeline/NetworkInterface.cc   |  2 +-
 src/mem/ruby/network/simple/Switch.cc              |  2 +-
 src/mem/ruby/network/simple/Throttle.cc            |  4 +--
 src/mem/ruby/slicc_interface/RubySlicc_Util.hh     |  5 ---
 13 files changed, 52 insertions(+), 54 deletions(-)

(limited to 'src')

diff --git a/src/mem/protocol/MOESI_CMP_directory-L2cache.sm b/src/mem/protocol/MOESI_CMP_directory-L2cache.sm
index fa01f925c..50af743c2 100644
--- a/src/mem/protocol/MOESI_CMP_directory-L2cache.sm
+++ b/src/mem/protocol/MOESI_CMP_directory-L2cache.sm
@@ -1389,7 +1389,7 @@ machine(L2Cache, "Token protocol") {
   action(uu_profileMiss, "\u", desc="Profile the demand miss") {
     peek(L1requestNetwork_in, RequestMsg) {
       // AccessModeType not implemented
-      profile_L2Cache_miss(convertToGenericType(in_msg.Type), in_msg.AccessMode, MessageSizeTypeToInt(in_msg.MessageSize),  in_msg.Prefetch, machineIDToNodeID(in_msg.Requestor));
+      //profile_L2Cache_miss(convertToGenericType(in_msg.Type), in_msg.AccessMode, MessageSizeTypeToInt(in_msg.MessageSize),  in_msg.Prefetch, machineIDToNodeID(in_msg.Requestor));
     }
   }
 
diff --git a/src/mem/protocol/MOESI_CMP_token-L2cache.sm b/src/mem/protocol/MOESI_CMP_token-L2cache.sm
index 21fbf0b95..0a58ed5cf 100644
--- a/src/mem/protocol/MOESI_CMP_token-L2cache.sm
+++ b/src/mem/protocol/MOESI_CMP_token-L2cache.sm
@@ -916,7 +916,7 @@ machine(L2Cache, "Token protocol") {
   action(uu_profileMiss, "\u", desc="Profile the demand miss") {
     peek(L1requestNetwork_in, RequestMsg) {
       // AccessModeType not implemented
-      profile_L2Cache_miss(convertToGenericType(in_msg.Type), in_msg.AccessMode, MessageSizeTypeToInt(in_msg.MessageSize),  in_msg.Prefetch, machineIDToNodeID(in_msg.Requestor));
+      //profile_L2Cache_miss(convertToGenericType(in_msg.Type), in_msg.AccessMode, MessageSizeTypeToInt(in_msg.MessageSize),  in_msg.Prefetch, machineIDToNodeID(in_msg.Requestor));
     }
   }
 
diff --git a/src/mem/protocol/MSI_MOSI_CMP_directory-L2cache.sm b/src/mem/protocol/MSI_MOSI_CMP_directory-L2cache.sm
index d68efc819..9f85e3a8f 100644
--- a/src/mem/protocol/MSI_MOSI_CMP_directory-L2cache.sm
+++ b/src/mem/protocol/MSI_MOSI_CMP_directory-L2cache.sm
@@ -978,7 +978,7 @@ machine(L2Cache, "MOSI Directory L2 Cache CMP") {
 
   action(uu_profileMiss, "\u", desc="Profile the demand miss") {
     peek(L1RequestIntraChipL2Network_in, RequestMsg) {
-      profile_L2Cache_miss(convertToGenericType(in_msg.Type), in_msg.AccessMode, MessageSizeTypeToInt(in_msg.MessageSize), in_msg.Prefetch, L1CacheMachIDToProcessorNum(in_msg.RequestorMachId));
+      //profile_L2Cache_miss(convertToGenericType(in_msg.Type), in_msg.AccessMode, MessageSizeTypeToInt(in_msg.MessageSize), in_msg.Prefetch, L1CacheMachIDToProcessorNum(in_msg.RequestorMachId));
     }
   }
 
diff --git a/src/mem/protocol/RubySlicc_Util.sm b/src/mem/protocol/RubySlicc_Util.sm
index 7f7ebf5ed..2aa494fff 100644
--- a/src/mem/protocol/RubySlicc_Util.sm
+++ b/src/mem/protocol/RubySlicc_Util.sm
@@ -37,7 +37,6 @@ Time zero_time();
 NodeID intToID(int nodenum);
 int IDToInt(NodeID id);
 int addressToInt(Address addr);
-int MessageSizeTypeToInt(MessageSizeType size_type);
 bool multicast_retry();
 int numberOfNodes();
 int numberOfL1CachePerChip();
diff --git a/src/mem/ruby/config/cfg.rb b/src/mem/ruby/config/cfg.rb
index a43b5e125..6b12ad22a 100644
--- a/src/mem/ruby/config/cfg.rb
+++ b/src/mem/ruby/config/cfg.rb
@@ -602,7 +602,7 @@ class Network < LibRubyObject
     vec += " buffer_size "+buffer_size.to_s
     vec += " link_latency "+adaptive_routing.to_s
     vec += " on_chip_latency "+on_chip_latency.to_s
-
+    vec += " control_msg_size "+control_msg_size.to_s
   end
 
   def printTopology()
diff --git a/src/mem/ruby/config/defaults.rb b/src/mem/ruby/config/defaults.rb
index e54b148e0..7d5d91ae2 100644
--- a/src/mem/ruby/config/defaults.rb
+++ b/src/mem/ruby/config/defaults.rb
@@ -82,6 +82,8 @@ class Network < LibRubyObject
 
   # on chip latency
   default_param :on_chip_latency, Integer, 1
+ 
+  default_param :control_msg_size, Integer, 8
 end
 
 class GarnetNetwork < Network
diff --git a/src/mem/ruby/network/Network.cc b/src/mem/ruby/network/Network.cc
index cb3507471..984ec7ca8 100644
--- a/src/mem/ruby/network/Network.cc
+++ b/src/mem/ruby/network/Network.cc
@@ -26,9 +26,44 @@ void Network::init(const vector<string> & argv)
      m_adaptive_routing = (argv[i+1]=="true");
    else if (argv[i] == "link_latency")
      m_link_latency = atoi(argv[i+1].c_str());
-
+   else if (argv[i] == "control_msg_size")
+     m_control_msg_size = atoi(argv[i+1].c_str());		 
   }
+
+  m_data_msg_size = RubySystem::getBlockSizeBytes() + m_control_msg_size;
+
   assert(m_virtual_networks != 0);
   assert(m_topology_ptr != NULL);
-//  printf ("HERE \n");
+}
+
+int Network::MessageSizeType_to_int(MessageSizeType size_type)
+{
+  switch(size_type) {
+  case MessageSizeType_Undefined:
+    ERROR_MSG("Can't convert Undefined MessageSizeType to integer");
+    break;
+  case MessageSizeType_Control:
+  case MessageSizeType_Request_Control:
+  case MessageSizeType_Reissue_Control:
+  case MessageSizeType_Response_Control:
+  case MessageSizeType_Writeback_Control:
+  case MessageSizeType_Forwarded_Control:
+  case MessageSizeType_Invalidate_Control:
+  case MessageSizeType_Unblock_Control:
+  case MessageSizeType_Persistent_Control:
+  case MessageSizeType_Completion_Control:
+    return m_control_msg_size;
+    break;
+  case MessageSizeType_Data:
+  case MessageSizeType_Response_Data:
+  case MessageSizeType_ResponseLocal_Data:
+  case MessageSizeType_ResponseL2hit_Data:
+  case MessageSizeType_Writeback_Data:
+    return m_data_msg_size;
+    break;
+  default:
+    ERROR_MSG("Invalid range for type MessageSizeType");
+    break;
+  }
+  return 0;
 }
diff --git a/src/mem/ruby/network/Network.hh b/src/mem/ruby/network/Network.hh
index 17fbaab22..e7c86b6b2 100644
--- a/src/mem/ruby/network/Network.hh
+++ b/src/mem/ruby/network/Network.hh
@@ -71,6 +71,8 @@ public:
   int getEndpointBandwidth() { return m_endpoint_bandwidth; }
   bool getAdaptiveRouting() {return m_adaptive_routing; }
   int getLinkLatency() { return m_link_latency; }
+  int MessageSizeType_to_int(MessageSizeType size_type);
+
 
   // returns the queue requested for the given component
   virtual MessageBuffer* getToNetQueue(NodeID id, bool ordered, int netNumber) = 0;
@@ -107,6 +109,8 @@ protected:
   Topology* m_topology_ptr;
   bool m_adaptive_routing;
   int m_link_latency;
+  int m_control_msg_size;
+  int m_data_msg_size;
 };
 
 // Output operator declaration
@@ -123,41 +127,4 @@ ostream& operator<<(ostream& out, const Network& obj)
   return out;
 }
 
-// Code to map network message size types to an integer number of bytes
-const int CONTROL_MESSAGE_SIZE = 8;
-const int DATA_MESSAGE_SIZE = (RubySystem::getBlockSizeBytes()+8);
-
-extern inline
-int MessageSizeType_to_int(MessageSizeType size_type)
-{
-  switch(size_type) {
-  case MessageSizeType_Undefined:
-    ERROR_MSG("Can't convert Undefined MessageSizeType to integer");
-    break;
-  case MessageSizeType_Control:
-  case MessageSizeType_Request_Control:
-  case MessageSizeType_Reissue_Control:
-  case MessageSizeType_Response_Control:
-  case MessageSizeType_Writeback_Control:
-  case MessageSizeType_Forwarded_Control:
-  case MessageSizeType_Invalidate_Control:
-  case MessageSizeType_Unblock_Control:
-  case MessageSizeType_Persistent_Control:
-  case MessageSizeType_Completion_Control:
-    return CONTROL_MESSAGE_SIZE;
-    break;
-  case MessageSizeType_Data:
-  case MessageSizeType_Response_Data:
-  case MessageSizeType_ResponseLocal_Data:
-  case MessageSizeType_ResponseL2hit_Data:
-  case MessageSizeType_Writeback_Data:
-    return DATA_MESSAGE_SIZE;
-    break;
-  default:
-    ERROR_MSG("Invalid range for type MessageSizeType");
-    break;
-  }
-  return 0;
-}
-
 #endif //NETWORK_H
diff --git a/src/mem/ruby/network/garnet-fixed-pipeline/NetworkInterface_d.cc b/src/mem/ruby/network/garnet-fixed-pipeline/NetworkInterface_d.cc
index f75997757..3377ffd1d 100644
--- a/src/mem/ruby/network/garnet-fixed-pipeline/NetworkInterface_d.cc
+++ b/src/mem/ruby/network/garnet-fixed-pipeline/NetworkInterface_d.cc
@@ -114,7 +114,7 @@ bool NetworkInterface_d::flitisizeMessage(MsgPtr msg_ptr, int vnet)
         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())/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
+        int num_flits = (int) ceil((double) m_net_ptr->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
         {
diff --git a/src/mem/ruby/network/garnet-flexible-pipeline/NetworkInterface.cc b/src/mem/ruby/network/garnet-flexible-pipeline/NetworkInterface.cc
index 119f064d3..597c942b7 100644
--- a/src/mem/ruby/network/garnet-flexible-pipeline/NetworkInterface.cc
+++ b/src/mem/ruby/network/garnet-flexible-pipeline/NetworkInterface.cc
@@ -109,7 +109,7 @@ bool NetworkInterface::flitisizeMessage(MsgPtr msg_ptr, int vnet)
         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())/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
+        int num_flits = (int) ceil((double) m_net_ptr->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
         {
diff --git a/src/mem/ruby/network/simple/Switch.cc b/src/mem/ruby/network/simple/Switch.cc
index e3420ddae..87021471f 100644
--- a/src/mem/ruby/network/simple/Switch.cc
+++ b/src/mem/ruby/network/simple/Switch.cc
@@ -169,7 +169,7 @@ void Switch::printStats(ostream& out) const
         int sum = message_counts[type].sum();
         if (sum != 0) {
           out << "  outgoing_messages_switch_" << m_switch_id << "_link_" << link << "_" << type
-              << ": " << sum << " " << sum * MessageSizeType_to_int(type)
+              << ": " << sum << " " << sum * (RubySystem::getNetwork()->MessageSizeType_to_int(type))
               << " " << message_counts[type] << " base_latency: " << throttle_ptr->getLatency() << endl;
         }
       }
diff --git a/src/mem/ruby/network/simple/Throttle.cc b/src/mem/ruby/network/simple/Throttle.cc
index 64cb2a33a..89d61f267 100644
--- a/src/mem/ruby/network/simple/Throttle.cc
+++ b/src/mem/ruby/network/simple/Throttle.cc
@@ -275,8 +275,8 @@ int network_message_to_size(NetworkMessage* net_msg_ptr)
   // Artificially increase the size of broadcast messages
   if (BROADCAST_SCALING > 1) {
     if (net_msg_ptr->getDestination().isBroadcast()) {
-      return (MessageSizeType_to_int(net_msg_ptr->getMessageSize()) * MESSAGE_SIZE_MULTIPLIER * BROADCAST_SCALING);
+      return (RubySystem::getNetwork()->MessageSizeType_to_int(net_msg_ptr->getMessageSize()) * MESSAGE_SIZE_MULTIPLIER * BROADCAST_SCALING);
     }
   }
-  return (MessageSizeType_to_int(net_msg_ptr->getMessageSize()) * MESSAGE_SIZE_MULTIPLIER);
+  return (RubySystem::getNetwork()->MessageSizeType_to_int(net_msg_ptr->getMessageSize()) * MESSAGE_SIZE_MULTIPLIER);
 }
diff --git a/src/mem/ruby/slicc_interface/RubySlicc_Util.hh b/src/mem/ruby/slicc_interface/RubySlicc_Util.hh
index e4e20c99a..a7b8a13fd 100644
--- a/src/mem/ruby/slicc_interface/RubySlicc_Util.hh
+++ b/src/mem/ruby/slicc_interface/RubySlicc_Util.hh
@@ -106,11 +106,6 @@ extern inline int addressToInt(Address addr)
   return (int) addr.getLineAddress();
 }
 
-extern inline int MessageSizeTypeToInt(MessageSizeType size_type)
-{
-  return MessageSizeType_to_int(size_type);
-}
-
 extern inline bool long_enough_ago(Time event)
 {
   return ((get_time() - event) > 200);
-- 
cgit v1.2.3


From 1a452d228b597ccf75d363c0dd6917ba547cac24 Mon Sep 17 00:00:00 2001
From: Derek Hower <drh5@cs.wisc.edu>
Date: Sun, 9 Aug 2009 13:58:40 -0500
Subject: protocol: added recycle actions to MOESI DMA events

---
 src/mem/protocol/MOESI_CMP_directory-dir.sm | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'src')

diff --git a/src/mem/protocol/MOESI_CMP_directory-dir.sm b/src/mem/protocol/MOESI_CMP_directory-dir.sm
index bafbc404e..8d8ee7f8a 100644
--- a/src/mem/protocol/MOESI_CMP_directory-dir.sm
+++ b/src/mem/protocol/MOESI_CMP_directory-dir.sm
@@ -698,7 +698,7 @@ machine(Directory, "Directory protocol")
   }
 
 
-  transition({MM, MO, MI, MIS, OS, OSS}, {GETS, GETX, PUTO, PUTO_SHARERS, PUTX, DMA_READ}) {
+  transition({MM, MO, MI, MIS, OS, OSS, XI_M, XI_U, OI_D}, {GETS, GETX, PUTO, PUTO_SHARERS, PUTX, DMA_READ, DMA_WRITE}) {
     zz_recycleRequest;
   }
 
@@ -713,7 +713,7 @@ machine(Directory, "Directory protocol")
     j_popIncomingUnblockQueue;
   }
 
-  transition({IS, SS, OO}, {GETX, PUTO, PUTO_SHARERS, PUTX, DMA_READ}) {
+  transition({IS, SS, OO}, {GETX, PUTO, PUTO_SHARERS, PUTX, DMA_READ, DMA_WRITE}) {
     zz_recycleRequest;
   }
 
-- 
cgit v1.2.3


From 35082a67b65457e36cffdc5f8a13aacaa4258939 Mon Sep 17 00:00:00 2001
From: Tushar Krishna <Tushar.Krishna@amd.com>
Date: Tue, 11 Aug 2009 15:19:04 -0700
Subject: ruby/network data_msg_size bug fix with updated stats

---
 src/mem/ruby/config/defaults.rb | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'src')

diff --git a/src/mem/ruby/config/defaults.rb b/src/mem/ruby/config/defaults.rb
index 5451c577e..384abd119 100644
--- a/src/mem/ruby/config/defaults.rb
+++ b/src/mem/ruby/config/defaults.rb
@@ -39,7 +39,7 @@ class Debug < LibRubyObject
   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, ""
+  default_param :filter_string, String, "none"
 
   # filters debugging messages based on priority (low, med, high)
   default_param :verbosity_string, String, "none"
-- 
cgit v1.2.3


From db40cb8f519259fb30128f7262fba5270424c7f8 Mon Sep 17 00:00:00 2001
From: Derek Hower <drh5@cs.wisc.edu>
Date: Thu, 13 Aug 2009 10:37:09 -0500
Subject: ruby: config bugfix

---
 src/mem/ruby/config/cfg.rb | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'src')

diff --git a/src/mem/ruby/config/cfg.rb b/src/mem/ruby/config/cfg.rb
index 82f0d2776..4142bc964 100644
--- a/src/mem/ruby/config/cfg.rb
+++ b/src/mem/ruby/config/cfg.rb
@@ -309,7 +309,7 @@ class CacheController < NetPort
       cache.controller = self
     }
 
-    if !@@total_cache_controllers.has_key?(mach_type)
+    if !@@total_cache_controllers.key?(mach_type)
       @@total_cache_controllers[mach_type] = 0
     end
     @version = @@total_cache_controllers[mach_type]
-- 
cgit v1.2.3


From 06c7ecb2079e69ea8d81a01d52ca6266649575f4 Mon Sep 17 00:00:00 2001
From: Nathan Binkert <nate@binkert.org>
Date: Sun, 16 Aug 2009 13:39:59 -0700
Subject: python: Make it possible to import the parts of m5 that are pure
 python

---
 src/python/m5/__init__.py | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

(limited to 'src')

diff --git a/src/python/m5/__init__.py b/src/python/m5/__init__.py
index 733258acf..c3512cd0d 100644
--- a/src/python/m5/__init__.py
+++ b/src/python/m5/__init__.py
@@ -103,8 +103,11 @@ try:
 except ImportError:
     internal = None
 
-import defines
-build_env.update(defines.buildEnv)
+try:
+    import defines
+    build_env.update(defines.buildEnv)
+except ImportError:
+    defines = None
 
 if internal:
     defines.compileDate = internal.core.compileDate
@@ -120,4 +123,8 @@ if internal:
 
 import SimObject
 import params
-import objects
+
+try:
+    import objects
+except ImportError:
+    objects = None
-- 
cgit v1.2.3


From 2334e6fdd515b47b3d4a295f1d4712a9dfff4dcb Mon Sep 17 00:00:00 2001
From: Nathan Binkert <nate@binkert.org>
Date: Sun, 16 Aug 2009 13:40:00 -0700
Subject: orderdict: Use DictMixin and add orderdict to m5.util

---
 src/python/SConscript           |  1 +
 src/python/m5/util/__init__.py  |  1 +
 src/python/m5/util/orderdict.py | 59 ++++++++++++++++++-----------------------
 3 files changed, 28 insertions(+), 33 deletions(-)

(limited to 'src')

diff --git a/src/python/SConscript b/src/python/SConscript
index a767545ec..b01b422f5 100644
--- a/src/python/SConscript
+++ b/src/python/SConscript
@@ -56,6 +56,7 @@ PySource('m5.util', 'm5/util/attrdict.py')
 PySource('m5.util', 'm5/util/jobfile.py')
 PySource('m5.util', 'm5/util/misc.py')
 PySource('m5.util', 'm5/util/multidict.py')
+PySource('m5.util', 'm5/util/orderdict.py')
 
 SwigSource('m5.internal', 'swig/core.i')
 SwigSource('m5.internal', 'swig/debug.i')
diff --git a/src/python/m5/util/__init__.py b/src/python/m5/util/__init__.py
index 5c4a066c6..48e8111bd 100644
--- a/src/python/m5/util/__init__.py
+++ b/src/python/m5/util/__init__.py
@@ -29,6 +29,7 @@
 from attrdict import attrdict, optiondict
 from misc import *
 from multidict import multidict
+from orderdict import orderdict
 import jobfile
 
 def print_list(items, indent=4):
diff --git a/src/python/m5/util/orderdict.py b/src/python/m5/util/orderdict.py
index 3f755d299..1ffbca87a 100644
--- a/src/python/m5/util/orderdict.py
+++ b/src/python/m5/util/orderdict.py
@@ -28,17 +28,20 @@
 
 __all__ = [ 'orderdict' ]
 
-class orderdict(dict):
-    def __init__(self, d = {}):
-        self._keys = d.keys()
-        super(orderdict, self).__init__(d)
+from UserDict import DictMixin
+
+class orderdict(dict, DictMixin):
+    def __init__(self, *args, **kwargs):
+        if len(args) > 1:
+            raise TypeError("expected at most one argument, got %d" % \
+                            len(args))
+        self._keys = []
+        self.update(*args, **kwargs)
 
     def __setitem__(self, key, item):
-        super(orderdict, self).__setitem__(key, item)
-        if not hasattr(self, '_keys'):
-            self._keys = [key,]
-        if key not in self._keys:
+        if key not in self:
             self._keys.append(key)
+        super(orderdict, self).__setitem__(key, item)
 
     def __delitem__(self, key):
         super(orderdict, self).__delitem__(key)
@@ -48,33 +51,23 @@ class orderdict(dict):
         super(orderdict, self).clear()
         self._keys = []
 
-    def items(self):
-        for i in self._keys:
-            yield i, self[i]
+    def iterkeys(self):
+        for key in self._keys:
+            yield key
 
-    def keys(self):
-        return self._keys
+    def itervalues(self):
+        for key in self._keys:
+            yield self[key]
 
-    def popitem(self):
-        if len(self._keys) == 0:
-            raise KeyError('dictionary is empty')
-        else:
-            key = self._keys[-1]
-            val = self[key]
-            del self[key]
-            return key, val
+    def iteritems(self):
+        for key in self._keys:
+            yield key, self[key]
 
-    def setdefault(self, key, failobj = None):
-        super(orderdict, self).setdefault(key, failobj)
-        if key not in self._keys:
-            self._keys.append(key)
-
-    def update(self, d):
-        for key in d.keys():
-            if not self.has_key(key):
-                self._keys.append(key)
-        super(orderdict, self).update(d)
+    def keys(self):
+        return self._keys[:]
 
     def values(self):
-        for i in self._keys:
-            yield self[i]
+        return [ self[key] for key in self._keys ]
+
+    def items(self):
+        return [ (self[key],key) for key in self._keys ]
-- 
cgit v1.2.3


From 2ecaa99025665573a95057c2600e8e74132e22f5 Mon Sep 17 00:00:00 2001
From: Nathan Binkert <nate@binkert.org>
Date: Sun, 16 Aug 2009 13:40:01 -0700
Subject: ply: add a base class called Grammar that encapsulates a ply grammar

---
 src/python/SConscript         |   1 +
 src/python/m5/util/grammar.py | 119 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 120 insertions(+)
 create mode 100644 src/python/m5/util/grammar.py

(limited to 'src')

diff --git a/src/python/SConscript b/src/python/SConscript
index b01b422f5..c36f03695 100644
--- a/src/python/SConscript
+++ b/src/python/SConscript
@@ -53,6 +53,7 @@ PySource('m5', 'm5/ticks.py')
 PySource('m5', 'm5/trace.py')
 PySource('m5.util', 'm5/util/__init__.py')
 PySource('m5.util', 'm5/util/attrdict.py')
+PySource('m5.util', 'm5/util/grammar.py')
 PySource('m5.util', 'm5/util/jobfile.py')
 PySource('m5.util', 'm5/util/misc.py')
 PySource('m5.util', 'm5/util/multidict.py')
diff --git a/src/python/m5/util/grammar.py b/src/python/m5/util/grammar.py
new file mode 100644
index 000000000..93c2c84c4
--- /dev/null
+++ b/src/python/m5/util/grammar.py
@@ -0,0 +1,119 @@
+# Copyright (c) 2006-2009 Nathan Binkert <nate@binkert.org>
+# 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.
+
+from ply import lex, yacc
+
+class TokenError(lex.LexError):
+    def __init__(self, msg, t):
+        super(TokenError, self).__init__(msg)
+        self.token = t
+
+class ParseError(yacc.YaccError):
+    def __init__(self, message, token=None):
+        super(ParseError, self).__init__(message)
+        self.token = token
+
+class Tokenizer(object):
+    def __init__(self, lexer, data):
+        if isinstance(data, basestring):
+            indata = [ data ]
+        elif isinstance(data, file):
+            indata = data.xreadlines()
+        else:
+            indata = data
+
+        def _input():
+            for i,line in enumerate(indata):
+                lexer.lineno = i + 1
+                lexer.input(line)
+                while True:
+                    tok = lexer.token()
+                    if not tok:
+                        break
+                    yield tok
+        self.input = _input()
+
+    def next(self):
+        return self.input.next()
+
+    def __iter__(self):
+        return self
+
+    def token(self):
+        try:
+            return self.next()
+        except StopIteration:
+            return None
+
+class Grammar(object):
+    def __init__(self, output=None, debug=False):
+        self.yacc_args = {}
+        self.yacc_args['debug'] = debug
+
+        if output:
+            import os
+
+            dir,tab = os.path.split(output)
+            if not tab.endswith('.py'):
+                raise AttributeError, 'The output file must end with .py'
+            self.yacc_args['outputdir'] = dir
+            self.yacc_args['tabmodule'] = tab[:-3]
+
+    def t_error(self, t):
+        raise lex.LexError("Illegal character %s @ %d:%d" % \
+              (`t.value[0]`, t.lineno, t.lexpos), `t.value[0]`)
+
+    def p_error(self, t):
+        if t:
+            msg = "Syntax error at %d:%d\n>>%s<<" % \
+                  (t.lineno, t.lexpos + 1, t.value)
+        else:
+            msg = "Syntax error at end of input"
+        raise ParseError(msg, t)
+
+    def __getattr__(self, attr):
+        if attr == 'parser':
+            import ply.yacc
+            parser = ply.yacc.yacc(module=self, **self.yacc_args)
+            self.parser = parser
+            return parser
+
+        if attr == 'lexer':
+            import ply.lex
+            lexer = ply.lex.lex(module=self)
+            self.lexer = lexer
+            return lexer
+
+        raise AttributeError, "'%s' object has no attribute '%s'" % \
+              (self.__class__.__name__, attr)
+
+    def parse(self, stmt, **kwargs):
+        self.lexer.lineno = 1
+        result = self.parser.parse(lexer=Tokenizer(self.lexer, stmt), **kwargs)
+        self.parser.restart()
+
+        return result
+
-- 
cgit v1.2.3


From a6b39c07d9d03955382a0e930b363c6e6fd4b942 Mon Sep 17 00:00:00 2001
From: Nathan Binkert <nate@binkert.org>
Date: Sun, 16 Aug 2009 13:40:03 -0700
Subject: code_formatter: Add a python class for writing code generator
 templates

---
 src/python/SConscript                |   1 +
 src/python/m5/util/__init__.py       |   1 +
 src/python/m5/util/code_formatter.py | 311 +++++++++++++++++++++++++++++++++++
 3 files changed, 313 insertions(+)
 create mode 100644 src/python/m5/util/code_formatter.py

(limited to 'src')

diff --git a/src/python/SConscript b/src/python/SConscript
index c36f03695..bb892f376 100644
--- a/src/python/SConscript
+++ b/src/python/SConscript
@@ -53,6 +53,7 @@ PySource('m5', 'm5/ticks.py')
 PySource('m5', 'm5/trace.py')
 PySource('m5.util', 'm5/util/__init__.py')
 PySource('m5.util', 'm5/util/attrdict.py')
+PySource('m5.util', 'm5/util/code_formatter.py')
 PySource('m5.util', 'm5/util/grammar.py')
 PySource('m5.util', 'm5/util/jobfile.py')
 PySource('m5.util', 'm5/util/misc.py')
diff --git a/src/python/m5/util/__init__.py b/src/python/m5/util/__init__.py
index 48e8111bd..3930c8b6f 100644
--- a/src/python/m5/util/__init__.py
+++ b/src/python/m5/util/__init__.py
@@ -27,6 +27,7 @@
 # Authors: Nathan Binkert
 
 from attrdict import attrdict, optiondict
+from code_formatter import code_formatter
 from misc import *
 from multidict import multidict
 from orderdict import orderdict
diff --git a/src/python/m5/util/code_formatter.py b/src/python/m5/util/code_formatter.py
new file mode 100644
index 000000000..919a6423b
--- /dev/null
+++ b/src/python/m5/util/code_formatter.py
@@ -0,0 +1,311 @@
+# Copyright (c) 2006-2009 Nathan Binkert <nate@binkert.org>
+# 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.
+
+import inspect
+import os
+import re
+import string
+
+class lookup(object):
+    def __init__(self, formatter, frame, *args, **kwargs):
+        self.frame = frame
+        self.formatter = formatter
+        self.dict = self.formatter._dict
+        self.args = args
+        self.kwargs = kwargs
+        self.locals = {}
+
+    def __setitem__(self, item, val):
+        self.locals[item] = val
+
+    def __getitem__(self, item):
+        if item in self.locals:
+            return self.locals[item]
+
+        if item in self.kwargs:
+            return self.kwargs[item]
+
+        if item == '__file__':
+            return self.frame.f_code.co_filename
+
+        if item == '__line__':
+            return self.frame.f_lineno
+
+        if item in self.dict:
+            return self.dict[item]
+
+        if self.formatter.locals or self.formatter.globals:
+            if self.formatter.locals and item in self.frame.f_locals:
+                return self.frame.f_locals[item]
+
+            if self.formatter.globals and item in self.frame.f_globals:
+                return self.frame.f_globals[item]
+
+        if item in __builtins__:
+            return __builtins__[item]
+
+        try:
+            item = int(item)
+            return self.args[item]
+        except ValueError:
+            pass
+        raise IndexError, "Could not find '%s'" % item
+
+class code_formatter_meta(type):
+    pattern = r"""
+    (?:
+      %(delim)s(?P<escaped>%(delim)s)              | # escaped delimiter
+      ^(?P<indent>[ ]*)%(delim)s(?P<lone>%(ident)s)$ | # lone identifier
+      %(delim)s(?P<ident>%(ident)s)                | # identifier
+      %(delim)s%(lb)s(?P<b_ident>%(ident)s)%(rb)s  | # braced identifier
+      %(delim)s(?P<pos>%(pos)s)                    | # positional parameter
+      %(delim)s%(lb)s(?P<b_pos>%(pos)s)%(rb)s      | # braced positional
+      %(delim)s%(ldb)s(?P<eval>.*?)%(rdb)s         | # double braced expression
+      %(delim)s(?P<invalid>)                       # ill-formed delimiter exprs
+    )
+    """
+    def __init__(cls, name, bases, dct):
+        super(code_formatter_meta, cls).__init__(name, bases, dct)
+        if 'pattern' in dct:
+            pat = cls.pattern
+        else:
+            # tuple expansion to ensure strings are proper length
+            lb,rb = cls.braced
+            lb1,lb2,rb2,rb1 = cls.double_braced
+            pat = code_formatter_meta.pattern % {
+                'delim' : re.escape(cls.delim),
+                'ident' : cls.ident,
+                'pos' : cls.pos,
+                'lb' : re.escape(lb),
+                'rb' : re.escape(rb),
+                'ldb' : re.escape(lb1+lb2),
+                'rdb' : re.escape(rb2+rb1),
+                }
+        cls.pattern = re.compile(pat, re.VERBOSE | re.DOTALL | re.MULTILINE)
+
+class code_formatter(object):
+    __metaclass__ = code_formatter_meta
+
+    delim = r'$'
+    ident = r'[_A-z]\w*'
+    pos = r'[0-9]+'
+    braced = r'{}'
+    double_braced = r'{{}}'
+
+    globals = True
+    locals = True
+    fix_newlines = True
+    def __init__(self, *args, **kwargs):
+        self._data = []
+        self._dict = {}
+        self._indent_level = 0
+        self._indent_spaces = 4
+        self.globals = kwargs.pop('globals',type(self).globals)
+        self.locals = kwargs.pop('locals', type(self).locals)
+        self._fix_newlines = \
+                kwargs.pop('fix_newlines', type(self).fix_newlines)
+
+        if args:
+            self.__call__(args)
+
+    def indent(self):
+        self._indent_level += self._indent_spaces
+
+    def dedent(self):
+        assert self._indent_level >= self._indent_spaces
+        self._indent_level -= self._indent_spaces
+
+    def fix(self, status):
+        previous = self._fix_newlines
+        self._fix_newlines = status
+        return previous
+
+    def nofix(self):
+        previous = self._fix_newlines
+        self._fix_newlines = False
+        return previous
+
+    def clear():
+        self._data = []
+
+    def write(self, *args):
+        f = file(os.path.join(*args), "w")
+        for data in self._data:
+            f.write(data)
+        f.close()
+
+    def __str__(self):
+        data = string.join(self._data, '')
+        self._data = [ data ]
+        return data
+
+    def __getitem__(self, item):
+        return self._dict[item]
+
+    def __setitem__(self, item, value):
+        self._dict[item] = value
+
+    def __delitem__(self, item):
+        del self._dict[item]
+
+    def __contains__(self, item):
+        return item in self._dict
+
+    def __iadd__(self, data):
+        self.append(data)
+
+    def append(self, data):
+        if isinstance(data, code_formatter):
+            self._data.extend(data._data)
+        else:
+            self._append(str(data))
+
+    def _append(self, data):
+        if not self._fix_newlines:
+            self._data.append(data)
+            return
+
+        initial_newline = not self._data or self._data[-1] == '\n'
+        for line in data.splitlines():
+            if line:
+                if self._indent_level:
+                    self._data.append(' ' * self._indent_level)
+                self._data.append(line)
+
+            if line or not initial_newline:
+                self._data.append('\n')
+
+            initial_newline = False
+
+    def insert_newline(self):
+        self._data.append('\n')
+
+    def __call__(self, format, *args, **kwargs):
+        frame = inspect.currentframe().f_back
+
+        l = lookup(self, frame, *args, **kwargs)
+        def convert(match):
+            ident = match.group('lone')
+            # check for a lone identifier
+            if ident:
+                indent = match.group('indent') # must be spaces
+                lone = '%s' % (l[ident], )
+
+                def indent_lines(gen):
+                    for line in gen:
+                        yield indent
+                        yield line
+                return ''.join(indent_lines(lone.splitlines(True)))
+
+            # check for an identifier, braced or not
+            ident = match.group('ident') or match.group('b_ident')
+            if ident is not None:
+                return '%s' % (l[ident], )
+
+            # check for a positional parameter, braced or not
+            pos = match.group('pos') or match.group('b_pos')
+            if pos is not None:
+                pos = int(pos)
+                if pos > len(args):
+                    raise ValueError \
+                        ('Positional parameter #%d not found in pattern' % pos,
+                         code_formatter.pattern)
+                return '%s' % (args[int(pos)], )
+
+            # check for a double braced expression
+            eval_expr = match.group('eval')
+            if eval_expr is not None:
+                result = eval(eval_expr, {}, l)
+                return '%s' % (result, )
+
+            # check for an escaped delimiter
+            if match.group('escaped') is not None:
+                return '$'
+
+            # At this point, we have to match invalid
+            if match.group('invalid') is None:
+                # didn't match invalid!
+                raise ValueError('Unrecognized named group in pattern',
+                                 code_formatter.pattern)
+
+            i = match.start('invalid')
+            if i == 0:
+                colno = 1
+                lineno = 1
+            else:
+                lines = format[:i].splitlines(True)
+                colno = i - reduce(lambda x,y: x+y, (len(z) for z in lines))
+                lineno = len(lines)
+
+                raise ValueError('Invalid format string: line %d, col %d' %
+                                 (lineno, colno))
+
+        d = code_formatter.pattern.sub(convert, format)
+        self._append(d)
+
+__all__ = [ "code_formatter" ]
+
+if __name__ == '__main__':
+    from code_formatter import code_formatter
+    f = code_formatter()
+
+    class Foo(dict):
+        def __init__(self, **kwargs):
+            self.update(kwargs)
+        def __getattr__(self, attr):
+            return self[attr]
+
+    x = "this is a test"
+    l = [ [Foo(x=[Foo(y=9)])] ]
+
+    y = code_formatter()
+    y('''
+{
+    this_is_a_test();
+}
+''')
+    f('    $y')
+    f('''$__file__:$__line__
+{''')
+    f("${{', '.join(str(x) for x in xrange(4))}}")
+    f('${x}')
+    f('$x')
+    f.indent()
+    for i in xrange(5):
+        f('$x')
+        f('$i')
+        f('$0', "zero")
+        f('$1 $0', "zero", "one")
+        f('${0}', "he went")
+        f('${0}asdf', "he went")
+    f.dedent()
+
+    f('''
+    ${{l[0][0]["x"][0].y}}
+}
+''', 1, 9)
+
+    print f,
-- 
cgit v1.2.3