mirror of https://github.com/YosysHQ/picorv32.git
Added ENABLE_IRQ_QREGS and ENABLE_IRQ_TIMER
This commit is contained in:
parent
e5e5494ca2
commit
46026ba985
14
README.md
14
README.md
|
@ -153,7 +153,19 @@ interface only becomes functional when ENABLE_PCPI is set as well.
|
|||
|
||||
#### ENABLE_IRQ (default = 0)
|
||||
|
||||
Set this to 1 to enable IRQs.
|
||||
Set this to 1 to enable IRQs. (see "" below for a discussion of IRQs)
|
||||
|
||||
#### ENABLE_IRQ_QREGS (default = 1)
|
||||
|
||||
Set this to 0 to disable support for the `getq` and `setq` instructions. Without
|
||||
the q-registers, the irq return address will be stored in x3 (gp) and the IRQ
|
||||
bitmask in x4 (tp), the global pointer and thread pointer registers according
|
||||
to the RISC-V ABI. Code generated from ordinary C code will not interact with
|
||||
those registers.
|
||||
|
||||
#### ENABLE_IRQ_TIMER (default = 1)
|
||||
|
||||
Set this to 0 to disable support for the `timer` instruction.
|
||||
|
||||
#### MASKED_IRQ (default = 32'h 0000_0000)
|
||||
|
||||
|
|
|
@ -5,11 +5,16 @@
|
|||
// binary, for any purpose, commercial or non-commercial, and by any
|
||||
// means.
|
||||
|
||||
#define ENABLE_QREGS
|
||||
#define ENABLE_RVTST
|
||||
#define ENABLE_SIEVE
|
||||
#define ENABLE_MULTST
|
||||
#define ENABLE_STATS
|
||||
|
||||
#ifndef ENABLE_QREGS
|
||||
# undef ENABLE_RVTST
|
||||
#endif
|
||||
|
||||
#include "custom_ops.S"
|
||||
|
||||
.section .text
|
||||
|
@ -36,6 +41,8 @@ reset_vec:
|
|||
irq_vec:
|
||||
/* save registers */
|
||||
|
||||
#ifdef ENABLE_QREGS
|
||||
|
||||
setq q2, x1
|
||||
setq q3, x2
|
||||
|
||||
|
@ -81,6 +88,43 @@ irq_vec:
|
|||
sw x30, 30*4(x1)
|
||||
sw x31, 31*4(x1)
|
||||
|
||||
#else // ENABLE_QREGS
|
||||
|
||||
sw gp, 0*4+0x200(zero)
|
||||
sw x1, 1*4+0x200(zero)
|
||||
sw x2, 2*4+0x200(zero)
|
||||
sw x3, 3*4+0x200(zero)
|
||||
sw x4, 4*4+0x200(zero)
|
||||
sw x5, 5*4+0x200(zero)
|
||||
sw x6, 6*4+0x200(zero)
|
||||
sw x7, 7*4+0x200(zero)
|
||||
sw x8, 8*4+0x200(zero)
|
||||
sw x9, 9*4+0x200(zero)
|
||||
sw x10, 10*4+0x200(zero)
|
||||
sw x11, 11*4+0x200(zero)
|
||||
sw x12, 12*4+0x200(zero)
|
||||
sw x13, 13*4+0x200(zero)
|
||||
sw x14, 14*4+0x200(zero)
|
||||
sw x15, 15*4+0x200(zero)
|
||||
sw x16, 16*4+0x200(zero)
|
||||
sw x17, 17*4+0x200(zero)
|
||||
sw x18, 18*4+0x200(zero)
|
||||
sw x19, 19*4+0x200(zero)
|
||||
sw x20, 20*4+0x200(zero)
|
||||
sw x21, 21*4+0x200(zero)
|
||||
sw x22, 22*4+0x200(zero)
|
||||
sw x23, 23*4+0x200(zero)
|
||||
sw x24, 24*4+0x200(zero)
|
||||
sw x25, 25*4+0x200(zero)
|
||||
sw x26, 26*4+0x200(zero)
|
||||
sw x27, 27*4+0x200(zero)
|
||||
sw x28, 28*4+0x200(zero)
|
||||
sw x29, 29*4+0x200(zero)
|
||||
sw x30, 30*4+0x200(zero)
|
||||
sw x31, 31*4+0x200(zero)
|
||||
|
||||
#endif // ENABLE_QREGS
|
||||
|
||||
/* call interrupt handler C function */
|
||||
|
||||
lui sp, %hi(irq_stack)
|
||||
|
@ -91,13 +135,19 @@ irq_vec:
|
|||
addi a0, a0, %lo(irq_regs)
|
||||
|
||||
// arg1 = interrupt type
|
||||
#ifdef ENABLE_QREGS
|
||||
getq a1, q1
|
||||
#else
|
||||
addi a1, tp, 0
|
||||
#endif
|
||||
|
||||
// call to C function
|
||||
jal ra, irq
|
||||
|
||||
/* restore registers */
|
||||
|
||||
#ifdef ENABLE_QREGS
|
||||
|
||||
// new irq_regs address returned from C code in a0
|
||||
addi x1, a0, 0
|
||||
|
||||
|
@ -143,8 +193,54 @@ irq_vec:
|
|||
getq x1, q1
|
||||
getq x2, q2
|
||||
|
||||
#else // ENABLE_QREGS
|
||||
|
||||
// new irq_regs address returned from C code in a0
|
||||
addi a1, zero, 0x200
|
||||
beq a0, a1, 1f
|
||||
sbreak
|
||||
1:
|
||||
|
||||
lw gp, 0*4+0x200(zero)
|
||||
lw x1, 1*4+0x200(zero)
|
||||
lw x2, 2*4+0x200(zero)
|
||||
// do not restore x3 (gp)
|
||||
lw x4, 4*4+0x200(zero)
|
||||
lw x5, 5*4+0x200(zero)
|
||||
lw x6, 6*4+0x200(zero)
|
||||
lw x7, 7*4+0x200(zero)
|
||||
lw x8, 8*4+0x200(zero)
|
||||
lw x9, 9*4+0x200(zero)
|
||||
lw x10, 10*4+0x200(zero)
|
||||
lw x11, 11*4+0x200(zero)
|
||||
lw x12, 12*4+0x200(zero)
|
||||
lw x13, 13*4+0x200(zero)
|
||||
lw x14, 14*4+0x200(zero)
|
||||
lw x15, 15*4+0x200(zero)
|
||||
lw x16, 16*4+0x200(zero)
|
||||
lw x17, 17*4+0x200(zero)
|
||||
lw x18, 18*4+0x200(zero)
|
||||
lw x19, 19*4+0x200(zero)
|
||||
lw x20, 20*4+0x200(zero)
|
||||
lw x21, 21*4+0x200(zero)
|
||||
lw x22, 22*4+0x200(zero)
|
||||
lw x23, 23*4+0x200(zero)
|
||||
lw x24, 24*4+0x200(zero)
|
||||
lw x25, 25*4+0x200(zero)
|
||||
lw x26, 26*4+0x200(zero)
|
||||
lw x27, 27*4+0x200(zero)
|
||||
lw x28, 28*4+0x200(zero)
|
||||
lw x29, 29*4+0x200(zero)
|
||||
lw x30, 30*4+0x200(zero)
|
||||
lw x31, 31*4+0x200(zero)
|
||||
|
||||
#endif // ENABLE_QREGS
|
||||
|
||||
retirq
|
||||
|
||||
#ifndef ENABLE_QREGS
|
||||
.balign 0x200
|
||||
#endif
|
||||
irq_regs:
|
||||
// registers are saved to this memory region during interrupt handling
|
||||
// the program counter is saved as register 0
|
||||
|
|
33
picorv32.v
33
picorv32.v
|
@ -33,6 +33,8 @@ module picorv32 #(
|
|||
parameter [ 0:0] ENABLE_PCPI = 0,
|
||||
parameter [ 0:0] ENABLE_MUL = 0,
|
||||
parameter [ 0:0] ENABLE_IRQ = 0,
|
||||
parameter [ 0:0] ENABLE_IRQ_QREGS = 1,
|
||||
parameter [ 0:0] ENABLE_IRQ_TIMER = 1,
|
||||
parameter [31:0] MASKED_IRQ = 32'h 0000_0000,
|
||||
parameter [31:0] PROGADDR_RESET = 32'h 0000_0000,
|
||||
parameter [31:0] PROGADDR_IRQ = 32'h 0000_0010
|
||||
|
@ -75,8 +77,8 @@ module picorv32 #(
|
|||
localparam integer irq_buserror = 2;
|
||||
|
||||
localparam integer irqregs_offset = ENABLE_REGS_16_31 ? 32 : 16;
|
||||
localparam integer regfile_size = (ENABLE_REGS_16_31 ? 32 : 16) + 4*ENABLE_IRQ;
|
||||
localparam integer regindex_bits = (ENABLE_REGS_16_31 ? 5 : 4) + ENABLE_IRQ;
|
||||
localparam integer regfile_size = (ENABLE_REGS_16_31 ? 32 : 16) + 4*ENABLE_IRQ*ENABLE_IRQ_QREGS;
|
||||
localparam integer regindex_bits = (ENABLE_REGS_16_31 ? 5 : 4) + ENABLE_IRQ*ENABLE_IRQ_QREGS;
|
||||
|
||||
localparam WITH_PCPI = ENABLE_PCPI || ENABLE_MUL;
|
||||
|
||||
|
@ -379,11 +381,11 @@ module picorv32 #(
|
|||
decoded_rs1 <= mem_rdata_latched[19:15];
|
||||
decoded_rs2 <= mem_rdata_latched[24:20];
|
||||
|
||||
if (mem_rdata_latched[6:0] == 7'b0001011 && mem_rdata_latched[31:25] == 7'b0000000 && ENABLE_IRQ)
|
||||
if (mem_rdata_latched[6:0] == 7'b0001011 && mem_rdata_latched[31:25] == 7'b0000000 && ENABLE_IRQ && ENABLE_IRQ_QREGS)
|
||||
decoded_rs1[regindex_bits-1] <= 1; // instr_getq
|
||||
|
||||
if (mem_rdata_latched[6:0] == 7'b0001011 && mem_rdata_latched[31:25] == 7'b0000010 && ENABLE_IRQ)
|
||||
decoded_rs1 <= irqregs_offset; // instr_retirq
|
||||
decoded_rs1 <= ENABLE_IRQ_QREGS ? irqregs_offset : 3; // instr_retirq
|
||||
end
|
||||
|
||||
if (decoder_trigger && !decoder_pseudo_trigger) begin
|
||||
|
@ -437,10 +439,10 @@ module picorv32 #(
|
|||
instr_rdinstr <= (mem_rdata_q[6:0] == 7'b1110011 && mem_rdata_q[31:12] == 'b11000000001000000010) && ENABLE_COUNTERS;
|
||||
instr_rdinstrh <= (mem_rdata_q[6:0] == 7'b1110011 && mem_rdata_q[31:12] == 'b11001000001000000010) && ENABLE_COUNTERS;
|
||||
|
||||
instr_getq <= mem_rdata_q[6:0] == 7'b0001011 && mem_rdata_q[31:25] == 7'b0000000 && ENABLE_IRQ;
|
||||
instr_setq <= mem_rdata_q[6:0] == 7'b0001011 && mem_rdata_q[31:25] == 7'b0000001 && ENABLE_IRQ;
|
||||
instr_getq <= mem_rdata_q[6:0] == 7'b0001011 && mem_rdata_q[31:25] == 7'b0000000 && ENABLE_IRQ && ENABLE_IRQ_QREGS;
|
||||
instr_setq <= mem_rdata_q[6:0] == 7'b0001011 && mem_rdata_q[31:25] == 7'b0000001 && ENABLE_IRQ && ENABLE_IRQ_QREGS;
|
||||
instr_maskirq <= mem_rdata_q[6:0] == 7'b0001011 && mem_rdata_q[31:25] == 7'b0000011 && ENABLE_IRQ;
|
||||
instr_timer <= mem_rdata_q[6:0] == 7'b0001011 && mem_rdata_q[31:25] == 7'b0000101 && ENABLE_IRQ;
|
||||
instr_timer <= mem_rdata_q[6:0] == 7'b0001011 && mem_rdata_q[31:25] == 7'b0000101 && ENABLE_IRQ && ENABLE_IRQ_TIMER;
|
||||
|
||||
is_slli_srli_srai <= is_alu_reg_imm && |{
|
||||
mem_rdata_q[14:12] == 3'b001 && mem_rdata_q[31:25] == 7'b0000000,
|
||||
|
@ -579,7 +581,7 @@ module picorv32 #(
|
|||
|
||||
next_irq_pending = irq_pending;
|
||||
|
||||
if (ENABLE_IRQ && timer) begin
|
||||
if (ENABLE_IRQ && ENABLE_IRQ_TIMER && timer) begin
|
||||
if (timer - 1 == 0)
|
||||
next_irq_pending[irq_timer] = 1;
|
||||
timer <= timer - 1;
|
||||
|
@ -665,7 +667,10 @@ module picorv32 #(
|
|||
irq_state <=
|
||||
irq_state == 2'b00 ? 2'b01 :
|
||||
irq_state == 2'b01 ? 2'b10 : 2'b00;
|
||||
latched_rd <= irqregs_offset | irq_state[0];
|
||||
if (ENABLE_IRQ_QREGS)
|
||||
latched_rd <= irqregs_offset | irq_state[0];
|
||||
else
|
||||
latched_rd <= irq_state[0] ? 4 : 3;
|
||||
end else
|
||||
if (ENABLE_IRQ && (decoder_trigger || do_waitirq) && instr_waitirq) begin
|
||||
if (irq_pending) begin
|
||||
|
@ -762,12 +767,12 @@ module picorv32 #(
|
|||
mem_do_rinst <= mem_do_prefetch;
|
||||
cpu_state <= cpu_state_exec;
|
||||
end else
|
||||
if (ENABLE_IRQ && instr_getq) begin
|
||||
if (ENABLE_IRQ && ENABLE_IRQ_QREGS && instr_getq) begin
|
||||
reg_out <= cpuregs[decoded_rs1];
|
||||
latched_store <= 1;
|
||||
cpu_state <= cpu_state_fetch;
|
||||
end else
|
||||
if (ENABLE_IRQ && instr_setq) begin
|
||||
if (ENABLE_IRQ && ENABLE_IRQ_QREGS && instr_setq) begin
|
||||
reg_out <= cpuregs[decoded_rs1];
|
||||
latched_rd <= latched_rd | irqregs_offset;
|
||||
latched_store <= 1;
|
||||
|
@ -787,7 +792,7 @@ module picorv32 #(
|
|||
irq_mask <= (decoded_rs1 ? cpuregs[decoded_rs1] : 0) | MASKED_IRQ;
|
||||
cpu_state <= cpu_state_fetch;
|
||||
end else
|
||||
if (ENABLE_IRQ && instr_timer) begin
|
||||
if (ENABLE_IRQ && ENABLE_IRQ_TIMER && instr_timer) begin
|
||||
latched_store <= 1;
|
||||
reg_out <= timer;
|
||||
timer <= decoded_rs1 ? cpuregs[decoded_rs1] : 0;
|
||||
|
@ -1140,6 +1145,8 @@ module picorv32_axi #(
|
|||
parameter [ 0:0] ENABLE_PCPI = 0,
|
||||
parameter [ 0:0] ENABLE_MUL = 0,
|
||||
parameter [ 0:0] ENABLE_IRQ = 0,
|
||||
parameter [ 0:0] ENABLE_IRQ_QREGS = 1,
|
||||
parameter [ 0:0] ENABLE_IRQ_TIMER = 1,
|
||||
parameter [31:0] MASKED_IRQ = 32'h 0000_0000,
|
||||
parameter [31:0] PROGADDR_RESET = 32'h 0000_0000,
|
||||
parameter [31:0] PROGADDR_IRQ = 32'h 0000_0010
|
||||
|
@ -1229,6 +1236,8 @@ module picorv32_axi #(
|
|||
.ENABLE_PCPI (ENABLE_PCPI ),
|
||||
.ENABLE_MUL (ENABLE_MUL ),
|
||||
.ENABLE_IRQ (ENABLE_IRQ ),
|
||||
.ENABLE_IRQ_QREGS (ENABLE_IRQ_QREGS ),
|
||||
.ENABLE_IRQ_TIMER (ENABLE_IRQ_TIMER ),
|
||||
.MASKED_IRQ (MASKED_IRQ ),
|
||||
.PROGADDR_RESET (PROGADDR_RESET ),
|
||||
.PROGADDR_IRQ (PROGADDR_IRQ )
|
||||
|
|
Loading…
Reference in New Issue