diff --git a/litex/soc/cores/cpu/cdim/__init__.py b/litex/soc/cores/cpu/cdim/__init__.py new file mode 100644 index 000000000..bd6a427d2 --- /dev/null +++ b/litex/soc/cores/cpu/cdim/__init__.py @@ -0,0 +1 @@ +from litex.soc.cores.cpu.cdim.core import CDIM diff --git a/litex/soc/cores/cpu/cdim/boot-helper.S b/litex/soc/cores/cpu/cdim/boot-helper.S new file mode 100644 index 000000000..1f46d3769 --- /dev/null +++ b/litex/soc/cores/cpu/cdim/boot-helper.S @@ -0,0 +1,4 @@ +.section .text, "ax", @progbits +.global boot_helper +boot_helper: + jr $a3 diff --git a/litex/soc/cores/cpu/cdim/core.py b/litex/soc/cores/cpu/cdim/core.py new file mode 100644 index 000000000..17e6f842e --- /dev/null +++ b/litex/soc/cores/cpu/cdim/core.py @@ -0,0 +1,129 @@ +# +# This file is part of LiteX. +# +# Copyright (c) 2024 Jiaxun Yang +# SPDX-License-Identifier: BSD-2-Clause + +import os + +from migen import * +from litex.gen import * + +from litex.soc.interconnect import axi +from litex.soc.cores.cpu import CPU, CPU_GCC_TRIPLE_MIPS + +class CDIM(CPU): + category = "softcore" + family = "mips" + name = "cdim" + human_name = "CQU CDIM" + variants = ["standard"] + data_width = 32 + endianness = "little" + gcc_triple = CPU_GCC_TRIPLE_MIPS + linker_output_format = "elf32-tradlittlemips" + nop = "nop" + io_regions = {0x1000_0000: 0x0c00_0000} # Origin, Length. + + # GCC Flags. + @property + def gcc_flags(self): + flags = "-march=mips32 -mabi=32 -EL -msoft-float" + flags += " -D__cdim__ " + flags += " -DUART_POLLING" + return flags + + # Memory Mapping. + @property + def mem_map(self): + # Based on vanilla sysmap.h + return { + "main_ram" : 0x0000_0000, + "csr" : 0x1800_0000, + "sram" : 0x1c00_0000, + "rom" : 0x1fc0_0000, + } + + def __init__(self, platform, variant="standard"): + self.platform = platform + self.variant = variant + self.reset = Signal() + self.interrupt = Signal(6) + # Peripheral bus (Connected to main SoC's bus). + axi_if = axi.AXIInterface(data_width=32, address_width=32, id_width=4) + self.periph_buses = [axi_if] + # Memory buses (Connected directly to LiteDRAM). + self.memory_buses = [] + + # CPU Instance. + self.cpu_params = dict( + # Clk / Rst + i_aclk = ClockSignal("sys"), + i_aresetn = ~ResetSignal("sys") & ~self.reset, + + # Interrupts + i_ext_int= self.interrupt, + + # AXI interface + o_arid = axi_if.ar.id, + o_araddr = axi_if.ar.addr, + o_arlen = axi_if.ar.len, + o_arsize = axi_if.ar.size, + o_arburst = axi_if.ar.burst, + o_arlock = axi_if.ar.lock, + o_arcache = axi_if.ar.cache, + o_arprot = axi_if.ar.prot, + o_arvalid = axi_if.ar.valid, + i_arready = axi_if.ar.ready, + + i_rid = axi_if.r.id, + i_rdata = axi_if.r.data, + i_rresp = axi_if.r.resp, + i_rlast = axi_if.r.last, + i_rvalid = axi_if.r.valid, + o_rready = axi_if.r.ready, + + o_awid = axi_if.aw.id, + o_awaddr = axi_if.aw.addr, + o_awlen = axi_if.aw.len, + o_awsize = axi_if.aw.size, + o_awburst = axi_if.aw.burst, + o_awlock = axi_if.aw.lock, + o_awcache = axi_if.aw.cache, + o_awprot = axi_if.aw.prot, + o_awvalid = axi_if.aw.valid, + i_awready = axi_if.aw.ready, + + o_wid = axi_if.w.id, + o_wdata = axi_if.w.data, + o_wstrb = axi_if.w.strb, + o_wlast = axi_if.w.last, + o_wvalid = axi_if.w.valid, + i_wready = axi_if.w.ready, + + i_bid = axi_if.b.id, + i_bresp = axi_if.b.resp, + i_bvalid = axi_if.b.valid, + o_bready = axi_if.b.ready, + ) + + # Add sources + basedir = os.path.join("CDIM", "mycpu") + self.platform.add_source_dir(basedir) + platform.add_verilog_include_path(basedir) + + def set_reset_address(self, reset_address): + # Hardcoded reset address. + assert reset_address == 0x1fc0_0000 + self.reset_address = reset_address + + def bios_map(self, addr, cached): + # We can't access beyond KSEG0/1 in BIOS + assert addr < 0x2000_0000 + if cached: + return addr + 0x8000_0000 + else: + return addr + 0xa000_0000 + + def do_finalize(self): + self.specials += Instance("mycpu_top", **self.cpu_params) diff --git a/litex/soc/cores/cpu/cdim/crt0.S b/litex/soc/cores/cpu/cdim/crt0.S new file mode 100644 index 000000000..65b575720 --- /dev/null +++ b/litex/soc/cores/cpu/cdim/crt0.S @@ -0,0 +1,44 @@ +.global main +.global isr +.global _start + +_start: + j crt_init + nop + nop + nop + nop + nop + nop + nop + +crt_init: + la $sp, _fstack + +data_init: + la $t0, _fdata + la $t1, _edata + la $t2, _fdata_rom +data_loop: + beq $t0, $t1, data_done + lw $t3, 0($t2) + sw $t3, 0($t0) + addiu $t0, $t0,4 + addiu $t2, $t2,4 + b data_loop +data_done: + +bss_init: + la $t0, _fbss + la $t1, _ebss +bss_loop: + beq $t0, $t1, bss_done + sw $zero, 0($t0) + addiu $t0, $t0, 4 + b bss_loop +bss_done: + + la $t9, main + jalr $t9 +inf_loop: + b inf_loop diff --git a/litex/soc/cores/cpu/cdim/irq.h b/litex/soc/cores/cpu/cdim/irq.h new file mode 100644 index 000000000..95e2cfe43 --- /dev/null +++ b/litex/soc/cores/cpu/cdim/irq.h @@ -0,0 +1,45 @@ +#ifndef __IRQ_H +#define __IRQ_H + +#include +#include "system.h" +#include "generated/soc.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +static inline unsigned int irq_getie(void) +{ + return 0; /* FIXME */ +} + +static inline void irq_setie(unsigned int ie) +{ + /* TODO */ +} + +static inline unsigned int irq_getmask(void) +{ + return (1 << UART_INTERRUPT); // FIXME +} + +static inline void irq_setmask(unsigned int mask) +{ + /* TODO */ +} + +static inline unsigned int irq_pending(void) +{ + /* TODO */ + return 0; +} + + +#ifdef __cplusplus +} +#endif + +#endif /* __IRQ_H */ diff --git a/litex/soc/cores/cpu/cdim/system.h b/litex/soc/cores/cpu/cdim/system.h new file mode 100644 index 000000000..262446a62 --- /dev/null +++ b/litex/soc/cores/cpu/cdim/system.h @@ -0,0 +1,19 @@ +#ifndef __SYSTEM_H +#define __SYSTEM_H + +#ifdef __cplusplus +extern "C" { +#endif + +__attribute__((unused)) static void flush_cpu_icache(void){}; /* No instruction cache */ +__attribute__((unused)) static void flush_cpu_dcache(void){}; /* No instruction cache */ +void flush_l2_cache(void); + +void busy_wait(unsigned int ms); +void busy_wait_us(unsigned int us); + +#ifdef __cplusplus +} +#endif + +#endif /* __SYSTEM_H */