litex icon indicating copy to clipboard operation
litex copied to clipboard

Builder enhancements

Open AndrewD opened this issue 1 year ago • 2 comments

Various enhancements to reduce boilerplate code in target arguments and to cleanly allow a target to initialise memory with a custom firmware (for example).

Custom firmware example:

class MySimSoC(SoCCore): def init(self, firmware, **kwargs):

    self.firmware = firmware

    if self.firmware:
        self.add_config("MAIN_RAM_INIT") # target software is in ram
       self.add_constant("ROM_BOOT_ADDRESS", self.bus.regions["main_ram"].origin)

def initialize_memory(self, software_dir, **kwargs):
    if not self.firmware:
        return

    filename  = os.path.join(software_dir, "firmware", "firmware.bin")
    data = get_mem_data(filename, endianness="little")
    # This can not generate MAIN_RAM_INIT so must set it manually in soc.__init__()
    self.init_rom(name="main_ram", contents=data, auto_size=False)

Build --------------------------------------------------------------------------------------------

def main(): from litex.build.parser import LiteXArgumentParser bool_action = argparse.BooleanOptionalAction parser = LiteXArgumentParser(platform=Platform, soc=MySimSoC, description="My simulation.")

# NOTE: all target arguments have a default here, not in soc.__init__(), so they are documented.
parser.add_target_argument("--firmware", default=True, action=bool_action,      help="compile and load firmware in main_ram.")

# Create SoC.
soc = MySimSoC(**parser.soc_argdict)

# add custom firmware: compiled by connecting here and stored in initialize_memory()
src="firmware"
src_dir = os.path.join(os.path.abspath(os.path.dirname(__file__)), src)
builder = Builder(soc, **parser.builder_argdict)
builder.add_software_package(src, src_dir)

# Build/Run SoC
builder.build(sim_config=sim_config, **parser.toolchain_argdict, run=True)

AndrewD avatar Sep 01 '23 04:09 AndrewD

Thanks @AndrewD, I'll review it very soon.

enjoy-digital avatar Sep 01 '23 06:09 enjoy-digital

For convenience: the code above with ``` before/after

class MySimSoC(SoCCore): def **init**(self, firmware, **kwargs):

    self.firmware = firmware

    if self.firmware:
        self.add_config("MAIN_RAM_INIT") # target software is in ram
       self.add_constant("ROM_BOOT_ADDRESS", self.bus.regions["main_ram"].origin)

def initialize_memory(self, software_dir, **kwargs):
    if not self.firmware:
        return

    filename  = os.path.join(software_dir, "firmware", "firmware.bin")
    data = get_mem_data(filename, endianness="little")
    # This can not generate MAIN_RAM_INIT so must set it manually in soc.__init__()
    self.init_rom(name="main_ram", contents=data, auto_size=False)

# Build --------------------------------------------------------------------------------------------

def main(): from litex.build.parser import LiteXArgumentParser bool_action = argparse.BooleanOptionalAction parser = LiteXArgumentParser(platform=Platform, soc=MySimSoC, description="My simulation.")

    # NOTE: all target arguments have a default here, not in soc.__init__(), so they are documented.
    parser.add_target_argument("--firmware", default=True, action=bool_action,      help="compile and load firmware in main_ram.")

    # Create SoC.
    soc = MySimSoC(**parser.soc_argdict)

    # add custom firmware: compiled by connecting here and stored in initialize_memory()
    src="firmware"
    src_dir = os.path.join(os.path.abspath(os.path.dirname(__file__)), src)
    builder = Builder(soc, **parser.builder_argdict)
    builder.add_software_package(src, src_dir)

    # Build/Run SoC
    builder.build(sim_config=sim_config, **parser.toolchain_argdict, run=True)

josuah avatar Sep 03 '23 13:09 josuah