--- /dev/null
+# litex/soc/cores/cpu/rocket/core.py
+# Rocket Chip core support for the LiteX SoC.
+#
+# Author: Gabriel L. Somlo <somlo@cmu.edu>
+# Copyright (c) 2019, Carnegie Mellon University
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials provided
+# with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import os
+
+from migen import *
+
+from litex.soc.interconnect import axi
+from litex.soc.interconnect import wishbone
+
+CPU_VARIANTS = ["standard"]
+
+GCC_FLAGS = {
+ "standard": "-march=rv64imac -mabi=lp64 ",
+}
+
+class RocketRV64(Module):
+ @property
+ def name(self):
+ return "rocket"
+
+ @property
+ def endianness(self):
+ return "little"
+
+ @property
+ def gcc_triple(self):
+ return ("riscv64-unknown-elf")
+
+ @property
+ def gcc_flags(self):
+ flags = "-mno-save-restore "
+ flags += GCC_FLAGS[self.variant]
+ flags += "-D__rocket__ "
+ return flags
+
+ @property
+ def linker_output_format(self):
+ return "elf64-littleriscv"
+
+ @property
+ def reserved_interrupts(self):
+ return {}
+
+ def __init__(self, platform, cpu_reset_addr, variant="standard"):
+ assert variant in CPU_VARIANTS, "Unsupported variant %s" % variant
+ assert cpu_reset_addr == 0x10000000, "cpu_reset_addr hardcoded in Chisel elaboration!"
+
+ self.platform = platform
+ self.variant = variant
+ self.reset = Signal()
+
+ self.interrupt = Signal(4)
+
+ self.mem_axi = mem_axi = axi.AXIInterface(
+ data_width=64, address_width=32, id_width=4)
+ self.mmio_axi = mmio_axi = axi.AXIInterface(
+ data_width=64, address_width=32, id_width=4)
+
+ self.mem_wb = mem_wb = wishbone.Interface(data_width=64, adr_width=29)
+ self.mmio_wb = mmio_wb = wishbone.Interface(data_width=64, adr_width=29)
+
+ self.ibus = ibus = wishbone.Interface()
+ self.dbus = dbus = wishbone.Interface()
+
+
+ # # #
+
+ self.specials += Instance("ExampleRocketSystem",
+ # clock, reset
+ i_clock=ClockSignal(),
+ i_reset=ResetSignal() | self.reset,
+
+ # debug (ignored)
+ #o_debug_clockeddmi_dmi_req_ready=,
+ i_debug_clockeddmi_dmi_req_valid=0,
+ i_debug_clockeddmi_dmi_req_bits_addr=0,
+ i_debug_clockeddmi_dmi_req_bits_data=0,
+ i_debug_clockeddmi_dmi_req_bits_op=0,
+ i_debug_clockeddmi_dmi_resp_ready=0,
+ #o_debug_clockeddmi_dmi_resp_valid=,
+ #o_debug_clockeddmi_dmi_resp_bits_data=,
+ #o_debug_clockeddmi_dmi_resp_bits_resp=,
+ i_debug_clockeddmi_dmiClock=0,
+ i_debug_clockeddmi_dmiReset=0,
+ #o_debug_ndreset=,
+ #o_debug_dmactive=,
+
+
+ # irq
+ i_interrupts=self.interrupt,
+
+ # axi memory (L1-cached)
+ i_mem_axi4_0_aw_ready=mem_axi.aw.ready,
+ o_mem_axi4_0_aw_valid=mem_axi.aw.valid,
+ o_mem_axi4_0_aw_bits_id=mem_axi.aw.id,
+ o_mem_axi4_0_aw_bits_addr=mem_axi.aw.addr,
+ o_mem_axi4_0_aw_bits_len=mem_axi.aw.len,
+ o_mem_axi4_0_aw_bits_size=mem_axi.aw.size,
+ o_mem_axi4_0_aw_bits_burst=mem_axi.aw.burst,
+ o_mem_axi4_0_aw_bits_lock=mem_axi.aw.lock,
+ o_mem_axi4_0_aw_bits_cache=mem_axi.aw.cache,
+ o_mem_axi4_0_aw_bits_prot=mem_axi.aw.prot,
+ o_mem_axi4_0_aw_bits_qos=mem_axi.aw.qos,
+
+ i_mem_axi4_0_w_ready=mem_axi.w.ready,
+ o_mem_axi4_0_w_valid=mem_axi.w.valid,
+ o_mem_axi4_0_w_bits_data=mem_axi.w.data,
+ o_mem_axi4_0_w_bits_strb=mem_axi.w.strb,
+ o_mem_axi4_0_w_bits_last=mem_axi.w.last,
+
+ o_mem_axi4_0_b_ready=mem_axi.b.ready,
+ i_mem_axi4_0_b_valid=mem_axi.b.valid,
+ i_mem_axi4_0_b_bits_id=mem_axi.b.id,
+ i_mem_axi4_0_b_bits_resp=mem_axi.b.resp,
+
+ i_mem_axi4_0_ar_ready=mem_axi.ar.ready,
+ o_mem_axi4_0_ar_valid=mem_axi.ar.valid,
+ o_mem_axi4_0_ar_bits_id=mem_axi.ar.id,
+ o_mem_axi4_0_ar_bits_addr=mem_axi.ar.addr,
+ o_mem_axi4_0_ar_bits_len=mem_axi.ar.len,
+ o_mem_axi4_0_ar_bits_size=mem_axi.ar.size,
+ o_mem_axi4_0_ar_bits_burst=mem_axi.ar.burst,
+ o_mem_axi4_0_ar_bits_lock=mem_axi.ar.lock,
+ o_mem_axi4_0_ar_bits_cache=mem_axi.ar.cache,
+ o_mem_axi4_0_ar_bits_prot=mem_axi.ar.prot,
+ o_mem_axi4_0_ar_bits_qos=mem_axi.ar.qos,
+
+ o_mem_axi4_0_r_ready=mem_axi.r.ready,
+ i_mem_axi4_0_r_valid=mem_axi.r.valid,
+ i_mem_axi4_0_r_bits_id=mem_axi.r.id,
+ i_mem_axi4_0_r_bits_data=mem_axi.r.data,
+ i_mem_axi4_0_r_bits_resp=mem_axi.r.resp,
+ i_mem_axi4_0_r_bits_last=mem_axi.r.last,
+
+ # axi mmio (not cached)
+ i_mmio_axi4_0_aw_ready=mmio_axi.aw.ready,
+ o_mmio_axi4_0_aw_valid=mmio_axi.aw.valid,
+ o_mmio_axi4_0_aw_bits_id=mmio_axi.aw.id,
+ o_mmio_axi4_0_aw_bits_addr=mmio_axi.aw.addr,
+ o_mmio_axi4_0_aw_bits_len=mmio_axi.aw.len,
+ o_mmio_axi4_0_aw_bits_size=mmio_axi.aw.size,
+ o_mmio_axi4_0_aw_bits_burst=mmio_axi.aw.burst,
+ o_mmio_axi4_0_aw_bits_lock=mmio_axi.aw.lock,
+ o_mmio_axi4_0_aw_bits_cache=mmio_axi.aw.cache,
+ o_mmio_axi4_0_aw_bits_prot=mmio_axi.aw.prot,
+ o_mmio_axi4_0_aw_bits_qos=mmio_axi.aw.qos,
+
+ i_mmio_axi4_0_w_ready=mmio_axi.w.ready,
+ o_mmio_axi4_0_w_valid=mmio_axi.w.valid,
+ o_mmio_axi4_0_w_bits_data=mmio_axi.w.data,
+ o_mmio_axi4_0_w_bits_strb=mmio_axi.w.strb,
+ o_mmio_axi4_0_w_bits_last=mmio_axi.w.last,
+
+ o_mmio_axi4_0_b_ready=mmio_axi.b.ready,
+ i_mmio_axi4_0_b_valid=mmio_axi.b.valid,
+ i_mmio_axi4_0_b_bits_id=mmio_axi.b.id,
+ i_mmio_axi4_0_b_bits_resp=mmio_axi.b.resp,
+
+ i_mmio_axi4_0_ar_ready=mmio_axi.ar.ready,
+ o_mmio_axi4_0_ar_valid=mmio_axi.ar.valid,
+ o_mmio_axi4_0_ar_bits_id=mmio_axi.ar.id,
+ o_mmio_axi4_0_ar_bits_addr=mmio_axi.ar.addr,
+ o_mmio_axi4_0_ar_bits_len=mmio_axi.ar.len,
+ o_mmio_axi4_0_ar_bits_size=mmio_axi.ar.size,
+ o_mmio_axi4_0_ar_bits_burst=mmio_axi.ar.burst,
+ o_mmio_axi4_0_ar_bits_lock=mmio_axi.ar.lock,
+ o_mmio_axi4_0_ar_bits_cache=mmio_axi.ar.cache,
+ o_mmio_axi4_0_ar_bits_prot=mmio_axi.ar.prot,
+ o_mmio_axi4_0_ar_bits_qos=mmio_axi.ar.qos,
+
+ o_mmio_axi4_0_r_ready=mmio_axi.r.ready,
+ i_mmio_axi4_0_r_valid=mmio_axi.r.valid,
+ i_mmio_axi4_0_r_bits_id=mmio_axi.r.id,
+ i_mmio_axi4_0_r_bits_data=mmio_axi.r.data,
+ i_mmio_axi4_0_r_bits_resp=mmio_axi.r.resp,
+ i_mmio_axi4_0_r_bits_last=mmio_axi.r.last,
+ )
+
+ # adapt axi interfaces to wishbone
+ mem_a2w = ResetInserter()(
+ axi.AXI2Wishbone(mem_axi, mem_wb, base_address=0))
+ mmio_a2w = ResetInserter()(
+ axi.AXI2Wishbone(mmio_axi, mmio_wb, base_address=0))
+ # NOTE: AXI2Wishbone FSMs must be reset with the CPU!
+ self.comb += [
+ mem_a2w.reset.eq(ResetSignal() | self.reset),
+ mmio_a2w.reset.eq(ResetSignal() | self.reset),
+ ]
+
+ # down-convert wishbone from 64 to 32 bit data width
+ mem_dc = wishbone.Converter(mem_wb, ibus)
+ mmio_dc = wishbone.Converter(mmio_wb, dbus)
+
+ self.submodules += mem_a2w, mem_dc, mmio_a2w, mmio_dc
+
+ # add verilog sources
+ self.add_sources(platform)
+
+ @staticmethod
+ def add_sources(platform):
+ vdir = os.path.join(
+ os.path.abspath(os.path.dirname(__file__)), "verilog")
+ platform.add_sources(
+ os.path.join(vdir, "generated-src"),
+ "freechips.rocketchip.system.LitexConfig.v",
+ "freechips.rocketchip.system.LitexConfig.behav_srams.v",
+ )
+ platform.add_sources(
+ os.path.join(vdir, "vsrc"),
+ "plusarg_reader.v",
+ "AsyncResetReg.v",
+ "EICG_wrapper.v",
+ )
#endif
#include <system.h>
+#include <generated/csr.h>
#ifdef __picorv32__
// PicoRV32 has a very limited interrupt support, implemented via custom
extern void _irq_setmask(unsigned int);
#endif
+#ifdef __rocket__
+// The RocketChip uses a Platform-Level Interrupt Controller (PLIC) which
+// is programmed and queried via a set of MMIO registers.
+
+#define PLIC_BASE 0x0c000000L // Base address and per-pin priority array
+#define PLIC_PENDING 0x0c001000L // Bit field matching currently pending pins
+#define PLIC_ENABLED 0x0c002000L // Bit field corresponding to the current mask
+#define PLIC_THRSHLD 0x0c200000L // Per-pin priority must be >= this to trigger
+#define PLIC_CLAIM 0x0c200004L // Claim & completion register address
+#endif /* __rocket__ */
+
static inline unsigned int irq_getie(void)
{
#if defined (__lm32__)
return (csrr(mstatus) & CSR_MSTATUS_MIE) != 0;
#elif defined (__minerva__)
return (csrr(mstatus) & CSR_MSTATUS_MIE) != 0;
+#elif defined (__rocket__)
+ return (csrr(mstatus) & CSR_MSTATUS_MIE) != 0;
#else
#error Unsupported architecture
#endif
if(ie) csrs(mstatus,CSR_MSTATUS_MIE); else csrc(mstatus,CSR_MSTATUS_MIE);
#elif defined (__minerva__)
if(ie) csrs(mstatus,CSR_MSTATUS_MIE); else csrc(mstatus,CSR_MSTATUS_MIE);
+#elif defined (__rocket__)
+ if(ie) csrs(mstatus,CSR_MSTATUS_MIE); else csrc(mstatus,CSR_MSTATUS_MIE);
#else
#error Unsupported architecture
#endif
unsigned int mask;
asm volatile ("csrr %0, %1" : "=r"(mask) : "i"(CSR_IRQ_MASK));
return mask;
+#elif defined (__rocket__)
+ return csr_readl(PLIC_ENABLED) >> 1;
#else
#error Unsupported architecture
#endif
asm volatile ("csrw %0, %1" :: "i"(CSR_IRQ_MASK), "r"(mask));
#elif defined (__minerva__)
asm volatile ("csrw %0, %1" :: "i"(CSR_IRQ_MASK), "r"(mask));
+#elif defined (__rocket__)
+ csr_writel(mask << 1, PLIC_ENABLED);
#else
#error Unsupported architecture
#endif
unsigned int pending;
asm volatile ("csrr %0, %1" : "=r"(pending) : "i"(CSR_IRQ_PENDING));
return pending;
+#elif defined (__rocket__)
+ return csr_readl(PLIC_PENDING) >> 1;
#else
#error Unsupported architecture
#endif