commit
4cdd679908
|
@ -9,10 +9,12 @@ class PicoRV32(Module):
|
||||||
name = "picorv32"
|
name = "picorv32"
|
||||||
endianness = "little"
|
endianness = "little"
|
||||||
gcc_triple = ("riscv64-unknown-elf", "riscv32-unknown-elf")
|
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"
|
linker_output_format = "elf32-littleriscv"
|
||||||
|
|
||||||
def __init__(self, platform, progaddr_reset, variant):
|
def __init__(self, platform, progaddr_reset, variant):
|
||||||
|
self.gcc_flags = ""
|
||||||
|
|
||||||
self.reset = Signal()
|
self.reset = Signal()
|
||||||
self.ibus = i = wishbone.Interface()
|
self.ibus = i = wishbone.Interface()
|
||||||
self.dbus = d = wishbone.Interface()
|
self.dbus = d = wishbone.Interface()
|
||||||
|
@ -29,31 +31,53 @@ class PicoRV32(Module):
|
||||||
mem_wstrb = Signal(4)
|
mem_wstrb = Signal(4)
|
||||||
mem_rdata = Signal(32)
|
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" : progaddr_reset + 0x00000010,
|
||||||
|
"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",
|
self.specials += Instance("picorv32",
|
||||||
# parameters
|
# parameters dictionary
|
||||||
p_ENABLE_COUNTERS=1,
|
**picorv32_params,
|
||||||
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,
|
|
||||||
|
|
||||||
# clock / reset
|
# clock / reset
|
||||||
i_clk=ClockSignal(),
|
i_clk=ClockSignal(),
|
||||||
|
|
|
@ -18,7 +18,23 @@ _start:
|
||||||
|
|
||||||
.org 0x00000010 # IRQ
|
.org 0x00000010 # IRQ
|
||||||
_irq_vector:
|
_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 */
|
/* restore x1 - x2 from q registers */
|
||||||
picorv32_getq_insn(x1, q1)
|
picorv32_getq_insn(x1, q1)
|
||||||
picorv32_getq_insn(x2, q2)
|
picorv32_getq_insn(x2, q2)
|
||||||
|
ret
|
||||||
/* return from interrupt */
|
|
||||||
picorv32_retirq_insn()
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reset handler, branched to from the vector.
|
* Reset handler, branched to from the vector.
|
||||||
|
@ -180,9 +194,23 @@ _crt0:
|
||||||
la t1, _irq_mask
|
la t1, _irq_mask
|
||||||
sw t0, 0(t1)
|
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 */
|
/* set main stack */
|
||||||
la sp, _fstack
|
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 */
|
/* jump to main */
|
||||||
jal ra, main
|
jal ra, main
|
||||||
|
|
||||||
|
@ -206,7 +234,7 @@ _irq_enable:
|
||||||
picorv32_maskirq_insn(zero, t0)
|
picorv32_maskirq_insn(zero, t0)
|
||||||
ret
|
ret
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Disable interrupts by masking all interrupts (the mask should already be
|
* Disable interrupts by masking all interrupts (the mask should already be
|
||||||
* up to date)
|
* up to date)
|
||||||
*/
|
*/
|
||||||
|
@ -239,7 +267,7 @@ _irq_setmask:
|
||||||
picorv32_maskirq_insn(zero, a0)
|
picorv32_maskirq_insn(zero, a0)
|
||||||
1:
|
1:
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
||||||
.section .bss
|
.section .bss
|
||||||
irq_regs:
|
irq_regs:
|
||||||
|
@ -272,4 +300,3 @@ _irq_mask:
|
||||||
.global _irq_enabled
|
.global _irq_enabled
|
||||||
_irq_enabled:
|
_irq_enabled:
|
||||||
.word 0
|
.word 0
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue