litex
litex copied to clipboard
Builder enhancements
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)
Thanks @AndrewD, I'll review it very soon.
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)