From 46026ba985d1ffb062802651d99ae34d5b1f773d Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 28 Jun 2015 22:09:51 +0200 Subject: [PATCH] Added ENABLE_IRQ_QREGS and ENABLE_IRQ_TIMER --- README.md | 14 ++++++- firmware/start.S | 96 ++++++++++++++++++++++++++++++++++++++++++++++++ picorv32.v | 33 +++++++++++------ 3 files changed, 130 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 45f220f..ef5db86 100644 --- a/README.md +++ b/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) diff --git a/firmware/start.S b/firmware/start.S index c5e1901..9e9ad75 100644 --- a/firmware/start.S +++ b/firmware/start.S @@ -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 diff --git a/picorv32.v b/picorv32.v index 79fbbc5..c4e2d2c 100644 --- a/picorv32.v +++ b/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 )