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