[top_englishbreakfast] Add script to prepare SW

Currently, our SW build cannot deal with different top levels. This commit
adds a script to modify the sources produced by topgen such that the
required SW can be built.

Signed-off-by: Pirmin Vogel <vogelpi@lowrisc.org>
diff --git a/hw/top_englishbreakfast/util/prepare_sw.py b/hw/top_englishbreakfast/util/prepare_sw.py
new file mode 100755
index 0000000..66aebd1
--- /dev/null
+++ b/hw/top_englishbreakfast/util/prepare_sw.py
@@ -0,0 +1,113 @@
+#!/usr/bin/env python3
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+r"""Script to prepare SW for non-earlgrey tops
+"""
+
+import sys
+import subprocess
+import re
+from pathlib import Path
+
+
+def main():
+
+    # Config
+    name_old = 'earlgrey'
+    name = 'englishbreakfast'
+
+    topname = 'top_' + name
+
+    # We first need to run topgen in order to create all auto-generated files.
+    path_root = str(Path(__file__).resolve().parents[3])
+    path_in = path_root + '/hw/' + topname + '/data/'
+    path_out = path_root + '/hw/' + topname
+    cmd = [path_root + '/util/topgen.py',  # "--verbose",
+           "-t", path_in + topname + '.hjson',
+           "-c", path_in,
+           "-o", path_out]
+
+    try:
+        print("Running topgen...")
+        subprocess.run(cmd,
+                       check=True,
+                       stdout=subprocess.PIPE,
+                       stderr=subprocess.STDOUT,
+                       universal_newlines=True)
+
+    except subprocess.CalledProcessError as e:
+        print("topgen failed: " + str(e))
+        sys.exit(1)
+
+    # We need to patch some files:
+    # 1. meson.build needs to be pointed to the proper auto-gen files.
+    # 2. SW sources currently contain hardcoded references to top_earlgrey. We
+    #    need to change some file and variable names in auto-generated files.
+    # 3. The build system still uses some sources from the original top level.
+    #    We thus need to replace those with the new sources patched in 2.
+
+    # 1.
+    cmd = ['sed', '-i', "s/TOPNAME='top_{}'/TOPNAME='top_{}'/g".format(name_old, name),
+           path_root + '/meson.build']
+    try:
+        print("Adjusting meson.build...")
+        subprocess.run(cmd,
+                       check=True,
+                       stdout=subprocess.PIPE,
+                       stderr=subprocess.STDOUT,
+                       universal_newlines=True)
+
+    except subprocess.CalledProcessError as e:
+        print("Adjustment of meson.build failed: " + str(e))
+        sys.exit(1)
+
+    # 2. and 3.
+    print("Adjusting SW files generated by topgen...")
+    files = ['top_' + name + '.c',
+             'top_' + name + '.h',
+             'top_' + name + '_memory.h',
+             'top_' + name + '_memory.ld']
+    path_in = path_root + '/hw/top_' + name + '/sw/autogen/'
+    path_out = path_root + '/hw/top_' + name_old + '/sw/autogen/'
+
+    for file_name in files:
+
+        # Read file produced by topgen.
+        with open(path_in + file_name, "r") as file_in:
+            text = file_in.read()
+
+        text = re.sub(name, name_old, text)
+        text = re.sub(name.capitalize(), name_old.capitalize(), text)
+        text = re.sub(name.upper(), name_old.upper(), text)
+
+        # Write file that SW build can deal with.
+        file_name_new = re.sub(name, name_old, file_name)
+        with open(path_in + file_name_new, "w") as file_out:
+            file_out.write(text)
+
+        # Overwrite the files in the tree of the original top level. They are still used by the
+        # SW build.
+        with open(path_out + file_name_new, "w") as file_out:
+            file_out.write(text)
+
+    # Generate the boot_rom to enable the FPGA build.
+    print("Generating boot ROM...")
+    cmd = ['ninja', '-C', path_root + '/build-out',
+           'sw/device/boot_rom/boot_rom_export_fpga_nexysvideo']
+    try:
+        subprocess.run(cmd,
+                       check=True,
+                       stdout=subprocess.PIPE,
+                       stderr=subprocess.STDOUT,
+                       universal_newlines=True)
+
+    except subprocess.CalledProcessError as e:
+        print("Failed to generate boot ROM: " + str(e))
+        sys.exit(1)
+
+    return 0
+
+
+if __name__ == "__main__":
+    main()
diff --git a/meson.build b/meson.build
index 2b12355..53d70f5 100644
--- a/meson.build
+++ b/meson.build
@@ -178,11 +178,12 @@
 )
 
 # TODO: Considering moving these into hw/ip directories.
