Added ENABLE_IRQ_QREGS and ENABLE_IRQ_TIMER

This commit is contained in:
Clifford Wolf 2015-06-28 22:09:51 +02:00
parent e5e5494ca2
commit 46026ba985
3 changed files with 130 additions and 13 deletions

View File

@ -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)

View File

@ -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

View File

@ -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;
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 )