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