Implemented waitirq instruction
This commit is contained in:
parent
9a4a06d981
commit
5d4ce82050
37
README.md
37
README.md
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
30
picorv32.v
30
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};
|
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
|
||||||
|
|
Loading…
Reference in New Issue