Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Builder enhancements #1759

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

AndrewD
Copy link
Collaborator

@AndrewD AndrewD commented Sep 1, 2023

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)

Andrew Dennison added 4 commits September 1, 2023 12:51
allows use of parser.set_defaults() to more cleanly manage
defaults for a target.
Also changes arguments to enabled {True,False} vs "not disabled".
if soc is set this automatically passes arguments to the soc
in soc_argdict to simplify board platforms. Example usage below:

    # IOs ----------------------------------------------------------------------------------------------

    _io = [
        # Clk / Rst.
        ("sys_clk", 0, Pins(1)),
        ("sys_rst", 0, Pins(1)),
    ]

    # Platform -----------------------------------------------------------------------------------------

    class Platform(SimPlatform):
        name = "sim"
        def __init__(self):
            SimPlatform.__init__(self, "SIM", _io)

    # MySimSoC ----------------------------------------------------------------------------------------

    class MySimSoC(SoCCore):
        def __init__(self, sys_clk_freq, etherbone, etherbone_mac_address, etherbone_ip_address, **kwargs):
            # etc

    # 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("--sys-clk-freq", default=100e6, type=float, help="System clock frequency.")
        parser.add_target_argument("--etherbone", default=False, action=bool_action,  help="Include Etherbone support.")
        parser.add_target_argument("--etherbone-mac-address", default=0x10e2d5000000, help="Etherbone MAC address.")
        parser.add_target_argument("--etherbone-ip-address", default="192.168.1.50", help="Etherbone IP address.")

        # override some defaults
        parser.set_defaults(trace=True)
        parser.set_defaults(trace_fst=True)
        parser.set_defaults(timer_uptime=True)
        parser.set_defaults(integrated_rom_size=0x10000)
        parser.set_defaults(integrated_main_ram_size=0x10000)
        parser.set_defaults(uart_name="sim") # "crossover" for terminal via etherbone
        parser.set_defaults(soc_csv="scr.csv")
        args = parser.parse_args()

        # etc

        # Create SoC.
        soc = MySimSoC(**parser.soc_argdict) # args are automatically passed
allows use of parser.set_defaults()
@enjoy-digital
Copy link
Owner

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

@josuah
Copy link
Contributor

josuah commented Sep 3, 2023

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)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants