From d16833d86e6af3d829a0b24b5d45e6e844ef0766 Mon Sep 17 00:00:00 2001 From: Sylvain Lefebvre Date: Mon, 30 Oct 2023 10:13:17 +0100 Subject: [PATCH] ice-v swirl, fixed issue when stalling on write fault in cache --- projects/common/qpsram2x.si | 2 +- projects/ice-v/CPUs/ice-v-swirl.si | 33 +++++++++++++++++++++++++++++- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/projects/common/qpsram2x.si b/projects/common/qpsram2x.si index c8772346..8f0bc70b 100644 --- a/projects/common/qpsram2x.si +++ b/projects/common/qpsram2x.si @@ -198,7 +198,7 @@ $$else $$ if qpsram_fast then 16 : 6; $$ else - 16 : 7; // icebreaker, icestick <= 60 use 8, faster 7 + 16 : 7; // icebreaker, icestick <= 60 MHz $$ end $$end after = 4; diff --git a/projects/ice-v/CPUs/ice-v-swirl.si b/projects/ice-v/CPUs/ice-v-swirl.si index 2db04671..8ca715dd 100644 --- a/projects/ice-v/CPUs/ice-v-swirl.si +++ b/projects/ice-v/CPUs/ice-v-swirl.si @@ -152,6 +152,10 @@ $$end always { +$$if DEBUG_swirl then + uint1 debug_on = 1; +$$end + // tracks whether a register was written cycle before uint1 reg_was_written(0); reg_was_written = xregsA.wenable1; @@ -172,8 +176,10 @@ $$if ICEV_BRANCH_PRED then uint$addrW+2$ bpred_n(0); $$end $$if DEBUG_swirl then +if (debug_on) { __display("[1] cycle:%d stall_cpu:%b refetch:%b refetch_addr:%x pc:%x",cycle,stall_cpu,refetch,refetch_addr<<2,pc<<2); __display("[1] cycle:%d imem.addr:%x imem.rdata:%x dmem.addr:%x dmem.rdata:%x",cycle,imem.addr<<2,imem.rdata,dmem.addr<<2,dmem.rdata); +} $$end // capture pc, instr in pipeline pc = (exec.working | hold) ? pc : imem.addr; @@ -205,6 +211,7 @@ $$else $$end : pc; $$if DEBUG_swirl then +if (debug_on) { if (~stall_cpu | on_stall) { __display("[1] instr: %x @%x (bubble:%b reset:%b refetch:%b hold:%b stall_cpu:%b alu:%b rs1 %d rs2 %d)", instr,pc<<2,bubble,reset,refetch,hold,stall_cpu,exec.working,xregsA.addr0,xregsB.addr0); @@ -212,6 +219,7 @@ $$if DEBUG_swirl then __display("[1] pc @%x following branch to @%x",pc<<2,imem.addr<<2); } } +} $$end // remember ALU was just busy alu_was_working vv= exec.working; @@ -262,34 +270,42 @@ $$end // update bubble bubble = (bubble | refetch | exec.working | hold); $$if DEBUG_swirl then +if (debug_on) { if (~stall_cpu | on_stall) { __display("[2] instr: %x @%x (bubble:%b bpred:%b) rA:%x rB:%x",instr,pc<<2,bubble,bpred,xregsA.rdata0,xregsB.rdata0); } +} $$end $$if DEBUG_swirl then +if (debug_on) { if (~stall_cpu | on_stall) { if (hold) { __display("[2] *** data hazard (c) *** rs1[%d] rs2[%d](%b) rd(stage3)[%d]",Rtype(instr).rs1,Rtype(instr).rs2,has_rs2,exec.write_rd); } } +} $$end // [data hazards] case (a) detection // instruction in stage 3 wrote on input registers read after stage 1 // the value is thus incorrect, use the previously written value instead if (Rtype(instr).rs1 == xregsA.addr1 & reg_was_written) { $$if DEBUG_swirl then +if (debug_on) { if (~stall_cpu | on_stall) { __display("[2] *** data hazard (a) on rs1 *** rs1[%d] rs2[%d] rd_was[%d]",Rtype(instr).rs1,Rtype(instr).rs2,xregsA.addr1); } +} $$end xa_regR = 0; xa_regW = 0; xa_regW_prev = 1; xa_keep = 0; // ^^^^^^^^^^^^^ selects value previously written } if (Rtype(instr).rs2 == xregsA.addr1 & reg_was_written & has_rs2) { $$if DEBUG_swirl then +if (debug_on) { if (~stall_cpu | on_stall) { __display("[2] *** data hazard (a) on rs2 *** rs1[%d] rs2[%d] rd_was[%d]",Rtype(instr).rs1,Rtype(instr).rs2,xregsA.addr1); } +} $$end xb_regR = 0; xb_regW = 0; xb_regW_prev = 1; xb_keep = 0; // same for rs2 } @@ -299,17 +315,21 @@ $$end // (checks with rd and write_rd from stage 4) if (~no_rd & Rtype(instr).rs1 == rd) { $$if DEBUG_swirl then +if (debug_on) { if (~stall_cpu | on_stall) { __display("[2] *** data hazard (b) on rs1 *** rs1[%d] rs2[%d] rd(stage4)[%d]",Rtype(instr).rs1,Rtype(instr).rs2,rd); } +} $$end xa_regR = 0; xa_regW = 1; xa_regW_prev = 0; xa_keep = 0; } if (~no_rd & (Rtype(instr).rs2 == rd) & has_rs2) { // same for rs2 $$if DEBUG_swirl then +if (debug_on) { if (~stall_cpu | on_stall) { __display("[2] *** data hazard (b) on rs2 *** rs1[%d] rs2[%d] rd(stage4)[%d]",Rtype(instr).rs1,Rtype(instr).rs2,rd); } +} $$end xb_regR = 0; xb_regW = 1; xb_regW_prev = 0; xb_keep = 0; // ^^^^^^^^^^^ selects value being written @@ -324,15 +344,18 @@ $$end bubble = ((bubble & ~alu_was_working) | refetch | exec.working); stage3_bubble ^= bubble; $$if DEBUG_swirl then +if (debug_on) { if (~stall_cpu | on_stall) { __display("[3] instr: %x @%x (bubble:%b bpred:%b)",instr,pc<<2,bubble,bpred); } +} $$end // memory address from which to load/store $$if not ICEV_STALL then dmem.addr = (exec.n >> 2); $$else - dmem.addr = (exec.store|exec.load)&~bubble ? (exec.n >> 2) : dmem.addr; + dmem.addr = (exec.store|exec.load) & ~bubble & ~jumping + ? (exec.n >> 2) : dmem.addr; // ^^ if a cache is used, we preserve dmem.addr when not accessing dmem $$end if (exec.store & ~bubble & ~jumping) { @@ -390,6 +413,7 @@ $$if ICEV_VERILATOR_TRACE then } $$end $$if DEBUG_swirl then +if (debug_on) { if (~stall_cpu | on_stall) { __display("[4] instr: %x @%x (bubble:%b jump:%b bpred:%b load:%b) reinstr:%d",instr,pc<<2,bubble,jump,bpred,load,reinstr); if (instr_done) { @@ -400,6 +424,7 @@ $$if DEBUG_swirl then if (xregsA.wenable1) { __display("[4] wreg:[%d]=%x",Rtype(instr).rd,xregsA.wdata1); } +} $$end // signal a jump if needed (flushes pipeline and jumps) @@ -416,6 +441,7 @@ $$end : pc; // stay on same $$if DEBUG_swirl then +if (debug_on) { if (~stall_cpu | on_stall) { if (bpred & ~refetch) { __display("[4] pc @%x branch predicted towards @%x (jump %b)",pc<<2,alu_n,jump); @@ -424,6 +450,7 @@ $$if DEBUG_swirl then __display("[4] REFETCH to @%x (stall_cpu %b jump %b bpred %b)",refetch_addr<<2,stall_cpu,jump,bpred); } } +} $$end } } // end of pipeline @@ -444,9 +471,11 @@ $$end // ^^---------\ // capture xb from stage 2 so that stage 3 assign above sees the correct value $$if DEBUG_swirl then +if (debug_on) { if (dmem.wenable) { __display("[3] store @%x = %x",dmem.addr<<2,dmem.wdata); } +} $$end xb = exec.xb; // register bank B follows A writes @@ -454,6 +483,7 @@ $$end xregsB.wdata1 = xregsA.wdata1; xregsB.addr1 = xregsA.addr1; $$if DEBUG_swirl then +if (debug_on) { if (~stall_cpu) { __display("exec.xa = %x exec.xb = %x mem.wdata = %x",exec.xa,exec.xb,dmem.wdata); __display("exec.jump = %b exec.n = %x",exec.jump,exec.n); @@ -461,6 +491,7 @@ $$if DEBUG_swirl then __display("xb_keep %b xb_regR %b xb_regW %b xb_regW_prev %b",xb_keep,xb_regR,xb_regW,xb_regW_prev); __display("imem.addr @%x, dmem.addr @%x\n",imem.addr<<2,dmem.addr<<2); } +} $$end $$if SIMULATION then