diff --git a/core/commit_stage.sv b/core/commit_stage.sv index 37b69af04f..8f168be1eb 100644 --- a/core/commit_stage.sv +++ b/core/commit_stage.sv @@ -127,7 +127,7 @@ module commit_stage we_gpr_o[0] = 1'b1; end // check whether the instruction we retire was a store - if (commit_instr_i[0].fu == STORE && !instr_0_is_amo) begin + if ((!CVA6Cfg.RVA && commit_instr_i[0].fu == STORE) || (CVA6Cfg.RVA && commit_instr_i[0].fu == STORE && !instr_0_is_amo)) begin // check if the LSU is ready to accept another commit entry (e.g.: a non-speculative store) if (commit_lsu_ready_i) begin commit_ack_o[0] = 1'b1; @@ -185,7 +185,7 @@ module commit_stage // from interrupt service routine // Fence synchronizes data and instruction streams. That means that we need to flush the private icache // and the private dcache. This is the most expensive instruction. - if (commit_instr_i[0].op == FENCE_I || (flush_dcache_i && commit_instr_i[0].fu != STORE)) begin + if (commit_instr_i[0].op == FENCE_I || (flush_dcache_i && DCACHE_TYPE == int'(config_pkg::WB) && commit_instr_i[0].fu != STORE)) begin commit_ack_o[0] = no_st_pending_i; // tell the controller to flush the I$ fence_i_o = no_st_pending_i; diff --git a/core/controller.sv b/core/controller.sv index eec20cb092..6ce91f0e8a 100644 --- a/core/controller.sv +++ b/core/controller.sv @@ -175,7 +175,7 @@ module controller // ---------------------- always_comb begin // halt the core if the fence is active - halt_o = halt_csr_i || halt_acc_i || fence_active_q; + halt_o = halt_csr_i || halt_acc_i || (DCACHE_TYPE == int'(config_pkg::WB) && fence_active_q); end // ---------------------- diff --git a/core/csr_regfile.sv b/core/csr_regfile.sv index 86b0342172..ec851b2f27 100644 --- a/core/csr_regfile.sv +++ b/core/csr_regfile.sv @@ -1067,7 +1067,7 @@ module csr_regfile trap_to_priv_lvl = riscv::PRIV_LVL_M; // Exception is taken and we are not in debug mode // exceptions in debug mode don't update any fields - if (!debug_mode_q && ex_i.cause != riscv::DEBUG_REQUEST && ex_i.valid) begin + if ((CVA6Cfg.DebugEn && !debug_mode_q && ex_i.cause != riscv::DEBUG_REQUEST && ex_i.valid) || (!CVA6Cfg.DebugEn && ex_i.valid)) begin // do not flush, flush is reserved for CSR writes with side effects flush_o = 1'b0; // figure out where to trap to @@ -1081,7 +1081,8 @@ module csr_regfile )-1:0]]))) begin // traps never transition from a more-privileged mode to a less privileged mode // so if we are already in M mode, stay there - trap_to_priv_lvl = (priv_lvl_o == riscv::PRIV_LVL_M) ? riscv::PRIV_LVL_M : riscv::PRIV_LVL_S; + if(priv_lvl_o == riscv::PRIV_LVL_M) trap_to_priv_lvl = riscv::PRIV_LVL_M; + else trap_to_priv_lvl = riscv::PRIV_LVL_S; end // trap to supervisor mode @@ -1287,32 +1288,28 @@ module csr_regfile CSR_SET: csr_wdata = csr_wdata_i | csr_rdata; CSR_CLEAR: csr_wdata = (~csr_wdata_i) & csr_rdata; CSR_READ: csr_we = 1'b0; - SRET: begin - if (CVA6Cfg.RVS) begin - // the return should not have any write or read side-effects - csr_we = 1'b0; - csr_read = 1'b0; - sret = 1'b1; // signal a return from supervisor mode - end - end MRET: begin // the return should not have any write or read side-effects csr_we = 1'b0; csr_read = 1'b0; mret = 1'b1; // signal a return from machine mode end - DRET: begin - if (CVA6Cfg.DebugEn) begin + default: begin + if(CVA6Cfg.RVS && csr_op_i == SRET) begin + // the return should not have any write or read side-effects + csr_we = 1'b0; + csr_read = 1'b0; + sret = 1'b1; // signal a return from supervisor mode + end else if(CVA6Cfg.DebugEn && csr_op_i == DRET) begin // the return should not have any write or read side-effects csr_we = 1'b0; csr_read = 1'b0; dret = 1'b1; // signal a return from debug mode + end else begin + csr_we = 1'b0; + csr_read = 1'b0; end end - default: begin - csr_we = 1'b0; - csr_read = 1'b0; - end endcase // if we are violating our privilges do not update the architectural state if (privilege_violation) begin @@ -1343,19 +1340,19 @@ module csr_regfile privilege_violation = 1'b1; end // check access to debug mode only CSRs - if (csr_addr_i[11:4] == 8'h7b && !debug_mode_q) begin + if ((CVA6Cfg.DebugEn && csr_addr_i[11:4] == 8'h7b) || (!CVA6Cfg.DebugEn && csr_addr_i[11:4] == 8'h7b && !debug_mode_q)) begin privilege_violation = 1'b1; end // check counter-enabled counter CSR accesses // counter address range is C00 to C1F if (csr_addr_i inside {[riscv::CSR_CYCLE : riscv::CSR_HPM_COUNTER_31]}) begin - unique case (priv_lvl_o) - riscv::PRIV_LVL_M: privilege_violation = 1'b0; - riscv::PRIV_LVL_S: if (CVA6Cfg.RVS) privilege_violation = ~mcounteren_q[csr_addr_i[4:0]]; - riscv::PRIV_LVL_U: - if (CVA6Cfg.RVU) - privilege_violation = ~mcounteren_q[csr_addr_i[4:0]] & ~scounteren_q[csr_addr_i[4:0]]; - endcase + if(priv_lvl_o == riscv::PRIV_LVL_M) begin + privilege_violation = 1'b0; + end else if(priv_lvl_o == riscv::PRIV_LVL_S && CVA6Cfg.RVS) begin + privilege_violation = ~mcounteren_q[csr_addr_i[4:0]]; + end else if(priv_lvl_o == riscv::PRIV_LVL_U && CVA6Cfg.RVU) begin + privilege_violation = ~mcounteren_q[csr_addr_i[4:0]] & ~scounteren_q[csr_addr_i[4:0]]; + end end end end @@ -1394,7 +1391,7 @@ module csr_regfile wfi_d = 1'b0; // or alternatively if there is no exception pending and we are not in debug mode wait here // for the interrupt - end else if (!debug_mode_q && csr_op_i == WFI && !ex_i.valid) begin + end else if (((CVA6Cfg.DebugEn && !debug_mode_q) && csr_op_i == WFI && !ex_i.valid) || (!CVA6Cfg.DebugEn && csr_op_i == WFI && !ex_i.valid)) begin wfi_d = 1'b1; end end @@ -1418,7 +1415,7 @@ module csr_regfile // privilege level we are jumping and whether the vectored mode is // activated for _that_ privilege level. if (ex_i.cause[riscv::XLEN-1] && - ((trap_to_priv_lvl == riscv::PRIV_LVL_M && mtvec_q[0]) + ((((CVA6Cfg.RVS || CVA6Cfg.RVU) && trap_to_priv_lvl == riscv::PRIV_LVL_M && mtvec_q[0]) || (!CVA6Cfg.RVS && !CVA6Cfg.RVU && mtvec_q[0])) || (CVA6Cfg.RVS && trap_to_priv_lvl == riscv::PRIV_LVL_S && stvec_q[0]))) begin trap_vector_base_o[7:2] = ex_i.cause[5:0]; end