+TOPNAME='top_earlgrey'
 hw_ip_aes_reg_h = gen_hw_hdr.process('hw/ip/aes/data/aes.hjson')
 hw_ip_alert_handler_reg_h = gen_hw_hdr.process('hw/ip/alert_handler/data/alert_handler.hjson')
 hw_ip_aon_timer_reg_h = gen_hw_hdr.process('hw/ip/aon_timer/data/aon_timer.hjson')
-hw_ip_clkgmr_reg_h = gen_hw_hdr.process('hw/top_earlgrey/ip/clkmgr/data/autogen/clkmgr.hjson')
-hw_ip_flash_ctrl_reg_h = gen_hw_hdr.process('hw/top_earlgrey/ip/flash_ctrl/data/autogen/flash_ctrl.hjson')
+hw_ip_clkgmr_reg_h = gen_hw_hdr.process('hw/' + TOPNAME + '/ip/clkmgr/data/autogen/clkmgr.hjson')
+hw_ip_flash_ctrl_reg_h = gen_hw_hdr.process('hw/' + TOPNAME + '/ip/flash_ctrl/data/autogen/flash_ctrl.hjson')
 hw_ip_gpio_reg_h = gen_hw_hdr.process('hw/ip/gpio/data/gpio.hjson')
 hw_ip_hmac_reg_h = gen_hw_hdr.process('hw/ip/hmac/data/hmac.hjson')
 hw_ip_i2c_reg_h = gen_hw_hdr.process('hw/ip/i2c/data/i2c.hjson')
@@ -193,10 +194,10 @@
 hw_ip_rv_timer_reg_h = gen_hw_hdr.process('hw/ip/rv_timer/data/rv_timer.hjson')
 hw_ip_uart_reg_h = gen_hw_hdr.process('hw/ip/uart/data/uart.hjson')
 hw_ip_usbdev_reg_h = gen_hw_hdr.process('hw/ip/usbdev/data/usbdev.hjson')
-hw_ip_pwrmgr_reg_h = gen_hw_hdr.process('hw/top_earlgrey/ip/pwrmgr/data/autogen/pwrmgr.hjson')
-hw_ip_rstmgr_reg_h = gen_hw_hdr.process('hw/top_earlgrey/ip/rstmgr/data/autogen/rstmgr.hjson')
-hw_top_earlgrey_pinmux_reg_h = gen_hw_hdr.process('hw/top_earlgrey/ip/pinmux/data/autogen/pinmux.hjson')
-hw_top_earlgrey_rv_plic_reg_h = gen_hw_hdr.process('hw/top_earlgrey/ip/rv_plic/data/autogen/rv_plic.hjson')
+hw_ip_pwrmgr_reg_h = gen_hw_hdr.process('hw/' + TOPNAME + '/ip/pwrmgr/data/autogen/pwrmgr.hjson')
+hw_ip_rstmgr_reg_h = gen_hw_hdr.process('hw/' + TOPNAME + '/ip/rstmgr/data/autogen/rstmgr.hjson')
+hw_top_earlgrey_pinmux_reg_h = gen_hw_hdr.process('hw/' + TOPNAME + '/ip/pinmux/data/autogen/pinmux.hjson')
+hw_top_earlgrey_rv_plic_reg_h = gen_hw_hdr.process('hw/' + TOPNAME + '/ip/rv_plic/data/autogen/rv_plic.hjson')
 
 # Top Earlgrey library (top_earlgrey)
 # The sources for this are generated into the hw hierarchy.
@@ -204,7 +205,7 @@
   link_with: static_library(
     'top_earlgrey_ot',
     sources: [
-      'hw/top_earlgrey/sw/autogen/top_earlgrey.c',
+      'hw/' + TOPNAME + '/sw/autogen/top_earlgrey.c',
     ],
   )
 )