read_config.py revision 12409
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() 8510458Sandreas.hansson@arm.com low, high = param.split(':') 8610458Sandreas.hansson@arm.com return m5.objects.AddrRange(long(low), long(high)) 8710458Sandreas.hansson@arm.com 8810458Sandreas.hansson@arm.comdef memory_bandwidth_parser(cls, flags, param): 8910458Sandreas.hansson@arm.com # The string will be in tick/byte 9010458Sandreas.hansson@arm.com # Convert to byte/tick 9110458Sandreas.hansson@arm.com value = 1.0 / float(param) 9210458Sandreas.hansson@arm.com # Convert to byte/s 9310458Sandreas.hansson@arm.com value = ticks.fromSeconds(value) 9410458Sandreas.hansson@arm.com return cls('%fB/s' % value) 9510458Sandreas.hansson@arm.com 9610458Sandreas.hansson@arm.com# These parameters have trickier parsing from .ini files than might be 9710458Sandreas.hansson@arm.com# expected 9810458Sandreas.hansson@arm.comparam_parsers = { 9910458Sandreas.hansson@arm.com 'Bool': simple_parser(), 10010458Sandreas.hansson@arm.com 'ParamValue': no_parser, 10110458Sandreas.hansson@arm.com 'NumericParamValue': simple_parser(cast=long), 10210458Sandreas.hansson@arm.com 'TickParamValue': tick_parser(), 10310458Sandreas.hansson@arm.com 'Frequency': tick_parser(cast=m5.objects.Latency), 10411228SAndrew.Bardsley@arm.com 'Current': simple_parser(suffix='A'), 10510458Sandreas.hansson@arm.com 'Voltage': simple_parser(suffix='V'), 10610458Sandreas.hansson@arm.com 'Enum': simple_parser(), 10710458Sandreas.hansson@arm.com 'MemorySize': simple_parser(suffix='B'), 10810458Sandreas.hansson@arm.com 'MemorySize32': simple_parser(suffix='B'), 10910458Sandreas.hansson@arm.com 'AddrRange': addr_range_parser, 11010458Sandreas.hansson@arm.com 'String': simple_parser(), 11110458Sandreas.hansson@arm.com 'MemoryBandwidth': memory_bandwidth_parser, 11211228SAndrew.Bardsley@arm.com 'Time': simple_parser(), 11311228SAndrew.Bardsley@arm.com 'EthernetAddr': simple_parser() 11410458Sandreas.hansson@arm.com } 11510458Sandreas.hansson@arm.com 11610458Sandreas.hansson@arm.comfor name, parser in param_parsers.iteritems(): 11710458Sandreas.hansson@arm.com setattr(m5.params.__dict__[name], 'parse_ini', classmethod(parser)) 11810458Sandreas.hansson@arm.com 11910458Sandreas.hansson@arm.comclass PortConnection(object): 12010458Sandreas.hansson@arm.com """This class is similar to m5.params.PortRef but with just enough 12110458Sandreas.hansson@arm.com information for ConfigManager""" 12210458Sandreas.hansson@arm.com 12310458Sandreas.hansson@arm.com def __init__(self, object_name, port_name, index): 12410458Sandreas.hansson@arm.com self.object_name = object_name 12510458Sandreas.hansson@arm.com self.port_name = port_name 12610458Sandreas.hansson@arm.com self.index = index 12710458Sandreas.hansson@arm.com 12810458Sandreas.hansson@arm.com @classmethod 12910458Sandreas.hansson@arm.com def from_string(cls, str): 13010458Sandreas.hansson@arm.com m = re.match('(.*)\.([^.\[]+)(\[(\d+)\])?', str) 13110458Sandreas.hansson@arm.com object_name, port_name, whole_index, index = m.groups() 13210458Sandreas.hansson@arm.com if index is not None: 13310458Sandreas.hansson@arm.com index = int(index) 13410458Sandreas.hansson@arm.com else: 13510458Sandreas.hansson@arm.com index = 0 13610458Sandreas.hansson@arm.com 13710458Sandreas.hansson@arm.com return PortConnection(object_name, port_name, index) 13810458Sandreas.hansson@arm.com 13910458Sandreas.hansson@arm.com def __str__(self): 14010458Sandreas.hansson@arm.com return '%s.%s[%d]' % (self.object_name, self.port_name, self.index) 14110458Sandreas.hansson@arm.com 14210458Sandreas.hansson@arm.com def __cmp__(self, right): 14310458Sandreas.hansson@arm.com return cmp((self.object_name, self.port_name, self.index), 14410458Sandreas.hansson@arm.com (right.object_name, right.port_name, right.index)) 14510458Sandreas.hansson@arm.com 14610458Sandreas.hansson@arm.comdef to_list(v): 14710458Sandreas.hansson@arm.com """Convert any non list to a singleton list""" 14810458Sandreas.hansson@arm.com if isinstance(v, list): 14910458Sandreas.hansson@arm.com return v 15010458Sandreas.hansson@arm.com else: 15110458Sandreas.hansson@arm.com return [v] 15210458Sandreas.hansson@arm.com 15310458Sandreas.hansson@arm.comclass ConfigManager(object): 15410458Sandreas.hansson@arm.com """Manager for parsing a Root configuration from a config file""" 15510458Sandreas.hansson@arm.com def __init__(self, config): 15610458Sandreas.hansson@arm.com self.config = config 15710458Sandreas.hansson@arm.com self.objects_by_name = {} 15810458Sandreas.hansson@arm.com self.flags = config.get_flags() 15910458Sandreas.hansson@arm.com 16010458Sandreas.hansson@arm.com def find_object(self, object_name): 16110458Sandreas.hansson@arm.com """Find and configure (with just non-SimObject parameters) 16210458Sandreas.hansson@arm.com a single object""" 16310458Sandreas.hansson@arm.com 16410458Sandreas.hansson@arm.com if object_name == 'Null': 16510458Sandreas.hansson@arm.com return NULL 16610458Sandreas.hansson@arm.com 16710458Sandreas.hansson@arm.com if object_name in self.objects_by_name: 16810458Sandreas.hansson@arm.com return self.objects_by_name[object_name] 16910458Sandreas.hansson@arm.com 17010458Sandreas.hansson@arm.com object_type = self.config.get_param(object_name, 'type') 17110458Sandreas.hansson@arm.com 17210458Sandreas.hansson@arm.com if object_type not in sim_object_classes_by_name: 17310458Sandreas.hansson@arm.com raise Exception('No SimObject type %s is available to' 17410458Sandreas.hansson@arm.com ' build: %s' % (object_type, object_name)) 17510458Sandreas.hansson@arm.com 17610458Sandreas.hansson@arm.com object_class = sim_object_classes_by_name[object_type] 17710458Sandreas.hansson@arm.com 17810458Sandreas.hansson@arm.com parsed_params = {} 17910458Sandreas.hansson@arm.com 18010458Sandreas.hansson@arm.com for param_name, param in object_class._params.iteritems(): 18110458Sandreas.hansson@arm.com if issubclass(param.ptype, m5.params.ParamValue): 18210458Sandreas.hansson@arm.com if isinstance(param, m5.params.VectorParamDesc): 18310458Sandreas.hansson@arm.com param_values = self.config.get_param_vector(object_name, 18410458Sandreas.hansson@arm.com param_name) 18510458Sandreas.hansson@arm.com 18610458Sandreas.hansson@arm.com param_value = [ param.ptype.parse_ini(self.flags, value) 18710458Sandreas.hansson@arm.com for value in param_values ] 18810458Sandreas.hansson@arm.com else: 18910458Sandreas.hansson@arm.com param_value = param.ptype.parse_ini( 19010458Sandreas.hansson@arm.com self.flags, self.config.get_param(object_name, 19110458Sandreas.hansson@arm.com param_name)) 19210458Sandreas.hansson@arm.com 19310458Sandreas.hansson@arm.com parsed_params[param_name] = param_value 19410458Sandreas.hansson@arm.com 19510458Sandreas.hansson@arm.com obj = object_class(**parsed_params) 19610458Sandreas.hansson@arm.com self.objects_by_name[object_name] = obj 19710458Sandreas.hansson@arm.com 19810458Sandreas.hansson@arm.com return obj 19910458Sandreas.hansson@arm.com 20010458Sandreas.hansson@arm.com def fill_in_simobj_parameters(self, object_name, obj): 20110458Sandreas.hansson@arm.com """Fill in all references to other SimObjects in an objects 20210458Sandreas.hansson@arm.com parameters. This relies on all referenced objects having been 20310458Sandreas.hansson@arm.com created""" 20410458Sandreas.hansson@arm.com 20510458Sandreas.hansson@arm.com if object_name == 'Null': 20610458Sandreas.hansson@arm.com return NULL 20710458Sandreas.hansson@arm.com 20810458Sandreas.hansson@arm.com for param_name, param in obj.__class__._params.iteritems(): 20910458Sandreas.hansson@arm.com if issubclass(param.ptype, m5.objects.SimObject): 21010458Sandreas.hansson@arm.com if isinstance(param, m5.params.VectorParamDesc): 21110458Sandreas.hansson@arm.com param_values = self.config.get_param_vector(object_name, 21210458Sandreas.hansson@arm.com param_name) 21310458Sandreas.hansson@arm.com 21410458Sandreas.hansson@arm.com setattr(obj, param_name, [ self.objects_by_name[name] 21510458Sandreas.hansson@arm.com for name in param_values ]) 21610458Sandreas.hansson@arm.com else: 21710458Sandreas.hansson@arm.com param_value = self.config.get_param(object_name, 21810458Sandreas.hansson@arm.com param_name) 21910458Sandreas.hansson@arm.com 22010458Sandreas.hansson@arm.com if param_value != 'Null': 22110458Sandreas.hansson@arm.com setattr(obj, param_name, self.objects_by_name[ 22210458Sandreas.hansson@arm.com param_value]) 22310458Sandreas.hansson@arm.com 22410458Sandreas.hansson@arm.com return obj 22510458Sandreas.hansson@arm.com 22610458Sandreas.hansson@arm.com def fill_in_children(self, object_name, obj): 22710458Sandreas.hansson@arm.com """Fill in the children of this object. This relies on all the 22810458Sandreas.hansson@arm.com referenced objects having been created""" 22910458Sandreas.hansson@arm.com 23010458Sandreas.hansson@arm.com children = self.config.get_object_children(object_name) 23110458Sandreas.hansson@arm.com 23210458Sandreas.hansson@arm.com for child_name, child_paths in children: 23310458Sandreas.hansson@arm.com param = obj.__class__._params.get(child_name, None) 23410458Sandreas.hansson@arm.com 23510458Sandreas.hansson@arm.com if isinstance(child_paths, list): 23610458Sandreas.hansson@arm.com child_list = [ self.objects_by_name[path] 23710458Sandreas.hansson@arm.com for path in child_paths ] 23810458Sandreas.hansson@arm.com else: 23910458Sandreas.hansson@arm.com child_list = self.objects_by_name[child_paths] 24010458Sandreas.hansson@arm.com 24110458Sandreas.hansson@arm.com obj.add_child(child_name, child_list) 24210458Sandreas.hansson@arm.com 24310458Sandreas.hansson@arm.com for path in to_list(child_paths): 24410458Sandreas.hansson@arm.com self.fill_in_children(path, self.objects_by_name[path]) 24510458Sandreas.hansson@arm.com 24610458Sandreas.hansson@arm.com return obj 24710458Sandreas.hansson@arm.com 24810458Sandreas.hansson@arm.com def parse_port_name(self, port): 24910458Sandreas.hansson@arm.com """Parse the name of a port""" 25010458Sandreas.hansson@arm.com 25110458Sandreas.hansson@arm.com m = re.match('(.*)\.([^.\[]+)(\[(\d+)\])?', port) 25210458Sandreas.hansson@arm.com peer, peer_port, whole_index, index = m.groups() 25310458Sandreas.hansson@arm.com if index is not None: 25410458Sandreas.hansson@arm.com index = int(index) 25510458Sandreas.hansson@arm.com else: 25610458Sandreas.hansson@arm.com index = 0 25710458Sandreas.hansson@arm.com 25810458Sandreas.hansson@arm.com return (peer, self.objects_by_name[peer], peer_port, index) 25910458Sandreas.hansson@arm.com 26010458Sandreas.hansson@arm.com def gather_port_connections(self, object_name, obj): 26110458Sandreas.hansson@arm.com """Gather all the port-to-port connections from the named object. 26210458Sandreas.hansson@arm.com Returns a list of (PortConnection, PortConnection) with unordered 26310458Sandreas.hansson@arm.com (wrt. master/slave) connection information""" 26410458Sandreas.hansson@arm.com 26510458Sandreas.hansson@arm.com if object_name == 'Null': 26610458Sandreas.hansson@arm.com return NULL 26710458Sandreas.hansson@arm.com 26810458Sandreas.hansson@arm.com parsed_ports = [] 26910458Sandreas.hansson@arm.com for port_name, port in obj.__class__._ports.iteritems(): 27010458Sandreas.hansson@arm.com # Assume that unnamed ports are unconnected 27110458Sandreas.hansson@arm.com peers = self.config.get_port_peers(object_name, port_name) 27210458Sandreas.hansson@arm.com 27310458Sandreas.hansson@arm.com for index, peer in zip(xrange(0, len(peers)), peers): 27410458Sandreas.hansson@arm.com parsed_ports.append(( 27510458Sandreas.hansson@arm.com PortConnection(object_name, port.name, index), 27610458Sandreas.hansson@arm.com PortConnection.from_string(peer))) 27710458Sandreas.hansson@arm.com 27810458Sandreas.hansson@arm.com return parsed_ports 27910458Sandreas.hansson@arm.com 28010458Sandreas.hansson@arm.com def bind_ports(self, connections): 28110458Sandreas.hansson@arm.com """Bind all ports from the given connection list. Note that the 28210458Sandreas.hansson@arm.com connection list *must* list all connections with both (slave,master) 28310458Sandreas.hansson@arm.com and (master,slave) orderings""" 28410458Sandreas.hansson@arm.com 28510458Sandreas.hansson@arm.com # Markup a dict of how many connections are made to each port. 28610458Sandreas.hansson@arm.com # This will be used to check that the next-to-be-made connection 28710458Sandreas.hansson@arm.com # has a suitable port index 28810458Sandreas.hansson@arm.com port_bind_indices = {} 28910458Sandreas.hansson@arm.com for from_port, to_port in connections: 29010458Sandreas.hansson@arm.com port_bind_indices[ 29110458Sandreas.hansson@arm.com (from_port.object_name, from_port.port_name)] = 0 29210458Sandreas.hansson@arm.com 29310458Sandreas.hansson@arm.com def port_has_correct_index(port): 29410458Sandreas.hansson@arm.com return port_bind_indices[ 29510458Sandreas.hansson@arm.com (port.object_name, port.port_name)] == port.index 29610458Sandreas.hansson@arm.com 29710458Sandreas.hansson@arm.com def increment_port_index(port): 29810458Sandreas.hansson@arm.com port_bind_indices[ 29910458Sandreas.hansson@arm.com (port.object_name, port.port_name)] += 1 30010458Sandreas.hansson@arm.com 30110458Sandreas.hansson@arm.com # Step through the sorted connections. Exactly one of 30210458Sandreas.hansson@arm.com # each (slave,master) and (master,slave) pairs will be 30310458Sandreas.hansson@arm.com # bindable because the connections are sorted. 30410458Sandreas.hansson@arm.com # For example: port_bind_indices 30510458Sandreas.hansson@arm.com # left right left right 30610458Sandreas.hansson@arm.com # a.b[0] -> d.f[1] 0 0 X 30710458Sandreas.hansson@arm.com # a.b[1] -> e.g 0 0 BIND! 30810458Sandreas.hansson@arm.com # e.g -> a.b[1] 1 X 0 30910458Sandreas.hansson@arm.com # d.f[0] -> f.h 0 0 BIND! 31010458Sandreas.hansson@arm.com # d.f[1] -> a.b[0] 1 0 BIND! 31110458Sandreas.hansson@arm.com connections_to_make = [] 31210458Sandreas.hansson@arm.com for connection in sorted(connections): 31310458Sandreas.hansson@arm.com from_port, to_port = connection 31410458Sandreas.hansson@arm.com 31510458Sandreas.hansson@arm.com if (port_has_correct_index(from_port) and 31610458Sandreas.hansson@arm.com port_has_correct_index(to_port)): 31710458Sandreas.hansson@arm.com 31810458Sandreas.hansson@arm.com connections_to_make.append((from_port, to_port)) 31910458Sandreas.hansson@arm.com 32010458Sandreas.hansson@arm.com increment_port_index(from_port) 32110458Sandreas.hansson@arm.com increment_port_index(to_port) 32210458Sandreas.hansson@arm.com 32310458Sandreas.hansson@arm.com # Exactly half of the connections (ie. all of them, one per 32410458Sandreas.hansson@arm.com # direction) must now have been made 32510458Sandreas.hansson@arm.com if (len(connections_to_make) * 2) != len(connections): 32610458Sandreas.hansson@arm.com raise Exception('Port bindings can\'t be ordered') 32710458Sandreas.hansson@arm.com 32810458Sandreas.hansson@arm.com # Actually do the binding 32910458Sandreas.hansson@arm.com for from_port, to_port in connections_to_make: 33010458Sandreas.hansson@arm.com from_object = self.objects_by_name[from_port.object_name] 33110458Sandreas.hansson@arm.com to_object = self.objects_by_name[to_port.object_name] 33210458Sandreas.hansson@arm.com 33310458Sandreas.hansson@arm.com setattr(from_object, from_port.port_name, 33410458Sandreas.hansson@arm.com getattr(to_object, to_port.port_name)) 33510458Sandreas.hansson@arm.com 33610458Sandreas.hansson@arm.com def find_all_objects(self): 33710458Sandreas.hansson@arm.com """Find and build all SimObjects from the config file and connect 33810458Sandreas.hansson@arm.com their ports together as described. Does not instantiate system""" 33910458Sandreas.hansson@arm.com 34010458Sandreas.hansson@arm.com # Build SimObjects for all sections of the config file 34110458Sandreas.hansson@arm.com # populating not-SimObject-valued parameters 34210458Sandreas.hansson@arm.com for object_name in self.config.get_all_object_names(): 34310458Sandreas.hansson@arm.com self.find_object(object_name) 34410458Sandreas.hansson@arm.com 34510458Sandreas.hansson@arm.com # Add children to objects in the hierarchy from root 34610458Sandreas.hansson@arm.com self.fill_in_children('root', self.find_object('root')) 34710458Sandreas.hansson@arm.com 34810458Sandreas.hansson@arm.com # Now fill in SimObject-valued parameters in the knowledge that 34910458Sandreas.hansson@arm.com # this won't be interpreted as becoming the parent of objects 35010458Sandreas.hansson@arm.com # which are already in the root hierarchy 35110458Sandreas.hansson@arm.com for name, obj in self.objects_by_name.iteritems(): 35210458Sandreas.hansson@arm.com self.fill_in_simobj_parameters(name, obj) 35310458Sandreas.hansson@arm.com 35410458Sandreas.hansson@arm.com # Gather a list of all port-to-port connections 35510458Sandreas.hansson@arm.com connections = [] 35610458Sandreas.hansson@arm.com for name, obj in self.objects_by_name.iteritems(): 35710458Sandreas.hansson@arm.com connections += self.gather_port_connections(name, obj) 35810458Sandreas.hansson@arm.com 35910458Sandreas.hansson@arm.com # Find an acceptable order to bind those port connections and 36010458Sandreas.hansson@arm.com # bind them 36110458Sandreas.hansson@arm.com self.bind_ports(connections) 36210458Sandreas.hansson@arm.com 36310458Sandreas.hansson@arm.comclass ConfigFile(object): 36410458Sandreas.hansson@arm.com def get_flags(self): 36510458Sandreas.hansson@arm.com return set() 36610458Sandreas.hansson@arm.com 36710458Sandreas.hansson@arm.com def load(self, config_file): 36810458Sandreas.hansson@arm.com """Load the named config file""" 36910458Sandreas.hansson@arm.com pass 37010458Sandreas.hansson@arm.com 37110458Sandreas.hansson@arm.com def get_all_object_names(self): 37210458Sandreas.hansson@arm.com """Get a list of all the SimObject paths in the configuration""" 37310458Sandreas.hansson@arm.com pass 37410458Sandreas.hansson@arm.com 37510458Sandreas.hansson@arm.com def get_param(self, object_name, param_name): 37610458Sandreas.hansson@arm.com """Get a single param or SimObject reference from the configuration 37710458Sandreas.hansson@arm.com as a string""" 37810458Sandreas.hansson@arm.com pass 37910458Sandreas.hansson@arm.com 38010458Sandreas.hansson@arm.com def get_param_vector(self, object_name, param_name): 38110458Sandreas.hansson@arm.com """Get a vector param or vector of SimObject references from the 38210458Sandreas.hansson@arm.com configuration as a list of strings""" 38310458Sandreas.hansson@arm.com pass 38410458Sandreas.hansson@arm.com 38510458Sandreas.hansson@arm.com def get_object_children(self, object_name): 38610458Sandreas.hansson@arm.com """Get a list of (name, paths) for each child of this object. 38710458Sandreas.hansson@arm.com paths is either a single string object path or a list of object 38810458Sandreas.hansson@arm.com paths""" 38910458Sandreas.hansson@arm.com pass 39010458Sandreas.hansson@arm.com 39110458Sandreas.hansson@arm.com def get_port_peers(self, object_name, port_name): 39210458Sandreas.hansson@arm.com """Get the list of connected port names (in the string form 39310458Sandreas.hansson@arm.com object.port(\[index\])?) of the port object_name.port_name""" 39410458Sandreas.hansson@arm.com pass 39510458Sandreas.hansson@arm.com 39610458Sandreas.hansson@arm.comclass ConfigIniFile(ConfigFile): 39710458Sandreas.hansson@arm.com def __init__(self): 39810458Sandreas.hansson@arm.com self.parser = ConfigParser.ConfigParser() 39910458Sandreas.hansson@arm.com 40010458Sandreas.hansson@arm.com def load(self, config_file): 40110458Sandreas.hansson@arm.com self.parser.read(config_file) 40210458Sandreas.hansson@arm.com 40310458Sandreas.hansson@arm.com def get_all_object_names(self): 40410458Sandreas.hansson@arm.com return self.parser.sections() 40510458Sandreas.hansson@arm.com 40610458Sandreas.hansson@arm.com def get_param(self, object_name, param_name): 40710458Sandreas.hansson@arm.com return self.parser.get(object_name, param_name) 40810458Sandreas.hansson@arm.com 40910458Sandreas.hansson@arm.com def get_param_vector(self, object_name, param_name): 41010458Sandreas.hansson@arm.com return self.parser.get(object_name, param_name).split() 41110458Sandreas.hansson@arm.com 41210458Sandreas.hansson@arm.com def get_object_children(self, object_name): 41310458Sandreas.hansson@arm.com if self.parser.has_option(object_name, 'children'): 41410458Sandreas.hansson@arm.com children = self.parser.get(object_name, 'children') 41510458Sandreas.hansson@arm.com child_names = children.split() 41610458Sandreas.hansson@arm.com else: 41710458Sandreas.hansson@arm.com child_names = [] 41810458Sandreas.hansson@arm.com 41910458Sandreas.hansson@arm.com def make_path(child_name): 42010458Sandreas.hansson@arm.com if object_name == 'root': 42110458Sandreas.hansson@arm.com return child_name 42210458Sandreas.hansson@arm.com else: 42310458Sandreas.hansson@arm.com return '%s.%s' % (object_name, child_name) 42410458Sandreas.hansson@arm.com 42510458Sandreas.hansson@arm.com return [ (name, make_path(name)) for name in child_names ] 42610458Sandreas.hansson@arm.com 42710458Sandreas.hansson@arm.com def get_port_peers(self, object_name, port_name): 42810458Sandreas.hansson@arm.com if self.parser.has_option(object_name, port_name): 42910458Sandreas.hansson@arm.com peer_string = self.parser.get(object_name, port_name) 43010458Sandreas.hansson@arm.com return peer_string.split() 43110458Sandreas.hansson@arm.com else: 43210458Sandreas.hansson@arm.com return [] 43310458Sandreas.hansson@arm.com 43410458Sandreas.hansson@arm.comclass ConfigJsonFile(ConfigFile): 43510458Sandreas.hansson@arm.com def __init__(self): 43610458Sandreas.hansson@arm.com pass 43710458Sandreas.hansson@arm.com 43810458Sandreas.hansson@arm.com def is_sim_object(self, node): 43910458Sandreas.hansson@arm.com return isinstance(node, dict) and 'path' in node 44010458Sandreas.hansson@arm.com 44110458Sandreas.hansson@arm.com def find_all_objects(self, node): 44210458Sandreas.hansson@arm.com if self.is_sim_object(node): 44310458Sandreas.hansson@arm.com self.object_dicts[node['path']] = node 44410458Sandreas.hansson@arm.com 44510458Sandreas.hansson@arm.com if isinstance(node, list): 44610458Sandreas.hansson@arm.com for elem in node: 44710458Sandreas.hansson@arm.com self.find_all_objects(elem) 44810458Sandreas.hansson@arm.com elif isinstance(node, dict): 44910458Sandreas.hansson@arm.com for elem in node.itervalues(): 45010458Sandreas.hansson@arm.com self.find_all_objects(elem) 45110458Sandreas.hansson@arm.com 45210458Sandreas.hansson@arm.com def load(self, config_file): 45310458Sandreas.hansson@arm.com root = json.load(open(config_file, 'r')) 45410458Sandreas.hansson@arm.com self.object_dicts = {} 45510458Sandreas.hansson@arm.com self.find_all_objects(root) 45610458Sandreas.hansson@arm.com 45710458Sandreas.hansson@arm.com def get_all_object_names(self): 45810458Sandreas.hansson@arm.com return sorted(self.object_dicts.keys()) 45910458Sandreas.hansson@arm.com 46010458Sandreas.hansson@arm.com def parse_param_string(self, node): 46110458Sandreas.hansson@arm.com if node is None: 46210458Sandreas.hansson@arm.com return "Null" 46310458Sandreas.hansson@arm.com elif self.is_sim_object(node): 46410458Sandreas.hansson@arm.com return node['path'] 46510458Sandreas.hansson@arm.com else: 46610458Sandreas.hansson@arm.com return str(node) 46710458Sandreas.hansson@arm.com 46810458Sandreas.hansson@arm.com def get_param(self, object_name, param_name): 46910458Sandreas.hansson@arm.com obj = self.object_dicts[object_name] 47010458Sandreas.hansson@arm.com 47110458Sandreas.hansson@arm.com return self.parse_param_string(obj[param_name]) 47210458Sandreas.hansson@arm.com 47310458Sandreas.hansson@arm.com def get_param_vector(self, object_name, param_name): 47410458Sandreas.hansson@arm.com obj = self.object_dicts[object_name] 47510458Sandreas.hansson@arm.com 47610458Sandreas.hansson@arm.com return [ self.parse_param_string(p) for p in obj[param_name] ] 47710458Sandreas.hansson@arm.com 47810458Sandreas.hansson@arm.com def get_object_children(self, object_name): 47910458Sandreas.hansson@arm.com """It is difficult to tell which elements are children in the 48010458Sandreas.hansson@arm.com JSON file as there is no explicit 'children' node. Take any 48110458Sandreas.hansson@arm.com element which is a full SimObject description or a list of 48210458Sandreas.hansson@arm.com SimObject descriptions. This will not work with a mixed list of 48310458Sandreas.hansson@arm.com references and descriptions but that's a scenario that isn't 48410458Sandreas.hansson@arm.com possible (very likely?) with gem5's binding/naming rules""" 48510458Sandreas.hansson@arm.com obj = self.object_dicts[object_name] 48610458Sandreas.hansson@arm.com 48710458Sandreas.hansson@arm.com children = [] 48810458Sandreas.hansson@arm.com for name, node in obj.iteritems(): 48910458Sandreas.hansson@arm.com if self.is_sim_object(node): 49010458Sandreas.hansson@arm.com children.append((name, node['path'])) 49110458Sandreas.hansson@arm.com elif isinstance(node, list) and node != [] and all([ 49210458Sandreas.hansson@arm.com self.is_sim_object(e) for e in node ]): 49310458Sandreas.hansson@arm.com children.append((name, [ e['path'] for e in node ])) 49410458Sandreas.hansson@arm.com 49510458Sandreas.hansson@arm.com return children 49610458Sandreas.hansson@arm.com 49710458Sandreas.hansson@arm.com def get_port_peers(self, object_name, port_name): 49810458Sandreas.hansson@arm.com """Get the 'peer' element of any node with 'peer' and 'role' 49910458Sandreas.hansson@arm.com elements""" 50010458Sandreas.hansson@arm.com obj = self.object_dicts[object_name] 50110458Sandreas.hansson@arm.com 50210458Sandreas.hansson@arm.com peers = [] 50310458Sandreas.hansson@arm.com if port_name in obj and 'peer' in obj[port_name] and \ 50410458Sandreas.hansson@arm.com 'role' in obj[port_name]: 50510458Sandreas.hansson@arm.com peers = to_list(obj[port_name]['peer']) 50610458Sandreas.hansson@arm.com 50710458Sandreas.hansson@arm.com return peers 50810458Sandreas.hansson@arm.com 50910458Sandreas.hansson@arm.comparser = argparse.ArgumentParser() 51010458Sandreas.hansson@arm.com 51110458Sandreas.hansson@arm.comparser.add_argument('config_file', metavar='config-file.ini', 51210458Sandreas.hansson@arm.com help='.ini configuration file to load and run') 51312409Sgabeblack@google.comparser.add_argument('--checkpoint-dir', type=str, default=None, 51412409Sgabeblack@google.com help='A checkpoint to directory to restore when starting ' 51512409Sgabeblack@google.com 'the simulation') 51610458Sandreas.hansson@arm.com 51710458Sandreas.hansson@arm.comargs = parser.parse_args(sys.argv[1:]) 51810458Sandreas.hansson@arm.com 51910458Sandreas.hansson@arm.comif args.config_file.endswith('.ini'): 52010458Sandreas.hansson@arm.com config = ConfigIniFile() 52110458Sandreas.hansson@arm.com config.load(args.config_file) 52210458Sandreas.hansson@arm.comelse: 52310458Sandreas.hansson@arm.com config = ConfigJsonFile() 52410458Sandreas.hansson@arm.com config.load(args.config_file) 52510458Sandreas.hansson@arm.com 52610458Sandreas.hansson@arm.comticks.fixGlobalFrequency() 52710458Sandreas.hansson@arm.com 52810458Sandreas.hansson@arm.commgr = ConfigManager(config) 52910458Sandreas.hansson@arm.com 53010458Sandreas.hansson@arm.commgr.find_all_objects() 53110458Sandreas.hansson@arm.com 53212409Sgabeblack@google.comm5.instantiate(args.checkpoint_dir) 53310458Sandreas.hansson@arm.com 53410458Sandreas.hansson@arm.comexit_event = m5.simulate() 53510458Sandreas.hansson@arm.comprint 'Exiting @ tick %i because %s' % ( 53610458Sandreas.hansson@arm.com m5.curTick(), exit_event.getCause()) 537