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 Branch Predictor.
|
* you may not use this file except in compliance with the License.
|
* @details This module gives about 5% of performance improvement (CPI)
|
* 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 "br_predic.h"
|
#include "br_predic.h"
|
|
|
namespace debugger {
|
namespace debugger {
|
Line 19... |
Line 27... |
sensitive << i_resp_mem_data;
|
sensitive << i_resp_mem_data;
|
sensitive << i_f_predic_miss;
|
sensitive << i_f_predic_miss;
|
sensitive << i_e_npc;
|
sensitive << i_e_npc;
|
sensitive << i_ra;
|
sensitive << i_ra;
|
sensitive << r.npc;
|
sensitive << r.npc;
|
|
sensitive << r.resp_mem_data;
|
|
sensitive << r.resp_mem_addr;
|
|
|
SC_METHOD(registers);
|
SC_METHOD(registers);
|
sensitive << i_clk.pos();
|
sensitive << i_clk.pos();
|
};
|
};
|
|
|
Line 36... |
Line 46... |
sc_trace(o_vcd, i_e_npc, "/top/proc0/bp0/i_e_npc");
|
sc_trace(o_vcd, i_e_npc, "/top/proc0/bp0/i_e_npc");
|
sc_trace(o_vcd, i_ra, "/top/proc0/bp0/i_ra");
|
sc_trace(o_vcd, i_ra, "/top/proc0/bp0/i_ra");
|
|
|
sc_trace(o_vcd, o_npc_predict, "/top/proc0/bp0/o_npc_predict");
|
sc_trace(o_vcd, o_npc_predict, "/top/proc0/bp0/o_npc_predict");
|
sc_trace(o_vcd, r.npc, "/top/proc0/bp0/r_npc");
|
sc_trace(o_vcd, r.npc, "/top/proc0/bp0/r_npc");
|
|
sc_trace(o_vcd, r.resp_mem_data, "/top/proc0/bp0/r_resp_mem_data");
|
|
sc_trace(o_vcd, r.resp_mem_addr, "/top/proc0/bp0/r_resp_mem_addr");
|
|
sc_trace(o_vcd, wb_npc, "/top/proc0/bp0/wb_npc");
|
}
|
}
|
}
|
}
|
|
|
void BranchPredictor::comb() {
|
void BranchPredictor::comb() {
|
v = r;
|
v = r;
|
|
sc_uint<BUS_ADDR_WIDTH> wb_jal_off;
|
sc_uint<32> wb_tmp;
|
sc_uint<32> wb_tmp;
|
sc_uint<BUS_ADDR_WIDTH> wb_npc;
|
|
sc_uint<BUS_ADDR_WIDTH> wb_off;
|
|
|
|
wb_tmp = i_resp_mem_data.read();
|
if (i_resp_mem_valid.read()) {
|
if (i_f_predic_miss.read()) {
|
v.resp_mem_addr = i_resp_mem_addr.read();
|
wb_npc = i_e_npc.read() + 4;
|
v.resp_mem_data = i_resp_mem_data.read();
|
} else {
|
|
wb_npc = r.npc.read() + 4;
|
|
}
|
}
|
|
wb_tmp = r.resp_mem_data.read();
|
|
wb_npc = r.npc.read();
|
|
|
if (wb_tmp[31]) {
|
if (wb_tmp[31]) {
|
wb_off(BUS_ADDR_WIDTH-1, 20) = ~0;
|
wb_jal_off(BUS_ADDR_WIDTH-1, 20) = ~0;
|
} else {
|
} else {
|
wb_off(BUS_ADDR_WIDTH-1, 20) = 0;
|
wb_jal_off(BUS_ADDR_WIDTH-1, 20) = 0;
|
}
|
}
|
wb_off(19, 12) = wb_tmp(19, 12);
|
wb_jal_off(19, 12) = wb_tmp(19, 12);
|
wb_off[11] = wb_tmp[20];
|
wb_jal_off[11] = wb_tmp[20];
|
wb_off(10, 1) = wb_tmp(30, 21);
|
wb_jal_off(10, 1) = wb_tmp(30, 21);
|
wb_off[0] = 0;
|
wb_jal_off[0] = 0;
|
|
|
if (i_resp_mem_valid.read()) {
|
if (i_f_predic_miss.read()) {
|
if (wb_tmp == 0x00008067) {
|
wb_npc = i_e_npc.read();
|
// ret pseudo-instruction: Dhry score 34816 -> 35136
|
} else if (wb_tmp == 0x00008067) {
|
v.npc = i_ra.read()(BUS_ADDR_WIDTH-1, 0);
|
// ret32 pseudo-instruction:
|
} else if (wb_tmp(6, 0) == 0x6f) {
|
wb_npc = i_ra.read()(BUS_ADDR_WIDTH-1, 0);
|
|
//} else if (wb_tmp(6, 0) == 0x6f) {
|
// jal instruction: Dhry score 35136 -> 36992
|
// jal instruction: Dhry score 35136 -> 36992
|
v.npc = i_resp_mem_addr.read() + wb_off;
|
//wb_npc = r.resp_mem_addr.read() + wb_jal_off;
|
} else if (i_req_mem_fire.read()) {
|
} else {
|
v.npc = wb_npc;
|
wb_npc = r.npc.read() + 2;
|
}
|
}
|
} else if (i_req_mem_fire.read()) {
|
|
|
if (i_req_mem_fire.read()) {
|
v.npc = wb_npc;
|
v.npc = wb_npc;
|
}
|
}
|
|
|
if (!i_nrst.read()) {
|
if (!i_nrst.read()) {
|
v.npc = RESET_VECTOR;
|
v.npc = RESET_VECTOR - 2;
|
|
v.resp_mem_addr = RESET_VECTOR;
|
|
v.resp_mem_data = 0;
|
}
|
}
|
|
|
o_npc_predict = r.npc;
|
o_npc_predict = wb_npc;
|
}
|
}
|
|
|
void BranchPredictor::registers() {
|
void BranchPredictor::registers() {
|
r = v;
|
r = v;
|
}
|
}
|