From 2cb6886ef82543c9c83dfde7d95bc499037062df Mon Sep 17 00:00:00 2001 From: Mateusz Holenko Date: Thu, 17 Oct 2019 13:21:29 +0200 Subject: [PATCH] Rework handling address/size values in `Configuration` Parse values known to be numbers and calculate base and shadowed addresses of registers, peripherals and memory regions when parsing the csv file. This eliminates the need to parse/calculate those values every time data is read from the dictionaries. --- generate-renode-scripts.py | 73 ++++++++++++++------------------------ litex/configuration.py | 25 ++++++++++--- 2 files changed, 47 insertions(+), 51 deletions(-) diff --git a/generate-renode-scripts.py b/generate-renode-scripts.py index 9d4bb5b71..d4504050f 100755 --- a/generate-renode-scripts.py +++ b/generate-renode-scripts.py @@ -21,21 +21,21 @@ configuration = None -def generate_sysbus_registration(address, shadow_base, size=None, - skip_braces=False, region=None): +def generate_sysbus_registration(descriptor, + skip_braces=False, region=None, skip_size=False): """ Generates system bus registration information consisting of a base address and an optional shadow address. Args: - address (int): peripheral's base address - shadow_base (int or None): shadow base address - size (int or None): peripheral's size, if None the value provided - by the peripheral in runtime is taken + descriptor (dict): dictionary containing 'address', + 'shadowed_address' (might be None) and + optionally 'size' fields skip_braces (bool): determines if the registration info should be put in braces region (str or None): name of the region, if None the default one is assumed + skip_size (bool): if set to true do not set size Returns: string: registration information @@ -50,12 +50,11 @@ def generate_registration_entry(address, size=None, name=None): return "sysbus <{}, +{}>".format(hex(address), hex(size)) return "sysbus {}".format(hex(address)) - if shadow_base: - shadowed_address = address | int(shadow_base, 0) - - if shadowed_address == address: - address &= ~int(shadow_base, 0) + address = descriptor['address'] + shadowed_address = descriptor['shadowed_address'] + size = descriptor['size'] if 'size' in descriptor and not skip_size else None + if shadowed_address: result = "{}; {}".format( generate_registration_entry(address, size, region), generate_registration_entry(shadowed_address, size, region)) @@ -68,12 +67,11 @@ def generate_registration_entry(address, size=None, name=None): return result -def generate_ethmac(peripheral, shadow_base, **kwargs): +def generate_ethmac(peripheral, **kwargs): """ Generates definition of 'ethmac' peripheral. Args: peripheral (dict): peripheral description - shadow_base (int or None): shadow base address kwargs (dict): additional parameters, including 'buffer' Returns: @@ -81,6 +79,7 @@ def generate_ethmac(peripheral, shadow_base, **kwargs): """ buf = kwargs['buffer']() phy = kwargs['phy']() + phy['size'] = 0x800 result = """ ethmac: Network.LiteX_Ethernet @ {{ @@ -88,17 +87,11 @@ def generate_ethmac(peripheral, shadow_base, **kwargs): {}; {} }} -""".format(generate_sysbus_registration(int(peripheral['address'], 0), - shadow_base, - 0x100, +""".format(generate_sysbus_registration(peripheral, skip_braces=True), - generate_sysbus_registration(int(buf['address'], 0), - shadow_base, - int(buf['size'], 0), + generate_sysbus_registration(buf, skip_braces=True, region='buffer'), - generate_sysbus_registration(int(phy['address'], 0), - shadow_base, - 0x800, + generate_sysbus_registration(phy, skip_braces=True, region='phy')) if 'interrupt' in peripheral['constants']: @@ -114,12 +107,11 @@ def generate_ethmac(peripheral, shadow_base, **kwargs): return result -def generate_memory_region(region_descriptor, shadow_base): +def generate_memory_region(region_descriptor): """ Generates definition of memory region. Args: region_descriptor (dict): memory region description - shadow_base (int or None): shadow base address Returns: string: repl definition of the memory region @@ -129,18 +121,15 @@ def generate_memory_region(region_descriptor, shadow_base): {}: Memory.MappedMemory @ {} size: {} """.format(region_descriptor['name'], - generate_sysbus_registration(int(region_descriptor['address'], 0), - shadow_base), - hex(size)) + generate_sysbus_registration(region_descriptor, skip_size=True), + hex(region_descriptor['size'])) -def generate_silencer(peripheral, shadow_base, **kwargs): +def generate_silencer(peripheral, **kwargs): """ Silences access to a memory region. Args: peripheral (dict): peripheral description - shadow_base (int or None): unused, just for compatibility with other - functions kwargs (dict): additional parameters, not used Returns: @@ -192,12 +181,11 @@ def generate_cpu(time_provider): raise Exception('Unsupported cpu type: {}'.format(kind)) -def generate_peripheral(peripheral, shadow_base, **kwargs): +def generate_peripheral(peripheral, **kwargs): """ Generates definition of a peripheral. Args: peripheral (dict): peripheral description - shadow_base (int or None): shadow base address kwargs (dict): additional parameterss, including 'model' and 'properties' @@ -208,8 +196,7 @@ def generate_peripheral(peripheral, shadow_base, **kwargs): result = '\n{}: {} @ {}\n'.format( kwargs['name'] if 'name' in kwargs else peripheral['name'], kwargs['model'], - generate_sysbus_registration(int(peripheral['address'], 0), - shadow_base)) + generate_sysbus_registration(peripheral)) for constant, val in peripheral['constants'].items(): if constant == 'interrupt': @@ -228,12 +215,11 @@ def generate_peripheral(peripheral, shadow_base, **kwargs): return result -def generate_spiflash(peripheral, shadow_base, **kwargs): +def generate_spiflash(peripheral, **kwargs): """ Generates definition of an SPI controller with attached flash memory. Args: peripheral (dict): peripheral description - shadow_base (int or None): shadow base address kwargs (dict): additional parameterss, including 'model' and 'properties' @@ -249,13 +235,12 @@ def generate_spiflash(peripheral, shadow_base, **kwargs): mt25q: SPI.Micron_MT25Q @ spi underlyingMemory: spiflash """.format( - generate_sysbus_registration(int(peripheral['address'], 0), - shadow_base, skip_braces=True)) + generate_sysbus_registration(peripheral, skip_braces=True)) return result -def generate_cas(peripheral, shadow_base, **kwargs): - result = generate_peripheral(peripheral, shadow_base, model='GPIOPort.LiteX_ControlAndStatus', ignored_constants=['leds_count', 'switches_count', 'buttons_count']) +def generate_cas(peripheral, **kwargs): + result = generate_peripheral(peripheral, model='GPIOPort.LiteX_ControlAndStatus', ignored_constants=['leds_count', 'switches_count', 'buttons_count']) leds_count = int(peripheral['constants']['leds_count']) switches_count = int(peripheral['constants']['switches_count']) @@ -351,13 +336,9 @@ def generate_repl(): } } - shadow_base = (configuration.constants['shadow_base']['value'] - if 'shadow_base' in configuration.constants - else None) - for mem_region in configuration.mem_regions.values(): if mem_region['name'] not in non_generated_mem_regions: - result += generate_memory_region(mem_region, shadow_base) + result += generate_memory_region(mem_region) result += generate_cpu('cpu_timer' if 'cpu' in configuration.peripherals else None) @@ -368,7 +349,7 @@ def generate_repl(): continue h = name_to_handler[name] - result += h['handler'](peripheral, shadow_base, **h) + result += h['handler'](peripheral, **h) return result diff --git a/litex/configuration.py b/litex/configuration.py index 1caa1618c..3352e3013 100644 --- a/litex/configuration.py +++ b/litex/configuration.py @@ -9,6 +9,7 @@ """ import csv +import itertools class Configuration(object): @@ -21,6 +22,7 @@ def __init__(self, conf_file): with open(conf_file) as csvfile: self._parse_csv(list(csv.reader(Configuration._remove_comments(csvfile)))) + self._normalize_addresses() @staticmethod def _remove_comments(data): @@ -40,7 +42,7 @@ def _parse_csv(self, data): for _type, _name, _address, _, __ in data: if _type == 'csr_base': self.peripherals[_name] = {'name': _name, - 'address': _address, + 'address': int(_address, 0), 'constants': {}} for _type, _name, _val, _val2, _val3 in data: @@ -50,8 +52,8 @@ def _parse_csv(self, data): elif _type == 'csr_register': # csr_register,info_dna_id,0xe0006800,8,ro self.registers[_name] = {'name': _name, - 'address': _val, - 'size': _val2, + 'address': int(_val, 0), + 'size': int(_val2, 0), 'r': _val3} elif _type == 'constant': found = False @@ -66,7 +68,20 @@ def _parse_csv(self, data): self.constants[_name] = {'name': _name, 'value': _val} elif _type == 'memory_region': self.mem_regions[_name] = {'name': _name, - 'address': _val, - 'size': _val2} + 'address': int(_val, 0), + 'size': int(_val2, 0)} else: print('Skipping unexpected CSV entry: {} {}'.format(_type, _name)) + + def _normalize_addresses(self): + shadow_base = (int(self.constants['shadow_base']['value'], 0) + if 'shadow_base' in self.constants + else None) + + for r in itertools.chain(self.mem_regions.values(), self.registers.values(), self.peripherals.values()): + if shadow_base is None: + r['shadowed_address'] = None + else: + r['shadowed_address'] = r['address'] | shadow_base + if r['shadowed_address'] == r['address']: + r['address'] &= ~shadow_base