Implemented waitirq instruction

This commit is contained in:
Clifford Wolf 2015-06-26 10:39:08 +02:00
parent 9a4a06d981
commit 5d4ce82050
3 changed files with 42 additions and 28 deletions

View File

@ -164,10 +164,10 @@ when saving/restoring register values in the IRQ handler.
#### getq rd, qs #### getq rd, qs
This instruction copies the value from a q-register to a general-purpose 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 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: Example assembler code using the `custom0` mnemonic:
@ -180,10 +180,10 @@ Example assembler code using the `custom0` mnemonic:
#### setq qd, rs #### setq qd, rs
This instruction copies the value from a general-purpose register to a 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 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: Example assembler code using the `custom0` mnemonic:
@ -196,11 +196,11 @@ Example assembler code using the `custom0` mnemonic:
#### retirq #### retirq
Return from interrupt. This instruction copies the value from `q0` 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: encoded under the `custom0` opcode:
0000010 00000 00000 000 00000 0001011 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: 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 This opcodes writes a new value to the irq mask register and reads the old
value. value.
Enable/disable interrupt sources. The Instruction is encoded under the Enable/disable interrupt sources. This instruction is encoded under the
`custom0` opcode: `custom0` opcode:
0000011 00000 XXXXX 000 XXXXX 0001011 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: 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 An illegal instruction or bus error while the illegal instruction or bus error
interrupt is disabled will cause the processor to halt. interrupt is disabled will cause the processor to halt.
#### waitirq (unimplemented) #### waitirq
Pause execution until an interrupt triggers. The Instruction is encoded under the Pause execution until an interrupt triggers. This instruction is encoded under the
`custom0` opcode: `custom0` opcode. The bitmask of pending IRQs is written to `rd`.
0000100 00000 00000 000 00000 0001011 0000100 00000 00000 000 XXXXX 0001011
f7 f5 rs f3 rd opcode f7 rs2 rs f3 rd opcode
Example assembler code using the `custom0` mnemonic: Example assembler code using the `custom0` mnemonic:
| Instruction | Assember Code | | Instruction | Assember Code |
| ------------------| --------------------| | ------------------| --------------------|
| waitirq | custom0 0, 0, 0, 4 | | waitirq x1 | custom0 1, 0, 0, 4 |
#### timer #### timer
Reset the timer counter to a new value. The counter counts down clock cycles and 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 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 0000101 00000 XXXXX 000 XXXXX 0001011
f7 f5 rs f3 rd opcode f7 rs2 rs f3 rd opcode
Example assembler code using the `custom0` mnemonic: Example assembler code using the `custom0` mnemonic:
| Instruction | Assember Code | | Instruction | Assember Code |
| ------------------| --------------------| | ------------------| --------------------|
| timer x2 | custom0 0, 2, 0, 5 | | timer x1, x2 | custom0 1, 2, 0, 5 |
Todos: Todos:

View File

@ -6,10 +6,11 @@
#define TEST(n) \ #define TEST(n) \
.global n; .global n ## _ret; \ .global n; .global n ## _ret; \
addi x1, zero, 1000; \ addi x1, zero, 1000; \
custom0 0,1,0,5; /* timer x1 */ \ custom0 0,1,0,5; /* timer zero, x1 */ \
jal zero,n; n ## _ret: jal zero,n; n ## _ret:
reset_vec: reset_vec:
custom0 0,0,0,4 // waitirq zero
custom0 0,0,0,3 // maskirq zero, zero custom0 0,0,0,3 // maskirq zero, zero
j start j start
nop nop

View File

@ -291,12 +291,12 @@ module picorv32 #(
is_compare <= |{is_beq_bne_blt_bge_bltu_bgeu, instr_slti, instr_slt, instr_sltiu, instr_sltu}; is_compare <= |{is_beq_bne_blt_bge_bltu_bgeu, instr_slti, instr_slt, instr_sltiu, instr_sltu};
if (mem_do_rinst && mem_done) begin if (mem_do_rinst && mem_done) begin
instr_lui <= mem_rdata_latched[6:0] == 7'b0110111; instr_lui <= mem_rdata_latched[6:0] == 7'b0110111;
instr_auipc <= mem_rdata_latched[6:0] == 7'b0010111; instr_auipc <= mem_rdata_latched[6:0] == 7'b0010111;
instr_jal <= mem_rdata_latched[6:0] == 7'b1101111;
instr_jal <= mem_rdata_latched[6:0] == 7'b1101111; instr_jalr <= mem_rdata_latched[6:0] == 7'b1100111;
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_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_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; 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_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_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_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; 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 && |{ 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; assign next_pc = latched_store && latched_branch ? reg_out : reg_next_pc;
reg [31:0] next_irq_pending; reg [31:0] next_irq_pending;
reg do_waitirq;
reg [31:0] alu_out; reg [31:0] alu_out;
reg alu_out_0; reg alu_out_0;
@ -507,6 +507,7 @@ module picorv32 #(
decoder_trigger_q <= decoder_trigger; decoder_trigger_q <= decoder_trigger;
decoder_trigger <= mem_do_rinst && mem_done; decoder_trigger <= mem_do_rinst && mem_done;
decoder_pseudo_trigger <= 0; decoder_pseudo_trigger <= 0;
do_waitirq <= 0;
if (!resetn) begin if (!resetn) begin
reg_pc <= PROGADDR_RESET; reg_pc <= PROGADDR_RESET;
@ -533,7 +534,7 @@ module picorv32 #(
trap <= 1; trap <= 1;
end end
cpu_state_fetch: begin cpu_state_fetch: begin
mem_do_rinst <= !decoder_trigger; mem_do_rinst <= !decoder_trigger && !do_waitirq;
mem_wordsize <= 0; mem_wordsize <= 0;
current_pc = reg_next_pc; current_pc = reg_next_pc;
@ -580,6 +581,15 @@ module picorv32 #(
irq_state == 2'b01 ? 2'b10 : 2'b00; irq_state == 2'b01 ? 2'b10 : 2'b00;
latched_rd <= irqregs_offset | irq_state[0]; latched_rd <= irqregs_offset | irq_state[0];
end else 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 if (decoder_trigger) begin
`ifdef DEBUG `ifdef DEBUG
$display("-- %-0t", $time); $display("-- %-0t", $time);
@ -664,7 +674,9 @@ module picorv32 #(
cpu_state <= cpu_state_fetch; cpu_state <= cpu_state_fetch;
end else end else
if (ENABLE_IRQ && instr_timer) begin 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; cpu_state <= cpu_state_fetch;
end else begin end else begin
`ifdef DEBUG `ifdef DEBUG