From d05fe673a0ea979a24773600616d31895ba0ef56 Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Mon, 29 Oct 2018 00:59:13 -0400 Subject: [PATCH 1/5] cpu/picorv32: Extract picorv32 parameters from Instance constructor to facilitate creating variant CPUs. --- litex/soc/cores/cpu/picorv32/core.py | 54 ++++++++++++++++------------ 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/litex/soc/cores/cpu/picorv32/core.py b/litex/soc/cores/cpu/picorv32/core.py index 7fe830d66..349cfe103 100644 --- a/litex/soc/cores/cpu/picorv32/core.py +++ b/litex/soc/cores/cpu/picorv32/core.py @@ -29,31 +29,39 @@ class PicoRV32(Module): mem_wstrb = Signal(4) mem_rdata = Signal(32) + # PicoRV32 parameters. To create a new variant, modify this dictionary + # and change the desired parameters. + picorv32_params = { + "p_ENABLE_COUNTERS" : 1, + "p_ENABLE_COUNTERS64" : 1, + # Changing REGS has no effect as on FPGAs, the registers are + # implemented using a register file stored in DPRAM. + "p_ENABLE_REGS_16_31" : 1, + "p_ENABLE_REGS_DUALPORT" : 1, + "p_LATCHED_MEM_RDATA" : 0, + "p_TWO_STAGE_SHIFT" : 1, + "p_TWO_CYCLE_COMPARE" : 0, + "p_TWO_CYCLE_ALU" : 0, + "p_CATCH_MISALIGN" : 1, + "p_CATCH_ILLINSN" : 1, + "p_ENABLE_PCPI" : 0, + "p_ENABLE_MUL" : 1, + "p_ENABLE_DIV" : 1, + "p_ENABLE_FAST_MUL" : 0, + "p_ENABLE_IRQ" : 1, + "p_ENABLE_IRQ_QREGS" : 1, + "p_ENABLE_IRQ_TIMER" : 1, + "p_ENABLE_TRACE" : 0, + "p_MASKED_IRQ" : 0x00000000, + "p_LATCHED_IRQ" : 0xffffffff, + "p_PROGADDR_RESET" : progaddr_reset, + "p_PROGADDR_IRQ" : 0x00000010, + "p_STACKADDR" : 0xffffffff + } + self.specials += Instance("picorv32", # parameters - p_ENABLE_COUNTERS=1, - p_ENABLE_COUNTERS64=1, - p_ENABLE_REGS_16_31=1, - p_ENABLE_REGS_DUALPORT=1, - p_LATCHED_MEM_RDATA=0, - p_TWO_STAGE_SHIFT=1, - p_TWO_CYCLE_COMPARE=0, - p_TWO_CYCLE_ALU=0, - p_CATCH_MISALIGN=1, - p_CATCH_ILLINSN=1, - p_ENABLE_PCPI=0, - p_ENABLE_MUL=1, - p_ENABLE_DIV=1, - p_ENABLE_FAST_MUL=0, - p_ENABLE_IRQ=1, - p_ENABLE_IRQ_QREGS=1, - p_ENABLE_IRQ_TIMER=1, - p_ENABLE_TRACE=0, - p_MASKED_IRQ=0x00000000, - p_LATCHED_IRQ=0xffffffff, - p_PROGADDR_RESET=progaddr_reset, - p_PROGADDR_IRQ=0x00000010, - p_STACKADDR=0xffffffff, + **picorv32_params, # clock / reset i_clk=ClockSignal(), From f69bd877b9bab95429a4074060fbf0d32c1e63cf Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Mon, 29 Oct 2018 01:41:02 -0400 Subject: [PATCH 2/5] cpu/picorv32: Create minimal variant (disable mul/div insns, most speed optimizations). --- litex/soc/cores/cpu/picorv32/core.py | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/litex/soc/cores/cpu/picorv32/core.py b/litex/soc/cores/cpu/picorv32/core.py index 349cfe103..41fdc9aae 100644 --- a/litex/soc/cores/cpu/picorv32/core.py +++ b/litex/soc/cores/cpu/picorv32/core.py @@ -9,10 +9,12 @@ class PicoRV32(Module): name = "picorv32" endianness = "little" gcc_triple = ("riscv64-unknown-elf", "riscv32-unknown-elf") - gcc_flags = "-D__picorv32__ -mno-save-restore -march=rv32im -mabi=ilp32" + gcc_flags_template = "-D__picorv32__ -mno-save-restore -march=rv32{ext} -mabi=ilp32" linker_output_format = "elf32-littleriscv" def __init__(self, platform, progaddr_reset, variant): + self.gcc_flags = "" + self.reset = Signal() self.ibus = i = wishbone.Interface() self.dbus = d = wishbone.Interface() @@ -59,8 +61,22 @@ class PicoRV32(Module): "p_STACKADDR" : 0xffffffff } + if variant == None: + self.gcc_flags = PicoRV32.gcc_flags_template.format(ext="im") + elif variant == "minimal": + picorv32_params.update({ + "p_ENABLE_COUNTERS" : 0, + "p_ENABLE_COUNTERS64" : 0, + "p_TWO_STAGE_SHIFT" : 0, + "p_CATCH_MISALIGN" : 0, + "p_ENABLE_MUL" : 0, + "p_ENABLE_DIV" : 0, + "p_ENABLE_IRQ_TIMER" : 0 + }) + self.gcc_flags = PicoRV32.gcc_flags_template.format(ext="i") + self.specials += Instance("picorv32", - # parameters + # parameters dictionary **picorv32_params, # clock / reset From 77389d27b53933dc5a85cfe86fbb2a0d1727cdec Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Thu, 1 Nov 2018 02:18:03 -0400 Subject: [PATCH 3/5] libbase/crt0-picorv32: Ensure BSS is cleared on boot. --- litex/soc/software/libbase/crt0-picorv32.S | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/litex/soc/software/libbase/crt0-picorv32.S b/litex/soc/software/libbase/crt0-picorv32.S index 1d6faa851..054f84d32 100644 --- a/litex/soc/software/libbase/crt0-picorv32.S +++ b/litex/soc/software/libbase/crt0-picorv32.S @@ -180,6 +180,14 @@ _crt0: la t1, _irq_mask sw t0, 0(t1) + /* Clear BSS */ + la t0, _fbss + la t1, _ebss +2: + sw zero, 0(t0) + addi t0, t0, 4 + bltu t0, t1, 2b + /* set main stack */ la sp, _fstack From f32121e0e1634c2a960cbcf72e3cc2684fc5d9cf Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Thu, 1 Nov 2018 02:23:01 -0400 Subject: [PATCH 4/5] cpu/picorv32: IRQ vector needs to be moved to 16 bytes after the RESET vector. --- litex/soc/cores/cpu/picorv32/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/litex/soc/cores/cpu/picorv32/core.py b/litex/soc/cores/cpu/picorv32/core.py index 41fdc9aae..93f3358a2 100644 --- a/litex/soc/cores/cpu/picorv32/core.py +++ b/litex/soc/cores/cpu/picorv32/core.py @@ -57,7 +57,7 @@ class PicoRV32(Module): "p_MASKED_IRQ" : 0x00000000, "p_LATCHED_IRQ" : 0xffffffff, "p_PROGADDR_RESET" : progaddr_reset, - "p_PROGADDR_IRQ" : 0x00000010, + "p_PROGADDR_IRQ" : progaddr_reset + 0x00000010, "p_STACKADDR" : 0xffffffff } From e56f71824d3943134182414b6c71428cada8d731 Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Thu, 1 Nov 2018 05:02:04 -0400 Subject: [PATCH 5/5] libbase/crt0-picorv32: Emulate support for a relocatable IRQ vector (hardcoded at synthesis time). --- litex/soc/software/libbase/crt0-picorv32.S | 33 +++++++++++++++++----- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/litex/soc/software/libbase/crt0-picorv32.S b/litex/soc/software/libbase/crt0-picorv32.S index 054f84d32..7e4c712b3 100644 --- a/litex/soc/software/libbase/crt0-picorv32.S +++ b/litex/soc/software/libbase/crt0-picorv32.S @@ -18,7 +18,23 @@ _start: .org 0x00000010 # IRQ _irq_vector: - j _irq + addi sp, sp, -16 + sw t0, 4(sp) + sw ra, 8(sp) + /* By convention, q2 holds true IRQ vector, but remains caller-save. + We rely on the assumption that compiler-generated code will never touch + the QREGs. q3 is truly scratch/caller-save. */ + picorv32_getq_insn(t0, q2) + sw t0, 12(sp) + + jalr t0 // Call the true IRQ vector. + + lw t0, 12(sp) + picorv32_setq_insn(q2, t0) // Restore the true IRQ vector. + lw ra, 8(sp) + lw t0, 4(sp) + addi sp, sp, 16 + picorv32_retirq_insn() // return from interrupt /* @@ -132,9 +148,7 @@ _irq: /* restore x1 - x2 from q registers */ picorv32_getq_insn(x1, q1) picorv32_getq_insn(x2, q2) - - /* return from interrupt */ - picorv32_retirq_insn() + ret /* * Reset handler, branched to from the vector. @@ -191,6 +205,12 @@ _crt0: /* set main stack */ la sp, _fstack + /* Set up address to IRQ handler since vector is hardcoded. + By convention, q2 keeps the pointer to the true IRQ handler, + to emulate relocatable interrupts. */ + la t0, _irq + picorv32_setq_insn(q2, t0) + /* jump to main */ jal ra, main @@ -214,7 +234,7 @@ _irq_enable: picorv32_maskirq_insn(zero, t0) ret -/* +/* * Disable interrupts by masking all interrupts (the mask should already be * up to date) */ @@ -247,7 +267,7 @@ _irq_setmask: picorv32_maskirq_insn(zero, a0) 1: ret - + .section .bss irq_regs: @@ -280,4 +300,3 @@ _irq_mask: .global _irq_enabled _irq_enabled: .word 0 -