| 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) {
  |