Standardize the `cpu_variant` strings.
authorTim 'mithro' Ansell <me@mith.ro>
Fri, 26 Apr 2019 21:20:21 +0000 (16:20 -0500)
committerTim 'mithro' Ansell <me@mith.ro>
Fri, 26 Apr 2019 22:44:30 +0000 (17:44 -0500)
Current valid `cpu_variant` values;
 * minimal  (alias: min)
 * lite     (alias: light, zephyr, nuttx)
 * standard (alias: std) - Default
 * full     (alias: everything)
 * linux

Fully documented in the [docs/Soft-CPU.md](docs/Soft-CPU.md) file
mirrored from the
[LiteX-BuildEnv Wiki](https://github.com/timvideos/litex-buildenv/wiki).

Also support "extensions" which are added to the `cpu_variant` with a
`+`. Currently only the `debug` extension is supported. In future hope
to add `mmu` and `hmul` extensions.

litex/soc/cores/cpu/lm32/core.py
litex/soc/cores/cpu/minerva/core.py
litex/soc/cores/cpu/mor1kx/core.py
litex/soc/cores/cpu/picorv32/core.py
litex/soc/cores/cpu/vexriscv/core.py
litex/soc/integration/soc_core.py

index e7b18bf647a2721d667f896db07e8f5715a34332..4fd6f1e5952d2858e2627c624e8e4d4511f5b353 100644 (file)
@@ -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))
index c864f3ae9c1b1599f3ed1a6958ab0a454d227c12..6b9cfa5dc3ceb049056d0041a8119474a5243c3d 100644 (file)
@@ -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()
index 3b55991b663d65649c94dff472a5a6043f634612..f6611c3e6e56b52c775b4ee197a246f4de4030af 100644 (file)
@@ -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":
index 93f3358a272b03e0ce6329160abe200961f4e84d..e2f3239326c264277e813a44c094cfc4826c0767 100644 (file)
@@ -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({
index 1c233f317d99cebd3411a408bbd31f618d77ba4b..f66473be3d8ca491dabcbbdd9a419448558dc01b 100644 (file)
@@ -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))
 
index 6cbd1dff43a49d32a80ca9873331248e9b28013d..f9507b731d1262baa6bc484d9469f7bf35850b54 100644 (file)
@@ -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