Skip to content

Commit

Permalink
Rework handling address/size values in Configuration
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
mateusz-holenko committed Oct 21, 2019
1 parent 462df23 commit 2cb6886
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 51 deletions.
73 changes: 27 additions & 46 deletions generate-renode-scripts.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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))
Expand All @@ -68,37 +67,31 @@ 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:
string: repl definition of the peripheral
"""
buf = kwargs['buffer']()
phy = kwargs['phy']()
phy['size'] = 0x800

result = """
ethmac: Network.LiteX_Ethernet @ {{
{};
{};
{}
}}
""".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']:
Expand All @@ -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
Expand All @@ -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:
Expand Down Expand Up @@ -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'
Expand All @@ -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':
Expand All @@ -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'
Expand All @@ -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'])
Expand Down Expand Up @@ -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)

Expand All @@ -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

Expand Down
25 changes: 20 additions & 5 deletions litex/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"""

import csv
import itertools


class Configuration(object):
Expand All @@ -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):
Expand All @@ -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:
Expand All @@ -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
Expand All @@ -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

0 comments on commit 2cb6886

Please sign in to comment.