diff --git a/litex/soc/cores/cpu/lm32/core.py b/litex/soc/cores/cpu/lm32/core.py index e7b18bf64..4fd6f1e59 100644 --- a/litex/soc/cores/cpu/lm32/core.py +++ b/litex/soc/cores/cpu/lm32/core.py @@ -12,8 +12,8 @@ class LM32(Module): gcc_flags = "-mbarrel-shift-enabled -mmultiply-enabled -mdivide-enabled -msign-extend-enabled" linker_output_format = "elf32-lm32" - def __init__(self, platform, eba_reset, variant=None): - assert variant in (None, "lite", "minimal"), "Unsupported variant %s" % variant + def __init__(self, platform, eba_reset, variant="standard"): + assert variant in ("standard", "lite", "minimal"), "Unsupported variant %s" % variant self.reset = Signal() self.ibus = i = wishbone.Interface() self.dbus = d = wishbone.Interface() @@ -66,7 +66,7 @@ class LM32(Module): self.add_sources(platform, variant) @staticmethod - def add_sources(platform, variant=None): + def add_sources(platform, variant): vdir = os.path.join( os.path.abspath(os.path.dirname(__file__)), "verilog") platform.add_sources(os.path.join(vdir, "submodule", "rtl"), @@ -93,5 +93,7 @@ class LM32(Module): platform.add_verilog_include_path(os.path.join(vdir, "config_minimal")) elif variant == "lite": platform.add_verilog_include_path(os.path.join(vdir, "config_lite")) - else: + elif variant == "standard": platform.add_verilog_include_path(os.path.join(vdir, "config")) + else: + raise TypeError("Unknown variant {}".format(variant)) diff --git a/litex/soc/cores/cpu/minerva/core.py b/litex/soc/cores/cpu/minerva/core.py index c864f3ae9..6b9cfa5dc 100644 --- a/litex/soc/cores/cpu/minerva/core.py +++ b/litex/soc/cores/cpu/minerva/core.py @@ -12,8 +12,8 @@ class Minerva(Module): gcc_flags = "-D__minerva__ -march=rv32i -mabi=ilp32" linker_output_format = "elf32-littleriscv" - def __init__(self, platform, cpu_reset_address, variant=None): - assert variant is None, "Unsupported variant %s" % variant + def __init__(self, platform, cpu_reset_address, variant="standard"): + assert variant is "standard", "Unsupported variant %s" % variant self.reset = Signal() self.ibus = wishbone.Interface() self.dbus = wishbone.Interface() diff --git a/litex/soc/cores/cpu/mor1kx/core.py b/litex/soc/cores/cpu/mor1kx/core.py index 3b55991b6..f6611c3e6 100644 --- a/litex/soc/cores/cpu/mor1kx/core.py +++ b/litex/soc/cores/cpu/mor1kx/core.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 import os from migen import * @@ -12,8 +13,8 @@ class MOR1KX(Module): gcc_flags = "-mhard-mul -mhard-div -mror" linker_output_format = "elf32-or1k" - def __init__(self, platform, reset_pc, variant=None): - assert variant in (None, "linux"), "Unsupported variant %s" % variant + def __init__(self, platform, reset_pc, variant="standard"): + assert variant in ("standard", "linux"), "Unsupported variant %s" % variant self.reset = Signal() self.ibus = i = wishbone.Interface() self.dbus = d = wishbone.Interface() @@ -47,7 +48,7 @@ class MOR1KX(Module): p_DBUS_WB_TYPE="B3_REGISTERED_FEEDBACK", ) - if variant == None: + if variant == "standard": # Use the default configuration pass elif variant == "linux": diff --git a/litex/soc/cores/cpu/picorv32/core.py b/litex/soc/cores/cpu/picorv32/core.py index 93f3358a2..e2f323932 100644 --- a/litex/soc/cores/cpu/picorv32/core.py +++ b/litex/soc/cores/cpu/picorv32/core.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 import os from migen import * @@ -12,7 +13,7 @@ class PicoRV32(Module): gcc_flags_template = "-D__picorv32__ -mno-save-restore -march=rv32{ext} -mabi=ilp32" linker_output_format = "elf32-littleriscv" - def __init__(self, platform, progaddr_reset, variant): + def __init__(self, platform, progaddr_reset, variant="standard"): self.gcc_flags = "" self.reset = Signal() @@ -61,7 +62,7 @@ class PicoRV32(Module): "p_STACKADDR" : 0xffffffff } - if variant == None: + if variant == "standard": self.gcc_flags = PicoRV32.gcc_flags_template.format(ext="im") elif variant == "minimal": picorv32_params.update({ diff --git a/litex/soc/cores/cpu/vexriscv/core.py b/litex/soc/cores/cpu/vexriscv/core.py index 1c233f317..f66473be3 100644 --- a/litex/soc/cores/cpu/vexriscv/core.py +++ b/litex/soc/cores/cpu/vexriscv/core.py @@ -6,18 +6,51 @@ from litex.soc.interconnect import wishbone from litex.soc.interconnect.csr import AutoCSR, CSRStatus, CSRStorage +CPU_VARIANTS = { + "minimal": "VexRiscv_Min", + "minimal+debug": "VexRiscv_MinDebug", + "lite": "VexRiscv_Lite", + "lite+debug": "VexRiscv_LiteDebug", + "standard": "VexRiscv", + "standard+debug": "VexRiscv_Debug", + "full": "VexRiscv_Full", + "full+debug": "VexRiscv_FullDebug", + "linux": "VexRiscv_Linux", +} + + +GCC_FLAGS = { + # /-------- Base ISA + # |/------- Hardware Multiply + Divide + # ||/----- Atomics + # |||/---- Compressed ISA + # ||||/--- Single-Precision Floating-Point + # |||||/-- Double-Precision Floating-Point + # imacfd + "minimal": "-march=rv32i -mabi=ilp32", + "minimal+debug": "-march=rv32i -mabi=ilp32", + "lite": "-march=rv32i -mabi=ilp32", + "lite+debug": "-march=rv32i -mabi=ilp32", + "standard": "-march=rv32im -mabi=ilp32", + "standard+debug": "-march=rv32im -mabi=ilp32", + # Does full have floating point? - Add -march=fd, and -mabi=fd + "full": "-march=rv32imac -mabi=ilp32", + "full+debug": "-march=rv32imac -mabi=ilp32", + "linux": "-march=rv32imac -mabi=ilp32", +} + + class VexRiscv(Module, AutoCSR): name = "vexriscv" endianness = "little" gcc_triple = ("riscv64-unknown-elf", "riscv32-unknown-elf") - gcc_flags = "-D__vexriscv__ -march=rv32im -mabi=ilp32" linker_output_format = "elf32-littleriscv" - def __init__(self, platform, cpu_reset_address, variant=None): - variant = "std" if variant is None else variant - variant = "std_debug" if variant == "debug" else variant - variants = ("std", "std_debug", "lite", "lite_debug", "min", "min_debug", "full", "full_debug") - assert variant in variants, "Unsupported variant %s" % variant + def __init__(self, platform, cpu_reset_address, variant="standard"): + assert variant in CPU_VARIANTS, "Unsupported variant %s" % variant + + self.gcc_flags = GCC_FLAGS[variant] + self.platform = platform self.variant = variant self.external_variant = None @@ -150,18 +183,8 @@ class VexRiscv(Module, AutoCSR): ) @staticmethod - def add_sources(platform, variant="std"): - verilog_variants = { - "std": "VexRiscv.v", - "std_debug": "VexRiscv_Debug.v", - "lite": "VexRiscv_Lite.v", - "lite_debug": "VexRiscv_LiteDebug.v", - "min": "VexRiscv_Min.v", - "min_debug": "VexRiscv_MinDebug.v", - "full": "VexRiscv_Full.v", - "full_debug": "VexRiscv_FullDebug.v", - } - cpu_filename = verilog_variants[variant] + def add_sources(platform, variant="standard"): + cpu_filename = CPU_VARIANTS[variant] vdir = os.path.join(os.path.abspath(os.path.dirname(__file__)), "verilog") platform.add_source(os.path.join(vdir, cpu_filename)) diff --git a/litex/soc/integration/soc_core.py b/litex/soc/integration/soc_core.py index 6cbd1dff4..f9507b731 100644 --- a/litex/soc/integration/soc_core.py +++ b/litex/soc/integration/soc_core.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 import os import struct import inspect @@ -23,6 +24,42 @@ __all__ = [ ] +CPU_VARIANTS = { + # "official name": ["alias 1", "alias 2"], + "minimal" : ["min",], + "lite" : ["light", "zephyr", "nuttx"], + "standard": [None, "std"], + "full": [], + "linux" : [], +} +CPU_VARIANTS_EXTENSIONS = ["debug"] + + +class InvalidCPUVariantError(ValueError): + def __init__(self, variant): + msg = """\ +Invalid cpu_variant value: {} + +Possible Values: +""".format(variant) + for k, v in CPU_VARIANTS.items(): + msg += " - {} (aliases: {})\n".format(k, ", ".join(str(s) for s in v)) + ValueError.__init__(self, msg) + + +class InvalidCPUExtensionError(ValueError): + def __init__(self, variant): + msg = """\ +Invalid extension in cpu_variant value: {} + +Possible Values: +""".format(variant) + for e in CPU_VARIANTS_EXTENSIONS.items(): + msg += " - {}\n".format(e) + ValueError.__init__(self, msg) + + + def version(with_time=True): import datetime import time @@ -77,6 +114,7 @@ def get_mem_data(filename, endianness="big", mem_size=None): i += 1 return data + class ReadOnlyDict(dict): def __readonly__(self, *args, **kwargs): raise RuntimeError("Cannot modify ReadOnlyDict") @@ -162,7 +200,25 @@ class SoCCore(Module): if cpu_type == "None": cpu_type = None self.cpu_type = cpu_type - self.cpu_variant = cpu_variant + + # Support the old style which used underscore for separator + cpu_variant = cpu_variant.replace('_', '+') + # Check for valid CPU variants. + cpu_variant_processor, *cpu_variant_ext = cpu_variant.split('+') + for key, values in CPU_VARIANTS.items(): + if cpu_variant_processor not in [key,]+values: + continue + self.cpu_variant = key + break + else: + raise InvalidCPUVariantError(cpu_variant) + + # Check for valid CPU extensions. + for ext in sorted(cpu_variant_ext): + if cpu_variant_ext not in CPU_VARIANTS_EXTENSIONS: + raise InvalidCPUExtension(cpu_variant) + self.cpu_variant += "+"+ext + if integrated_rom_size: cpu_reset_address = self.mem_map["rom"] self.cpu_reset_address = cpu_reset_address