cpu: Adding "variant" support.
authorTim 'mithro' Ansell <mithro@mithis.com>
Tue, 26 Sep 2017 00:01:36 +0000 (10:01 +1000)
committerTim 'mithro' Ansell <me@mith.ro>
Sat, 30 Dec 2017 00:18:51 +0000 (01:18 +0100)
It is useful to support slightly different variants of the CPU
configurations. This adds a "cpu_variant" option.

For the mor1k we now have the default mor1k configuration and the
"linux" variant which enables the features needed for Linux support on
the mor1k.

Currently there are no variants for the lm32, but we will likely add a
"tiny" variant for usage on the iCE40.

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

index a6c9f33972702b215e5b73363f5b7c5f2c96ae47..743a61f635004e2ebfe445071956096091771cc2 100644 (file)
@@ -6,7 +6,8 @@ from litex.soc.interconnect import wishbone
 
 
 class LM32(Module):
-    def __init__(self, platform, eba_reset):
+    def __init__(self, platform, eba_reset, variant=None):
+        assert variant == None, "No lm32 variants currently supported."
         self.ibus = i = wishbone.Interface()
         self.dbus = d = wishbone.Interface()
         self.interrupt = Signal(32)
index d74e0654dbcb29d148a50d67d1db389026ec958f..872300595ce6256076ef427cf3f6947cadce2253 100644 (file)
@@ -6,16 +6,15 @@ from litex.soc.interconnect import wishbone
 
 
 class MOR1KX(Module):
-    def __init__(self, platform, reset_pc):
+    def __init__(self, platform, reset_pc, variant=None):
+        assert variant in (None, "linux"), "Unsupported variant %s" % variant
         self.ibus = i = wishbone.Interface()
         self.dbus = d = wishbone.Interface()
         self.interrupt = Signal(32)
 
         # # #
 
-        i_adr_o = Signal(32)
-        d_adr_o = Signal(32)
-        self.specials += Instance("mor1kx",
+        cpu_args = dict(
             p_FEATURE_INSTRUCTIONCACHE="ENABLED",
             p_OPTION_ICACHE_BLOCK_WIDTH=4,
             p_OPTION_ICACHE_SET_WIDTH=8,
@@ -39,6 +38,35 @@ class MOR1KX(Module):
             p_OPTION_RESET_PC=reset_pc,
             p_IBUS_WB_TYPE="B3_REGISTERED_FEEDBACK",
             p_DBUS_WB_TYPE="B3_REGISTERED_FEEDBACK",
+        )
+
+        if variant == None:
+            # Use the default configuration
+            pass
+        elif variant == "linux":
+            cpu_args.update(dict(
+                # Linux needs the memory management units.
+                p_FEATURE_IMMU="ENABLED",
+                p_FEATURE_DMMU="ENABLED",
+                # FIXME: Currently we need the or1k timer when we should be
+                # using the litex timer.
+                p_FEATURE_TIMER="ENABLED",
+            ))
+            # FIXME: Check if these are needed?
+            use_defaults = (
+                "p_FEATURE_SYSCALL", "p_FEATURE_TRAP", "p_FEATURE_RANGE",
+                "p_FEATURE_OVERFLOW",
+            )
+            for to_remove in use_defaults:
+                del cpu_args[to_remove]
+
+        else:
+            assert False, "Unsupported variant %s" % variant
+
+        i_adr_o = Signal(32)
+        d_adr_o = Signal(32)
+        self.specials += Instance("mor1kx",
+            **cpu_args,
 
             i_clk=ClockSignal(),
             i_rst=ResetSignal(),
index 1b30c904377a87bc4be8dc6a737fbc19c4d6c613..0a9c98b693f561cc2604a75e22b438fab41dd3f3 100644 (file)
@@ -60,7 +60,7 @@ class SoCCore(Module):
         "csr":      0x60000000,  # (default shadow @0xe0000000)
     }
     def __init__(self, platform, clk_freq,
-                cpu_type="lm32", cpu_reset_address=0x00000000,
+                cpu_type="lm32", cpu_reset_address=0x00000000, cpu_variant=None,
                 integrated_rom_size=0, integrated_rom_init=[],
                 integrated_sram_size=4096,
                 integrated_main_ram_size=0, integrated_main_ram_init=[],
@@ -76,6 +76,7 @@ class SoCCore(Module):
         self.clk_freq = clk_freq
 
         self.cpu_type = cpu_type
+        self.cpu_variant = cpu_variant
         if integrated_rom_size:
             cpu_reset_address = self.mem_map["rom"]
         self.cpu_reset_address = cpu_reset_address
@@ -103,16 +104,18 @@ class SoCCore(Module):
 
         if cpu_type is not None:
             if cpu_type == "lm32":
-                self.add_cpu_or_bridge(lm32.LM32(platform, self.cpu_reset_address))
+                self.add_cpu_or_bridge(lm32.LM32(platform, self.cpu_reset_address, self.cpu_variant))
             elif cpu_type == "or1k":
-                self.add_cpu_or_bridge(mor1kx.MOR1KX(platform, self.cpu_reset_address))
+                self.add_cpu_or_bridge(mor1kx.MOR1KX(platform, self.cpu_reset_address, self.cpu_variant))
             elif cpu_type == "riscv32":
-                self.add_cpu_or_bridge(picorv32.PicoRV32(platform, self.cpu_reset_address))
+                self.add_cpu_or_bridge(picorv32.PicoRV32(platform, self.cpu_reset_address, self.cpu_variant))
             else:
                 raise ValueError("Unsupported CPU type: {}".format(cpu_type))
             self.add_wb_master(self.cpu_or_bridge.ibus)
             self.add_wb_master(self.cpu_or_bridge.dbus)
         self.config["CPU_TYPE"] = str(cpu_type).upper()
+        if self.cpu_variant:
+            self.config["CPU_VARIANT"] = str(cpu_type).upper()
 
         if integrated_rom_size:
             self.submodules.rom = wishbone.SRAM(integrated_rom_size, read_only=True, init=integrated_rom_init)