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)
|
#### 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)
|
#### MASKED_IRQ (default = 32'h 0000_0000)
|
||||||
|
|
||||||
|
|
|
@ -5,11 +5,16 @@
|
||||||
// binary, for any purpose, commercial or non-commercial, and by any
|
// binary, for any purpose, commercial or non-commercial, and by any
|
||||||
// means.
|
// means.
|
||||||
|
|
||||||
|
#define ENABLE_QREGS
|
||||||
#define ENABLE_RVTST
|
#define ENABLE_RVTST
|
||||||
#define ENABLE_SIEVE
|
#define ENABLE_SIEVE
|
||||||
#define ENABLE_MULTST
|
#define ENABLE_MULTST
|
||||||
#define ENABLE_STATS
|
#define ENABLE_STATS
|
||||||
|
|
||||||
|
#ifndef ENABLE_QREGS
|
||||||
|
# undef ENABLE_RVTST
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "custom_ops.S"
|
#include "custom_ops.S"
|
||||||
|
|
||||||
.section .text
|
.section .text
|
||||||
|
@ -36,6 +41,8 @@ reset_vec:
|
||||||
irq_vec:
|
irq_vec:
|
||||||
/* save registers */
|
/* save registers */
|
||||||
|
|
||||||
|
#ifdef ENABLE_QREGS
|
||||||
|
|
||||||
setq q2, x1
|
setq q2, x1
|
||||||
setq q3, x2
|
setq q3, x2
|
||||||
|
|
||||||
|
@ -81,6 +88,43 @@ irq_vec:
|
||||||
sw x30, 30*4(x1)
|
sw x30, 30*4(x1)
|
||||||
sw x31, 31*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 */
|
/* call interrupt handler C function */
|
||||||
|
|
||||||
lui sp, %hi(irq_stack)
|
lui sp, %hi(irq_stack)
|
||||||
|
@ -91,13 +135,19 @@ irq_vec:
|
||||||
addi a0, a0, %lo(irq_regs)
|
addi a0, a0, %lo(irq_regs)
|
||||||
|
|
||||||
// arg1 = interrupt type
|
// arg1 = interrupt type
|
||||||
|
#ifdef ENABLE_QREGS
|
||||||
getq a1, q1
|
getq a1, q1
|
||||||
|
#else
|
||||||
|
addi a1, tp, 0
|
||||||
|
#endif
|
||||||
|
|
||||||
// call to C function
|
// call to C function
|
||||||
jal ra, irq
|
jal ra, irq
|
||||||
|
|
||||||
/* restore registers */
|
/* restore registers */
|
||||||
|
|
||||||
|
#ifdef ENABLE_QREGS
|
||||||
|
|
||||||
// new irq_regs address returned from C code in a0
|
// new irq_regs address returned from C code in a0
|
||||||
addi x1, a0, 0
|
addi x1, a0, 0
|
||||||
|
|
||||||
|
@ -143,8 +193,54 @@ irq_vec:
|
||||||
getq x1, q1
|
getq x1, q1
|
||||||
getq x2, q2
|
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
|
retirq
|
||||||
|
|
||||||
|
#ifndef ENABLE_QREGS
|
||||||
|
.balign 0x200
|
||||||
|
#endif
|
||||||
irq_regs:
|
irq_regs:
|
||||||
// registers are saved to this memory region during interrupt handling
|
// registers are saved to this memory region during interrupt handling
|
||||||
// the program counter is saved as register 0
|
// 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_PCPI = 0,
|
||||||
parameter [ 0:0] ENABLE_MUL = 0,
|
parameter [ 0:0] ENABLE_MUL = 0,
|
||||||
parameter [ 0:0] ENABLE_IRQ = 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] MASKED_IRQ = 32'h 0000_0000,
|
||||||
parameter [31:0] PROGADDR_RESET = 32'h 0000_0000,
|
parameter [31:0] PROGADDR_RESET = 32'h 0000_0000,
|
||||||
parameter [31:0] PROGADDR_IRQ = 32'h 0000_0010
|
parameter [31:0] PROGADDR_IRQ = 32'h 0000_0010
|
||||||
|
@ -75,8 +77,8 @@ module picorv32 #(
|
||||||
localparam integer irq_buserror = 2;
|
localparam integer irq_buserror = 2;
|
||||||
|
|
||||||
localparam integer irqregs_offset = ENABLE_REGS_16_31 ? 32 : 16;
|
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 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;
|
localparam integer regindex_bits = (ENABLE_REGS_16_31 ? 5 : 4) + ENABLE_IRQ*ENABLE_IRQ_QREGS;
|
||||||
|
|
||||||
localparam WITH_PCPI = ENABLE_PCPI || ENABLE_MUL;
|
localparam WITH_PCPI = ENABLE_PCPI || ENABLE_MUL;
|
||||||
|
|
||||||
|
@ -379,11 +381,11 @@ module picorv32 #(
|
||||||
decoded_rs1 <= mem_rdata_latched[19:15];
|
decoded_rs1 <= mem_rdata_latched[19:15];
|
||||||
decoded_rs2 <= mem_rdata_latched[24:20];
|
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
|
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)
|
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
|
end
|
||||||
|
|
||||||
if (decoder_trigger && !decoder_pseudo_trigger) begin
|
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_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_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_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;
|
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_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 && |{
|
is_slli_srli_srai <= is_alu_reg_imm && |{
|
||||||
mem_rdata_q[14:12] == 3'b001 && mem_rdata_q[31:25] == 7'b0000000,
|
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;
|
next_irq_pending = irq_pending;
|
||||||
|
|
||||||
if (ENABLE_IRQ && timer) begin
|
if (ENABLE_IRQ && ENABLE_IRQ_TIMER && timer) begin
|
||||||
if (timer - 1 == 0)
|
if (timer - 1 == 0)
|
||||||
next_irq_pending[irq_timer] = 1;
|
next_irq_pending[irq_timer] = 1;
|
||||||
timer <= timer - 1;
|
timer <= timer - 1;
|
||||||
|
@ -665,7 +667,10 @@ module picorv32 #(
|
||||||
irq_state <=
|
irq_state <=
|
||||||
irq_state == 2'b00 ? 2'b01 :
|
irq_state == 2'b00 ? 2'b01 :
|
||||||
irq_state == 2'b01 ? 2'b10 : 2'b00;
|
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
|
end else
|
||||||
if (ENABLE_IRQ && (decoder_trigger || do_waitirq) && instr_waitirq) begin
|
if (ENABLE_IRQ && (decoder_trigger || do_waitirq) && instr_waitirq) begin
|
||||||
if (irq_pending) begin
|
if (irq_pending) begin
|
||||||
|
@ -762,12 +767,12 @@ module picorv32 #(
|
||||||
mem_do_rinst <= mem_do_prefetch;
|
mem_do_rinst <= mem_do_prefetch;
|
||||||
cpu_state <= cpu_state_exec;
|
cpu_state <= cpu_state_exec;
|
||||||
end else
|
end else
|
||||||
if (ENABLE_IRQ && instr_getq) begin
|
if (ENABLE_IRQ && ENABLE_IRQ_QREGS && instr_getq) begin
|
||||||
reg_out <= cpuregs[decoded_rs1];
|
reg_out <= cpuregs[decoded_rs1];
|
||||||
latched_store <= 1;
|
latched_store <= 1;
|
||||||
cpu_state <= cpu_state_fetch;
|
cpu_state <= cpu_state_fetch;
|
||||||
end else
|
end else
|
||||||
if (ENABLE_IRQ && instr_setq) begin
|
if (ENABLE_IRQ && ENABLE_IRQ_QREGS && instr_setq) begin
|
||||||
reg_out <= cpuregs[decoded_rs1];
|
reg_out <= cpuregs[decoded_rs1];
|
||||||
latched_rd <= latched_rd | irqregs_offset;
|
latched_rd <= latched_rd | irqregs_offset;
|
||||||
latched_store <= 1;
|
latched_store <= 1;
|
||||||
|
@ -787,7 +792,7 @@ module picorv32 #(
|
||||||
irq_mask <= (decoded_rs1 ? cpuregs[decoded_rs1] : 0) | MASKED_IRQ;
|
irq_mask <= (decoded_rs1 ? cpuregs[decoded_rs1] : 0) | MASKED_IRQ;
|
||||||
cpu_state <= cpu_state_fetch;
|
cpu_state <= cpu_state_fetch;
|
||||||
end else
|
end else
|
||||||
if (ENABLE_IRQ && instr_timer) begin
|
if (ENABLE_IRQ && ENABLE_IRQ_TIMER && instr_timer) begin
|
||||||
latched_store <= 1;
|
latched_store <= 1;
|
||||||
reg_out <= timer;
|
reg_out <= timer;
|
||||||
timer <= decoded_rs1 ? cpuregs[decoded_rs1] : 0;
|
timer <= decoded_rs1 ? cpuregs[decoded_rs1] : 0;
|
||||||
|
@ -1140,6 +1145,8 @@ module picorv32_axi #(
|
||||||
parameter [ 0:0] ENABLE_PCPI = 0,
|
parameter [ 0:0] ENABLE_PCPI = 0,
|
||||||
parameter [ 0:0] ENABLE_MUL = 0,
|
parameter [ 0:0] ENABLE_MUL = 0,
|
||||||
parameter [ 0:0] ENABLE_IRQ = 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] MASKED_IRQ = 32'h 0000_0000,
|
||||||
parameter [31:0] PROGADDR_RESET = 32'h 0000_0000,
|
parameter [31:0] PROGADDR_RESET = 32'h 0000_0000,
|
||||||
parameter [31:0] PROGADDR_IRQ = 32'h 0000_0010
|
parameter [31:0] PROGADDR_IRQ = 32'h 0000_0010
|
||||||
|
@ -1229,6 +1236,8 @@ module picorv32_axi #(
|
||||||
.ENABLE_PCPI (ENABLE_PCPI ),
|
.ENABLE_PCPI (ENABLE_PCPI ),
|
||||||
.ENABLE_MUL (ENABLE_MUL ),
|
.ENABLE_MUL (ENABLE_MUL ),
|
||||||
.ENABLE_IRQ (ENABLE_IRQ ),
|
.ENABLE_IRQ (ENABLE_IRQ ),
|
||||||
|
.ENABLE_IRQ_QREGS (ENABLE_IRQ_QREGS ),
|
||||||
|
.ENABLE_IRQ_TIMER (ENABLE_IRQ_TIMER ),
|
||||||
.MASKED_IRQ (MASKED_IRQ ),
|
.MASKED_IRQ (MASKED_IRQ ),
|
||||||
.PROGADDR_RESET (PROGADDR_RESET ),
|
.PROGADDR_RESET (PROGADDR_RESET ),
|
||||||
.PROGADDR_IRQ (PROGADDR_IRQ )
|
.PROGADDR_IRQ (PROGADDR_IRQ )
|
||||||
|
|
Loading…
Reference in New Issue