diff --git a/conf/README.md b/conf/README.md new file mode 100644 index 0000000..07a1067 --- /dev/null +++ b/conf/README.md @@ -0,0 +1,278 @@ +# Linux SDK SoC Configuration Generator + +To enhance the convenience and efficiency of porting the Nuclei Linux SDK for our users, we've developed a Python script +designed to automate the generation of customized configuration files which located in `conf/`. + +With the help of the script, it will speedup the bringup of your SoC prototype using Nuclei RISC-V CPU IP, and can also evaluate +it using Nuclei QEMU. + +By leveraging **conf/evalsoc** as the default reference template, this tool accept a **SoC configuration file** provided by you +to generate proper linux sdk configuration files for your customized SoC. + +This script assumed your SoC used Nuclei RISC-V CPU and UART/QSPI IP, UART0, QSPI0 connected to SPIFlash, QSPI2 connected to SDCard. + +> If you are not using our IP, it may need more efforts to modify opensbi, uboot and linux drivers. + +> If you are using Nuclei UART/QSPI IP, the IP uboot and linux driver is still in development. + +## SoC Configuration File + +The configuration file is in JSON format,mainly used to config ddr, flash address,size and device irq. + +A typical config file as following: + +~~~json +{ + "general_config": { + "ddr": { + "base": "0x80000000", + "size": "0x80000000" + }, + "norflash": { + "base": "0x20000000", + "size": "32M" + }, + "iregion": { + "base": "0x18000000" + }, + "uart0": { + "base": "0x10013000", + "irq": "33" + }, + "uart1": { + "base": "0x10023000", + "irq": "34" + }, + "qspi0": { + "base": "0x10014000", + "irq": "35" + }, + "qspi2": { + "base": "0x10034000", + "irq": "37" + }, + "cpu_freq": "50000000", + "timer_freq": "32768" + } +} +~~~ + +- `general_config` is mainly used to configure the board resource or chip base address + +- `base` property : base address, only support hex format + +- `size` property : size, support hex, dec, size string format + +- `irq` property : peripheral interrupt id, dec format + +The `irq` peripheral interrupt id is equal to hardware interrupt wire connect number plus one, users should follow this rule when configuring irq. + +| IRQ_HW_ID | PLIC Interrupt ID | Source | +| --------- | ----------------- | ------ | +| 32 | 33 | uart0 | +| 34 | 35 | qspi0 | +| 35 | 36 | qspi1 | +| 36 | 37 | qspi2 | + +The **iregion** is Nuclei RISC-V CPU internal region, you should provide correct iregion base to match with your SoC. + +If **ddr** parameter is not exist, we will use `base:0x80000000`,`size:0x80000000` as default value. + +If other parameters are not exist, we will skip update them. + +## How to use + +Change directory to `/conf/`, then execute the python script `genconf.py`. + +~~~shell +$cd nuclei-linux-sdk/conf +$ ./genconf.py --help +usage: genconf.py [-h] [--conf CONF] [--refsoc REFSOC] custsoc + +Generate configuration files based on a reference SOC. + +positional arguments: + custsoc new config files directory. + +optional arguments: + -h, --help show this help message and exit + --conf CONF json config file (default: genconf.json). + --refsoc REFSOC reference soc config (default: evalsoc). +~~~ + +generate named **rvsoc** config files with default `evalsoc` and `genconf.json` + +~~~shell +$./genconf.py rvsoc +~~~ + +generate named **rvsoc** config files based on `xxxsoc` with `xxx.json`, support `xxxsoc` and +`xxx.json` have exist in the same directory. + +~~~shell +$./genconf.py --conf xxx.json --refsoc xxxsoc rvsoc +~~~ + +After generate config files, you can build your linux sdk using command: + +> Assume you want to use ux900fd CORE. + +~~~shell +cd /path/to/nuclei-linux-sdk +# you are now in the root of Nuclei Linux SDK +# build your rvsoc and use ux900fd core +make SOC=rvsoc CORE=ux900fd freeloader bootimages +# run and evaluate it on qemu +make SOC=rvsoc CORE=ux900fd run_qemu +~~~ + +More detail about how to build linux sdk, please refer to Linux SDK top **README.md**. + +## Example + +generate rv64 rvsoc config files log as following: + +~~~shell +nuclei-linux-sdk/conf$ ./genconf.py rvsoc +===Start generating rvsoc config files based on evalsoc=== + +>>>Updating opensbi... +Create 'rvsoc/opensbi/customsoc.c' based on 'rvsoc/opensbi/evalsoc.c'. +Replace string evalsoc with customsoc in rvsoc/opensbi/customsoc.c +Note: All custom soc should use customsoc.c for nuclei generic soc support + +>>>Updating uboot config... +- rvsoc/uboot_rv32imac_sd_config: +Update with CONFIG_TEXT_BASE=0x80400000 + +Update with CONFIG_SYS_LOAD_ADDR=0x80400000 + +Update with CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x80400000 + +- rvsoc/uboot_rv64imac_flash_config: +Update with CONFIG_TEXT_BASE=0x80200000 + +Update with CONFIG_SYS_LOAD_ADDR=0x80200000 + +Update with CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x80200000 + +Update with CONFIG_BOOTCOMMAND="bootm 0x83000000 0x88300000 0x88000000" + +- rvsoc/uboot_rv32imafdc_flash_config: +Update with CONFIG_TEXT_BASE=0x80400000 + +Update with CONFIG_SYS_LOAD_ADDR=0x80400000 + +Update with CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x80400000 + +Update with CONFIG_BOOTCOMMAND="bootm 0x83000000 0x88300000 0x88000000" + +- rvsoc/uboot_rv64imac_sd_config: +Update with CONFIG_TEXT_BASE=0x80200000 + +Update with CONFIG_SYS_LOAD_ADDR=0x80200000 + +Update with CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x80200000 + +- rvsoc/uboot_rv32imac_flash_config: +Update with CONFIG_TEXT_BASE=0x80400000 + +Update with CONFIG_SYS_LOAD_ADDR=0x80400000 + +Update with CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x80400000 + +Update with CONFIG_BOOTCOMMAND="bootm 0x83000000 0x88300000 0x88000000" + +- rvsoc/uboot_rv64imafdc_sd_config: +Update with CONFIG_TEXT_BASE=0x80200000 + +Update with CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x80200000 + +Update with CONFIG_SYS_LOAD_ADDR=0x80200000 + +- rvsoc/uboot_rv32imafdc_sd_config: +Update with CONFIG_TEXT_BASE=0x80400000 + +Update with CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x80400000 + +Update with CONFIG_SYS_LOAD_ADDR=0x80400000 + +- rvsoc/uboot_rv64imafdc_flash_config: +Update with CONFIG_TEXT_BASE=0x80200000 + +Update with CONFIG_SYS_LOAD_ADDR=0x80200000 + +Update with CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x80200000 + +Update with CONFIG_BOOTCOMMAND="bootm 0x83000000 0x88300000 0x88000000" + + +>>>Updating freeloader.mk... +Update DDR_BASE to 0x80000000 +Update FLASH_BASE to 0x20000000 +Update FLASH_SIZE to 32M +Update AMPFW_SIZE to 0x400000 +Update AMP_START_CORE to 8 +Update AMPFW_START_OFFSET to 0x7e000000 + +>>>Updating build.mk... +Update FW_TEXT_START to 0x80000000 +Update UIMAGE_AE_CMD to -a 0x80400000 -e 0x80400000 +Update QEMU_MACHINE_OPTS to -M nuclei_evalsoc,soc-cfg=conf/rvsoc/rvsoc.json,download=flashxip -smp 8 + +Updating dts... +- rvsoc/nuclei_rv32imafdc.dts: +Replace string evalsoc with rvsoc in rvsoc/nuclei_rv32imafdc.dts +Update TIMERCLK_FREQ to 32768 +Update CPUCLK_FREQ to 50000000 +Update memory@80000000 to memory@80000000, and update reg value. +Update interrupt-controller@1c000000 to interrupt-controller@1c000000, and update reg value. +Update clint@18031000 to clint@18031000, and update reg value. +Update uart0@10013000 to uart0: serial@10013000, and update reg value. +Update uart1@10023000 to uart1: serial@10023000, and update reg value. +Update qspi0@10014000 to qspi0: spi@10014000, and update reg value. +Update qspi2@10034000 to qspi2: spi@10034000, and update reg value. +- rvsoc/nuclei_rv64imac.dts: +Replace string evalsoc with rvsoc in rvsoc/nuclei_rv64imac.dts +Update TIMERCLK_FREQ to 32768 +Update CPUCLK_FREQ to 50000000 +Update memory@80000000 to memory@80000000, and update reg value. +Update interrupt-controller@1c000000 to interrupt-controller@1c000000, and update reg value. +Update clint@18031000 to clint@18031000, and update reg value. +Update uart0@10013000 to uart0: serial@10013000, and update reg value. +Update uart1@10023000 to uart1: serial@10023000, and update reg value. +Update qspi0@10014000 to qspi0: spi@10014000, and update reg value. +Update qspi2@10034000 to qspi2: spi@10034000, and update reg value. +- rvsoc/nuclei_rv32imac.dts: +Replace string evalsoc with rvsoc in rvsoc/nuclei_rv32imac.dts +Update TIMERCLK_FREQ to 32768 +Update CPUCLK_FREQ to 50000000 +Update memory@80000000 to memory@80000000, and update reg value. +Update interrupt-controller@1c000000 to interrupt-controller@1c000000, and update reg value. +Update clint@18031000 to clint@18031000, and update reg value. +Update uart0@10013000 to uart0: serial@10013000, and update reg value. +Update uart1@10023000 to uart1: serial@10023000, and update reg value. +Update qspi0@10014000 to qspi0: spi@10014000, and update reg value. +Update qspi2@10034000 to qspi2: spi@10034000, and update reg value. +- rvsoc/nuclei_rv64imafdc.dts: +Replace string evalsoc with rvsoc in rvsoc/nuclei_rv64imafdc.dts +Update TIMERCLK_FREQ to 32768 +Update CPUCLK_FREQ to 50000000 +Update memory@80000000 to memory@80000000, and update reg value. +Update interrupt-controller@1c000000 to interrupt-controller@1c000000, and update reg value. +Update clint@18031000 to clint@18031000, and update reg value. +Update uart0@10013000 to uart0: serial@10013000, and update reg value. +Update uart1@10023000 to uart1: serial@10023000, and update reg value. +Update qspi0@10014000 to qspi0: spi@10014000, and update reg value. +Update qspi2@10034000 to qspi2: spi@10034000, and update reg value. + +>>>Updating uboot.cmd... +Update kernel_addr to 0x83000000, rootfs_addr to 0x88300000, fdt_addr to 0x88000000 +===generate successfully!=== + +Here are the reference build commands for compiling Linux SDK for you: +$cd .. +$make SOC=rvsoc CORE=ux900fd BOOT_MODE=sd freeloader bootimages +$make SOC=rvsoc CORE=ux900fd BOOT_MODE=sd run_qemu +Please adjust the compilation parameters according to your real environment. +~~~ diff --git a/conf/genconf.json b/conf/genconf.json index e33f70e..19b4113 100755 --- a/conf/genconf.json +++ b/conf/genconf.json @@ -1,6 +1,6 @@ { "general_config": { - "sdram": { + "ddr": { "base": "0x80000000", "size": "0x80000000" }, @@ -29,9 +29,5 @@ }, "cpu_freq": "50000000", "timer_freq": "32768" - }, - - "uboot_config": { - "CONFIG_TEXT_BASE": "0x80200000" } } diff --git a/conf/genconf.py b/conf/genconf.py index ea6ec94..a341a7b 100755 --- a/conf/genconf.py +++ b/conf/genconf.py @@ -5,36 +5,44 @@ import sys import os import shutil +import argparse def is_uboot_flash_config_format(s): + s = os.path.basename(s) pattern = r'^uboot_\w+_flash_config$' return bool(re.match(pattern, s)) def update_uboot_defconfig(config_file): with open(config_file, 'r') as f: defconfig_content = f.readlines() + if "uboot_rv32" in config_file: + uboot_text_base = hex(int(board_ddr_base, 16) + 0x400000) + else: + uboot_text_base = hex(int(board_ddr_base, 16) + 0x200000) + uboot_cust_sys_init_sp_addr = uboot_text_base + uboot_sys_load_addr = uboot_text_base updated_content = [] for line in defconfig_content: if 'CONFIG_TEXT_BASE=' in line: line = f'CONFIG_TEXT_BASE={uboot_text_base}\n' - print("%s: Updated with %s" %(config_file, line)) + print("Update with %s" %(line)) if 'CONFIG_SYS_TEXT_BASE=' in line: line = f'CONFIG_SYS_TEXT_BASE={uboot_text_base}\n' - print("%s: Updated with %s" %(config_file, line)) + print("Update with %s" %(line)) elif 'CONFIG_CUSTOM_SYS_INIT_SP_ADDR=' in line: line = f'CONFIG_CUSTOM_SYS_INIT_SP_ADDR={uboot_cust_sys_init_sp_addr}\n' - print("%s: Updated with %s" %(config_file, line)) + print("Update with %s" %(line)) elif 'CONFIG_SYS_LOAD_ADDR=' in line: line = f'CONFIG_SYS_LOAD_ADDR={uboot_sys_load_addr}\n' - print("%s: Updated with %s" %(config_file, line)) + print("Update with %s" %(line)) elif 'CONFIG_BOOTCOMMAND=' in line: #update flashboot config bootm if is_uboot_flash_config_format(config_file): - kernel_addr = hex(int(board_sdram_base, 16) + 0x3000000) - rootfs_addr = hex(int(board_sdram_base, 16) + 0x8300000) - fdt_addr = hex(int(board_sdram_base, 16) + 0x8000000) + kernel_addr = hex(int(board_ddr_base, 16) + 0x3000000) + rootfs_addr = hex(int(board_ddr_base, 16) + 0x8300000) + fdt_addr = hex(int(board_ddr_base, 16) + 0x8000000) line = f'CONFIG_BOOTCOMMAND="bootm {kernel_addr} {rootfs_addr} {fdt_addr}"\n' - print("%s: Updated with %s" %(config_file, line)) + print("Update with %s" %(line)) updated_content.append(line) with open(config_file, 'w') as f: @@ -62,9 +70,13 @@ def update_uboot_cmd(file_path, kernel_load_address, rootfs_load_address, fdt_lo with open(file_path, 'w') as f: f.write(updated_content) - print("%s: Updated kernel_addr to %s, rootfs_addr to %s, fdt_addr to %s" %(file_path, kernel_load_address, rootfs_load_address, fdt_load_address)) + print("Update kernel_addr to %s, rootfs_addr to %s, fdt_addr to %s" %(kernel_load_address, rootfs_load_address, fdt_load_address)) def update_dts_clk_freq(dts_file_path, macro_name, new_freq_value): + if new_freq_value is None: + print("new value is None,skip clk update %s" % macro_name) + return + with open(dts_file_path, 'r') as f: dts_content = f.read() # 使用.format()方法构建正则表达式和替换字符串 @@ -76,14 +88,14 @@ def update_dts_clk_freq(dts_file_path, macro_name, new_freq_value): updated_text = pattern_compiled.sub(replacement, dts_content) with open(dts_file_path, 'w') as f: f.write(updated_text) - print("%s: Updated %s to %s" %(dts_file_path, macro_name, new_freq_value)) + print("Update %s to %s" %(macro_name, new_freq_value)) def update_dts_node(dts_file_path, node_name, new_base_address, new_reg_values, new_interrupts=None): with open(dts_file_path, 'r') as f: dts_content = f.read() # 构造正则表达式以匹配整个节点 - pattern_node = re.compile( r'({}(?:\s*:\s*(\w+))?@(\w+))\s*{{(?:.*?reg\s*=\s*<([^>]*)>;)?(?:.*?interrupts\s*=\s*<([^>]*)>;)?.*?}}'.format(re.escape(node_name)), + pattern_node = re.compile(r'({}(?:\s*:\s*(\w+))?@(\w+))\s*{{(?:.*?reg\s*=\s*<([^>]*)>;)?(?:.*?interrupts\s*=\s*<([^>]*)>;)?.*?}}'.format(re.escape(node_name)), re.DOTALL ) @@ -111,7 +123,7 @@ def update_dts_node(dts_file_path, node_name, new_base_address, new_reg_values, # 将新的内容写回文件 with open(dts_file_path, 'w') as f: f.write(new_reg_content) - print(f"{dts_file_path}: Updated {node_name}@{old_base_address} to {new_node_name}, and updated reg value.") + print(f"Update {node_name}@{old_base_address} to {new_node_name}, and update reg value.") else: print("Node not found!") @@ -128,11 +140,15 @@ def update_build_variable(makefile_path, variable_name, new_value): with open(makefile_path, 'w') as file: file.write(content) - print("%s: Updated %s to %s" %(makefile_path, variable_name, new_value)) + print("Update %s to %s" %(variable_name, new_value)) else: print("not match %s" % variable_name) def update_freeloader_variable(makefile_path, variable_name, new_value): + if new_value is None: + print("new value is None,skip update %s" % variable_name) + return + with open(makefile_path, 'r') as file: content = file.read() @@ -143,7 +159,7 @@ def update_freeloader_variable(makefile_path, variable_name, new_value): content = re.sub(pattern, new_line, content, flags=re.MULTILINE) with open(makefile_path, 'w') as file: file.write(content) - print("%s: Updated %s to %s" %(makefile_path, variable_name, new_value)) + print("Update %s to %s" %(variable_name, new_value)) else: print("not match %s" % variable_name) @@ -151,7 +167,7 @@ def replace_in_file(file_path, old_string, new_string): # 读取文件内容 with open(file_path, 'r') as file: file_data = file.read() - print("%s: Replace string %s with %s" %(file_path, old_string, new_string)); + print("Replace string %s with %s in %s" %(old_string, new_string, file_path)); # 替换文件中的指定字符串 file_data = file_data.replace(old_string, new_string) @@ -182,253 +198,288 @@ def parse_size(size_str, output_format='numeric'): else: raise ValueError("Invalid output_format, must be 'numeric' or 'string'") -if len(sys.argv) < 4: - print("Usage: genconf.py conf.json custsoc refsoc\n" - " conf.json: json config file.\n" - " refsoc: reference soc config,you can use evalsoc as reference or others.\n" - " custsoc: new config files created by genconf.py.\n") - exit(1) -if not os.path.exists(sys.argv[1]): - print("%s not exist!\n" % sys.argv[1]) - exit(1) -elif os.path.exists(sys.argv[2]): - print("%s have exist!\n" % sys.argv[2]) - exit(1) -elif os.path.exists(sys.argv[3]): - shutil.copytree(sys.argv[3], sys.argv[2]) - print("===start generate %s based on %s===\n" % (sys.argv[2], sys.argv[3])) -else: - print("%s not exist!\n" % sys.argv[3]) - exit(1) - -try: - # save file path before switch working directory. - config_file_path = os.path.abspath(sys.argv[1]) - generated_file_path = os.path.abspath(sys.argv[2]) - # switch to custsoc directory - os.chdir(sys.argv[2]) - - with open(config_file_path, 'r') as conf_file: - conf_data = json.load(conf_file) - - if 'general_config' in conf_data: - general_config = conf_data['general_config'] - if 'sdram' in general_config: - sdram_config = general_config['sdram'] - if 'base' not in sdram_config: - sdram_config['base'] = "0x80000000" # 或其他合适的默认值 - if 'size' not in sdram_config: - sdram_config['size'] = "0x80000000" # 或其他合适的默认值 - if 'norflash' in general_config: - norflash_config = general_config['norflash'] - if 'base' not in norflash_config: - norflash_config['base'] = "0x20000000" # 或其他合适的默认值 - if 'size' not in norflash_config: - norflash_config['size'] = "32M" # 设置默认值 - if 'iregion' in general_config: - iregion_config = general_config['iregion'] - if 'base' not in iregion_config: - iregion_config['base'] = "0x18000000" # 或其他合适的默认值 - if 'uart0' in general_config: - uart0_config = general_config['uart0'] - if 'base' not in uart0_config: - uart0_config['base'] = "0x10013000" # 或其他合适的默认值 - if 'irq' not in uart0_config: - uart0_config['irq'] = "33" # 设置默认值 - if 'uart1' in general_config: - uart1_config = general_config['uart1'] - if 'base' not in uart1_config: - uart1_config['base'] = "0x10023000" # 或其他合适的默认值 - if 'irq' not in uart1_config: - uart1_config['irq'] = "34" # 设置默认值 - if 'qspi0' in general_config: - qspi0_config = general_config['qspi0'] - if 'base' not in qspi0_config: - qspi0_config['base'] = "0x10014000" # 或其他合适的默认值 - if 'irq' not in qspi0_config: - qspi0_config['irq'] = "35" # 设置默认值 - if 'qspi2' in general_config: - qspi2_config = general_config['qspi2'] - if 'base' not in qspi2_config: - qspi2_config['base'] = "0x10034000" # 或其他合适的默认值 - if 'irq' not in qspi2_config: - qspi2_config['irq'] = "37" # 设置默认值 - if 'cpu_freq' not in general_config: - general_config['cpu_freq'] = "50000000" # 或其他合适的默认值 - if 'timer_freq' not in general_config: - general_config['timer_freq'] = "32768" # 或其他合适的默认值 - if 'ampfw_size' not in general_config: - general_config['ampfw_size'] = "0x400000" # 或其他合适的默认值 - if 'amp_core' not in general_config: - general_config['amp_core'] = "8" # 或其他合适的默认值 - - if 'uboot_config' in conf_data: - uboot_config = conf_data['uboot_config'] - if 'CONFIG_TEXT_BASE' not in uboot_config: - uboot_config['CONFIG_TEXT_BASE'] = "0x80200000" # 或其他合适的默认值 - - uboot_text_base = uboot_config['CONFIG_TEXT_BASE'] - uboot_cust_sys_init_sp_addr = uboot_text_base - uboot_sys_load_addr = uboot_text_base - board_sdram_base = sdram_config['base'] - board_sdram_size = hex(parse_size(sdram_config['size'])) - board_flash_base = norflash_config['base'] - board_flash_size = parse_size(norflash_config['size'], 'string') - board_iregion_base = iregion_config['base'] - board_uart0_base = uart0_config['base'] - board_uart0_irq = uart0_config['irq'] - board_uart1_base = uart1_config['base'] - board_uart1_irq = uart1_config['irq'] - board_qspi0_base = qspi0_config['base'] - board_qspi0_irq = qspi0_config['irq'] - board_qspi2_base = qspi2_config['base'] - board_qspi2_irq = qspi2_config['irq'] - board_ampfw_size = hex(parse_size(general_config['ampfw_size'])) - board_ampcore_num = general_config['amp_core'] - board_cpu_freq = general_config['cpu_freq'] - board_timer_freq = general_config['timer_freq'] - if ((int(board_sdram_base, 16) & 0xF0000000) != (int(uboot_text_base, 16) & 0xF0000000) - or (int(board_sdram_base, 16) & 0xF0000000) != (int(uboot_cust_sys_init_sp_addr, 16) & 0xF0000000) - or (int(board_sdram_base, 16) & 0xF0000000) != (int(uboot_sys_load_addr, 16) & 0xF0000000)): - print("Warning: sdram base addr is not match with uboot text base addr,please check %s file!" %(sys.argv[1])) - print("generate failed!\n") - os.chdir(os.path.dirname(config_file_path)) - shutil.rmtree(generated_file_path) - exit(1) - - # update custsoc file - opensbi_config_mk = "%s/opensbi/config.mk" % (generated_file_path) - if os.path.exists(opensbi_config_mk): # v5.10 SDK branch +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description="Generate configuration files based on a reference SOC." + ) + parser.add_argument("--conf", type=str, default="genconf.json", help="json config file (default: genconf.json, for rv64).If you want to generate rv32 config file, please refer to README.md.") + parser.add_argument("--refsoc", type=str, default="evalsoc", help="reference soc config (default: evalsoc).") + parser.add_argument("custsoc", type=str, help="new config files directory.") + + args = parser.parse_args() + + # check if custsoc arg exist + if args.custsoc is None: + print("Error: custsoc parameter is required but not provided.") + parser.print_help() + sys.exit(1) + + # check if refsoc exist + if not os.path.exists(args.refsoc): + print("Error: %s referenc soc not exist!\n" % args.refsoc) + parser.print_help() + sys.exit(1) + + # check if refsoc and custsoc in same directory + if os.path.abspath(args.refsoc) == os.path.abspath(args.custsoc): + print("Error: refsoc and custsoc cannot be the same directory!") + parser.print_help() + sys.exit(1) + + # if custsoc exist,ask if overwrite + if os.path.exists(args.custsoc): + print(f"{args.custsoc} already exists. Do you want to overwrite it? (y/n)") + response = input().strip().lower() + if response != 'y': + print("Exiting without overwriting.") + sys.exit(1) + shutil.rmtree(args.custsoc) + # copy refsoc to custsoc + shutil.copytree(args.refsoc, args.custsoc) + # copy json file to custsoc dir + cust_json_file = "%s/%s.json" %(args.custsoc, args.custsoc) + shutil.copy(args.conf, cust_json_file) + print(f"===Start generating {args.custsoc} config files based on {args.refsoc}===") + + board_flash_base = None + board_flash_size = None + board_iregion_base = None + board_uart0_base = None + board_uart0_irq = None + board_uart1_base = None + board_uart1_irq = None + board_qspi0_base = None + board_qspi0_irq = None + board_qspi2_base = None + board_qspi2_irq = None + board_ampfw_size = None + board_ampcore_num = None + board_cpu_freq = None + board_timer_freq = None + + try: + cust_file = args.custsoc + + with open(args.conf, 'r') as conf_file: + conf_data = json.load(conf_file) + + if 'general_config' in conf_data: + general_config = conf_data['general_config'] + if 'ddr' in general_config: + ddr_config = general_config['ddr'] + if 'base' not in ddr_config: + print("ddr base is empty value, use 0x80000000 as default.") + ddr_config['base'] = "0x80000000" + if 'size' not in ddr_config: + print("ddr size is empty value, use 0x80000000 as default.") + ddr_config['size'] = "0x80000000" + if 'norflash' in general_config: + norflash_config = general_config['norflash'] + if 'base' in norflash_config: + board_flash_base = norflash_config['base'] + if 'size' in norflash_config: + board_flash_size = norflash_config['size'] + if 'iregion' in general_config: + iregion_config = general_config['iregion'] + if 'base' in iregion_config: + board_iregion_base = iregion_config['base'] + if 'uart0' in general_config: + uart0_config = general_config['uart0'] + if 'base' in uart0_config: + board_uart0_base = uart0_config['base'] + if 'irq' in uart0_config: + board_uart0_irq = uart0_config['irq'] + if 'uart1' in general_config: + uart1_config = general_config['uart1'] + if 'base' in uart1_config: + board_uart1_base = uart1_config['base'] + if 'irq' in uart1_config: + board_uart1_irq = uart1_config['irq'] + if 'qspi0' in general_config: + qspi0_config = general_config['qspi0'] + if 'base' in qspi0_config: + board_qspi0_base = qspi0_config['base'] + if 'irq' in qspi0_config: + board_qspi0_irq = qspi0_config['irq'] + if 'qspi2' in general_config: + qspi2_config = general_config['qspi2'] + if 'base' in qspi2_config: + board_qspi2_base = qspi2_config['base'] + if 'irq' in qspi2_config: + board_qspi2_irq = qspi2_config['irq'] + if 'cpu_freq' in general_config: + board_cpu_freq = general_config['cpu_freq'] + if 'timer_freq' in general_config: + board_timer_freq = general_config['timer_freq'] + if 'ampfw_size' not in general_config: + general_config['ampfw_size'] = "0x400000" + if 'amp_core' not in general_config: + general_config['amp_core'] = "8" + else: + print("Warning: json config file maybe empty! use basic default value.") + ddr_config['base'] = "0x80000000" + ddr_config['size'] = "0x80000000" + general_config['ampfw_size'] = "0x400000" + general_config['amp_core'] = "8" + + board_ddr_base = ddr_config['base'] + board_ddr_size = hex(parse_size(ddr_config['size'])) + if board_flash_size is not None: + board_flash_size = parse_size(board_flash_size, 'string') + board_ampfw_size = hex(parse_size(general_config['ampfw_size'])) + board_ampcore_num = general_config['amp_core'] + + print("\n>>>Updating opensbi...") + # update custsoc file + opensbi_config_mk = "%s/opensbi/config.mk" % (cust_file) + if os.path.exists(opensbi_config_mk): # v5.10 SDK branch + variable_name = 'FW_TEXT_START' + update_freeloader_variable(opensbi_config_mk, variable_name, board_ddr_base) + replace_in_file(opensbi_config_mk, args.refsoc, args.custsoc) + else: #v6.x branch + new_opensbi_file = "%s/opensbi/%s.c" % (cust_file, 'customsoc') + old_opensbi_file = "%s/opensbi/%s.c" % (cust_file, args.refsoc) + if not os.path.exists(new_opensbi_file): + os.rename(old_opensbi_file, new_opensbi_file) + print(f"Create '{new_opensbi_file}' based on '{old_opensbi_file}'.") + replace_in_file(new_opensbi_file, args.refsoc, 'customsoc') + print("Note: All custom soc should use customsoc.c for nuclei generic soc support") + + print("\n>>>Updating uboot config...") + # update uboot defconfig + matching_cfg_files = glob.glob("%s/uboot_rv*_config" %(cust_file)) + + for config_file in matching_cfg_files: + print("- %s:" % config_file) + update_uboot_defconfig(config_file) + + print("\n>>>Updating freeloader.mk..."); + # update freeloader.mk + makefile_path = "%s/freeloader.mk" %(cust_file) + variable_name = 'DDR_BASE' + update_freeloader_variable(makefile_path, variable_name, board_ddr_base) + + makefile_path = "%s/freeloader.mk" %(cust_file) + variable_name = 'FLASH_BASE' + update_freeloader_variable(makefile_path, variable_name, board_flash_base) + + makefile_path = "%s/freeloader.mk" %(cust_file) + variable_name = 'FLASH_SIZE' + update_freeloader_variable(makefile_path, variable_name, board_flash_size) + + makefile_path = "%s/freeloader.mk" %(cust_file) + variable_name = 'AMPFW_SIZE' + update_freeloader_variable(makefile_path, variable_name, board_ampfw_size) + + makefile_path = "%s/freeloader.mk" %(cust_file) + variable_name = 'AMP_START_CORE' + update_freeloader_variable(makefile_path, variable_name, board_ampcore_num) + + makefile_path = "%s/freeloader.mk" %(cust_file) + variable_name = 'AMPFW_START_OFFSET' + reserve_ampmem = int(board_ampfw_size,16) * int(board_ampcore_num) + if int(board_ddr_size,16) > reserve_ampmem: + amp_start_offset = int(board_ddr_size,16) - reserve_ampmem + else: + print("generate failed!\n") + print("Warning: ddr size is less than amp core memory requirements") + print("ddr size:%s amp core:%s ampfw size:%s" %(hex(int(board_ddr_size,16)), int(board_ampcore_num), hex(int(board_ampfw_size,16)))) + shutil.rmtree(cust_file) + sys.exit(1) + update_freeloader_variable(makefile_path, variable_name, hex(amp_start_offset)) + + print("\n>>>Updating build.mk...") + # update build.mk + makefile_path = "%s/build.mk" %(cust_file) variable_name = 'FW_TEXT_START' - update_freeloader_variable(opensbi_config_mk, variable_name, board_sdram_base) - replace_in_file(opensbi_config_mk, sys.argv[3], sys.argv[2]) - else: #v6.x branch - new_opensbi_file = "%s/opensbi/%s.c" % (generated_file_path, 'customsoc') - old_opensbi_file = "%s/opensbi/%s.c" % (generated_file_path, sys.argv[3]) - os.rename(old_opensbi_file, new_opensbi_file) - print(f"file '{old_opensbi_file}' have been renamed to '{new_opensbi_file}'.") - replace_in_file(new_opensbi_file, sys.argv[3], 'customsoc') - - # update uboot defconfig - matching_cfg_files = glob.glob('uboot_rv*_config') - - for config_file in matching_cfg_files: - update_uboot_defconfig(config_file) - - # update freeloader.mk - makefile_path = 'freeloader.mk' - variable_name = 'DDR_BASE' - update_freeloader_variable(makefile_path, variable_name, board_sdram_base) - - makefile_path = 'freeloader.mk' - variable_name = 'FLASH_BASE' - update_freeloader_variable(makefile_path, variable_name, board_flash_base) - - makefile_path = 'freeloader.mk' - variable_name = 'FLASH_SIZE' - update_freeloader_variable(makefile_path, variable_name, board_flash_size) - - makefile_path = 'freeloader.mk' - variable_name = 'AMPFW_SIZE' - update_freeloader_variable(makefile_path, variable_name, board_ampfw_size) - - makefile_path = 'freeloader.mk' - variable_name = 'AMP_START_CORE' - update_freeloader_variable(makefile_path, variable_name, board_ampcore_num) - - makefile_path = 'freeloader.mk' - variable_name = 'AMPFW_START_OFFSET' - if int(board_sdram_size,16) > int(board_ampcore_num) * int(board_ampfw_size,16): - amp_start_offset = int(board_sdram_size,16) - int(board_ampcore_num) * int(board_ampfw_size,16) - else: + update_build_variable(makefile_path, variable_name, board_ddr_base) + + makefile_path = "%s/build.mk" %(cust_file) + variable_name = 'UIMAGE_AE_CMD' + kernel_offset = 0x00400000 + load_addr = int(board_ddr_base, 16) + kernel_offset + entry_point = int(board_ddr_base, 16) + kernel_offset + uimage_ae_cmd_val = f"-a 0x{load_addr:08X} -e 0x{entry_point:08X}" + update_build_variable(makefile_path, variable_name, uimage_ae_cmd_val) + + makefile_path = "%s/build.mk" %(cust_file) + variable_name = 'QEMU_MACHINE_OPTS' + update_build_variable(makefile_path, variable_name, "-M nuclei_evalsoc,soc-cfg=conf/%s,download=flashxip -smp 8" %(cust_json_file)) + + print("\nUpdating dts...") + # update dts + matching_dts_files = glob.glob("%s/nuclei_rv*.dts" %(cust_file)) + + for dts_file in matching_dts_files: + print("- %s:" % dts_file) + # replace string + replace_in_file(dts_file, args.refsoc, args.custsoc) + # update freq + update_dts_clk_freq(dts_file, 'TIMERCLK_FREQ', board_timer_freq) + update_dts_clk_freq(dts_file, 'CPUCLK_FREQ', board_cpu_freq) + + # update memory dts node + ddr_base_hex = hex(int(board_ddr_base, 16)) + ddr_size_hex = hex(int(board_ddr_size, 16) - reserve_ampmem) + memory_reg_val = f"0x0 0x{ddr_base_hex.lstrip('0x')} 0x0 0x{ddr_size_hex.lstrip('0x')}" + update_dts_node(dts_file, 'memory', ddr_base_hex.lstrip('0x'), memory_reg_val) + + if board_iregion_base is not None: + # update plic dts node + plic_base_hex = hex(int(board_iregion_base, 16) + 0x4000000) + plic_size_hex = hex(0x4000000) + plic_reg_val = f"0x0 0x{plic_base_hex.lstrip('0x')} 0x0 0x{plic_size_hex.lstrip('0x')}" + update_dts_node(dts_file, 'interrupt-controller', plic_base_hex.lstrip('0x'), plic_reg_val) + + # update clint dts node + clint_base_hex = hex(int(board_iregion_base, 16) + 0x31000) + clint_size_hex = hex(0xC000) + clint_reg_val = f"0x0 0x{clint_base_hex.lstrip('0x')} 0x0 0x{clint_size_hex.lstrip('0x')}" + update_dts_node(dts_file, 'clint', clint_base_hex.lstrip('0x'), clint_reg_val) + + if board_uart0_base is not None: + # update uart0 dts node + uart0_base_hex = hex(int(board_uart0_base, 16)) + uart0_size_hex = hex(0x1000) + uart0_reg_val = f"0x0 0x{uart0_base_hex.lstrip('0x')} 0x0 0x{uart0_size_hex.lstrip('0x')}" + update_dts_node(dts_file, 'uart0', uart0_base_hex.lstrip('0x'), uart0_reg_val, board_uart0_irq) + + if board_uart1_base is not None: + # update uart1 dts node + uart1_base_hex = hex(int(board_uart1_base, 16)) + uart1_size_hex = hex(0x1000) + uart1_reg_val = f"0x0 0x{uart1_base_hex.lstrip('0x')} 0x0 0x{uart1_size_hex.lstrip('0x')}" + update_dts_node(dts_file, 'uart1', uart1_base_hex.lstrip('0x'), uart1_reg_val, board_uart1_irq) + + if board_qspi0_base is not None: + # update qspi0 dts node + qspi0_base_hex = hex(int(board_qspi0_base, 16)) + qspi0_size_hex = hex(0x1000) + qspi0_reg_val = f"0x0 0x{qspi0_base_hex.lstrip('0x')} 0x0 0x{qspi0_size_hex.lstrip('0x')}" + update_dts_node(dts_file, 'qspi0', qspi0_base_hex.lstrip('0x'), qspi0_reg_val, board_qspi0_irq) + + if board_qspi2_base is not None: + # update qspi2 dts node + qspi2_base_hex = hex(int(board_qspi2_base, 16)) + qspi2_size_hex = hex(0x1000) + qspi2_reg_val = f"0x0 0x{qspi2_base_hex.lstrip('0x')} 0x0 0x{qspi2_size_hex.lstrip('0x')}" + update_dts_node(dts_file, 'qspi2', qspi2_base_hex.lstrip('0x'), qspi2_reg_val, board_qspi2_irq) + print("\n>>>Updating uboot.cmd...") + # update uboot.cmd + uboot_cmd_file = "%s/uboot.cmd" %(cust_file) + kernel_load_addr = hex(int(board_ddr_base, 16) + 0x3000000) + rootfs_load_addr = hex(int(board_ddr_base, 16) + 0x8300000) + fdt_load_addr = hex(int(board_ddr_base, 16) + 0x8000000) + update_uboot_cmd(uboot_cmd_file, kernel_load_addr, rootfs_load_addr, fdt_load_addr) + + print("===generate successfully!===\n") + print("Here are the reference build commands for compiling Linux SDK for you:") + print("$cd ..") + print("$make SOC=%s CORE=ux900fd BOOT_MODE=sd freeloader bootimages" % args.custsoc) + print("$make SOC=%s CORE=ux900fd BOOT_MODE=sd run_qemu" % args.custsoc) + print("Please adjust the compilation parameters according to your real environment.") + except Exception as e: + print(f'Exception occur: {e}') + # back to orgin working directory,remote generated files + shutil.rmtree(cust_file) print("generate failed!\n") - print("Warning: sdram size is less than amp core memory requirements") - print("sdram size:%s amp core:%s ampfw size:%s" %(hex(int(board_sdram_size,16)), int(board_ampcore_num), hex(int(board_ampfw_size,16)))) - os.chdir(os.path.dirname(config_file_path)) - shutil.rmtree(generated_file_path) - exit(1) - update_freeloader_variable(makefile_path, variable_name, hex(amp_start_offset)) - - # update build.mk - makefile_path = 'build.mk' - variable_name = 'FW_TEXT_START' - update_build_variable(makefile_path, variable_name, board_sdram_base) - - makefile_path = 'build.mk' - variable_name = 'UIMAGE_AE_CMD' - kernel_offset = 0x00400000 - load_addr = int(board_sdram_base, 16) + kernel_offset - entry_point = int(board_sdram_base, 16) + kernel_offset - uimage_ae_cmd_val = f"-a 0x{load_addr:08X} -e 0x{entry_point:08X}" - update_build_variable(makefile_path, variable_name, uimage_ae_cmd_val) - - makefile_path = 'build.mk' - variable_name = 'QEMU_MACHINE_OPTS' - update_build_variable(makefile_path, variable_name, "") - - # update dts - matching_dts_files = glob.glob('nuclei_rv*.dts') - reserve_ampmem = int(board_ampfw_size,16) * int(board_ampcore_num) - for dts_file in matching_dts_files: - # replace string - replace_in_file(dts_file, sys.argv[3], sys.argv[2]) - # update freq - update_dts_clk_freq(dts_file, 'TIMERCLK_FREQ', board_timer_freq) - update_dts_clk_freq(dts_file, 'CPUCLK_FREQ', board_cpu_freq) - - # update memory dts node - sdram_base_hex = hex(int(board_sdram_base, 16)) - sdram_size_hex = hex(int(board_sdram_size, 16) - reserve_ampmem) - memory_reg_val = f"0x0 0x{sdram_base_hex.lstrip('0x')} 0x0 0x{sdram_size_hex.lstrip('0x')}" - update_dts_node(dts_file, 'memory', sdram_base_hex.lstrip('0x'), memory_reg_val) - - # update plic dts node - plic_base_hex = hex(int(board_iregion_base, 16) + 0x4000000) - plic_size_hex = hex(0x4000000) - plic_reg_val = f"0x0 0x{plic_base_hex.lstrip('0x')} 0x0 0x{plic_size_hex.lstrip('0x')}" - update_dts_node(dts_file, 'interrupt-controller', plic_base_hex.lstrip('0x'), plic_reg_val) - - # update clint dts node - clint_base_hex = hex(int(board_iregion_base, 16) + 0x31000) - clint_size_hex = hex(0xC000) - clint_reg_val = f"0x0 0x{clint_base_hex.lstrip('0x')} 0x0 0x{clint_size_hex.lstrip('0x')}" - update_dts_node(dts_file, 'clint', clint_base_hex.lstrip('0x'), clint_reg_val) - - # update uart0 dts node - uart0_base_hex = hex(int(board_uart0_base, 16)) - uart0_size_hex = hex(0x1000) - uart0_reg_val = f"0x0 0x{uart0_base_hex.lstrip('0x')} 0x0 0x{uart0_size_hex.lstrip('0x')}" - update_dts_node(dts_file, 'uart0', uart0_base_hex.lstrip('0x'), uart0_reg_val, board_uart0_irq) - - # update uart1 dts node - uart1_base_hex = hex(int(board_uart1_base, 16)) - uart1_size_hex = hex(0x1000) - print(">>>>>>> %s" % uart1_base_hex) - uart1_reg_val = f"0x0 0x{uart1_base_hex.lstrip('0x')} 0x0 0x{uart1_size_hex.lstrip('0x')}" - update_dts_node(dts_file, 'uart1', uart1_base_hex.lstrip('0x'), uart1_reg_val, board_uart1_irq) - - # update qspi0 dts node - qspi0_base_hex = hex(int(board_qspi0_base, 16)) - qspi0_size_hex = hex(0x1000) - qspi0_reg_val = f"0x0 0x{qspi0_base_hex.lstrip('0x')} 0x0 0x{qspi0_size_hex.lstrip('0x')}" - update_dts_node(dts_file, 'qspi0', qspi0_base_hex.lstrip('0x'), qspi0_reg_val, board_qspi0_irq) - - # update qspi2 dts node - qspi2_base_hex = hex(int(board_qspi2_base, 16)) - qspi2_size_hex = hex(0x1000) - qspi2_reg_val = f"0x0 0x{qspi2_base_hex.lstrip('0x')} 0x0 0x{qspi2_size_hex.lstrip('0x')}" - update_dts_node(dts_file, 'qspi2', qspi2_base_hex.lstrip('0x'), qspi2_reg_val, board_qspi2_irq) - # update uboot.cmd - uboot_cmd_file = 'uboot.cmd' - kernel_load_addr = hex(int(board_sdram_base, 16) + 0x3000000) - rootfs_load_addr = hex(int(board_sdram_base, 16) + 0x8300000) - fdt_load_addr = hex(int(board_sdram_base, 16) + 0x8000000) - update_uboot_cmd(uboot_cmd_file, kernel_load_addr, rootfs_load_addr, fdt_load_addr) - - print("===generate successfully!===\n") -except Exception as e: - print(f'Exception occur: {e}') - # back to orgin working directory,remote generated files - os.chdir(os.path.dirname(config_file_path)) - shutil.rmtree(generated_file_path) - print("===generate failed!===\n")