summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2009-08-17 00:21:57 -0700
committerGabe Black <gblack@eecs.umich.edu>2009-08-17 00:21:57 -0700
commita43ae579dd3128a0ced2238532f26d99db197361 (patch)
tree271a90c0fdfde8b58180ee494c528a3fbec57588 /src
parent32c8514b450a7dda77a3963d00642fcc5de658da (diff)
parenta6b39c07d9d03955382a0e930b363c6e6fd4b942 (diff)
downloadgem5-a43ae579dd3128a0ced2238532f26d99db197361.tar.xz
Merge with head.
Diffstat (limited to 'src')
-rw-r--r--src/mem/protocol/MOESI_CMP_directory-dir.sm15
-rw-r--r--src/mem/protocol/MOESI_CMP_directory-dma.sm17
-rw-r--r--src/mem/protocol/MOESI_CMP_token-L2cache.sm2
-rw-r--r--src/mem/protocol/MSI_MOSI_CMP_directory-L2cache.sm2
-rw-r--r--src/mem/protocol/RubySlicc_Util.sm1
-rw-r--r--src/mem/ruby/config/cfg.rb6
-rw-r--r--src/mem/ruby/config/defaults.rb4
-rw-r--r--src/mem/ruby/network/Network.cc39
-rw-r--r--src/mem/ruby/network/Network.hh41
-rw-r--r--src/mem/ruby/network/garnet-fixed-pipeline/NetworkInterface_d.cc2
-rw-r--r--src/mem/ruby/network/garnet-flexible-pipeline/NetworkInterface.cc2
-rw-r--r--src/mem/ruby/network/simple/Switch.cc2
-rw-r--r--src/mem/ruby/network/simple/Throttle.cc4
-rw-r--r--src/mem/ruby/slicc_interface/RubySlicc_Util.hh5
-rw-r--r--src/python/SConscript3
-rw-r--r--src/python/m5/__init__.py13
-rw-r--r--src/python/m5/util/__init__.py2
-rw-r--r--src/python/m5/util/code_formatter.py311
-rw-r--r--src/python/m5/util/grammar.py119
-rw-r--r--src/python/m5/util/orderdict.py59
20 files changed, 543 insertions, 106 deletions
diff --git a/src/mem/protocol/MOESI_CMP_directory-dir.sm b/src/mem/protocol/MOESI_CMP_directory-dir.sm
index edd67707e..8d8ee7f8a 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;
@@ -695,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;
}
@@ -710,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;
}
diff --git a/src/mem/protocol/MOESI_CMP_directory-dma.sm b/src/mem/protocol/MOESI_CMP_directory-dma.sm
index 74246c730..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,11 +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);
- } else if (in_msg.Type == CoherenceResponseType:DATA_EXCLUSIVE) {
- trigger(Event:Data, 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, 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");
}
@@ -125,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;
@@ -139,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;
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 b37725402..312682bd7 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 ffc36dd67..445bb4885 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
@@ -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]
@@ -631,7 +631,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 4723df505..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"
@@ -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 0ea5df08b..3d4fa3e5c 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);
diff --git a/src/python/SConscript b/src/python/SConscript
index a767545ec..bb892f376 100644
--- a/src/python/SConscript
+++ b/src/python/SConscript
@@ -53,9 +53,12 @@ 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')
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/__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
diff --git a/src/python/m5/util/__init__.py b/src/python/m5/util/__init__.py
index 5c4a066c6..3930c8b6f 100644
--- a/src/python/m5/util/__init__.py
+++ b/src/python/m5/util/__init__.py
@@ -27,8 +27,10 @@
# 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
import jobfile
def print_list(items, indent=4):
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,
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
+
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 ]