From 5d4ce82050445770bb022778cbc6738d25cfe583 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 26 Jun 2015 10:39:08 +0200 Subject: [PATCH] Implemented waitirq instruction --- README.md | 37 +++++++++++++++++++------------------ firmware/start.S | 3 ++- picorv32.v | 30 +++++++++++++++++++++--------- 3 files changed, 42 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 6dc9b19..dc2c572 100644 --- a/README.md +++ b/README.md @@ -164,10 +164,10 @@ when saving/restoring register values in the IRQ handler. #### getq rd, qs This instruction copies the value from a q-register to a general-purpose -register. The Instruction is encoded under the `custom0` opcode: +register. This instruction is encoded under the `custom0` opcode: 0000000 00000 000XX 000 XXXXX 0001011 - f7 f5 qs f3 rd opcode + f7 rs2 qs f3 rd opcode Example assembler code using the `custom0` mnemonic: @@ -180,10 +180,10 @@ Example assembler code using the `custom0` mnemonic: #### setq qd, rs This instruction copies the value from a general-purpose register to a -q-register. The Instruction is encoded under the `custom0` opcode: +q-register. This instruction is encoded under the `custom0` opcode: 0000001 00000 XXXXX 000 000XX 0001011 - f7 f5 rs f3 qd opcode + f7 rs2 rs f3 qd opcode Example assembler code using the `custom0` mnemonic: @@ -196,11 +196,11 @@ Example assembler code using the `custom0` mnemonic: #### retirq Return from interrupt. This instruction copies the value from `q0` -to the program counter and re-enables interrupts. The Instruction is +to the program counter and re-enables interrupts. This instruction is encoded under the `custom0` opcode: 0000010 00000 00000 000 00000 0001011 - f7 f5 rs f3 rd opcode + f7 rs2 rs f3 rd opcode Example assembler code using the `custom0` mnemonic: @@ -214,11 +214,11 @@ The "IRQ Mask" register contains a birtmask of masked (disabled) interrupts. This opcodes writes a new value to the irq mask register and reads the old value. -Enable/disable interrupt sources. The Instruction is encoded under the +Enable/disable interrupt sources. This instruction is encoded under the `custom0` opcode: 0000011 00000 XXXXX 000 XXXXX 0001011 - f7 f5 rs f3 rd opcode + f7 rs2 rs f3 rd opcode Example assembler code using the `custom0` mnemonic: @@ -231,34 +231,35 @@ The processor starts with all interrupts disabled. An illegal instruction or bus error while the illegal instruction or bus error interrupt is disabled will cause the processor to halt. -#### waitirq (unimplemented) +#### waitirq -Pause execution until an interrupt triggers. The Instruction is encoded under the -`custom0` opcode: +Pause execution until an interrupt triggers. This instruction is encoded under the +`custom0` opcode. The bitmask of pending IRQs is written to `rd`. - 0000100 00000 00000 000 00000 0001011 - f7 f5 rs f3 rd opcode + 0000100 00000 00000 000 XXXXX 0001011 + f7 rs2 rs f3 rd opcode Example assembler code using the `custom0` mnemonic: | Instruction | Assember Code | | ------------------| --------------------| -| waitirq | custom0 0, 0, 0, 4 | +| waitirq x1 | custom0 1, 0, 0, 4 | #### timer Reset the timer counter to a new value. The counter counts down clock cycles and triggers the timer interrupt when transitioning from 1 to 0. Setting the -counter to zero disables the timer. +counter to zero disables the timer. The old value of the counter is written to +`rd`. - 0000101 00000 XXXXX 000 00000 0001011 - f7 f5 rs f3 rd opcode + 0000101 00000 XXXXX 000 XXXXX 0001011 + f7 rs2 rs f3 rd opcode Example assembler code using the `custom0` mnemonic: | Instruction | Assember Code | | ------------------| --------------------| -| timer x2 | custom0 0, 2, 0, 5 | +| timer x1, x2 | custom0 1, 2, 0, 5 | Todos: diff --git a/firmware/start.S b/firmware/start.S index 3e4705a..990cf06 100644 --- a/firmware/start.S +++ b/firmware/start.S @@ -6,10 +6,11 @@ #define TEST(n) \ .global n; .global n ## _ret; \ addi x1, zero, 1000; \ - custom0 0,1,0,5; /* timer x1 */ \ + custom0 0,1,0,5; /* timer zero, x1 */ \ jal zero,n; n ## _ret: reset_vec: + custom0 0,0,0,4 // waitirq zero custom0 0,0,0,3 // maskirq zero, zero j start nop diff --git a/picorv32.v b/picorv32.v index 7ff1023..9b0f51e 100644 --- a/picorv32.v +++ b/picorv32.v @@ -291,12 +291,12 @@ module picorv32 #( is_compare <= |{is_beq_bne_blt_bge_bltu_bgeu, instr_slti, instr_slt, instr_sltiu, instr_sltu}; if (mem_do_rinst && mem_done) begin - instr_lui <= mem_rdata_latched[6:0] == 7'b0110111; - instr_auipc <= mem_rdata_latched[6:0] == 7'b0010111; - - instr_jal <= mem_rdata_latched[6:0] == 7'b1101111; - instr_jalr <= mem_rdata_latched[6:0] == 7'b1100111; - instr_retirq <= mem_rdata_latched[6:0] == 7'b0001011 && mem_rdata_latched[31:25] == 7'b0000010 && ENABLE_IRQ; + instr_lui <= mem_rdata_latched[6:0] == 7'b0110111; + instr_auipc <= mem_rdata_latched[6:0] == 7'b0010111; + instr_jal <= mem_rdata_latched[6:0] == 7'b1101111; + instr_jalr <= mem_rdata_latched[6:0] == 7'b1100111; + instr_retirq <= mem_rdata_latched[6:0] == 7'b0001011 && mem_rdata_latched[31:25] == 7'b0000010 && ENABLE_IRQ; + instr_waitirq <= mem_rdata_latched[6:0] == 7'b0001011 && mem_rdata_latched[31:25] == 7'b0000100 && ENABLE_IRQ; is_beq_bne_blt_bge_bltu_bgeu <= mem_rdata_latched[6:0] == 7'b1100011; is_lb_lh_lw_lbu_lhu <= mem_rdata_latched[6:0] == 7'b0000011; @@ -367,7 +367,6 @@ module picorv32 #( 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_maskirq <= mem_rdata_q[6:0] == 7'b0001011 && mem_rdata_q[31:25] == 7'b0000011 && ENABLE_IRQ; - instr_waitirq <= mem_rdata_q[6:0] == 7'b0001011 && mem_rdata_q[31:25] == 7'b0000100 && ENABLE_IRQ; instr_timer <= mem_rdata_q[6:0] == 7'b0001011 && mem_rdata_q[31:25] == 7'b0000101 && ENABLE_IRQ; is_slli_srli_srai <= is_alu_reg_imm && |{ @@ -439,6 +438,7 @@ module picorv32 #( assign next_pc = latched_store && latched_branch ? reg_out : reg_next_pc; reg [31:0] next_irq_pending; + reg do_waitirq; reg [31:0] alu_out; reg alu_out_0; @@ -507,6 +507,7 @@ module picorv32 #( decoder_trigger_q <= decoder_trigger; decoder_trigger <= mem_do_rinst && mem_done; decoder_pseudo_trigger <= 0; + do_waitirq <= 0; if (!resetn) begin reg_pc <= PROGADDR_RESET; @@ -533,7 +534,7 @@ module picorv32 #( trap <= 1; end cpu_state_fetch: begin - mem_do_rinst <= !decoder_trigger; + mem_do_rinst <= !decoder_trigger && !do_waitirq; mem_wordsize <= 0; current_pc = reg_next_pc; @@ -580,6 +581,15 @@ module picorv32 #( irq_state == 2'b01 ? 2'b10 : 2'b00; latched_rd <= irqregs_offset | irq_state[0]; end else + if (ENABLE_IRQ && (decoder_trigger || do_waitirq) && instr_waitirq) begin + if (irq_pending) begin + latched_store <= 1; + reg_out <= irq_pending; + reg_next_pc <= current_pc + 4; + mem_do_rinst <= 1; + end else + do_waitirq <= 1; + end else if (decoder_trigger) begin `ifdef DEBUG $display("-- %-0t", $time); @@ -664,7 +674,9 @@ module picorv32 #( cpu_state <= cpu_state_fetch; end else if (ENABLE_IRQ && instr_timer) begin - timer <= cpuregs[decoded_rs1]; + latched_store <= 1; + reg_out <= timer; + timer <= decoded_rs1 ? cpuregs[decoded_rs1] : 0; cpu_state <= cpu_state_fetch; end else begin `ifdef DEBUG