Encode in q0 LSB if interrupted instruction is compressed

This commit is contained in:
Clifford Wolf 2016-06-01 12:39:00 +02:00
parent fd18475e23
commit 490a734519
3 changed files with 35 additions and 16 deletions

View File

@ -463,6 +463,10 @@ address and `q1` contains a bitmask of all IRQs to be handled. This means one
call to the interrupt handler needs to service more than one IRQ when more than call to the interrupt handler needs to service more than one IRQ when more than
one bit is set in `q1`. one bit is set in `q1`.
When support for compressed instructions is enabled, then the LSB of q0 is set
when the interrupted instruction is a compressed instruction. This can be used if
the IRQ handler wants to decode the interrupted instruction.
Registers `q2` and `q3` are uninitialized and can be used as temporary storage Registers `q2` and `q3` are uninitialized and can be used as temporary storage
when saving/restoring register values in the IRQ handler. when saving/restoring register values in the IRQ handler.

View File

@ -13,6 +13,27 @@ uint32_t *irq(uint32_t *regs, uint32_t irqs)
static unsigned int ext_irq_5_count = 0; static unsigned int ext_irq_5_count = 0;
static unsigned int timer_irq_count = 0; static unsigned int timer_irq_count = 0;
// checking compressed isa q0 reg handling
{
uint32_t pc = (regs[0] & 1) ? regs[0] - 3 : regs[0] - 4;
uint32_t instr = *(uint16_t*)pc;
if ((instr & 3) == 3)
instr = instr | (*(uint16_t*)(pc + 2)) << 16;
if (((instr & 3) != 3) != (regs[0] & 1)) {
print_str("Mismatch between q0 LSB and decoded instruction word! q0=0x");
print_hex(regs[0], 8);
print_str(", instr=0x");
if ((instr & 3) == 3)
print_hex(instr, 8);
else
print_hex(instr, 4);
print_str("\n");
__asm__ volatile ("sbreak");
}
}
if ((irqs & (1<<4)) != 0) { if ((irqs & (1<<4)) != 0) {
ext_irq_4_count++; ext_irq_4_count++;
// print_str("[EXT-IRQ-4]"); // print_str("[EXT-IRQ-4]");
@ -30,21 +51,11 @@ uint32_t *irq(uint32_t *regs, uint32_t irqs)
if ((irqs & 6) != 0) if ((irqs & 6) != 0)
{ {
uint32_t pc = regs[0] - 2; uint32_t pc = (regs[0] & 1) ? regs[0] - 3 : regs[0] - 4;
uint16_t *instr_hwords = (uint16_t*)pc;
uint32_t instr = *(uint16_t*)pc; uint32_t instr = *(uint16_t*)pc;
if ((*instr_hwords & 3) == 3) { if ((instr & 3) == 3)
pc -= 2; instr = instr | (*(uint16_t*)(pc + 2)) << 16;
instr = (instr << 16) | *(uint16_t*)pc;
} else {
int cnt_3 = 0;
while ((*(--instr_hwords) & 3) == 3 && cnt_3 < 20) cnt_3++;
if ((cnt_3 & 1) != 0) {
pc -= 2;
instr = (instr << 16) | *(uint16_t*)pc;
}
}
print_str("\n"); print_str("\n");
print_str("------------------------------------------------------------\n"); print_str("------------------------------------------------------------\n");

View File

@ -128,6 +128,7 @@ module picorv32 #(
wire [31:0] next_pc; wire [31:0] next_pc;
reg irq_delay;
reg irq_active; reg irq_active;
reg [31:0] irq_mask; reg [31:0] irq_mask;
reg [31:0] irq_pending; reg [31:0] irq_pending;
@ -1093,7 +1094,7 @@ module picorv32 #(
clear_prefetched_high_word = COMPRESSED_ISA; clear_prefetched_high_word = COMPRESSED_ISA;
end end
assign launch_next_insn = cpu_state == cpu_state_fetch && decoder_trigger && (!ENABLE_IRQ || irq_active || !(irq_pending & ~irq_mask)); assign launch_next_insn = cpu_state == cpu_state_fetch && decoder_trigger && (!ENABLE_IRQ || irq_delay || irq_active || !(irq_pending & ~irq_mask));
always @(posedge clk) begin always @(posedge clk) begin
trap <= 0; trap <= 0;
@ -1155,6 +1156,7 @@ module picorv32 #(
pcpi_valid <= 0; pcpi_valid <= 0;
pcpi_timeout <= 0; pcpi_timeout <= 0;
irq_active <= 0; irq_active <= 0;
irq_delay <= 0;
irq_mask <= ~0; irq_mask <= ~0;
next_irq_pending = 0; next_irq_pending = 0;
irq_state <= 0; irq_state <= 0;
@ -1186,7 +1188,7 @@ module picorv32 #(
cpuregs[latched_rd] <= latched_stalu ? alu_out_q : reg_out; cpuregs[latched_rd] <= latched_stalu ? alu_out_q : reg_out;
end end
ENABLE_IRQ && irq_state[0]: begin ENABLE_IRQ && irq_state[0]: begin
cpuregs[latched_rd] <= current_pc; cpuregs[latched_rd] <= current_pc | latched_compr;
current_pc = PROGADDR_IRQ; current_pc = PROGADDR_IRQ;
irq_active <= 1; irq_active <= 1;
mem_do_rinst <= 1; mem_do_rinst <= 1;
@ -1210,10 +1212,11 @@ module picorv32 #(
latched_rd <= decoded_rd; latched_rd <= decoded_rd;
latched_compr <= compressed_instr; latched_compr <= compressed_instr;
if (ENABLE_IRQ && ((decoder_trigger && !irq_active && |(irq_pending & ~irq_mask)) || irq_state)) begin if (ENABLE_IRQ && ((decoder_trigger && !irq_active && !irq_delay && |(irq_pending & ~irq_mask)) || irq_state)) begin
irq_state <= irq_state <=
irq_state == 2'b00 ? 2'b01 : irq_state == 2'b00 ? 2'b01 :
irq_state == 2'b01 ? 2'b10 : 2'b00; irq_state == 2'b01 ? 2'b10 : 2'b00;
latched_compr <= latched_compr;
if (ENABLE_IRQ_QREGS) if (ENABLE_IRQ_QREGS)
latched_rd <= irqregs_offset | irq_state[0]; latched_rd <= irqregs_offset | irq_state[0];
else else
@ -1230,6 +1233,7 @@ module picorv32 #(
end else end else
if (decoder_trigger) begin if (decoder_trigger) begin
`debug($display("-- %-0t", $time);) `debug($display("-- %-0t", $time);)
irq_delay <= irq_active;
reg_next_pc <= current_pc + (compressed_instr ? 2 : 4); reg_next_pc <= current_pc + (compressed_instr ? 2 : 4);
if (ENABLE_COUNTERS) begin if (ENABLE_COUNTERS) begin
count_instr <= count_instr + 1; count_instr <= count_instr + 1;