diff --git a/CHANGES b/CHANGES index b859ff84e..e0c13c942 100644 --- a/CHANGES +++ b/CHANGES @@ -20,11 +20,13 @@ - cpu/eos_s3: Add LiteX BIOS/Bare Metal software support. - litex_sim: Add .json support for --rom/ram/sdram-init. - soc/add_uart: Allow multiple UARTs in the same design. + - cores/cpu: Add out-of-tree support. [> API changes/Deprecation -------------------------- - Fully deprecate SoCSDRAM/SPIFlash core (replaced by LiteSPI). - UART "bridge" name deprecated in favor of "crossover" (already supported). + - "external" CPU class support deprecated (replaced by out-of-tree support). [> 2021.12, released on January 5th 2022 ---------------------------------------- diff --git a/litex/soc/cores/cpu/__init__.py b/litex/soc/cores/cpu/__init__.py index 76ebeb116..611ead38b 100644 --- a/litex/soc/cores/cpu/__init__.py +++ b/litex/soc/cores/cpu/__init__.py @@ -1,10 +1,15 @@ # # This file is part of LiteX. # -# Copyright (c) 2015-2020 Florent Kermarrec +# Copyright (c) 2015-2022 Florent Kermarrec # Copyright (c) 2017-2018 Tim 'mithro' Ansell # SPDX-License-Identifier: BSD-2-Clause +import os +import sys +import inspect +import importlib + from migen import * # CPU ---------------------------------------------------------------------------------------------- @@ -30,34 +35,19 @@ class CPU(Module): pass class CPUNone(CPU): - variants = ["standard"] - data_width = 32 - endianness = "little" - reset_address = 0x00000000 - io_regions = {0x00000000: 0x100000000} # origin, length - periph_buses = [] - memory_buses = [] - mem_map = { + variants = ["standard"] + data_width = 32 + endianness = "little" + reset_address = 0x00000000 + io_regions = {0x00000000: 0x100000000} # origin, length + periph_buses = [] + memory_buses = [] + mem_map = { "csr" : 0x00000000, "ethmac" : 0x00020000, # FIXME: Remove. "spiflash" : 0x10000000, # FIXME: Remove. } -CPU_GCC_TRIPLE_RISCV32 = ( - "riscv64-unknown-elf", - "riscv64-unknown-linux-gnu", - "riscv32-unknown-elf", - "riscv32-unknown-linux-gnu", - "riscv64-elf", - "riscv32-elf", - "riscv-none-embed", - "riscv-none-elf", - "riscv64-linux", - "riscv64-linux-gnu", - "riscv-sifive-elf", - "riscv64-none-elf", -) - CPU_GCC_TRIPLE_RISCV64 = ( "riscv64-unknown-elf", "riscv64-unknown-linux-gnu", @@ -68,78 +58,50 @@ CPU_GCC_TRIPLE_RISCV64 = ( "riscv64-none-elf", ) +CPU_GCC_TRIPLE_RISCV32 = CPU_GCC_TRIPLE_RISCV64 + ( + "riscv32-unknown-elf", + "riscv32-unknown-linux-gnu", + "riscv32-elf", + "riscv-none-embed", + "riscv-none-elf", +) + # CPUS --------------------------------------------------------------------------------------------- -# LM32 -from litex.soc.cores.cpu.lm32 import LM32 +def collect_cpus(): + cpus = {"None" : CPUNone} + paths = [ + # Add litex.soc.cores.cpu path. + os.path.dirname(__file__), + # Add execution path. + os.getcwd() + ] -# OpenRisc -from litex.soc.cores.cpu.mor1kx import MOR1KX -from litex.soc.cores.cpu.marocchino import Marocchino + exec_dir = os.getcwd() -# OpenPower -from litex.soc.cores.cpu.microwatt import Microwatt + # Search for CPUs in paths. + for path in paths: + for file in os.listdir(path): -# RISC-V (32-bit) -from litex.soc.cores.cpu.serv import SERV -from litex.soc.cores.cpu.femtorv import FemtoRV -from litex.soc.cores.cpu.picorv32 import PicoRV32 -from litex.soc.cores.cpu.minerva import Minerva -from litex.soc.cores.cpu.vexriscv import VexRiscv -from litex.soc.cores.cpu.vexriscv_smp import VexRiscvSMP -from litex.soc.cores.cpu.ibex import Ibex -from litex.soc.cores.cpu.cv32e40p import CV32E40P + # Verify that it's a path... + cpu_path = os.path.join(path, file) + if not os.path.isdir(cpu_path): + continue -# RISC-V (64-bit) -from litex.soc.cores.cpu.rocket import RocketRV64 -from litex.soc.cores.cpu.blackparrot import BlackParrotRV64 + # ... and that core.py is present. + cpu_core = os.path.join(cpu_path, "core.py") + if not os.path.exists(cpu_core): + continue -# Zynq -from litex.soc.cores.cpu.zynq7000 import Zynq7000 + # OK, it seems to be a CPU; now get the class and add it to dict. + cpu = file + cpu_module = f"{cpu}" + sys.path.append(path) + for cpu_name, cpu_cls in inspect.getmembers(importlib.import_module(cpu_module), inspect.isclass): + if cpu.replace("_", "") == cpu_name.lower(): + cpus[cpu] = cpu_cls -# EOS-S3 -from litex.soc.cores.cpu.eos_s3 import EOS_S3 + # Return collected CPUs. + return cpus -# Gowin EMCU -from litex.soc.cores.cpu.gowin_emcu import GowinEMCU - -CPUS = { - # None - "None" : CPUNone, - - # External (CPU class provided externally by design/user) - "external" : None, - - # LM32 - "lm32" : LM32, - - # OpenRisc - "mor1kx" : MOR1KX, - "marocchino" : Marocchino, - - # OpenPower - "microwatt" : Microwatt, - - # RISC-V (32-bit) - "serv" : SERV, - "femtorv" : FemtoRV, - "picorv32" : PicoRV32, - "minerva" : Minerva, - "vexriscv" : VexRiscv, - "vexriscv_smp": VexRiscvSMP, - "ibex" : Ibex, - "cv32e40p" : CV32E40P, - - # RISC-V (64-bit) - "rocket" : RocketRV64, - "blackparrot" : BlackParrotRV64, - - # Zynq - "zynq7000" : Zynq7000, - - # EOS-S3 - "eos_s3" : EOS_S3, - - # Gowin EMCU - 'gowin_emcu' : GowinEMCU -} +CPUS = collect_cpus() diff --git a/litex/soc/integration/soc.py b/litex/soc/integration/soc.py index 734898b8b..3ef6a7186 100644 --- a/litex/soc/integration/soc.py +++ b/litex/soc/integration/soc.py @@ -884,7 +884,7 @@ class SoC(Module): self.add_config("CSR_DATA_WIDTH", self.csr.data_width) self.add_config("CSR_ALIGNMENT", self.csr.alignment) - def add_cpu(self, name="vexriscv", variant="standard", cls=None, reset_address=None, cfu=None): + def add_cpu(self, name="vexriscv", variant="standard", reset_address=None, cfu=None): # Check that CPU is supported. if name not in cpu.CPUS.keys(): self.logger.error("{} CPU {}, supporteds: {}.".format( @@ -894,12 +894,7 @@ class SoC(Module): raise SoCError() # Add CPU. - if name == "external" and cls is None: - self.logger.error("{} CPU requires {} to be specified.".format( - colorer(name), - colorer("cpu_cls", color="red"))) - raise SoCError() - cpu_cls = cls if cls is not None else cpu.CPUS[name] + cpu_cls = cpu.CPUS[name] if (variant not in cpu_cls.variants) and (cpu_cls is not cpu.CPUNone): self.logger.error("{} CPU variant {}, supporteds: {}.".format( colorer(variant), diff --git a/litex/soc/integration/soc_core.py b/litex/soc/integration/soc_core.py index 3802f20c5..6aaae1e0f 100644 --- a/litex/soc/integration/soc_core.py +++ b/litex/soc/integration/soc_core.py @@ -69,7 +69,6 @@ class SoCCore(LiteXSoC): cpu_type = "vexriscv", cpu_reset_address = None, cpu_variant = None, - cpu_cls = None, cpu_cfu = None, # CFU parameters @@ -149,7 +148,6 @@ class SoCCore(LiteXSoC): self.cpu_type = cpu_type self.cpu_variant = cpu_variant - self.cpu_cls = cpu_cls # ROM. # Initialize ROM from binary file when provided. @@ -187,7 +185,6 @@ class SoCCore(LiteXSoC): name = str(cpu_type), variant = "standard" if cpu_variant is None else cpu_variant, reset_address = None if integrated_rom_size else cpu_reset_address, - cls = cpu_cls, cfu = cpu_cfu) # Add User's interrupts