Line 1... |
Line 1... |
/**
|
/*
|
* @file
|
* Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com
|
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
|
*
|
* @author Sergey Khabarov - sergeykhbr@gmail.com
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
* @brief CPU Instruction Execution stage.
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
*/
|
*/
|
|
|
#include "execute.h"
|
#include "execute.h"
|
#include "riscv-isa.h"
|
#include "riscv-isa.h"
|
|
|
Line 16... |
Line 25... |
sensitive << i_pipeline_hold;
|
sensitive << i_pipeline_hold;
|
sensitive << i_d_valid;
|
sensitive << i_d_valid;
|
sensitive << i_d_pc;
|
sensitive << i_d_pc;
|
sensitive << i_d_instr;
|
sensitive << i_d_instr;
|
sensitive << i_wb_done;
|
sensitive << i_wb_done;
|
sensitive << i_memop_load;
|
|
sensitive << i_memop_store;
|
sensitive << i_memop_store;
|
|
sensitive << i_memop_load;
|
sensitive << i_memop_sign_ext;
|
sensitive << i_memop_sign_ext;
|
sensitive << i_memop_size;
|
sensitive << i_memop_size;
|
sensitive << i_unsigned_op;
|
sensitive << i_unsigned_op;
|
sensitive << i_rv32;;
|
sensitive << i_rv32;
|
|
sensitive << i_compressed;
|
sensitive << i_isa_type;
|
sensitive << i_isa_type;
|
sensitive << i_ivec;
|
sensitive << i_ivec;
|
sensitive << i_rdata1;
|
|
sensitive << i_rdata2;
|
|
sensitive << i_csr_rdata;
|
|
sensitive << i_ext_irq;
|
|
sensitive << i_ie;
|
sensitive << i_ie;
|
sensitive << i_mtvec;
|
sensitive << i_mtvec;
|
sensitive << i_mode;
|
sensitive << i_mode;
|
sensitive << i_break_mode;
|
sensitive << i_break_mode;
|
sensitive << i_unsup_exception;
|
sensitive << i_unsup_exception;
|
|
sensitive << i_ext_irq;
|
sensitive << i_dport_npc_write;
|
sensitive << i_dport_npc_write;
|
sensitive << i_dport_npc;
|
sensitive << i_dport_npc;
|
|
sensitive << i_rdata1;
|
|
sensitive << i_rdata2;
|
|
sensitive << i_csr_rdata;
|
sensitive << r.d_valid;
|
sensitive << r.d_valid;
|
|
sensitive << r.pc;
|
sensitive << r.npc;
|
sensitive << r.npc;
|
sensitive << r.hazard_depth;
|
sensitive << r.instr;
|
sensitive << r.hazard_addr0;
|
|
sensitive << r.hazard_addr1;
|
|
sensitive << r.res_val;
|
sensitive << r.res_val;
|
sensitive << r.memop_load;
|
sensitive << r.memop_load;
|
sensitive << r.memop_store;
|
sensitive << r.memop_store;
|
sensitive << w_hazard_detected;
|
sensitive << r.memop_addr;
|
|
sensitive << r.multi_res_addr;
|
|
sensitive << r.multi_pc;
|
|
sensitive << r.multi_npc;
|
|
sensitive << r.multi_instr;
|
sensitive << r.multi_ena[Multi_MUL];
|
sensitive << r.multi_ena[Multi_MUL];
|
sensitive << r.multi_ena[Multi_DIV];
|
sensitive << r.multi_ena[Multi_DIV];
|
sensitive << r.multi_res_addr;
|
sensitive << r.multi_rv32;
|
|
sensitive << r.multi_unsigned;
|
|
sensitive << r.multi_residual_high;
|
sensitive << r.multiclock_ena;
|
sensitive << r.multiclock_ena;
|
|
sensitive << r.multi_a1;
|
|
sensitive << r.multi_a2;
|
|
sensitive << r.hazard_addr0;
|
|
sensitive << r.hazard_addr1;
|
|
sensitive << r.hazard_depth;
|
|
sensitive << r.ext_irq_pulser;
|
sensitive << r.trap_ena;
|
sensitive << r.trap_ena;
|
sensitive << r.breakpoint;
|
sensitive << r.breakpoint;
|
|
sensitive << r.trap_code;
|
|
sensitive << r.trap_pc;
|
|
sensitive << r.call;
|
|
sensitive << r.ret;
|
|
sensitive << w_hazard_detected;
|
sensitive << wb_arith_res.arr[Multi_MUL];
|
sensitive << wb_arith_res.arr[Multi_MUL];
|
sensitive << wb_arith_res.arr[Multi_DIV];
|
sensitive << wb_arith_res.arr[Multi_DIV];
|
sensitive << w_arith_valid[Multi_MUL];
|
sensitive << w_arith_valid[Multi_MUL];
|
sensitive << w_arith_valid[Multi_DIV];
|
sensitive << w_arith_valid[Multi_DIV];
|
|
sensitive << w_arith_busy[Multi_MUL];
|
|
sensitive << w_arith_busy[Multi_DIV];
|
|
sensitive << wb_shifter_a1;
|
|
sensitive << wb_shifter_a2;
|
sensitive << wb_sll;
|
sensitive << wb_sll;
|
sensitive << wb_sllw;
|
sensitive << wb_sllw;
|
sensitive << wb_srl;
|
sensitive << wb_srl;
|
sensitive << wb_srlw;
|
sensitive << wb_srlw;
|
sensitive << wb_sra;
|
sensitive << wb_sra;
|
Line 189... |
Line 219... |
bool w_memop_store;
|
bool w_memop_store;
|
bool w_memop_sign_ext;
|
bool w_memop_sign_ext;
|
sc_uint<2> wb_memop_size;
|
sc_uint<2> wb_memop_size;
|
sc_uint<BUS_ADDR_WIDTH> wb_memop_addr;
|
sc_uint<BUS_ADDR_WIDTH> wb_memop_addr;
|
sc_bv<Instr_Total> wv;
|
sc_bv<Instr_Total> wv;
|
|
int opcode_len;
|
|
|
bool w_pc_valid;
|
bool w_pc_valid;
|
bool w_d_acceptable;
|
bool w_d_acceptable;
|
bool w_multi_valid;
|
bool w_multi_valid;
|
bool w_multi_ena;
|
bool w_multi_ena;
|
Line 335... |
Line 366... |
w_gr_equal = 1;
|
w_gr_equal = 1;
|
}
|
}
|
|
|
// Relative Branch on some condition:
|
// Relative Branch on some condition:
|
w_pc_branch = 0;
|
w_pc_branch = 0;
|
if ((wv[Instr_BEQ] & (wb_sub64 == 0))
|
if ((wv[Instr_BEQ].to_bool() & (wb_sub64 == 0))
|
|| (wv[Instr_BGE] & (wb_sub64[63] == 0))
|
|| (wv[Instr_BGE].to_bool() & (wb_sub64[63] == 0))
|
|| (wv[Instr_BGEU] & (w_gr_equal))
|
|| (wv[Instr_BGEU].to_bool() & (w_gr_equal))
|
|| (wv[Instr_BLT] & (wb_sub64[63] == 1))
|
|| (wv[Instr_BLT].to_bool() & (wb_sub64[63] == 1))
|
|| (wv[Instr_BLTU] & (w_less))
|
|| (wv[Instr_BLTU].to_bool() & (w_less))
|
|| (wv[Instr_BNE] & (wb_sub64 != 0))) {
|
|| (wv[Instr_BNE].to_bool() & (wb_sub64 != 0))) {
|
w_pc_branch = 1;
|
w_pc_branch = 1;
|
}
|
}
|
|
|
|
opcode_len = 4;
|
|
if (i_compressed.read()) {
|
|
opcode_len = 2;
|
|
}
|
|
|
if (w_pc_branch) {
|
if (w_pc_branch) {
|
wb_npc = i_d_pc.read() + wb_off(BUS_ADDR_WIDTH-1, 0);
|
wb_npc = i_d_pc.read() + wb_off(BUS_ADDR_WIDTH-1, 0);
|
} else if (wv[Instr_JAL].to_bool()) {
|
} else if (wv[Instr_JAL].to_bool()) {
|
wb_res = i_d_pc.read() + 4;
|
wb_res = i_d_pc.read() + opcode_len;
|
wb_npc = wb_rdata1(BUS_ADDR_WIDTH-1, 0) + wb_off(BUS_ADDR_WIDTH-1, 0);
|
wb_npc = wb_rdata1(BUS_ADDR_WIDTH-1, 0) + wb_off(BUS_ADDR_WIDTH-1, 0);
|
} else if (wv[Instr_JALR].to_bool()) {
|
} else if (wv[Instr_JALR].to_bool()) {
|
wb_res = i_d_pc.read() + 4;
|
wb_res = i_d_pc.read() + opcode_len;
|
wb_npc = wb_rdata1(BUS_ADDR_WIDTH-1, 0) + wb_rdata2(BUS_ADDR_WIDTH-1, 0);
|
wb_npc = wb_rdata1(BUS_ADDR_WIDTH-1, 0) + wb_rdata2(BUS_ADDR_WIDTH-1, 0);
|
wb_npc[0] = 0;
|
wb_npc[0] = 0;
|
} else if ((wv[Instr_MRET] | wv[Instr_URET]).to_bool()) {
|
} else if ((wv[Instr_MRET] | wv[Instr_URET]).to_bool()) {
|
wb_res = i_d_pc.read() + 4;
|
wb_res = i_d_pc.read() + opcode_len;
|
w_xret = i_d_valid;
|
w_xret = i_d_valid.read() && w_pc_valid;
|
w_csr_wena = 0;
|
w_csr_wena = 0;
|
if (wv[Instr_URET].to_bool()) {
|
if (wv[Instr_URET].to_bool()) {
|
wb_csr_addr = CSR_uepc;
|
wb_csr_addr = CSR_uepc;
|
} else {
|
} else {
|
wb_csr_addr = CSR_mepc;
|
wb_csr_addr = CSR_mepc;
|
}
|
}
|
wb_npc = i_csr_rdata;
|
wb_npc = i_csr_rdata;
|
} else {
|
} else {
|
// Instr_HRET, Instr_SRET, Instr_FENCE, Instr_FENCE_I:
|
// Instr_HRET, Instr_SRET, Instr_FENCE, Instr_FENCE_I:
|
wb_npc = i_d_pc.read() + 4;
|
wb_npc = i_d_pc.read() + opcode_len;
|
}
|
}
|
|
|
if (i_memop_load) {
|
if (i_memop_load) {
|
wb_memop_addr =
|
wb_memop_addr =
|
wb_rdata1(BUS_ADDR_WIDTH-1, 0) + wb_rdata2(BUS_ADDR_WIDTH-1, 0);
|
wb_rdata1(BUS_ADDR_WIDTH-1, 0) + wb_rdata2(BUS_ADDR_WIDTH-1, 0);
|
Line 401... |
Line 437... |
|| (wv[Instr_URET] && i_mode.read() != PRV_U)) {
|
|| (wv[Instr_URET] && i_mode.read() != PRV_U)) {
|
w_exception_xret = 1;
|
w_exception_xret = 1;
|
}
|
}
|
|
|
w_exception = w_d_acceptable
|
w_exception = w_d_acceptable
|
& (i_unsup_exception.read() || w_exception_load || w_exception_store
|
& ((i_unsup_exception.read() & w_pc_valid) || w_exception_load
|
|| w_exception_xret || wv[Instr_ECALL] || wv[Instr_EBREAK]);
|
|| w_exception_store || w_exception_xret
|
|
|| wv[Instr_ECALL] || wv[Instr_EBREAK]);
|
|
|
/** Default number of cycles per instruction = 0 (1 clock per instr)
|
/** Default number of cycles per instruction = 0 (1 clock per instr)
|
* If instruction is multicycle then modify this value.
|
* If instruction is multicycle then modify this value.
|
*/
|
*/
|
v.multi_ena[Multi_MUL] = 0;
|
v.multi_ena[Multi_MUL] = 0;
|
Line 519... |
Line 556... |
}
|
}
|
|
|
wb_exception_code = 0;
|
wb_exception_code = 0;
|
if (i_ext_irq & i_ie & !r.ext_irq_pulser) { // Maskable traps (interrupts)
|
if (i_ext_irq & i_ie & !r.ext_irq_pulser) { // Maskable traps (interrupts)
|
v.trap_code_waiting[4] = 1;
|
v.trap_code_waiting[4] = 1;
|
v.trap_code_waiting(3, 0) = INTERRUPT_MExternal;
|
// INTERRUPT_MExternal - INTERRUPT_USoftware
|
|
v.trap_code_waiting(3, 0) = 11;
|
} else if (w_exception) { // Unmaskable traps (exceptions)
|
} else if (w_exception) { // Unmaskable traps (exceptions)
|
wb_exception_code[4] = 0;
|
wb_exception_code[4] = 0;
|
if (w_exception_load) {
|
if (w_exception_load) {
|
wb_exception_code(3, 0) = EXCEPTION_LoadMisalign;
|
wb_exception_code(3, 0) = EXCEPTION_LoadMisalign;
|
} else if (w_exception_store) {
|
} else if (w_exception_store) {
|