Merge pull request #1496 from MateuszKarlic/json2renode-update
json2renode: Multicore configuration support
This commit is contained in:
commit
7157b4c5e8
|
@ -1,6 +1,6 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""
|
"""
|
||||||
Copyright (c) 2019-2021 Antmicro <www.antmicro.com>
|
Copyright (c) 2019-2022 Antmicro <www.antmicro.com>
|
||||||
|
|
||||||
Renode platform definition (repl) and script (resc) generator for LiteX SoC.
|
Renode platform definition (repl) and script (resc) generator for LiteX SoC.
|
||||||
|
|
||||||
|
@ -20,6 +20,14 @@ import argparse
|
||||||
# and should not be generated automatically
|
# and should not be generated automatically
|
||||||
non_generated_mem_regions = ['ethmac', 'csr']
|
non_generated_mem_regions = ['ethmac', 'csr']
|
||||||
|
|
||||||
|
def get_soc_interrupt_parent(csr):
|
||||||
|
'''
|
||||||
|
We assume that for multi-core setups plic will be used hence cpu0 is enough
|
||||||
|
'''
|
||||||
|
if 'plic' in csr['memories']:
|
||||||
|
return 'plic'
|
||||||
|
else:
|
||||||
|
return 'cpu0'
|
||||||
|
|
||||||
def get_descriptor(csr, name, size=None):
|
def get_descriptor(csr, name, size=None):
|
||||||
res = { 'base': csr['csr_bases'][name], 'constants': {} }
|
res = { 'base': csr['csr_bases'][name], 'constants': {} }
|
||||||
|
@ -110,7 +118,8 @@ ethmac: Network.LiteX_Ethernet{} @ {{
|
||||||
|
|
||||||
interrupt_name = '{}_interrupt'.format(name)
|
interrupt_name = '{}_interrupt'.format(name)
|
||||||
if interrupt_name in csr['constants']:
|
if interrupt_name in csr['constants']:
|
||||||
result += ' -> cpu@{}\n'.format(
|
result += ' -> {}@{}\n'.format(
|
||||||
|
get_soc_interrupt_parent(csr),
|
||||||
csr['constants'][interrupt_name])
|
csr['constants'][interrupt_name])
|
||||||
|
|
||||||
result += """
|
result += """
|
||||||
|
@ -204,8 +213,54 @@ def get_cpu_type(csr):
|
||||||
|
|
||||||
return (kind, variant)
|
return (kind, variant)
|
||||||
|
|
||||||
|
def get_cpu_count(csr):
|
||||||
|
return csr['constants']['config_cpu_count']
|
||||||
|
|
||||||
def generate_cpu(csr, time_provider):
|
vexriscv_common_kind = {
|
||||||
|
'name': 'VexRiscv',
|
||||||
|
'variants': {
|
||||||
|
'linux': {
|
||||||
|
'properties': ['cpuType: "rv32ima"', 'privilegeArchitecture: PrivilegeArchitecture.Priv1_10'],
|
||||||
|
},
|
||||||
|
'i': {
|
||||||
|
'properties': ['cpuType: "rv32i"'],
|
||||||
|
},
|
||||||
|
'im': {
|
||||||
|
'properties': ['cpuType: "rv32im"'],
|
||||||
|
},
|
||||||
|
'ima': {
|
||||||
|
'properties': ['cpuType: "rv32ima"'],
|
||||||
|
},
|
||||||
|
'imac': {
|
||||||
|
'properties': ['cpuType: "rv32imac"'],
|
||||||
|
},
|
||||||
|
'others': {
|
||||||
|
'properties': ['cpuType: "rv32im"'],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'supports_time_provider': True,
|
||||||
|
}
|
||||||
|
cpu_kinds = {
|
||||||
|
'vexriscv': vexriscv_common_kind,
|
||||||
|
'vexriscv_smp': vexriscv_common_kind,
|
||||||
|
'picorv32': {
|
||||||
|
'name': 'PicoRV32',
|
||||||
|
'properties': ['cpuType: "rv32imc"'],
|
||||||
|
},
|
||||||
|
'minerva': {
|
||||||
|
'name': 'Minerva',
|
||||||
|
},
|
||||||
|
'ibex': {
|
||||||
|
'name': 'IbexRiscV32',
|
||||||
|
},
|
||||||
|
'cv32e40p': {
|
||||||
|
'name': 'CV32E40P',
|
||||||
|
'supports_time_provider': True,
|
||||||
|
'properties': ['cpuType: "rv32imc"'],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def generate_cpu(csr, time_provider, number_of_cores):
|
||||||
""" Generates definition of a CPU.
|
""" Generates definition of a CPU.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
@ -213,63 +268,39 @@ def generate_cpu(csr, time_provider):
|
||||||
"""
|
"""
|
||||||
kind, variant = get_cpu_type(csr)
|
kind, variant = get_cpu_type(csr)
|
||||||
|
|
||||||
if kind == 'vexriscv' or kind == 'vexriscv_smp':
|
try:
|
||||||
result = """
|
cpu = cpu_kinds[kind]
|
||||||
cpu: CPU.VexRiscv @ sysbus
|
|
||||||
|
cpu_string = f'{cpu["name"]} @ sysbus\n'
|
||||||
|
|
||||||
|
def unpack_properties(prop_list):
|
||||||
|
return ''.join([f' {prop}\n' for prop in prop_list])
|
||||||
|
|
||||||
|
if 'properties' in cpu:
|
||||||
|
cpu_string += unpack_properties(cpu["properties"])
|
||||||
|
|
||||||
|
if 'variants' in cpu:
|
||||||
|
variant = cpu['variants'].get(variant)
|
||||||
|
|
||||||
|
if variant is None:
|
||||||
|
variant = cpu['variants'].get('others', [])
|
||||||
|
|
||||||
|
if 'properties' in variant:
|
||||||
|
cpu_string += unpack_properties(variant["properties"])
|
||||||
|
|
||||||
|
except KeyError:
|
||||||
|
raise Exception(f'Unsupported cpu type: {kind}')
|
||||||
|
|
||||||
|
result = ''
|
||||||
|
for cpu_id in range(0, number_of_cores):
|
||||||
|
result += f"""
|
||||||
|
cpu{cpu_id}: CPU.{cpu_string.strip()}
|
||||||
|
hartId: {cpu_id}
|
||||||
"""
|
"""
|
||||||
if variant == 'linux':
|
if cpu.get('supports_time_provider', False):
|
||||||
result += """
|
result += f' timeProvider: {time_provider}\n'
|
||||||
cpuType: "rv32ima"
|
|
||||||
privilegeArchitecture: PrivilegeArchitecture.Priv1_10
|
|
||||||
"""
|
|
||||||
elif variant in ["i", "im", "ima", "imac"]:
|
|
||||||
result += """
|
|
||||||
cpuType: "rv32{}"
|
|
||||||
""".format(variant)
|
|
||||||
else:
|
|
||||||
result += """
|
|
||||||
cpuType: "rv32im"
|
|
||||||
"""
|
|
||||||
if time_provider:
|
|
||||||
result += """
|
|
||||||
timeProvider: {}
|
|
||||||
""".format(time_provider)
|
|
||||||
|
|
||||||
return result
|
return result
|
||||||
elif kind == 'picorv32':
|
|
||||||
return """
|
|
||||||
cpu: CPU.PicoRV32 @ sysbus
|
|
||||||
cpuType: "rv32imc"
|
|
||||||
"""
|
|
||||||
elif kind == 'minerva':
|
|
||||||
return """
|
|
||||||
cpu: CPU.Minerva @ sysbus
|
|
||||||
"""
|
|
||||||
elif kind == 'ibex':
|
|
||||||
return """
|
|
||||||
cpu: CPU.IbexRiscV32 @ sysbus
|
|
||||||
"""
|
|
||||||
elif kind == 'cv32e40p':
|
|
||||||
result = """
|
|
||||||
cpu: CPU.CV32E40P @ sysbus
|
|
||||||
"""
|
|
||||||
if variant == 'standard':
|
|
||||||
result += """
|
|
||||||
cpuType: "rv32imc"
|
|
||||||
"""
|
|
||||||
else:
|
|
||||||
result += """
|
|
||||||
cpuType: "rv32imc"
|
|
||||||
"""
|
|
||||||
if time_provider:
|
|
||||||
result += """
|
|
||||||
timeProvider: {}
|
|
||||||
""".format(time_provider)
|
|
||||||
|
|
||||||
return result
|
|
||||||
else:
|
|
||||||
raise Exception('Unsupported cpu type: {}'.format(kind))
|
|
||||||
|
|
||||||
|
|
||||||
def generate_peripheral(csr, name, **kwargs):
|
def generate_peripheral(csr, name, **kwargs):
|
||||||
""" Generates definition of a peripheral.
|
""" Generates definition of a peripheral.
|
||||||
|
@ -298,7 +329,7 @@ def generate_peripheral(csr, name, **kwargs):
|
||||||
for constant, val in peripheral['constants'].items():
|
for constant, val in peripheral['constants'].items():
|
||||||
if 'ignored_constants' not in kwargs or constant not in kwargs['ignored_constants']:
|
if 'ignored_constants' not in kwargs or constant not in kwargs['ignored_constants']:
|
||||||
if constant == 'interrupt':
|
if constant == 'interrupt':
|
||||||
result += ' -> cpu@{}\n'.format(val)
|
result += ' -> {}@{}\n'.format(get_soc_interrupt_parent(csr), val)
|
||||||
else:
|
else:
|
||||||
result += ' {}: {}\n'.format(constant, val)
|
result += ' {}: {}\n'.format(constant, val)
|
||||||
|
|
||||||
|
@ -413,31 +444,37 @@ mmc_controller: SD.LiteSDCard{} @ {{
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def generate_clint(clint, frequency):
|
def generate_clint(clint, frequency, number_of_cores):
|
||||||
# TODO: this is configuration for VexRiscv - add support for other CPU types
|
# TODO: this is configuration for VexRiscv - add support for other CPU types
|
||||||
result = """
|
result = """
|
||||||
clint: IRQControllers.CoreLevelInterruptor @ {}
|
clint: IRQControllers.CoreLevelInterruptor @ {}
|
||||||
frequency: {}
|
frequency: {}
|
||||||
[0, 1] -> cpu@[101, 100]
|
numberOfTargets: {}
|
||||||
""".format(generate_sysbus_registration(clint,
|
""".format(generate_sysbus_registration(clint,
|
||||||
skip_braces=True,
|
skip_braces=True,
|
||||||
skip_size=True),
|
skip_size=True),
|
||||||
frequency)
|
frequency, number_of_cores)
|
||||||
|
|
||||||
|
for cpu_id in range(0, number_of_cores):
|
||||||
|
result += f" [{2 * cpu_id}, {2 * cpu_id + 1}] -> cpu{cpu_id}@[101, 100]\n"
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def generate_plic(plic):
|
def generate_plic(plic, number_of_cores):
|
||||||
# TODO: this is configuration for linux-on-litex-vexriscv - add support for other CPU types
|
# TODO: this is configuration for linux-on-litex-vexriscv - add support for other CPU types
|
||||||
result = """
|
result = """
|
||||||
plic: IRQControllers.PlatformLevelInterruptController @ {}
|
plic: IRQControllers.PlatformLevelInterruptController @ {}
|
||||||
[0, 1] -> cpu@[11, 9]
|
|
||||||
numberOfSources: 31
|
numberOfSources: 31
|
||||||
numberOfContexts: 2
|
numberOfContexts: {}
|
||||||
prioritiesEnabled: false
|
prioritiesEnabled: false
|
||||||
""".format(generate_sysbus_registration(plic,
|
""".format(generate_sysbus_registration(plic,
|
||||||
skip_braces=True,
|
skip_braces=True,
|
||||||
skip_size=True))
|
skip_size=True),
|
||||||
|
2 * number_of_cores)
|
||||||
|
|
||||||
|
for cpu_id in range(0, number_of_cores):
|
||||||
|
result += f" [{2 * cpu_id}, {2 * cpu_id + 1}] -> cpu{cpu_id}@[11, 9]\n"
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
@ -489,6 +526,67 @@ def get_clock_frequency(csr):
|
||||||
# has different names
|
# has different names
|
||||||
return csr['constants']['config_clock_frequency' if 'config_clock_frequency' in csr['constants'] else 'system_clock_frequency']
|
return csr['constants']['config_clock_frequency' if 'config_clock_frequency' in csr['constants'] else 'system_clock_frequency']
|
||||||
|
|
||||||
|
def generate_gpio_port(csr, name, **kwargs):
|
||||||
|
peripheral = get_descriptor(csr, name)
|
||||||
|
|
||||||
|
ints = ''
|
||||||
|
if 'interrupt' in kwargs:
|
||||||
|
ints += f' IRQ -> {get_soc_interrupt_parent(csr)}@{kwargs["interrupt"]}'
|
||||||
|
if 'connections' in kwargs:
|
||||||
|
for irq, target in zip(kwargs['connections'], kwargs['connections_targets']):
|
||||||
|
ints += f' {irq} -> {target}\n'
|
||||||
|
|
||||||
|
result = """
|
||||||
|
gpio_{}: GPIOPort.LiteX_GPIO @ {}
|
||||||
|
type: {}
|
||||||
|
enableIrq: {}
|
||||||
|
{}
|
||||||
|
""".format(name,
|
||||||
|
generate_sysbus_registration(peripheral, skip_braces=True),
|
||||||
|
kwargs['type'],
|
||||||
|
'true' if kwargs['type'] != 'Type.Out' else 'false',
|
||||||
|
ints)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def generate_switches(csr, name, **kwargs):
|
||||||
|
interrupt_name = '{}_interrupt'.format(name)
|
||||||
|
result = generate_gpio_port(csr, name, **{'type': 'Type.In', 'interrupt': csr['constants'][interrupt_name], **kwargs})
|
||||||
|
|
||||||
|
# Litex puts 4 by default into dts (litex_json2dts)
|
||||||
|
count = int(csr['constants'].get(f'{name}_ngpio', 4))
|
||||||
|
|
||||||
|
for i in range(0, count):
|
||||||
|
result += """
|
||||||
|
{name}_{i}: Miscellaneous.Button @ {periph} {i}
|
||||||
|
-> {periph}@{i}
|
||||||
|
""".format(name=name, periph=f"gpio_{name}", i=i)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def generate_leds(csr, name, **kwargs):
|
||||||
|
# Litex puts 4 by default into dts (litex_json2dts)
|
||||||
|
count = int(csr['constants'].get(f'{name}_ngpio', 4))
|
||||||
|
|
||||||
|
result = generate_gpio_port(csr, name,
|
||||||
|
**{'type': 'Type.Out',
|
||||||
|
'connections': [*range(0, count)],
|
||||||
|
'connections_targets': [f'leds_{i}@0' for i in range(0, count)],
|
||||||
|
**kwargs})
|
||||||
|
|
||||||
|
for i in range(0, count):
|
||||||
|
result += """
|
||||||
|
{name}_{i}: Miscellaneous.LED @ {periph} {i}
|
||||||
|
""".format(name=name, periph=f"gpio_{name}", i=i)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def handled_peripheral(csr, name, **kwargs):
|
||||||
|
"""
|
||||||
|
Use this to silence warnings about unsupported peripherals, that are in reality emulated by other peripheral
|
||||||
|
e. g. mmc, ethmac
|
||||||
|
"""
|
||||||
|
return ''
|
||||||
|
|
||||||
peripherals_handlers = {
|
peripherals_handlers = {
|
||||||
'uart': {
|
'uart': {
|
||||||
|
@ -521,7 +619,7 @@ peripherals_handlers = {
|
||||||
},
|
},
|
||||||
'interrupts': {
|
'interrupts': {
|
||||||
# IRQ #100 in Renode's VexRiscv model is mapped to Machine Timer Interrupt
|
# IRQ #100 in Renode's VexRiscv model is mapped to Machine Timer Interrupt
|
||||||
'IRQ': lambda: 'cpu@100'
|
'IRQ': lambda: 'cpu0@100'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'ddrphy': {
|
'ddrphy': {
|
||||||
|
@ -559,12 +657,37 @@ peripherals_handlers = {
|
||||||
'handler': generate_video_framebuffer,
|
'handler': generate_video_framebuffer,
|
||||||
},
|
},
|
||||||
'video_framebuffer_vtg': {
|
'video_framebuffer_vtg': {
|
||||||
'handler': lambda *args, **kwargs: "", # This is handled by generate_video_framebuffer
|
'handler': handled_peripheral, # This is handled by generate_video_framebuffer
|
||||||
}
|
},
|
||||||
|
'leds': {
|
||||||
|
'handler': generate_leds,
|
||||||
|
},
|
||||||
|
'switches': {
|
||||||
|
'handler': generate_switches,
|
||||||
|
},
|
||||||
|
'mmcm': {
|
||||||
|
'handler': generate_peripheral,
|
||||||
|
'model': 'Miscellaneous.LiteX_MMCM',
|
||||||
|
'model_CSR32': 'Miscellaneous.LiteX_MMCM_CSR32',
|
||||||
|
'ignored_constants': ['lock_timeout', 'drdy_timeout'],
|
||||||
|
},
|
||||||
|
'ethphy': {
|
||||||
|
'handler': handled_peripheral # by generate_ethmac
|
||||||
|
},
|
||||||
|
# handled by generate_mmc
|
||||||
|
'sdblock2mem': {
|
||||||
|
'handler': handled_peripheral
|
||||||
|
},
|
||||||
|
'sdmem2block': {
|
||||||
|
'handler': handled_peripheral
|
||||||
|
},
|
||||||
|
'sdcore': {
|
||||||
|
'handler': handled_peripheral
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def genereate_etherbone_bridge(name, address, port):
|
def generate_etherbone_bridge(name, address, port):
|
||||||
# FIXME: for now the width is fixed to 0x800
|
# FIXME: for now the width is fixed to 0x800
|
||||||
return """
|
return """
|
||||||
{}: EtherboneBridge @ sysbus <{}, +0x800>
|
{}: EtherboneBridge @ sysbus <{}, +0x800>
|
||||||
|
@ -572,7 +695,7 @@ def genereate_etherbone_bridge(name, address, port):
|
||||||
""".format(name, hex(address), port)
|
""".format(name, hex(address), port)
|
||||||
|
|
||||||
|
|
||||||
def generate_repl(csr, etherbone_peripherals, autoalign):
|
def generate_repl(csr, etherbone_peripherals, autoalign, number_of_cores):
|
||||||
""" Generates platform definition.
|
""" Generates platform definition.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
@ -592,7 +715,6 @@ def generate_repl(csr, etherbone_peripherals, autoalign):
|
||||||
"""
|
"""
|
||||||
result = ""
|
result = ""
|
||||||
|
|
||||||
|
|
||||||
# RISC-V CPU in Renode requires memory region size
|
# RISC-V CPU in Renode requires memory region size
|
||||||
# to be a multiple of 4KB - this is a known limitation
|
# to be a multiple of 4KB - this is a known limitation
|
||||||
# (not a bug) and there are no plans to handle smaller
|
# (not a bug) and there are no plans to handle smaller
|
||||||
|
@ -611,16 +733,16 @@ def generate_repl(csr, etherbone_peripherals, autoalign):
|
||||||
|
|
||||||
time_provider = None
|
time_provider = None
|
||||||
if 'clint' in csr['memories']:
|
if 'clint' in csr['memories']:
|
||||||
result += generate_clint(csr['memories']['clint'], csr['constants']['config_clock_frequency'])
|
result += generate_clint(csr['memories']['clint'], csr['constants']['config_clock_frequency'], number_of_cores)
|
||||||
time_provider = 'clint'
|
time_provider = 'clint'
|
||||||
|
|
||||||
if 'plic' in csr['memories']:
|
if 'plic' in csr['memories']:
|
||||||
result += generate_plic(csr['memories']['plic'])
|
result += generate_plic(csr['memories']['plic'], number_of_cores)
|
||||||
|
|
||||||
if not time_provider and 'cpu' in csr['csr_bases']:
|
if not time_provider and 'cpu' in csr['csr_bases']:
|
||||||
time_provider = 'cpu_timer'
|
time_provider = 'cpu_timer'
|
||||||
|
|
||||||
result += generate_cpu(csr, time_provider)
|
result += generate_cpu(csr, time_provider, number_of_cores)
|
||||||
|
|
||||||
for name, address in csr['csr_bases'].items():
|
for name, address in csr['csr_bases'].items():
|
||||||
if name not in peripherals_handlers:
|
if name not in peripherals_handlers:
|
||||||
|
@ -631,7 +753,7 @@ def generate_repl(csr, etherbone_peripherals, autoalign):
|
||||||
if name in etherbone_peripherals:
|
if name in etherbone_peripherals:
|
||||||
# generate an etherbone bridge for the peripheral
|
# generate an etherbone bridge for the peripheral
|
||||||
port = etherbone_peripherals[name]
|
port = etherbone_peripherals[name]
|
||||||
result += genereate_etherbone_bridge(name, address, port)
|
result += generate_etherbone_bridge(name, address, port)
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
# generate an actual model of the peripheral
|
# generate an actual model of the peripheral
|
||||||
|
@ -674,6 +796,8 @@ def filter_memory_regions(raw_regions, alignment=None, autoalign=[]):
|
||||||
size_mismatch = r['size'] % alignment
|
size_mismatch = r['size'] % alignment
|
||||||
address_mismatch = r['base'] % alignment
|
address_mismatch = r['base'] % alignment
|
||||||
|
|
||||||
|
def print_autoalign_hint():
|
||||||
|
print('Hint: use "--auto-align {}" to force automatic alignement of the region'.format(r['name']))
|
||||||
if address_mismatch != 0:
|
if address_mismatch != 0:
|
||||||
if r['name'] in autoalign:
|
if r['name'] in autoalign:
|
||||||
r['original_address'] = r['base']
|
r['original_address'] = r['base']
|
||||||
|
@ -681,6 +805,7 @@ def filter_memory_regions(raw_regions, alignment=None, autoalign=[]):
|
||||||
print('Re-aligning `{}` memory region base address from {} to {} due to limitations in Renode'.format(r['name'], hex(r['original_address']), hex(r['base'])))
|
print('Re-aligning `{}` memory region base address from {} to {} due to limitations in Renode'.format(r['name'], hex(r['original_address']), hex(r['base'])))
|
||||||
else:
|
else:
|
||||||
print('Error: `{}` memory region base address ({}) is not aligned to {}. This configuration cannot be currently simulated in Renode'.format(r['name'], hex(r['size']), hex(alignment)))
|
print('Error: `{}` memory region base address ({}) is not aligned to {}. This configuration cannot be currently simulated in Renode'.format(r['name'], hex(r['size']), hex(alignment)))
|
||||||
|
print_autoalign_hint()
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
if size_mismatch != 0:
|
if size_mismatch != 0:
|
||||||
|
@ -690,6 +815,7 @@ def filter_memory_regions(raw_regions, alignment=None, autoalign=[]):
|
||||||
print('Extending `{}` memory region size from {} to {} due to limitations in Renode'.format(r['name'], hex(r['original_size']), hex(r['size'])))
|
print('Extending `{}` memory region size from {} to {} due to limitations in Renode'.format(r['name'], hex(r['original_size']), hex(r['size'])))
|
||||||
else:
|
else:
|
||||||
print('Error: `{}` memory region size ({}) is not aligned to {}. This configuration cannot be currently simulated in Renode'.format(r['name'], hex(r['size']), hex(alignment)))
|
print('Error: `{}` memory region size ({}) is not aligned to {}. This configuration cannot be currently simulated in Renode'.format(r['name'], hex(r['size']), hex(alignment)))
|
||||||
|
print_autoalign_hint()
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
if r['size'] == 0:
|
if r['size'] == 0:
|
||||||
|
@ -730,7 +856,7 @@ def find_memory_region(memory_regions, address):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def generate_resc(csr, args, flash_binaries={}, tftp_binaries={}):
|
def generate_resc(csr, number_of_cores, args, flash_binaries={}, tftp_binaries={}):
|
||||||
""" Generates platform definition.
|
""" Generates platform definition.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
@ -756,14 +882,15 @@ showAnalyzer sysbus.uart
|
||||||
showAnalyzer sysbus.uart Antmicro.Renode.Analyzers.LoggingUartAnalyzer
|
showAnalyzer sysbus.uart Antmicro.Renode.Analyzers.LoggingUartAnalyzer
|
||||||
""".format(cpu_type, args.repl)
|
""".format(cpu_type, args.repl)
|
||||||
|
|
||||||
rom_base = csr['memories']['rom']['base'] if 'rom' in csr['memories'] else None
|
opensbi_base = csr['memories']['opensbi']['base'] if 'opensbi' in csr['memories'] else None
|
||||||
if rom_base is not None and args.bios_binary:
|
if opensbi_base is not None and args.bios_binary:
|
||||||
# load LiteX BIOS to ROM
|
# load LiteX BIOS to ROM
|
||||||
result += """
|
result += """
|
||||||
sysbus LoadBinary @{} {}
|
sysbus LoadBinary @{} {}
|
||||||
cpu PC {}
|
""".format(args.bios_binary, hex(opensbi_base))
|
||||||
""".format(args.bios_binary, rom_base, rom_base)
|
|
||||||
|
|
||||||
|
for cpu_id in range(0, number_of_cores):
|
||||||
|
result += f"cpu{cpu_id} PC {hex(opensbi_base)}\n"
|
||||||
|
|
||||||
if args.tftp_ip:
|
if args.tftp_ip:
|
||||||
result += """
|
result += """
|
||||||
|
@ -792,16 +919,16 @@ connector Connect ethmac switch
|
||||||
connector Connect host.tap switch
|
connector Connect host.tap switch
|
||||||
""".format(args.configure_network)
|
""".format(args.configure_network)
|
||||||
elif flash_binaries:
|
elif flash_binaries:
|
||||||
if 'flash_boot_address' not in csr['constants']:
|
if 'spiflash' not in csr['memories']:
|
||||||
print('Warning! There is no flash memory to load binaries to')
|
print('Warning! There is no flash memory to load binaries to')
|
||||||
else:
|
else:
|
||||||
# load binaries to spiflash to boot from there
|
# load binaries to spiflash to boot from there
|
||||||
|
|
||||||
for offset in flash_binaries:
|
for offset in flash_binaries:
|
||||||
path = flash_binaries[offset]
|
path = flash_binaries[offset]
|
||||||
flash_boot_address = int(csr['constants']['flash_boot_address'], 0) + offset
|
flash_boot_address = int(csr['memories']['spiflash']['base']) + offset
|
||||||
|
|
||||||
firmware_data = open(path, 'rb').read()
|
firmware_data = open(os.path.expanduser(path), 'rb').read()
|
||||||
crc32 = zlib.crc32(firmware_data)
|
crc32 = zlib.crc32(firmware_data)
|
||||||
|
|
||||||
result += 'sysbus WriteDoubleWord {} {}\n'.format(hex(flash_boot_address), hex(len(firmware_data)))
|
result += 'sysbus WriteDoubleWord {} {}\n'.format(hex(flash_boot_address), hex(len(firmware_data)))
|
||||||
|
@ -950,8 +1077,10 @@ def main():
|
||||||
|
|
||||||
etherbone_peripherals = check_etherbone_peripherals(args.etherbone_peripherals)
|
etherbone_peripherals = check_etherbone_peripherals(args.etherbone_peripherals)
|
||||||
|
|
||||||
|
number_of_cores = get_cpu_count(csr)
|
||||||
|
|
||||||
if args.repl:
|
if args.repl:
|
||||||
print_or_save(args.repl, generate_repl(csr, etherbone_peripherals, args.autoalign_memor_regions))
|
print_or_save(args.repl, generate_repl(csr, etherbone_peripherals, args.autoalign_memor_regions, number_of_cores))
|
||||||
|
|
||||||
if args.resc:
|
if args.resc:
|
||||||
if not args.repl:
|
if not args.repl:
|
||||||
|
@ -961,7 +1090,7 @@ def main():
|
||||||
flash_binaries = parse_flash_binaries(csr, args)
|
flash_binaries = parse_flash_binaries(csr, args)
|
||||||
tftp_binaries = check_tftp_binaries(args)
|
tftp_binaries = check_tftp_binaries(args)
|
||||||
|
|
||||||
print_or_save(args.resc, generate_resc(csr, args,
|
print_or_save(args.resc, generate_resc(csr, number_of_cores, args,
|
||||||
flash_binaries,
|
flash_binaries,
|
||||||
tftp_binaries))
|
tftp_binaries))
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue