read_config.py revision 12410
110458Sandreas.hansson@arm.com# Copyright (c) 2014 ARM Limited 210458Sandreas.hansson@arm.com# All rights reserved. 310458Sandreas.hansson@arm.com# 410458Sandreas.hansson@arm.com# The license below extends only to copyright in the software and shall 510458Sandreas.hansson@arm.com# not be construed as granting a license to any other intellectual 610458Sandreas.hansson@arm.com# property including but not limited to intellectual property relating 710458Sandreas.hansson@arm.com# to a hardware implementation of the functionality of the software 810458Sandreas.hansson@arm.com# licensed hereunder. You may use the software subject to the license 910458Sandreas.hansson@arm.com# terms below provided that you ensure that this notice is replicated 1010458Sandreas.hansson@arm.com# unmodified and in its entirety in all distributions of the software, 1110458Sandreas.hansson@arm.com# modified or unmodified, in source code or in binary form. 1210458Sandreas.hansson@arm.com# 1310458Sandreas.hansson@arm.com# Redistribution and use in source and binary forms, with or without 1410458Sandreas.hansson@arm.com# modification, are permitted provided that the following conditions are 1510458Sandreas.hansson@arm.com# met: redistributions of source code must retain the above copyright 1610458Sandreas.hansson@arm.com# notice, this list of conditions and the following disclaimer; 1710458Sandreas.hansson@arm.com# redistributions in binary form must reproduce the above copyright 1810458Sandreas.hansson@arm.com# notice, this list of conditions and the following disclaimer in the 1910458Sandreas.hansson@arm.com# documentation and/or other materials provided with the distribution; 2010458Sandreas.hansson@arm.com# neither the name of the copyright holders nor the names of its 2110458Sandreas.hansson@arm.com# contributors may be used to endorse or promote products derived from 2210458Sandreas.hansson@arm.com# this software without specific prior written permission. 2310458Sandreas.hansson@arm.com# 2410458Sandreas.hansson@arm.com# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2510458Sandreas.hansson@arm.com# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2610458Sandreas.hansson@arm.com# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2710458Sandreas.hansson@arm.com# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2810458Sandreas.hansson@arm.com# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2910458Sandreas.hansson@arm.com# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3010458Sandreas.hansson@arm.com# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3110458Sandreas.hansson@arm.com# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3210458Sandreas.hansson@arm.com# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3310458Sandreas.hansson@arm.com# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3410458Sandreas.hansson@arm.com# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3510458Sandreas.hansson@arm.com# 3610458Sandreas.hansson@arm.com# Author: Andrew Bardsley 3710458Sandreas.hansson@arm.com 3810458Sandreas.hansson@arm.com# This script allows .ini and .json system config file generated from a 3910458Sandreas.hansson@arm.com# previous gem5 run to be read in and instantiated. 4010458Sandreas.hansson@arm.com# 4110458Sandreas.hansson@arm.com# This may be useful as a way of allowing variant run scripts (say, 4210458Sandreas.hansson@arm.com# with more complicated than usual checkpointing/stats dumping/ 4310458Sandreas.hansson@arm.com# simulation control) to read pre-described systems from config scripts 4410458Sandreas.hansson@arm.com# with better system-description capabilities. Splitting scripts 4510458Sandreas.hansson@arm.com# between system construction and run control may allow better 4610458Sandreas.hansson@arm.com# debugging. 4710458Sandreas.hansson@arm.com 4810458Sandreas.hansson@arm.comimport argparse 4910458Sandreas.hansson@arm.comimport ConfigParser 5010458Sandreas.hansson@arm.comimport inspect 5110458Sandreas.hansson@arm.comimport json 5210458Sandreas.hansson@arm.comimport re 5310458Sandreas.hansson@arm.comimport sys 5410458Sandreas.hansson@arm.com 5510458Sandreas.hansson@arm.comimport m5 5610458Sandreas.hansson@arm.comimport m5.ticks as ticks 5710458Sandreas.hansson@arm.com 5810458Sandreas.hansson@arm.comsim_object_classes_by_name = { 5910458Sandreas.hansson@arm.com cls.__name__: cls for cls in m5.objects.__dict__.itervalues() 6010458Sandreas.hansson@arm.com if inspect.isclass(cls) and issubclass(cls, m5.objects.SimObject) } 6110458Sandreas.hansson@arm.com 6210458Sandreas.hansson@arm.com# Add some parsing functions to Param classes to handle reading in .ini 6310458Sandreas.hansson@arm.com# file elements. This could be moved into src/python/m5/params.py if 6410458Sandreas.hansson@arm.com# reading .ini files from Python proves to be useful 6510458Sandreas.hansson@arm.com 6610458Sandreas.hansson@arm.comdef no_parser(cls, flags, param): 6710458Sandreas.hansson@arm.com raise Exception('Can\'t parse string: %s for parameter' 6810458Sandreas.hansson@arm.com ' class: %s' % (str(param), cls.__name__)) 6910458Sandreas.hansson@arm.com 7010458Sandreas.hansson@arm.comdef simple_parser(suffix='', cast=lambda i: i): 7110458Sandreas.hansson@arm.com def body(cls, flags, param): 7210458Sandreas.hansson@arm.com return cls(cast(param + suffix)) 7310458Sandreas.hansson@arm.com return body 7410458Sandreas.hansson@arm.com 7510458Sandreas.hansson@arm.com# def tick_parser(cast=m5.objects.Latency): # lambda i: i): 7610458Sandreas.hansson@arm.comdef tick_parser(cast=lambda i: i): 7710458Sandreas.hansson@arm.com def body(cls, flags, param): 7810458Sandreas.hansson@arm.com old_param = param 7910458Sandreas.hansson@arm.com ret = cls(cast(str(param) + 't')) 8010458Sandreas.hansson@arm.com return ret 8110458Sandreas.hansson@arm.com return body 8210458Sandreas.hansson@arm.com 8310458Sandreas.hansson@arm.comdef addr_range_parser(cls, flags, param): 8410458Sandreas.hansson@arm.com sys.stdout.flush() 8512410Sgabeblack@google.com (low, high, intlv_high_bit, xor_high_bit, 8612410Sgabeblack@google.com intlv_bits, intlv_match) = param.split(':') 8712410Sgabeblack@google.com return m5.objects.AddrRange( 8812410Sgabeblack@google.com start=long(low), end=long(high), 8912410Sgabeblack@google.com intlvHighBit=long(intlv_high_bit), xorHighBit=long(xor_high_bit), 9012410Sgabeblack@google.com intlvBits=long(intlv_bits), intlvMatch=long(intlv_match)) 9110458Sandreas.hansson@arm.com 9210458Sandreas.hansson@arm.comdef memory_bandwidth_parser(cls, flags, param): 9310458Sandreas.hansson@arm.com # The string will be in tick/byte 9410458Sandreas.hansson@arm.com # Convert to byte/tick 9510458Sandreas.hansson@arm.com value = 1.0 / float(param) 9610458Sandreas.hansson@arm.com # Convert to byte/s 9710458Sandreas.hansson@arm.com value = ticks.fromSeconds(value) 9810458Sandreas.hansson@arm.com return cls('%fB/s' % value) 9910458Sandreas.hansson@arm.com 10010458Sandreas.hansson@arm.com# These parameters have trickier parsing from .ini files than might be 10110458Sandreas.hansson@arm.com# expected 10210458Sandreas.hansson@arm.comparam_parsers = { 10310458Sandreas.hansson@arm.com 'Bool': simple_parser(), 10410458Sandreas.hansson@arm.com 'ParamValue': no_parser, 10510458Sandreas.hansson@arm.com 'NumericParamValue': simple_parser(cast=long), 10610458Sandreas.hansson@arm.com 'TickParamValue': tick_parser(), 10710458Sandreas.hansson@arm.com 'Frequency': tick_parser(cast=m5.objects.Latency), 10811228SAndrew.Bardsley@arm.com 'Current': simple_parser(suffix='A'), 10910458Sandreas.hansson@arm.com 'Voltage': simple_parser(suffix='V'), 11010458Sandreas.hansson@arm.com 'Enum': simple_parser(), 11110458Sandreas.hansson@arm.com 'MemorySize': simple_parser(suffix='B'), 11210458Sandreas.hansson@arm.com 'MemorySize32': simple_parser(suffix='B'), 11310458Sandreas.hansson@arm.com 'AddrRange': addr_range_parser, 11410458Sandreas.hansson@arm.com 'String': simple_parser(), 11510458Sandreas.hansson@arm.com 'MemoryBandwidth': memory_bandwidth_parser, 11611228SAndrew.Bardsley@arm.com 'Time': simple_parser(), 11711228SAndrew.Bardsley@arm.com 'EthernetAddr': simple_parser() 11810458Sandreas.hansson@arm.com } 11910458Sandreas.hansson@arm.com 12010458Sandreas.hansson@arm.comfor name, parser in param_parsers.iteritems(): 12110458Sandreas.hansson@arm.com setattr(m5.params.__dict__[name], 'parse_ini', classmethod(parser)) 12210458Sandreas.hansson@arm.com 12310458Sandreas.hansson@arm.comclass PortConnection(object): 12410458Sandreas.hansson@arm.com """This class is similar to m5.params.PortRef but with just enough 12510458Sandreas.hansson@arm.com information for ConfigManager""" 12610458Sandreas.hansson@arm.com 12710458Sandreas.hansson@arm.com def __init__(self, object_name, port_name, index): 12810458Sandreas.hansson@arm.com self.object_name = object_name 12910458Sandreas.hansson@arm.com self.port_name = port_name 13010458Sandreas.hansson@arm.com self.index = index 13110458Sandreas.hansson@arm.com 13210458Sandreas.hansson@arm.com @classmethod 13310458Sandreas.hansson@arm.com def from_string(cls, str): 13410458Sandreas.hansson@arm.com m = re.match('(.*)\.([^.\[]+)(\[(\d+)\])?', str) 13510458Sandreas.hansson@arm.com object_name, port_name, whole_index, index = m.groups() 13610458Sandreas.hansson@arm.com if index is not None: 13710458Sandreas.hansson@arm.com index = int(index) 13810458Sandreas.hansson@arm.com else: 13910458Sandreas.hansson@arm.com index = 0 14010458Sandreas.hansson@arm.com 14110458Sandreas.hansson@arm.com return PortConnection(object_name, port_name, index) 14210458Sandreas.hansson@arm.com 14310458Sandreas.hansson@arm.com def __str__(self): 14410458Sandreas.hansson@arm.com return '%s.%s[%d]' % (self.object_name, self.port_name, self.index) 14510458Sandreas.hansson@arm.com 14610458Sandreas.hansson@arm.com def __cmp__(self, right): 14710458Sandreas.hansson@arm.com return cmp((self.object_name, self.port_name, self.index), 14810458Sandreas.hansson@arm.com (right.object_name, right.port_name, right.index)) 14910458Sandreas.hansson@arm.com 15010458Sandreas.hansson@arm.comdef to_list(v): 15110458Sandreas.hansson@arm.com """Convert any non list to a singleton list""" 15210458Sandreas.hansson@arm.com if isinstance(v, list): 15310458Sandreas.hansson@arm.com return v 15410458Sandreas.hansson@arm.com else: 15510458Sandreas.hansson@arm.com return [v] 15610458Sandreas.hansson@arm.com 15710458Sandreas.hansson@arm.comclass ConfigManager(object): 15810458Sandreas.hansson@arm.com """Manager for parsing a Root configuration from a config file""" 15910458Sandreas.hansson@arm.com def __init__(self, config): 16010458Sandreas.hansson@arm.com self.config = config 16110458Sandreas.hansson@arm.com self.objects_by_name = {} 16210458Sandreas.hansson@arm.com self.flags = config.get_flags() 16310458Sandreas.hansson@arm.com 16410458Sandreas.hansson@arm.com def find_object(self, object_name): 16510458Sandreas.hansson@arm.com """Find and configure (with just non-SimObject parameters) 16610458Sandreas.hansson@arm.com a single object""" 16710458Sandreas.hansson@arm.com 16810458Sandreas.hansson@arm.com if object_name == 'Null': 16910458Sandreas.hansson@arm.com return NULL 17010458Sandreas.hansson@arm.com 17110458Sandreas.hansson@arm.com if object_name in self.objects_by_name: 17210458Sandreas.hansson@arm.com return self.objects_by_name[object_name] 17310458Sandreas.hansson@arm.com 17410458Sandreas.hansson@arm.com object_type = self.config.get_param(object_name, 'type') 17510458Sandreas.hansson@arm.com 17610458Sandreas.hansson@arm.com if object_type not in sim_object_classes_by_name: 17710458Sandreas.hansson@arm.com raise Exception('No SimObject type %s is available to' 17810458Sandreas.hansson@arm.com ' build: %s' % (object_type, object_name)) 17910458Sandreas.hansson@arm.com 18010458Sandreas.hansson@arm.com object_class = sim_object_classes_by_name[object_type] 18110458Sandreas.hansson@arm.com 18210458Sandreas.hansson@arm.com parsed_params = {} 18310458Sandreas.hansson@arm.com 18410458Sandreas.hansson@arm.com for param_name, param in object_class._params.iteritems(): 18510458Sandreas.hansson@arm.com if issubclass(param.ptype, m5.params.ParamValue): 18610458Sandreas.hansson@arm.com if isinstance(param, m5.params.VectorParamDesc): 18710458Sandreas.hansson@arm.com param_values = self.config.get_param_vector(object_name, 18810458Sandreas.hansson@arm.com param_name) 18910458Sandreas.hansson@arm.com 19010458Sandreas.hansson@arm.com param_value = [ param.ptype.parse_ini(self.flags, value) 19110458Sandreas.hansson@arm.com for value in param_values ] 19210458Sandreas.hansson@arm.com else: 19310458Sandreas.hansson@arm.com param_value = param.ptype.parse_ini( 19410458Sandreas.hansson@arm.com self.flags, self.config.get_param(object_name, 19510458Sandreas.hansson@arm.com param_name)) 19610458Sandreas.hansson@arm.com 19710458Sandreas.hansson@arm.com parsed_params[param_name] = param_value 19810458Sandreas.hansson@arm.com 19910458Sandreas.hansson@arm.com obj = object_class(**parsed_params) 20010458Sandreas.hansson@arm.com self.objects_by_name[object_name] = obj 20110458Sandreas.hansson@arm.com 20210458Sandreas.hansson@arm.com return obj 20310458Sandreas.hansson@arm.com 20410458Sandreas.hansson@arm.com def fill_in_simobj_parameters(self, object_name, obj): 20510458Sandreas.hansson@arm.com """Fill in all references to other SimObjects in an objects 20610458Sandreas.hansson@arm.com parameters. This relies on all referenced objects having been 20710458Sandreas.hansson@arm.com created""" 20810458Sandreas.hansson@arm.com 20910458Sandreas.hansson@arm.com if object_name == 'Null': 21010458Sandreas.hansson@arm.com return NULL 21110458Sandreas.hansson@arm.com 21210458Sandreas.hansson@arm.com for param_name, param in obj.__class__._params.iteritems(): 21310458Sandreas.hansson@arm.com if issubclass(param.ptype, m5.objects.SimObject): 21410458Sandreas.hansson@arm.com if isinstance(param, m5.params.VectorParamDesc): 21510458Sandreas.hansson@arm.com param_values = self.config.get_param_vector(object_name, 21610458Sandreas.hansson@arm.com param_name) 21710458Sandreas.hansson@arm.com 21810458Sandreas.hansson@arm.com setattr(obj, param_name, [ self.objects_by_name[name] 21910458Sandreas.hansson@arm.com for name in param_values ]) 22010458Sandreas.hansson@arm.com else: 22110458Sandreas.hansson@arm.com param_value = self.config.get_param(object_name, 22210458Sandreas.hansson@arm.com param_name) 22310458Sandreas.hansson@arm.com 22410458Sandreas.hansson@arm.com if param_value != 'Null': 22510458Sandreas.hansson@arm.com setattr(obj, param_name, self.objects_by_name[ 22610458Sandreas.hansson@arm.com param_value]) 22710458Sandreas.hansson@arm.com 22810458Sandreas.hansson@arm.com return obj 22910458Sandreas.hansson@arm.com 23010458Sandreas.hansson@arm.com def fill_in_children(self, object_name, obj): 23110458Sandreas.hansson@arm.com """Fill in the children of this object. This relies on all the 23210458Sandreas.hansson@arm.com referenced objects having been created""" 23310458Sandreas.hansson@arm.com 23410458Sandreas.hansson@arm.com children = self.config.get_object_children(object_name) 23510458Sandreas.hansson@arm.com 23610458Sandreas.hansson@arm.com for child_name, child_paths in children: 23710458Sandreas.hansson@arm.com param = obj.__class__._params.get(child_name, None) 23810458Sandreas.hansson@arm.com 23910458Sandreas.hansson@arm.com if isinstance(child_paths, list): 24010458Sandreas.hansson@arm.com child_list = [ self.objects_by_name[path] 24110458Sandreas.hansson@arm.com for path in child_paths ] 24210458Sandreas.hansson@arm.com else: 24310458Sandreas.hansson@arm.com child_list = self.objects_by_name[child_paths] 24410458Sandreas.hansson@arm.com 24510458Sandreas.hansson@arm.com obj.add_child(child_name, child_list) 24610458Sandreas.hansson@arm.com 24710458Sandreas.hansson@arm.com for path in to_list(child_paths): 24810458Sandreas.hansson@arm.com self.fill_in_children(path, self.objects_by_name[path]) 24910458Sandreas.hansson@arm.com 25010458Sandreas.hansson@arm.com return obj 25110458Sandreas.hansson@arm.com 25210458Sandreas.hansson@arm.com def parse_port_name(self, port): 25310458Sandreas.hansson@arm.com """Parse the name of a port""" 25410458Sandreas.hansson@arm.com 25510458Sandreas.hansson@arm.com m = re.match('(.*)\.([^.\[]+)(\[(\d+)\])?', port) 25610458Sandreas.hansson@arm.com peer, peer_port, whole_index, index = m.groups() 25710458Sandreas.hansson@arm.com if index is not None: 25810458Sandreas.hansson@arm.com index = int(index) 25910458Sandreas.hansson@arm.com else: 26010458Sandreas.hansson@arm.com index = 0 26110458Sandreas.hansson@arm.com 26210458Sandreas.hansson@arm.com return (peer, self.objects_by_name[peer], peer_port, index) 26310458Sandreas.hansson@arm.com 26410458Sandreas.hansson@arm.com def gather_port_connections(self, object_name, obj): 26510458Sandreas.hansson@arm.com """Gather all the port-to-port connections from the named object. 26610458Sandreas.hansson@arm.com Returns a list of (PortConnection, PortConnection) with unordered 26710458Sandreas.hansson@arm.com (wrt. master/slave) connection information""" 26810458Sandreas.hansson@arm.com 26910458Sandreas.hansson@arm.com if object_name == 'Null': 27010458Sandreas.hansson@arm.com return NULL 27110458Sandreas.hansson@arm.com 27210458Sandreas.hansson@arm.com parsed_ports = [] 27310458Sandreas.hansson@arm.com for port_name, port in obj.__class__._ports.iteritems(): 27410458Sandreas.hansson@arm.com # Assume that unnamed ports are unconnected 27510458Sandreas.hansson@arm.com peers = self.config.get_port_peers(object_name, port_name) 27610458Sandreas.hansson@arm.com 27710458Sandreas.hansson@arm.com for index, peer in zip(xrange(0, len(peers)), peers): 27810458Sandreas.hansson@arm.com parsed_ports.append(( 27910458Sandreas.hansson@arm.com PortConnection(object_name, port.name, index), 28010458Sandreas.hansson@arm.com PortConnection.from_string(peer))) 28110458Sandreas.hansson@arm.com 28210458Sandreas.hansson@arm.com return parsed_ports 28310458Sandreas.hansson@arm.com 28410458Sandreas.hansson@arm.com def bind_ports(self, connections): 28510458Sandreas.hansson@arm.com """Bind all ports from the given connection list. Note that the 28610458Sandreas.hansson@arm.com connection list *must* list all connections with both (slave,master) 28710458Sandreas.hansson@arm.com and (master,slave) orderings""" 28810458Sandreas.hansson@arm.com 28910458Sandreas.hansson@arm.com # Markup a dict of how many connections are made to each port. 29010458Sandreas.hansson@arm.com # This will be used to check that the next-to-be-made connection 29110458Sandreas.hansson@arm.com # has a suitable port index 29210458Sandreas.hansson@arm.com port_bind_indices = {} 29310458Sandreas.hansson@arm.com for from_port, to_port in connections: 29410458Sandreas.hansson@arm.com port_bind_indices[ 29510458Sandreas.hansson@arm.com (from_port.object_name, from_port.port_name)] = 0 29610458Sandreas.hansson@arm.com 29710458Sandreas.hansson@arm.com def port_has_correct_index(port): 29810458Sandreas.hansson@arm.com return port_bind_indices[ 29910458Sandreas.hansson@arm.com (port.object_name, port.port_name)] == port.index 30010458Sandreas.hansson@arm.com 30110458Sandreas.hansson@arm.com def increment_port_index(port): 30210458Sandreas.hansson@arm.com port_bind_indices[ 30310458Sandreas.hansson@arm.com (port.object_name, port.port_name)] += 1 30410458Sandreas.hansson@arm.com 30510458Sandreas.hansson@arm.com # Step through the sorted connections. Exactly one of 30610458Sandreas.hansson@arm.com # each (slave,master) and (master,slave) pairs will be 30710458Sandreas.hansson@arm.com # bindable because the connections are sorted. 30810458Sandreas.hansson@arm.com # For example: port_bind_indices 30910458Sandreas.hansson@arm.com # left right left right 31010458Sandreas.hansson@arm.com # a.b[0] -> d.f[1] 0 0 X 31110458Sandreas.hansson@arm.com # a.b[1] -> e.g 0 0 BIND! 31210458Sandreas.hansson@arm.com # e.g -> a.b[1] 1 X 0 31310458Sandreas.hansson@arm.com # d.f[0] -> f.h 0 0 BIND! 31410458Sandreas.hansson@arm.com # d.f[1] -> a.b[0] 1 0 BIND! 31510458Sandreas.hansson@arm.com connections_to_make = [] 31610458Sandreas.hansson@arm.com for connection in sorted(connections): 31710458Sandreas.hansson@arm.com from_port, to_port = connection 31810458Sandreas.hansson@arm.com 31910458Sandreas.hansson@arm.com if (port_has_correct_index(from_port) and 32010458Sandreas.hansson@arm.com port_has_correct_index(to_port)): 32110458Sandreas.hansson@arm.com 32210458Sandreas.hansson@arm.com connections_to_make.append((from_port, to_port)) 32310458Sandreas.hansson@arm.com 32410458Sandreas.hansson@arm.com increment_port_index(from_port) 32510458Sandreas.hansson@arm.com increment_port_index(to_port) 32610458Sandreas.hansson@arm.com 32710458Sandreas.hansson@arm.com # Exactly half of the connections (ie. all of them, one per 32810458Sandreas.hansson@arm.com # direction) must now have been made 32910458Sandreas.hansson@arm.com if (len(connections_to_make) * 2) != len(connections): 33010458Sandreas.hansson@arm.com raise Exception('Port bindings can\'t be ordered') 33110458Sandreas.hansson@arm.com 33210458Sandreas.hansson@arm.com # Actually do the binding 33310458Sandreas.hansson@arm.com for from_port, to_port in connections_to_make: 33410458Sandreas.hansson@arm.com from_object = self.objects_by_name[from_port.object_name] 33510458Sandreas.hansson@arm.com to_object = self.objects_by_name[to_port.object_name] 33610458Sandreas.hansson@arm.com 33710458Sandreas.hansson@arm.com setattr(from_object, from_port.port_name, 33810458Sandreas.hansson@arm.com getattr(to_object, to_port.port_name)) 33910458Sandreas.hansson@arm.com 34010458Sandreas.hansson@arm.com def find_all_objects(self): 34110458Sandreas.hansson@arm.com """Find and build all SimObjects from the config file and connect 34210458Sandreas.hansson@arm.com their ports together as described. Does not instantiate system""" 34310458Sandreas.hansson@arm.com 34410458Sandreas.hansson@arm.com # Build SimObjects for all sections of the config file 34510458Sandreas.hansson@arm.com # populating not-SimObject-valued parameters 34610458Sandreas.hansson@arm.com for object_name in self.config.get_all_object_names(): 34710458Sandreas.hansson@arm.com self.find_object(object_name) 34810458Sandreas.hansson@arm.com 34910458Sandreas.hansson@arm.com # Add children to objects in the hierarchy from root 35010458Sandreas.hansson@arm.com self.fill_in_children('root', self.find_object('root')) 35110458Sandreas.hansson@arm.com 35210458Sandreas.hansson@arm.com # Now fill in SimObject-valued parameters in the knowledge that 35310458Sandreas.hansson@arm.com # this won't be interpreted as becoming the parent of objects 35410458Sandreas.hansson@arm.com # which are already in the root hierarchy 35510458Sandreas.hansson@arm.com for name, obj in self.objects_by_name.iteritems(): 35610458Sandreas.hansson@arm.com self.fill_in_simobj_parameters(name, obj) 35710458Sandreas.hansson@arm.com 35810458Sandreas.hansson@arm.com # Gather a list of all port-to-port connections 35910458Sandreas.hansson@arm.com connections = [] 36010458Sandreas.hansson@arm.com for name, obj in self.objects_by_name.iteritems(): 36110458Sandreas.hansson@arm.com connections += self.gather_port_connections(name, obj) 36210458Sandreas.hansson@arm.com 36310458Sandreas.hansson@arm.com # Find an acceptable order to bind those port connections and 36410458Sandreas.hansson@arm.com # bind them 36510458Sandreas.hansson@arm.com self.bind_ports(connections) 36610458Sandreas.hansson@arm.com 36710458Sandreas.hansson@arm.comclass ConfigFile(object): 36810458Sandreas.hansson@arm.com def get_flags(self): 36910458Sandreas.hansson@arm.com return set() 37010458Sandreas.hansson@arm.com 37110458Sandreas.hansson@arm.com def load(self, config_file): 37210458Sandreas.hansson@arm.com """Load the named config file""" 37310458Sandreas.hansson@arm.com pass 37410458Sandreas.hansson@arm.com 37510458Sandreas.hansson@arm.com def get_all_object_names(self): 37610458Sandreas.hansson@arm.com """Get a list of all the SimObject paths in the configuration""" 37710458Sandreas.hansson@arm.com pass 37810458Sandreas.hansson@arm.com 37910458Sandreas.hansson@arm.com def get_param(self, object_name, param_name): 38010458Sandreas.hansson@arm.com """Get a single param or SimObject reference from the configuration 38110458Sandreas.hansson@arm.com as a string""" 38210458Sandreas.hansson@arm.com pass 38310458Sandreas.hansson@arm.com 38410458Sandreas.hansson@arm.com def get_param_vector(self, object_name, param_name): 38510458Sandreas.hansson@arm.com """Get a vector param or vector of SimObject references from the 38610458Sandreas.hansson@arm.com configuration as a list of strings""" 38710458Sandreas.hansson@arm.com pass 38810458Sandreas.hansson@arm.com 38910458Sandreas.hansson@arm.com def get_object_children(self, object_name): 39010458Sandreas.hansson@arm.com """Get a list of (name, paths) for each child of this object. 39110458Sandreas.hansson@arm.com paths is either a single string object path or a list of object 39210458Sandreas.hansson@arm.com paths""" 39310458Sandreas.hansson@arm.com pass 39410458Sandreas.hansson@arm.com 39510458Sandreas.hansson@arm.com def get_port_peers(self, object_name, port_name): 39610458Sandreas.hansson@arm.com """Get the list of connected port names (in the string form 39710458Sandreas.hansson@arm.com object.port(\[index\])?) of the port object_name.port_name""" 39810458Sandreas.hansson@arm.com pass 39910458Sandreas.hansson@arm.com 40010458Sandreas.hansson@arm.comclass ConfigIniFile(ConfigFile): 40110458Sandreas.hansson@arm.com def __init__(self): 40210458Sandreas.hansson@arm.com self.parser = ConfigParser.ConfigParser() 40310458Sandreas.hansson@arm.com 40410458Sandreas.hansson@arm.com def load(self, config_file): 40510458Sandreas.hansson@arm.com self.parser.read(config_file) 40610458Sandreas.hansson@arm.com 40710458Sandreas.hansson@arm.com def get_all_object_names(self): 40810458Sandreas.hansson@arm.com return self.parser.sections() 40910458Sandreas.hansson@arm.com 41010458Sandreas.hansson@arm.com def get_param(self, object_name, param_name): 41110458Sandreas.hansson@arm.com return self.parser.get(object_name, param_name) 41210458Sandreas.hansson@arm.com 41310458Sandreas.hansson@arm.com def get_param_vector(self, object_name, param_name): 41410458Sandreas.hansson@arm.com return self.parser.get(object_name, param_name).split() 41510458Sandreas.hansson@arm.com 41610458Sandreas.hansson@arm.com def get_object_children(self, object_name): 41710458Sandreas.hansson@arm.com if self.parser.has_option(object_name, 'children'): 41810458Sandreas.hansson@arm.com children = self.parser.get(object_name, 'children') 41910458Sandreas.hansson@arm.com child_names = children.split() 42010458Sandreas.hansson@arm.com else: 42110458Sandreas.hansson@arm.com child_names = [] 42210458Sandreas.hansson@arm.com 42310458Sandreas.hansson@arm.com def make_path(child_name): 42410458Sandreas.hansson@arm.com if object_name == 'root': 42510458Sandreas.hansson@arm.com return child_name 42610458Sandreas.hansson@arm.com else: 42710458Sandreas.hansson@arm.com return '%s.%s' % (object_name, child_name) 42810458Sandreas.hansson@arm.com 42910458Sandreas.hansson@arm.com return [ (name, make_path(name)) for name in child_names ] 43010458Sandreas.hansson@arm.com 43110458Sandreas.hansson@arm.com def get_port_peers(self, object_name, port_name): 43210458Sandreas.hansson@arm.com if self.parser.has_option(object_name, port_name): 43310458Sandreas.hansson@arm.com peer_string = self.parser.get(object_name, port_name) 43410458Sandreas.hansson@arm.com return peer_string.split() 43510458Sandreas.hansson@arm.com else: 43610458Sandreas.hansson@arm.com return [] 43710458Sandreas.hansson@arm.com 43810458Sandreas.hansson@arm.comclass ConfigJsonFile(ConfigFile): 43910458Sandreas.hansson@arm.com def __init__(self): 44010458Sandreas.hansson@arm.com pass 44110458Sandreas.hansson@arm.com 44210458Sandreas.hansson@arm.com def is_sim_object(self, node): 44310458Sandreas.hansson@arm.com return isinstance(node, dict) and 'path' in node 44410458Sandreas.hansson@arm.com 44510458Sandreas.hansson@arm.com def find_all_objects(self, node): 44610458Sandreas.hansson@arm.com if self.is_sim_object(node): 44710458Sandreas.hansson@arm.com self.object_dicts[node['path']] = node 44810458Sandreas.hansson@arm.com 44910458Sandreas.hansson@arm.com if isinstance(node, list): 45010458Sandreas.hansson@arm.com for elem in node: 45110458Sandreas.hansson@arm.com self.find_all_objects(elem) 45210458Sandreas.hansson@arm.com elif isinstance(node, dict): 45310458Sandreas.hansson@arm.com for elem in node.itervalues(): 45410458Sandreas.hansson@arm.com self.find_all_objects(elem) 45510458Sandreas.hansson@arm.com 45610458Sandreas.hansson@arm.com def load(self, config_file): 45710458Sandreas.hansson@arm.com root = json.load(open(config_file, 'r')) 45810458Sandreas.hansson@arm.com self.object_dicts = {} 45910458Sandreas.hansson@arm.com self.find_all_objects(root) 46010458Sandreas.hansson@arm.com 46110458Sandreas.hansson@arm.com def get_all_object_names(self): 46210458Sandreas.hansson@arm.com return sorted(self.object_dicts.keys()) 46310458Sandreas.hansson@arm.com 46410458Sandreas.hansson@arm.com def parse_param_string(self, node): 46510458Sandreas.hansson@arm.com if node is None: 46610458Sandreas.hansson@arm.com return "Null" 46710458Sandreas.hansson@arm.com elif self.is_sim_object(node): 46810458Sandreas.hansson@arm.com return node['path'] 46910458Sandreas.hansson@arm.com else: 47010458Sandreas.hansson@arm.com return str(node) 47110458Sandreas.hansson@arm.com 47210458Sandreas.hansson@arm.com def get_param(self, object_name, param_name): 47310458Sandreas.hansson@arm.com obj = self.object_dicts[object_name] 47410458Sandreas.hansson@arm.com 47510458Sandreas.hansson@arm.com return self.parse_param_string(obj[param_name]) 47610458Sandreas.hansson@arm.com 47710458Sandreas.hansson@arm.com def get_param_vector(self, object_name, param_name): 47810458Sandreas.hansson@arm.com obj = self.object_dicts[object_name] 47910458Sandreas.hansson@arm.com 48010458Sandreas.hansson@arm.com return [ self.parse_param_string(p) for p in obj[param_name] ] 48110458Sandreas.hansson@arm.com 48210458Sandreas.hansson@arm.com def get_object_children(self, object_name): 48310458Sandreas.hansson@arm.com """It is difficult to tell which elements are children in the 48410458Sandreas.hansson@arm.com JSON file as there is no explicit 'children' node. Take any 48510458Sandreas.hansson@arm.com element which is a full SimObject description or a list of 48610458Sandreas.hansson@arm.com SimObject descriptions. This will not work with a mixed list of 48710458Sandreas.hansson@arm.com references and descriptions but that's a scenario that isn't 48810458Sandreas.hansson@arm.com possible (very likely?) with gem5's binding/naming rules""" 48910458Sandreas.hansson@arm.com obj = self.object_dicts[object_name] 49010458Sandreas.hansson@arm.com 49110458Sandreas.hansson@arm.com children = [] 49210458Sandreas.hansson@arm.com for name, node in obj.iteritems(): 49310458Sandreas.hansson@arm.com if self.is_sim_object(node): 49410458Sandreas.hansson@arm.com children.append((name, node['path'])) 49510458Sandreas.hansson@arm.com elif isinstance(node, list) and node != [] and all([ 49610458Sandreas.hansson@arm.com self.is_sim_object(e) for e in node ]): 49710458Sandreas.hansson@arm.com children.append((name, [ e['path'] for e in node ])) 49810458Sandreas.hansson@arm.com 49910458Sandreas.hansson@arm.com return children 50010458Sandreas.hansson@arm.com 50110458Sandreas.hansson@arm.com def get_port_peers(self, object_name, port_name): 50210458Sandreas.hansson@arm.com """Get the 'peer' element of any node with 'peer' and 'role' 50310458Sandreas.hansson@arm.com elements""" 50410458Sandreas.hansson@arm.com obj = self.object_dicts[object_name] 50510458Sandreas.hansson@arm.com 50610458Sandreas.hansson@arm.com peers = [] 50710458Sandreas.hansson@arm.com if port_name in obj and 'peer' in obj[port_name] and \ 50810458Sandreas.hansson@arm.com 'role' in obj[port_name]: 50910458Sandreas.hansson@arm.com peers = to_list(obj[port_name]['peer']) 51010458Sandreas.hansson@arm.com 51110458Sandreas.hansson@arm.com return peers 51210458Sandreas.hansson@arm.com 51310458Sandreas.hansson@arm.comparser = argparse.ArgumentParser() 51410458Sandreas.hansson@arm.com 51510458Sandreas.hansson@arm.comparser.add_argument('config_file', metavar='config-file.ini', 51610458Sandreas.hansson@arm.com help='.ini configuration file to load and run') 51712409Sgabeblack@google.comparser.add_argument('--checkpoint-dir', type=str, default=None, 51812409Sgabeblack@google.com help='A checkpoint to directory to restore when starting ' 51912409Sgabeblack@google.com 'the simulation') 52010458Sandreas.hansson@arm.com 52110458Sandreas.hansson@arm.comargs = parser.parse_args(sys.argv[1:]) 52210458Sandreas.hansson@arm.com 52310458Sandreas.hansson@arm.comif args.config_file.endswith('.ini'): 52410458Sandreas.hansson@arm.com config = ConfigIniFile() 52510458Sandreas.hansson@arm.com config.load(args.config_file) 52610458Sandreas.hansson@arm.comelse: 52710458Sandreas.hansson@arm.com config = ConfigJsonFile() 52810458Sandreas.hansson@arm.com config.load(args.config_file) 52910458Sandreas.hansson@arm.com 53010458Sandreas.hansson@arm.comticks.fixGlobalFrequency() 53110458Sandreas.hansson@arm.com 53210458Sandreas.hansson@arm.commgr = ConfigManager(config) 53310458Sandreas.hansson@arm.com 53410458Sandreas.hansson@arm.commgr.find_all_objects() 53510458Sandreas.hansson@arm.com 53612409Sgabeblack@google.comm5.instantiate(args.checkpoint_dir) 53710458Sandreas.hansson@arm.com 53810458Sandreas.hansson@arm.comexit_event = m5.simulate() 53910458Sandreas.hansson@arm.comprint 'Exiting @ tick %i because %s' % ( 54010458Sandreas.hansson@arm.com m5.curTick(), exit_event.getCause()) 541