From 1b963bb2d5ecc250dc64e0266ac4534d772c1436 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Fri, 13 Dec 2019 23:58:14 +0100 Subject: [PATCH] soc/cores/cpu: add initial Microwatt gateware support Implementation tested on arty: cd litex/soc/cores/cpu/microwatt git clone https://github.com/antonblanchard/microwatt mv microwatt sources cd litex/boards/targets ./arty --cpu-type=microwatt --no-compile-gateware --- litex/soc/cores/cpu/__init__.py | 2 + litex/soc/cores/cpu/microwatt/__init__.py | 1 + litex/soc/cores/cpu/microwatt/core.py | 124 ++++++++++++++++++ .../cpu/microwatt/microwatt_wrapper.vhdl | 113 ++++++++++++++++ 4 files changed, 240 insertions(+) create mode 100644 litex/soc/cores/cpu/microwatt/__init__.py create mode 100644 litex/soc/cores/cpu/microwatt/core.py create mode 100644 litex/soc/cores/cpu/microwatt/microwatt_wrapper.vhdl diff --git a/litex/soc/cores/cpu/__init__.py b/litex/soc/cores/cpu/__init__.py index 6aeb6ba50..ba3963c93 100644 --- a/litex/soc/cores/cpu/__init__.py +++ b/litex/soc/cores/cpu/__init__.py @@ -32,6 +32,7 @@ from litex.soc.cores.cpu.picorv32 import PicoRV32 from litex.soc.cores.cpu.vexriscv import VexRiscv from litex.soc.cores.cpu.minerva import Minerva from litex.soc.cores.cpu.rocket import RocketRV64 +from litex.soc.cores.cpu.microwatt import Microwatt CPUS = { "lm32" : LM32, @@ -40,6 +41,7 @@ CPUS = { "vexriscv" : VexRiscv, "minerva" : Minerva, "rocket" : RocketRV64, + "microwatt" : Microwatt, } # CPU Variants/Extensions Definition --------------------------------------------------------------- diff --git a/litex/soc/cores/cpu/microwatt/__init__.py b/litex/soc/cores/cpu/microwatt/__init__.py new file mode 100644 index 000000000..7d06ce349 --- /dev/null +++ b/litex/soc/cores/cpu/microwatt/__init__.py @@ -0,0 +1 @@ +from litex.soc.cores.cpu.microwatt.core import Microwatt diff --git a/litex/soc/cores/cpu/microwatt/core.py b/litex/soc/cores/cpu/microwatt/core.py new file mode 100644 index 000000000..a3b62a016 --- /dev/null +++ b/litex/soc/cores/cpu/microwatt/core.py @@ -0,0 +1,124 @@ +# This file is Copyright (c) 2019 Florent Kermarrec +# License: BSD + +import os + +from migen import * + +from litex.soc.interconnect import wishbone +from litex.soc.cores.cpu import CPU + + +CPU_VARIANTS = ["standard"] + + +class Microwatt(CPU): + name = "microwatt" + data_width = 64 + endianness = "little" + gcc_triple = ("powerpc64le-linux") + linker_output_format = "elf64-powerpc64le" + io_regions = {0x80000000: 0x80000000} # origin, length FIXME: check default IO regions + + @property + def gcc_flags(self): + # FIXME: add default flags + flags += "-D__microwatt__ " + return flags + + def __init__(self, platform, variant="standard"): + assert variant in CPU_VARIANTS, "Unsupported variant %s" % variant + self.platform = platform + self.variant = variant + self.reset = Signal() + self.wb_insn = wb_insn = wishbone.Interface(data_width=64, adr_width=28) + self.wb_data = wb_data = wishbone.Interface(data_width=64, adr_width=28) + self.buses = [wb_insn, wb_data] + + # # # + + self.cpu_params = dict( + # Clock / Reset + i_clk = ClockSignal(), + i_rst = ResetSignal() | self.reset, + + # Wishbone instruction bus + i_wishbone_insn_dat_r = wb_insn.dat_r, + i_wishbone_insn_ack = wb_insn.ack, + i_wishbone_insn_stall = 0, + + o_wishbone_insn_adr = Cat(Signal(4), wb_insn.adr), + o_wishbone_insn_dat_w = wb_insn.dat_w, + o_wishbone_insn_cyc = wb_insn.cyc, + o_wishbone_insn_stb = wb_insn.stb, + o_wishbone_insn_sel = wb_insn.sel, + o_wishbone_insn_we = wb_insn.we, + + # Wishbone data bus + i_wishbone_data_dat_r = wb_data.dat_r, + i_wishbone_data_ack = wb_data.ack, + i_wishbone_data_stall = 0, + + o_wishbone_data_adr = Cat(Signal(4), wb_data.adr), + o_wishbone_data_dat_w = wb_data.dat_w, + o_wishbone_data_cyc = wb_data.cyc, + o_wishbone_data_stb = wb_data.stb, + o_wishbone_data_sel = wb_data.sel, + o_wishbone_data_we = wb_data.we, + + # Debug bus + i_dmi_addr = 0, + i_dmi_din = 0, + #o_dmi_dout =, + i_dmi_req = 0, + i_dmi_wr = 0, + #o_dmi_ack =, + ) + + # add vhdl sources + self.add_sources(platform) + + def set_reset_address(self, reset_address): + assert not hasattr(self, "reset_address") + self.reset_address = reset_address + assert reset_address == 0x00000000 + + @staticmethod + def add_sources(platform): + sdir = os.path.join(os.path.abspath(os.path.dirname(__file__)), "sources") + platform.add_source(os.path.join(sdir, "decode_types.vhdl")) + platform.add_source(os.path.join(sdir, "wishbone_types.vhdl")) + platform.add_source(os.path.join(sdir, "common.vhdl")) + platform.add_source(os.path.join(sdir, "fetch1.vhdl")) + platform.add_source(os.path.join(sdir, "fetch2.vhdl")) + platform.add_source(os.path.join(sdir, "decode1.vhdl")) + platform.add_source(os.path.join(sdir, "helpers.vhdl")) + platform.add_source(os.path.join(sdir, "decode2.vhdl")) + platform.add_source(os.path.join(sdir, "register_file.vhdl")) + platform.add_source(os.path.join(sdir, "cr_file.vhdl")) + platform.add_source(os.path.join(sdir, "crhelpers.vhdl")) + platform.add_source(os.path.join(sdir, "ppc_fx_insns.vhdl")) + platform.add_source(os.path.join(sdir, "sim_console.vhdl")) + platform.add_source(os.path.join(sdir, "logical.vhdl")) + platform.add_source(os.path.join(sdir, "countzero.vhdl")) + platform.add_source(os.path.join(sdir, "gpr_hazard.vhdl")) + platform.add_source(os.path.join(sdir, "cr_hazard.vhdl")) + platform.add_source(os.path.join(sdir, "control.vhdl")) + platform.add_source(os.path.join(sdir, "execute1.vhdl")) + platform.add_source(os.path.join(sdir, "loadstore1.vhdl")) + platform.add_source(os.path.join(sdir, "dcache.vhdl")) + platform.add_source(os.path.join(sdir, "multiply.vhdl")) + platform.add_source(os.path.join(sdir, "divider.vhdl")) + platform.add_source(os.path.join(sdir, "rotator.vhdl")) + platform.add_source(os.path.join(sdir, "writeback.vhdl")) + platform.add_source(os.path.join(sdir, "insn_helpers.vhdl")) + platform.add_source(os.path.join(sdir, "core.vhdl")) + platform.add_source(os.path.join(sdir, "icache.vhdl")) + platform.add_source(os.path.join(sdir, "plru.vhdl")) + platform.add_source(os.path.join(sdir, "cache_ram.vhdl")) + platform.add_source(os.path.join(sdir, "core_debug.vhdl")) + platform.add_source(os.path.join(sdir, "utils.vhdl")) + platform.add_source(os.path.join(sdir, "..", "microwatt_wrapper.vhdl")) + + def do_finalize(self): + self.specials += Instance("microwatt_wrapper", **self.cpu_params) diff --git a/litex/soc/cores/cpu/microwatt/microwatt_wrapper.vhdl b/litex/soc/cores/cpu/microwatt/microwatt_wrapper.vhdl new file mode 100644 index 000000000..9ee82ecec --- /dev/null +++ b/litex/soc/cores/cpu/microwatt/microwatt_wrapper.vhdl @@ -0,0 +1,113 @@ +-- This file is Copyright (c) 2019 Florent Kermarrec +-- License: BSD + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library work; +use work.common.all; +use work.wishbone_types.all; + +entity microwatt_wrapper is + generic ( + SIM : boolean := false; + DISABLE_FLATTEN : boolean := false + ); + port ( + clk : in std_logic; + rst : in std_logic; + + wishbone_insn_dat_r : in std_ulogic_vector(63 downto 0); + wishbone_insn_ack : in std_ulogic; + wishbone_insn_stall : in std_ulogic; + + wishbone_insn_adr : out std_ulogic_vector(31 downto 0); + wishbone_insn_dat_w : out std_ulogic_vector(63 downto 0); + wishbone_insn_cyc : out std_ulogic; + wishbone_insn_stb : out std_ulogic; + wishbone_insn_sel : out std_ulogic_vector(7 downto 0); + wishbone_insn_we : out std_ulogic; + + wishbone_data_dat_r : in std_ulogic_vector(63 downto 0); + wishbone_data_ack : in std_ulogic; + wishbone_data_stall : in std_ulogic; + + wishbone_data_adr : out std_ulogic_vector(31 downto 0); + wishbone_data_dat_w : out std_ulogic_vector(63 downto 0); + wishbone_data_cyc : out std_ulogic; + wishbone_data_stb : out std_ulogic; + wishbone_data_sel : out std_ulogic_vector(7 downto 0); + wishbone_data_we : out std_ulogic; + + dmi_addr : in std_ulogic_vector(3 downto 0); + dmi_din : in std_ulogic_vector(63 downto 0); + dmi_dout : out std_ulogic_vector(63 downto 0); + dmi_req : in std_ulogic; + dmi_wr : in std_ulogic; + dmi_ack : out std_ulogic; + + terminated_out : out std_logic + ); +end microwatt_wrapper; + +architecture rtl of microwatt_wrapper is + + signal wishbone_insn_in : wishbone_slave_out; + signal wishbone_insn_out : wishbone_master_out; + + signal wishbone_data_in : wishbone_slave_out; + signal wishbone_data_out : wishbone_master_out; + +begin + + -- wishbone_insn mapping + wishbone_insn_in.dat <= wishbone_insn_dat_r; + wishbone_insn_in.ack <= wishbone_insn_ack; + wishbone_insn_in.stall <= wishbone_insn_stall; + + wishbone_insn_adr <= wishbone_insn_out.adr; + wishbone_insn_dat_w <= wishbone_insn_out.dat; + wishbone_insn_cyc <= wishbone_insn_out.cyc; + wishbone_insn_stb <= wishbone_insn_out.stb; + wishbone_insn_sel <= wishbone_insn_out.sel; + wishbone_insn_we <= wishbone_insn_out.we; + + -- wishbone_data mapping + wishbone_data_in.dat <= wishbone_data_dat_r; + wishbone_data_in.ack <= wishbone_data_ack; + wishbone_data_in.stall <= wishbone_data_stall; + + wishbone_data_adr <= wishbone_data_out.adr; + wishbone_data_dat_w <= wishbone_data_out.dat; + wishbone_data_cyc <= wishbone_data_out.cyc; + wishbone_data_stb <= wishbone_data_out.stb; + wishbone_data_sel <= wishbone_data_out.sel; + wishbone_data_we <= wishbone_data_out.we; + + microwatt_core : entity work.core + generic map ( + SIM => SIM, + DISABLE_FLATTEN => DISABLE_FLATTEN + ) + port map ( + clk => clk, + rst => rst, + + wishbone_insn_in => wishbone_insn_in, + wishbone_insn_out => wishbone_insn_out, + + wishbone_data_in => wishbone_data_in, + wishbone_data_out => wishbone_data_out, + + dmi_addr => dmi_addr, + dmi_din => dmi_din, + dmi_dout => dmi_dout, + dmi_req => dmi_req, + dmi_wr => dmi_wr, + dmi_ack => dmi_ack, + + terminated_out => terminated_out + ); + +end rtl;