From cd5148d96126e8c9e14e6bfb0b4dbc1bbd6914dd Mon Sep 17 00:00:00 2001 From: Michal Sieron Date: Thu, 26 May 2022 09:54:43 +0200 Subject: [PATCH] Update litex_json2dts_zephyr Changes in Zephyr require updated script to generate correct overlay. This commit splits CSR regions that were being added to overlay as single register into separate registers with names. It also prints their size in bytes instead of used subregisters. I also added LITEX_CSR_DATA_WIDTH to generated config parameters. To limit code duplication, I added functions used for indenting text. Additionally, I updated formatting functions to take list of registers and then format it, instead of just surrounding already formatted text with braces. --- litex/tools/litex_json2dts_zephyr.py | 153 ++++++++++++++++++++++----- 1 file changed, 124 insertions(+), 29 deletions(-) diff --git a/litex/tools/litex_json2dts_zephyr.py b/litex/tools/litex_json2dts_zephyr.py index 3fcb40639..c42ce9338 100755 --- a/litex/tools/litex_json2dts_zephyr.py +++ b/litex/tools/litex_json2dts_zephyr.py @@ -22,49 +22,146 @@ import argparse import json +def get_registers_of(name, csr): + registers = csr['csr_registers'] + + return [ + { + **params, + # describe size in bytes, not number of subregisters + 'size': params['size'] * 4, + 'name': r[len(name) + 1:], + } + for r, params in registers.items() if r.startswith(name) + ] + + +# Indentation helpers +INDENT_STR = ' ' + + +def indent(line, levels=1): + return INDENT_STR * levels + line + + +def indent_all(text, levels=1): + return '\n'.join(map(indent, text.splitlines())) + + +def indent_all_but_first(text, levels=1): + lines = text.splitlines() + indented = indent_all('\n'.join(lines[1:]), levels) + if indented: + return lines[0] + '\n' + indented + else: + return lines[0] + + # DTS formatting -def dts_open(name, parm): return "&{} {{\n".format(parm.get('alias', name)) -def dts_close(): return "};\n" -def dts_intr(name, csr): return " interrupts = <{} 0>;\n".format( - hex(csr['constants'][name + '_interrupt'])) -def dts_reg(regs): return " reg = <{}>;\n".format(regs) +def dts_open(name, parm): + return "&{} {{\n".format(parm.get('alias', name)) + + +def dts_close(): + return "};\n" + + +def dts_intr(name, csr): + return indent("interrupts = <{} 0>;\n".format( + hex(csr['constants'][name + '_interrupt']) + )) + + +def dts_reg(regs): + dtsi = 'reg = <' + + formatted_registers = '\n'.join( + '0x{:x} 0x{:x}'.format(reg['addr'], reg['size']) + for reg in regs + ) + + dtsi += indent_all_but_first(formatted_registers) + dtsi += '>;' + + return indent_all(dtsi) + '\n' + + +def dts_reg_names(regs): + dtsi = 'reg-names = ' + + formatted_registers = ',\n'.join( + '"{}"'.format(reg['name']) + for reg in regs + ) + + dtsi += indent_all_but_first(formatted_registers) + dtsi += ';' + + return indent_all(dtsi) + '\n' # DTS handlers def disabled_handler(name, parm, csr): - return " status = \"disabled\";\n" + return indent('status = "disabled";\n') def ram_handler(name, parm, csr): - return dts_reg(" ".join([ - hex(csr['memories'][name]['base']), - hex(csr['memories'][name]['size'])])) + mem_reg = { + 'addr': csr['memories'][name]['base'], + 'size': csr['memories'][name]['size'], + } + + return dts_reg([mem_reg]) def ethmac_handler(name, parm, csr): - dtsi = dts_reg(" ".join([ - hex(csr['csr_bases'][name]), - hex(parm['size']), - hex(csr['memories'][name]['base']), - hex(csr['memories'][name]['size'])])) + rx_registers = get_registers_of(name + '_sram_writer', csr) + for reg in rx_registers: + reg['name'] = 'rx_' + reg['name'] + + tx_registers = get_registers_of(name + '_sram_reader', csr) + for reg in tx_registers: + reg['name'] = 'tx_' + reg['name'] + + eth_buffers = { + 'name': 'buffers', + 'addr': csr['memories'][name]['base'], + 'size': csr['memories'][name]['size'], + 'type': csr['memories'][name]['type'], + } + registers = rx_registers + tx_registers + [eth_buffers] + + dtsi = dts_reg(registers) + dtsi += dts_reg_names(registers) dtsi += dts_intr(name, csr) return dtsi def i2c_handler(name, parm, csr): - dtsi = dts_reg(" ".join([ - hex(csr['csr_bases'][name]), - hex(parm['size']), - hex(csr['csr_bases'][name] + parm['size']), - hex(parm['size'])])) - dtsi += dts_intr(name, csr) + registers = get_registers_of(name, csr) + if len(registers) == 0: + raise KeyError + + for reg in registers: + if reg["name"] == "w": + reg["name"] = "write" + elif reg["name"] == "r": + reg["name"] = "read" + + dtsi = dts_reg(registers) + dtsi += dts_reg_names(registers) + return dtsi def peripheral_handler(name, parm, csr): - dtsi = dts_reg(" ".join([ - hex(csr['csr_bases'][name]), - hex(parm['size'])])) + registers = get_registers_of(name, csr) + if len(registers) == 0: + raise KeyError + + dtsi = dts_reg(registers) + dtsi += dts_reg_names(registers) + try: dtsi += dts_intr(name, csr) except KeyError as e: @@ -76,29 +173,24 @@ overlay_handlers = { 'uart': { 'handler': peripheral_handler, 'alias': 'uart0', - 'size': 0x20, 'config_entry': 'UART_LITEUART' }, 'timer0': { 'handler': peripheral_handler, - 'size': 0x40, 'config_entry': 'LITEX_TIMER' }, 'ethmac': { 'handler': ethmac_handler, 'alias': 'eth0', - 'size': 0x80, 'config_entry': 'ETH_LITEETH' }, 'spiflash': { 'handler': peripheral_handler, 'alias': 'spi0', - 'size': 12, 'config_entry': 'SPI_LITESPI' }, 'i2c0' : { 'handler': i2c_handler, - 'size': 0x4, 'config_entry': 'I2C_LITEX' }, 'main_ram': { @@ -108,7 +200,6 @@ overlay_handlers = { 'identifier_mem': { 'handler': peripheral_handler, 'alias': 'dna0', - 'size': 0x100, } } @@ -137,6 +228,10 @@ def generate_dts_config(csr): if name not in overlay_handlers.keys(): print('No overlay handler for:', name, 'at', hex(value)) + cnf += ' -DCONFIG_LITEX_CSR_DATA_WIDTH={}'.format( + csr['constants']['config_csr_data_width'], + ) + return dts, cnf