OpenCores
URL https://opencores.org/ocsvn/riscv_vhdl/riscv_vhdl/trunk

Subversion Repositories riscv_vhdl

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /riscv_vhdl/trunk/debugger/src/cpu_sysc_plugin/riverlib
    from Rev 3 to Rev 4
    Reverse comparison

Rev 3 → Rev 4

/cache/cache_top.cpp
207,6 → 207,8
v.state = State_Idle;
}
 
w_ctrl_req_ready = 1;
 
o_req_mem_valid = i.req_mem_valid | d.req_mem_valid;
o_req_mem_write = w_mem_write;
o_req_mem_addr = wb_mem_addr;
/cache/dcache.cpp
47,7 → 47,7
sc_trace(o_vcd, r.dline_addr_req, "/top/cache0/d0/r_dline_addr_req");
sc_trace(o_vcd, r.dline_size_req, "/top/cache0/d0/r_dline_size_req");
sc_trace(o_vcd, r.state, "/top/cache0/d0/r_state");
}
sc_trace(o_vcd, w_wait_response, "/top/cache0/d0/w_wait_response"); }
}
 
void DCache::comb() {
70,6 → 70,11
wb_o_resp_data = 0;
wb_rtmp = 0;
 
w_wait_response = 0;
if (r.state.read() == State_WaitResp && i_resp_mem_data_valid.read() == 0) {
w_wait_response = 1;
}
 
switch (i_req_data_sz.read()) {
case 0:
wb_o_req_wdata = (i_req_data_data.read()(7, 0),
125,10 → 130,10
default:;
}
 
w_o_req_mem_valid = i_req_data_valid.read();
w_o_req_mem_valid = i_req_data_valid.read() && !w_wait_response;
wb_o_req_mem_addr = i_req_data_addr.read()(BUS_ADDR_WIDTH-1, 3) << 3;
w_o_req_data_ready = i_req_mem_ready.read();
w_req_fire = i_req_data_valid.read() && w_o_req_data_ready;
w_req_fire = w_o_req_mem_valid && w_o_req_data_ready;
switch (r.state.read()) {
case State_Idle:
if (i_req_data_valid.read()) {
/cache/dcache.h
61,10 → 61,9
sc_signal<sc_uint<2>> dline_size_req;
sc_signal<sc_uint<2>> state;
} v, r;
 
bool w_wait_response;
};
 
 
} // namespace debugger
 
#endif // __DEBUGGER_RIVERLIB_DCACHE_H__
/cache/icache.cpp
1,8 → 1,17
/**
* @file
* @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Instruction Cache.
/*
* Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* 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 "icache.h"
18,12 → 27,15
sensitive << i_resp_mem_data;
sensitive << i_resp_ctrl_ready;
sensitive << i_req_mem_ready;
sensitive << r.iline_addr;
sensitive << r.iline_data;
sensitive << r.iline_addr_hit;
sensitive << r.iline_data_hit;
sensitive << r.iline[0].addr;
sensitive << r.iline[0].data;
sensitive << r.iline[1].addr;
sensitive << r.iline[1].data;
sensitive << r.iline_addr_req;
sensitive << r.hit_line;
sensitive << r.addr_processing;
sensitive << r.double_req;
sensitive << r.delay_valid;
sensitive << r.delay_data;
sensitive << r.state;
 
SC_METHOD(registers);
45,19 → 57,26
sc_trace(o_vcd, i_resp_ctrl_ready, "/top/cache0/i0/i_resp_ctrl_ready");
sc_trace(o_vcd, o_resp_ctrl_addr, "/top/cache0/i0/o_resp_ctrl_addr");
sc_trace(o_vcd, o_resp_ctrl_data, "/top/cache0/i0/o_resp_ctrl_data");
sc_trace(o_vcd, r.iline_addr, "/top/cache0/i0/r_iline_addr");
sc_trace(o_vcd, r.iline_data, "/top/cache0/i0/r_iline_data");
sc_trace(o_vcd, r.iline_addr_hit, "/top/cache0/i0/r_iline_addr_hit");
sc_trace(o_vcd, r.iline_data_hit, "/top/cache0/i0/r_iline_data_hit");
sc_trace(o_vcd, r.iline[0].addr, "/top/cache0/i0/r_iline(0)_addr");
sc_trace(o_vcd, r.iline[0].data, "/top/cache0/i0/r_iline(0)_data");
sc_trace(o_vcd, r.iline[1].addr, "/top/cache0/i0/r_iline(1)_addr");
sc_trace(o_vcd, r.iline[1].data, "/top/cache0/i0/r_iline(1)_data");
sc_trace(o_vcd, r.iline_addr_req, "/top/cache0/i0/r_iline_addr_req");
sc_trace(o_vcd, r.hit_line, "/top/cache0/i0/r_hit_line");
sc_trace(o_vcd, r.addr_processing, "/top/cache0/i0/r_addr_processing");
sc_trace(o_vcd, r.double_req, "/top/cache0/i0/double_req");
sc_trace(o_vcd, r.delay_valid, "/top/cache0/i0/r_delay_valid");
sc_trace(o_vcd, r.delay_data, "/top/cache0/i0/r_delay_valid");
sc_trace(o_vcd, r.state, "/top/cache0/i0/r_state");
sc_trace(o_vcd, w_hit, "/top/cache0/i0/w_hit");
sc_trace(o_vcd, w_hit_line, "/top/cache0/i0/w_hit_line");
sc_trace(o_vcd, w_hit_req, "/top/cache0/i0/w_hit_req");
//sc_trace(o_vcd, wb_req_line, "/top/cache0/i0/wb_req_line");
//sc_trace(o_vcd, wb_cached_addr, "/top/cache0/i0/wb_cached_addr");
//sc_trace(o_vcd, wb_cached_data, "/top/cache0/i0/wb_cached_data");
sc_trace(o_vcd, w_need_mem_req, "/top/cache0/i0/w_need_mem_req");
sc_trace(o_vcd, wb_l[0].hit, "/top/cache0/i0/wb_l(0)_hit");
sc_trace(o_vcd, wb_l[1].hit, "/top/cache0/i0/wb_l(1)_hit");
sc_trace(o_vcd, wb_l[0].hit_data, "/top/cache0/i0/wb_l(0)_hit_data");
sc_trace(o_vcd, wb_l[1].hit_data, "/top/cache0/i0/wb_l(1)_hit_data");
sc_trace(o_vcd, wb_hit_word, "/top/cache0/i0/wb_hit_word");
sc_trace(o_vcd, wb_l[0].hit_hold, "/top/cache0/i0/wb_l(0).hit_hold");
sc_trace(o_vcd, wb_l[1].hit_hold, "/top/cache0/i0/wb_l(1).hit_hold");
sc_trace(o_vcd, w_reuse_lastline, "/top/cache0/i0/w_reuse_lastline");
sc_trace(o_vcd, w_wait_response, "/top/cache0/i0/w_wait_response");
}
}
 
66,35 → 85,130
bool w_o_req_ctrl_ready;
bool w_o_req_mem_valid;
sc_uint<BUS_ADDR_WIDTH> wb_o_req_mem_addr;
bool w_req_ctrl_valid;
bool w_req_fire;
bool w_o_resp_valid;
sc_uint<BUS_ADDR_WIDTH> wb_o_resp_addr;
sc_uint<32> wb_o_resp_data;
sc_uint<BUS_ADDR_WIDTH - 3> wb_req_line;
sc_uint<BUS_ADDR_WIDTH> wb_req_addr[2];
sc_uint<BUS_ADDR_WIDTH> wb_hold_addr[2];
v = r;
w_hit_req = 0;
w_hit_line = 0;
w_hit = 0;
 
wb_req_line = i_req_ctrl_addr.read()(BUS_ADDR_WIDTH-1, 3);
if (i_resp_mem_data_valid.read()
&& (wb_req_line == r.iline_addr_req.read()(BUS_ADDR_WIDTH-1, 3))) {
w_hit_req = 1;
w_wait_response = 0;
if (r.state.read() == State_WaitResp && i_resp_mem_data_valid.read() == 0) {
w_wait_response = 1;
}
if (wb_req_line == r.iline_addr.read()) {
w_hit_line = 1;
w_req_ctrl_valid = !w_wait_response
&& (i_req_ctrl_valid.read() || r.double_req.read());
wb_req_addr[0] = i_req_ctrl_addr.read();
wb_req_addr[1] = i_req_ctrl_addr.read() + 2;
 
wb_hold_addr[0] = r.addr_processing.read();
wb_hold_addr[1] = r.addr_processing.read() + 2;
 
for (int i = 0; i < ILINE_TOTAL; i++) {
wb_l[i].hit = 0;
wb_l[i].hit_data = 0;
if (wb_req_addr[i](BUS_ADDR_WIDTH-1, 3) == r.iline[0].addr.read()) {
wb_l[i].hit[Hit_Line1] = w_req_ctrl_valid;
wb_l[i].hit_data = r.iline[0].data.read();
} else if (wb_req_addr[i](BUS_ADDR_WIDTH-1, 3) ==
r.iline[1].addr.read()) {
wb_l[i].hit[Hit_Line2] = w_req_ctrl_valid;
wb_l[i].hit_data = r.iline[1].data.read();
} else if (wb_req_addr[i](BUS_ADDR_WIDTH-1, 3) ==
r.iline_addr_req.read()(BUS_ADDR_WIDTH-1, 3)) {
wb_l[i].hit[Hit_Response] = i_resp_mem_data_valid.read();
wb_l[i].hit_data = i_resp_mem_data.read();
}
 
wb_l[i].hit_hold = 0;
wb_l[i].hold_data = 0;
if (wb_hold_addr[i](BUS_ADDR_WIDTH-1, 3) == r.iline[0].addr.read()) {
wb_l[i].hit_hold[Hit_Line1] = 1;
wb_l[i].hold_data = r.iline[0].data.read();
} else if (wb_hold_addr[i](BUS_ADDR_WIDTH-1, 3) ==
r.iline[1].addr.read()) {
wb_l[i].hit_hold[Hit_Line2] = 1;
wb_l[i].hold_data = r.iline[1].data.read();
} else if (wb_hold_addr[i](BUS_ADDR_WIDTH-1, 3) ==
r.iline_addr_req.read()(BUS_ADDR_WIDTH-1, 3)) {
wb_l[i].hold_data = i_resp_mem_data.read();
}
}
w_hit = w_hit_req || w_hit_line;
 
w_o_req_mem_valid = !w_hit & i_req_ctrl_valid.read();
wb_o_req_mem_addr = i_req_ctrl_addr.read()(BUS_ADDR_WIDTH-1, 3) << 3;
w_o_req_ctrl_ready = w_hit | i_req_mem_ready.read();
w_req_fire = i_req_ctrl_valid.read() && w_o_req_ctrl_ready;
wb_hit_word = 0;
w_need_mem_req = 1;
if (wb_l[0].hit != 0 && wb_l[1].hit != 0) {
w_need_mem_req = 0;
}
switch (r.addr_processing.read()(2, 1)) {
case 0:
wb_hit_word = wb_l[0].hold_data(31, 0);
break;
case 1:
wb_hit_word = wb_l[0].hold_data(47, 16);
break;
case 2:
wb_hit_word = wb_l[0].hold_data(63, 32);
break;
default:
wb_hit_word = (wb_l[1].hold_data(15, 0) << 16)
| wb_l[0].hold_data(63, 48);
}
 
if (w_req_ctrl_valid && !w_need_mem_req) {
v.delay_valid = 1;
switch (i_req_ctrl_addr.read()(2, 1)) {
case 0:
v.delay_data = wb_l[0].hit_data(31, 0);
break;
case 1:
v.delay_data = wb_l[0].hit_data(47, 16);
break;
case 2:
v.delay_data = wb_l[0].hit_data(63, 32);
break;
default:
v.delay_data = (wb_l[1].hit_data(15, 0) << 16)
| wb_l[0].hit_data(63, 48);
}
} else if (i_resp_ctrl_ready.read()) {
v.delay_valid = 0;
v.delay_data = 0;
}
 
w_o_req_mem_valid = w_need_mem_req & w_req_ctrl_valid;
if (r.double_req.read()) {
if ((r.addr_processing.read()(BUS_ADDR_WIDTH-1, 3) ==
r.iline_addr_req.read()(BUS_ADDR_WIDTH-1, 3))
|| (r.addr_processing.read()(BUS_ADDR_WIDTH-1, 3) ==
wb_hold_addr[0](BUS_ADDR_WIDTH-1, 3))
) {
wb_o_req_mem_addr = wb_hold_addr[1](BUS_ADDR_WIDTH-1, 3) << 3;
} else {
wb_o_req_mem_addr = wb_hold_addr[0](BUS_ADDR_WIDTH-1, 3) << 3;
}
} else if (wb_l[0].hit == 0) {
wb_o_req_mem_addr = wb_req_addr[0](BUS_ADDR_WIDTH-1, 3) << 3;
} else {
wb_o_req_mem_addr = wb_req_addr[1](BUS_ADDR_WIDTH-1, 3) << 3;
}
 
w_o_req_ctrl_ready = !w_need_mem_req
| (i_req_mem_ready.read() & !w_wait_response);
w_req_fire = w_req_ctrl_valid && w_o_req_ctrl_ready;
 
if ((w_o_req_mem_valid && i_req_mem_ready.read() && !w_wait_response)
|| r.double_req.read()) {
v.iline_addr_req = wb_o_req_mem_addr;
}
 
switch (r.state.read()) {
case State_Idle:
if (i_req_ctrl_valid.read()) {
if (w_hit_line) {
if (w_req_ctrl_valid) {
if (!w_need_mem_req) {
v.state = State_WaitAccept;
} else if (i_req_mem_ready.read()) {
v.state = State_WaitResp;
106,7 → 220,7
case State_WaitGrant:
if (i_req_mem_ready.read()) {
v.state = State_WaitResp;
} else if (w_hit) {
} else if (!w_need_mem_req) {
/** Fetcher can change request address while request wasn't
* accepteed. */
v.state = State_WaitAccept;
116,11 → 230,11
if (i_resp_mem_data_valid.read()) {
if (!i_resp_ctrl_ready.read()) {
v.state = State_WaitAccept;
} else if (!i_req_ctrl_valid.read()) {
} else if (!w_req_ctrl_valid) {
v.state = State_Idle;
} else {
// New request
if (w_hit) {
if (!w_need_mem_req) {
v.state = State_WaitAccept;
} else if (i_req_mem_ready.read()) {
v.state = State_WaitResp;
132,10 → 246,10
break;
case State_WaitAccept:
if (i_resp_ctrl_ready.read()) {
if (!i_req_ctrl_valid.read()) {
if (!w_req_ctrl_valid) {
v.state = State_Idle;
} else {
if (w_hit) {
if (!w_need_mem_req) {
v.state = State_WaitAccept;
} else if (i_req_mem_ready.read()) {
v.state = State_WaitResp;
149,54 → 263,69
}
 
if (w_req_fire) {
v.iline_addr_req = i_req_ctrl_addr;
v.hit_line = 0;
if (w_hit_line) {
v.hit_line = 1;
v.iline_addr_hit = i_req_ctrl_addr;
if (i_req_ctrl_addr.read()[2] == 0) {
v.iline_data_hit = r.iline_data.read()(31, 0);
} else {
v.iline_data_hit = r.iline_data.read()(63, 32);
}
v.double_req = 0;
if (i_req_ctrl_addr.read()(2, 1) == 0x3
&& wb_l[0].hit == 0 && wb_l[1].hit == 0
&& r.double_req.read() == 0) {
v.double_req = 1;
}
if (!r.double_req.read()) {
v.addr_processing = i_req_ctrl_addr;
}
}
 
w_reuse_lastline = 0;
 
if (i_resp_mem_data_valid.read()) {
v.iline_addr = r.iline_addr_req.read()(BUS_ADDR_WIDTH-1, 3);
v.iline_data = i_resp_mem_data;
}
 
wb_o_resp_addr = r.iline_addr_req;
if (r.state.read() == State_WaitAccept) {
w_o_resp_valid = 1;
if (r.hit_line) {
wb_o_resp_addr = r.iline_addr_hit;
wb_o_resp_data = r.iline_data_hit;
/** Condition to avoid removing the last line:
*/
if (i_resp_ctrl_ready.read()) {
if ((wb_l[0].hit[Hit_Line2] || wb_l[1].hit[Hit_Line2]) == 1
&& r.iline[1].addr.read()
!= i_req_ctrl_addr.read()(BUS_ADDR_WIDTH-1, 3)) {
w_reuse_lastline = w_need_mem_req;
}
} else {
if (r.iline_addr_req.read()[2] == 0) {
wb_o_resp_data = r.iline_data.read()(31, 0);
} else {
wb_o_resp_data = r.iline_data.read()(63, 32);
if ((wb_l[0].hit_hold[Hit_Line2] || wb_l[1].hit_hold[Hit_Line2]) == 1
&& (wb_l[0].hit_hold[Hit_Line1] || wb_l[1].hit_hold[Hit_Line1]) == 0
&& r.iline[1].addr.read()
!= r.iline_addr_req.read()(BUS_ADDR_WIDTH-1, 3)) {
w_reuse_lastline = 1;
}
}
} else {
w_o_resp_valid = i_resp_mem_data_valid;
if (r.iline_addr_req.read()[2] == 0) {
wb_o_resp_data = i_resp_mem_data.read()(31, 0);
} else {
wb_o_resp_data = i_resp_mem_data.read()(63, 32);
if (!w_reuse_lastline) {
v.iline[1].addr = r.iline[0].addr;
v.iline[1].data = r.iline[0].data;
}
v.iline[0].addr = r.iline_addr_req.read()(BUS_ADDR_WIDTH-1, 3);
v.iline[0].data = i_resp_mem_data;
}
 
if (r.state.read() == State_WaitAccept) {
w_o_resp_valid = !r.double_req.read();
} else {
w_o_resp_valid = i_resp_mem_data_valid && !r.double_req.read();
}
if (r.delay_valid.read()) {
wb_o_resp_data = r.delay_data.read();
} else {
wb_o_resp_data = wb_hit_word;
}
wb_o_resp_addr = r.addr_processing;
 
 
if (!i_nrst.read()) {
v.iline[0].addr = ~0;
v.iline[0].data = 0;
v.iline[1].addr = ~0;
v.iline[1].data = 0;
v.iline_addr_req = 0;
v.iline_addr = ~0;
v.iline_data = 0;
v.iline_addr_hit = ~0;
v.iline_data_hit = 0;
v.hit_line = 0;
v.addr_processing = 0;
v.state = State_Idle;
v.double_req = 0;
v.delay_valid = 0;
v.delay_data = 0;
}
 
o_req_ctrl_ready = w_o_req_ctrl_ready;
/cache/icache.h
1,8 → 1,17
/**
* @file
* @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Instruction Cache.
/*
* Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* 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.
*/
 
#ifndef __DEBUGGER_RIVERLIB_ICACHE_H__
53,19 → 62,39
State_WaitResp,
State_WaitAccept
};
enum EHit {
Hit_Line1,
Hit_Line2,
Hit_Response,
Hit_Total
};
static const int ILINE_TOTAL = 2;
 
struct line_type {
sc_signal<sc_uint<BUS_ADDR_WIDTH - 3>> addr;
sc_signal<sc_uint<BUS_DATA_WIDTH>> data;
};
struct line_signal_type {
sc_bv<ILINE_TOTAL + 1> hit; // Hit_Total = ILINE_TOTAL + 1
sc_bv<ILINE_TOTAL> hit_hold;
sc_uint<BUS_DATA_WIDTH> hit_data;
sc_uint<BUS_DATA_WIDTH> hold_data;
};
 
struct RegistersType {
sc_signal<sc_uint<BUS_ADDR_WIDTH - 3>> iline_addr;
sc_signal<sc_uint<BUS_DATA_WIDTH>> iline_data;
line_type iline[ILINE_TOTAL];
sc_signal<sc_uint<BUS_ADDR_WIDTH>> iline_addr_req;
sc_signal<sc_uint<32>> iline_data_hit;
sc_signal<sc_uint<BUS_ADDR_WIDTH>> iline_addr_hit;
sc_signal<sc_uint<BUS_ADDR_WIDTH>> addr_processing;
sc_signal<sc_uint<2>> state;
sc_signal<bool> hit_line;
sc_signal<bool> double_req; // request 2-lines
sc_signal<bool> delay_valid;
sc_signal<sc_uint<32>> delay_data;
} v, r;
bool w_hit_req;
bool w_hit_line;
bool w_hit;
bool w_need_mem_req;
sc_uint<32> wb_hit_word;
line_signal_type wb_l[ILINE_TOTAL];
bool w_reuse_lastline;
bool w_wait_response;
};
 
 
/core/br_predic.cpp
1,9 → 1,17
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Branch Predictor.
* @details This module gives about 5% of performance improvement (CPI)
/*
* Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* 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 "br_predic.h"
21,6 → 29,8
sensitive << i_e_npc;
sensitive << i_ra;
sensitive << r.npc;
sensitive << r.resp_mem_data;
sensitive << r.resp_mem_addr;
 
SC_METHOD(registers);
sensitive << i_clk.pos();
38,52 → 48,57
 
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.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() {
v = r;
sc_uint<BUS_ADDR_WIDTH> wb_jal_off;
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_f_predic_miss.read()) {
wb_npc = i_e_npc.read() + 4;
} else {
wb_npc = r.npc.read() + 4;
if (i_resp_mem_valid.read()) {
v.resp_mem_addr = i_resp_mem_addr.read();
v.resp_mem_data = i_resp_mem_data.read();
}
wb_tmp = r.resp_mem_data.read();
wb_npc = r.npc.read();
 
 
if (wb_tmp[31]) {
wb_off(BUS_ADDR_WIDTH-1, 20) = ~0;
wb_jal_off(BUS_ADDR_WIDTH-1, 20) = ~0;
} 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_off[11] = wb_tmp[20];
wb_off(10, 1) = wb_tmp(30, 21);
wb_off[0] = 0;
wb_jal_off(19, 12) = wb_tmp(19, 12);
wb_jal_off[11] = wb_tmp[20];
wb_jal_off(10, 1) = wb_tmp(30, 21);
wb_jal_off[0] = 0;
 
if (i_resp_mem_valid.read()) {
if (wb_tmp == 0x00008067) {
// ret pseudo-instruction: Dhry score 34816 -> 35136
v.npc = i_ra.read()(BUS_ADDR_WIDTH-1, 0);
} else if (wb_tmp(6, 0) == 0x6f) {
// jal instruction: Dhry score 35136 -> 36992
v.npc = i_resp_mem_addr.read() + wb_off;
} else if (i_req_mem_fire.read()) {
v.npc = wb_npc;
}
} else if (i_req_mem_fire.read()) {
if (i_f_predic_miss.read()) {
wb_npc = i_e_npc.read();
} else if (wb_tmp == 0x00008067) {
// ret32 pseudo-instruction:
wb_npc = i_ra.read()(BUS_ADDR_WIDTH-1, 0);
//} else if (wb_tmp(6, 0) == 0x6f) {
// jal instruction: Dhry score 35136 -> 36992
//wb_npc = r.resp_mem_addr.read() + wb_jal_off;
} else {
wb_npc = r.npc.read() + 2;
}
if (i_req_mem_fire.read()) {
v.npc = wb_npc;
}
 
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() {
/core/br_predic.h
1,8 → 1,17
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief Branch predictor.
/*
* Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* 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.
*/
 
#ifndef __DEBUGGER_RIVERLIB_BR_PREDIC_H__
37,8 → 46,10
private:
struct RegistersType {
sc_signal<sc_uint<BUS_ADDR_WIDTH>> npc;
sc_signal<sc_uint<BUS_ADDR_WIDTH>> resp_mem_addr;
sc_signal<sc_uint<32>> resp_mem_data;
} v, r;
sc_signal<sc_uint<BUS_ADDR_WIDTH>> wb_npc;
sc_uint<BUS_ADDR_WIDTH> wb_npc;
};
 
 
/core/csr.cpp
1,97 → 1,107
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief CSR registers module.
*/
 
#include "csr.h"
#include "riscv-isa.h"
 
namespace debugger {
 
CsrRegs::CsrRegs(sc_module_name name_) : sc_module(name_) {
SC_METHOD(comb);
sensitive << i_nrst;
sensitive << i_xret;
sensitive << i_addr;
sensitive << i_wena;
sensitive << i_wdata;
sensitive << i_break_mode;
sensitive << i_breakpoint;
sensitive << i_trap_ena;
sensitive << i_trap_code;
sensitive << i_trap_pc;
sensitive << i_dport_ena;
sensitive << i_dport_write;
sensitive << i_dport_addr;
sensitive << i_dport_wdata;
sensitive << r.mtvec;
sensitive << r.mscratch;
sensitive << r.mbadaddr;
sensitive << r.mode;
sensitive << r.uie;
sensitive << r.mie;
sensitive << r.mpie;
sensitive << r.mpp;
sensitive << r.mepc;
sensitive << r.trap_irq;
sensitive << r.trap_code;
 
SC_METHOD(registers);
sensitive << i_clk.pos();
};
 
void CsrRegs::generateVCD(sc_trace_file *i_vcd, sc_trace_file *o_vcd) {
if (o_vcd) {
sc_trace(o_vcd, i_xret, "/top/proc0/csr0/i_xret");
sc_trace(o_vcd, i_addr, "/top/proc0/csr0/i_addr");
sc_trace(o_vcd, i_wena, "/top/proc0/csr0/i_wena");
sc_trace(o_vcd, i_wdata, "/top/proc0/csr0/i_wdata");
sc_trace(o_vcd, i_trap_ena, "/top/proc0/csr0/i_trap_ena");
sc_trace(o_vcd, i_trap_code, "/top/proc0/csr0/i_trap_code");
sc_trace(o_vcd, i_trap_pc, "/top/proc0/csr0/i_trap_pc");
sc_trace(o_vcd, o_mode, "/top/proc0/csr0/o_mode");
sc_trace(o_vcd, o_ie, "/top/proc0/csr0/o_ie");
sc_trace(o_vcd, o_rdata, "/top/proc0/csr0/o_rdata");
sc_trace(o_vcd, o_mtvec, "/top/proc0/csr0/o_mtvec");
sc_trace(o_vcd, i_dport_ena, "/top/proc0/csr0/i_dport_ena");
sc_trace(o_vcd, i_dport_write, "/top/proc0/csr0/i_dport_write");
sc_trace(o_vcd, i_dport_addr, "/top/proc0/csr0/i_dport_addr");
sc_trace(o_vcd, i_dport_wdata, "/top/proc0/csr0/i_dport_wdata");
sc_trace(o_vcd, o_dport_rdata, "/top/proc0/csr0/o_dport_rdata");
}
}
 
void CsrRegs::procedure_RegAccess(uint64_t iaddr, bool iwena,
sc_uint<RISCV_ARCH> iwdata,
RegistersType &ir, RegistersType *ov,
sc_uint<RISCV_ARCH> *ordata) {
*ordata = 0;
switch (iaddr) {
case CSR_misa:
/** Base[XLEN-1:XLEN-2]
* 1 = 32
* 2 = 64
* 3 = 128
*/
(*ordata)(RISCV_ARCH-1, RISCV_ARCH-2) = 2;
+/* + * Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 "csr.h" +#include "riscv-isa.h" + +namespace debugger { + +CsrRegs::CsrRegs(sc_module_name name_) : sc_module(name_) { + SC_METHOD(comb); + sensitive << i_nrst; + sensitive << i_xret; + sensitive << i_addr; + sensitive << i_wena; + sensitive << i_wdata; + sensitive << i_break_mode; + sensitive << i_breakpoint; + sensitive << i_trap_ena; + sensitive << i_trap_code; + sensitive << i_trap_pc; + sensitive << i_dport_ena; + sensitive << i_dport_write; + sensitive << i_dport_addr; + sensitive << i_dport_wdata; + sensitive << r.mtvec; + sensitive << r.mscratch; + sensitive << r.mbadaddr; + sensitive << r.mode; + sensitive << r.uie; + sensitive << r.mie; + sensitive << r.mpie; + sensitive << r.mpp; + sensitive << r.mepc; + sensitive << r.trap_irq; + sensitive << r.trap_code; + + SC_METHOD(registers); + sensitive << i_clk.pos(); +}; + +void CsrRegs::generateVCD(sc_trace_file *i_vcd, sc_trace_file *o_vcd) { + if (o_vcd) { + sc_trace(o_vcd, i_xret, "/top/proc0/csr0/i_xret"); + sc_trace(o_vcd, i_addr, "/top/proc0/csr0/i_addr"); + sc_trace(o_vcd, i_wena, "/top/proc0/csr0/i_wena"); + sc_trace(o_vcd, i_wdata, "/top/proc0/csr0/i_wdata"); + sc_trace(o_vcd, i_trap_ena, "/top/proc0/csr0/i_trap_ena"); + sc_trace(o_vcd, i_trap_code, "/top/proc0/csr0/i_trap_code"); + sc_trace(o_vcd, i_trap_pc, "/top/proc0/csr0/i_trap_pc"); + sc_trace(o_vcd, o_mode, "/top/proc0/csr0/o_mode"); + sc_trace(o_vcd, o_ie, "/top/proc0/csr0/o_ie"); + sc_trace(o_vcd, o_rdata, "/top/proc0/csr0/o_rdata"); + sc_trace(o_vcd, o_mtvec, "/top/proc0/csr0/o_mtvec"); + sc_trace(o_vcd, i_dport_ena, "/top/proc0/csr0/i_dport_ena"); + sc_trace(o_vcd, i_dport_write, "/top/proc0/csr0/i_dport_write"); + sc_trace(o_vcd, i_dport_addr, "/top/proc0/csr0/i_dport_addr"); + sc_trace(o_vcd, i_dport_wdata, "/top/proc0/csr0/i_dport_wdata"); + sc_trace(o_vcd, o_dport_rdata, "/top/proc0/csr0/o_dport_rdata"); + } +} + +void CsrRegs::procedure_RegAccess(uint64_t iaddr, bool iwena, + sc_uint iwdata, + RegistersType &ir, RegistersType *ov, + sc_uint *ordata) { + *ordata = 0; + switch (iaddr) { + case CSR_misa: + /** Base[XLEN-1:XLEN-2] + * 1 = 32 + * 2 = 64 + * 3 = 128 + */ + (*ordata)(RISCV_ARCH-1, RISCV_ARCH-2) = 2; + /** BitCharacterDescription + * 0 A Atomic extension + * 1 B Tentatively reserved for Bit operations extension + * 2 C Compressed extension + * 3 D Double-precision Foating-point extension + * 4 E RV32E base ISA (embedded) + * 5 F Single-precision Foating-point extension + * 6 G Additional standard extensions present + * 7 H Hypervisor mode implemented + * 8 I RV32I/64I/128I base ISA + * 9 J Reserved + * 10 K Reserved + * 11 L Tentatively reserved for Decimal Floating-Point extension + * 12 M Integer Multiply/Divide extension + * 13 N User-level interrupts supported + * 14 O Reserved + * 15 P Tentatively reserved for Packed-SIMD extension * 16 Q Quad-precision Foating-point extension * 17 R Reserved * 18 S Supervisor mode implemented @@ -103,148 +113,149 @@ * 24 Y Reserved * 25 Z Reserve */ - //(*ordata)['A' - 'A'] = 1; - (*ordata)['I' - 'A'] = 1; - (*ordata)['M' - 'A'] = 1; - (*ordata)['U' - 'A'] = 1; - break; - case CSR_mvendorid: - break; - case CSR_marchid: - break; - case CSR_mimplementationid: - break; - case CSR_mhartid: - break; - case CSR_uepc:// - User mode program counter - break; - case CSR_mstatus:// - Machine mode status register - (*ordata)[0] = ir.uie; - (*ordata)[3] = ir.mie; - (*ordata)[7] = ir.mpie; - (*ordata)(12, 11) = ir.mpp; - if (iwena) { - ov->uie = iwdata[0]; - ov->mie = iwdata[3]; - ov->mpie = iwdata[7]; - ov->mpp = iwdata(12, 11); - } - break; - case CSR_medeleg:// - Machine exception delegation - break; - case CSR_mideleg:// - Machine itnerrupt delegation - break; - case CSR_mie:// - Machine interrupt enable bit - break; - case CSR_mtvec: - (*ordata) = ir.mtvec; - if (iwena) { - ov->mtvec = iwdata; - } - break; - case CSR_mtimecmp:// - Machine wall-clock timer compare value - break; - case CSR_mscratch:// - Machine scratch register - (*ordata) = ir.mscratch; - if (iwena) { - ov->mscratch = iwdata; - } - break; - case CSR_mepc:// - Machine program counter - (*ordata) = ir.mepc; - if (iwena) { - ov->mepc = iwdata; - } - break; - case CSR_mcause:// - Machine trap cause - (*ordata) = 0; - (*ordata)[63] = ir.trap_irq; - (*ordata)(3, 0) = ir.trap_code; - break; - case CSR_mbadaddr:// - Machine bad address - (*ordata) = ir.mbadaddr; - break; - case CSR_mip:// - Machine interrupt pending - break; - default:; - } - -} - -void CsrRegs::comb() { - sc_uint wb_rdata = 0; - sc_uint wb_dport_rdata = 0; - bool w_ie; - bool w_dport_wena; - - v = r; - - w_dport_wena = i_dport_ena & i_dport_write; - - procedure_RegAccess(i_addr.read(), i_wena.read(), i_wdata.read(), - r, &v, &wb_rdata); - - procedure_RegAccess(i_dport_addr.read(), w_dport_wena, - i_dport_wdata.read(), r, &v, &wb_dport_rdata); - - - if (i_addr.read() == CSR_mepc && i_xret.read()) { - // Switch to previous mode - v.mie = r.mpie; - v.mpie = 1; - v.mode = r.mpp; - v.mpp = PRV_U; - } - - if (i_trap_ena.read() && (i_break_mode.read() || !i_breakpoint.read())) { - v.mie = 0; - v.mpp = r.mode; - v.mepc = i_trap_pc.read(); - v.mbadaddr = i_trap_pc.read(); - v.trap_code = i_trap_code.read()(3, 0); - v.trap_irq = i_trap_code.read()[4]; - v.mode = PRV_M; - switch (r.mode.read()) { - case PRV_U: - v.mpie = r.uie; - break; - case PRV_M: - v.mpie = r.mie; - break; - default:; - } - } - - w_ie = 0; - if ((r.mode.read() != PRV_M) || r.mie.read()) { - w_ie = 1; - } - - if (!i_nrst.read()) { - v.mtvec = 0; - v.mscratch = 0; - v.mbadaddr = 0; - v.mode = PRV_M; - v.uie = 0; - v.mie = 0; - v.mpie = 0; - v.mpp = 0; - v.mepc = 0; - v.trap_code = 0; - v.trap_irq = 0; - } - - - o_rdata = wb_rdata; - o_ie = w_ie; - o_mode = r.mode; - o_mtvec = r.mtvec.read()(BUS_ADDR_WIDTH - 1, 0); - o_dport_rdata = wb_dport_rdata; -} - -void CsrRegs::registers() { - r = v; -} - -} // namespace debugger - + //(*ordata)['A' - 'A'] = 1; + (*ordata)['I' - 'A'] = 1; + (*ordata)['M' - 'A'] = 1; + (*ordata)['U' - 'A'] = 1; + (*ordata)['C' - 'A'] = 1; + break; + case CSR_mvendorid: + break; + case CSR_marchid: + break; + case CSR_mimplementationid: + break; + case CSR_mhartid: + break; + case CSR_uepc:// - User mode program counter + break; + case CSR_mstatus:// - Machine mode status register + (*ordata)[0] = ir.uie; + (*ordata)[3] = ir.mie; + (*ordata)[7] = ir.mpie; + (*ordata)(12, 11) = ir.mpp; + if (iwena) { + ov->uie = iwdata[0]; + ov->mie = iwdata[3]; + ov->mpie = iwdata[7]; + ov->mpp = iwdata(12, 11); + } + break; + case CSR_medeleg:// - Machine exception delegation + break; + case CSR_mideleg:// - Machine itnerrupt delegation + break; + case CSR_mie:// - Machine interrupt enable bit + break; + case CSR_mtvec: + (*ordata) = ir.mtvec; + if (iwena) { + ov->mtvec = iwdata; + } + break; + case CSR_mtimecmp:// - Machine wall-clock timer compare value + break; + case CSR_mscratch:// - Machine scratch register + (*ordata) = ir.mscratch; + if (iwena) { + ov->mscratch = iwdata; + } + break; + case CSR_mepc:// - Machine program counter + (*ordata) = ir.mepc; + if (iwena) { + ov->mepc = iwdata; + } + break; + case CSR_mcause:// - Machine trap cause + (*ordata) = 0; + (*ordata)[63] = ir.trap_irq; + (*ordata)(3, 0) = ir.trap_code; + break; + case CSR_mbadaddr:// - Machine bad address + (*ordata) = ir.mbadaddr; + break; + case CSR_mip:// - Machine interrupt pending + break; + default:; + } + +} + +void CsrRegs::comb() { + sc_uint wb_rdata = 0; + sc_uint wb_dport_rdata = 0; + bool w_ie; + bool w_dport_wena; + + v = r; + + w_dport_wena = i_dport_ena & i_dport_write; + + procedure_RegAccess(i_addr.read(), i_wena.read(), i_wdata.read(), + r, &v, &wb_rdata); + + procedure_RegAccess(i_dport_addr.read(), w_dport_wena, + i_dport_wdata.read(), r, &v, &wb_dport_rdata); + + + if (i_addr.read() == CSR_mepc && i_xret.read()) { + // Switch to previous mode + v.mie = r.mpie; + v.mpie = 1; + v.mode = r.mpp; + v.mpp = PRV_U; + } + + if (i_trap_ena.read() && (i_break_mode.read() || !i_breakpoint.read())) { + v.mie = 0; + v.mpp = r.mode; + v.mepc = i_trap_pc.read(); + v.mbadaddr = i_trap_pc.read(); + v.trap_code = i_trap_code.read()(3, 0); + v.trap_irq = i_trap_code.read()[4]; + v.mode = PRV_M; + switch (r.mode.read()) { + case PRV_U: + v.mpie = r.uie; + break; + case PRV_M: + v.mpie = r.mie; + break; + default:; + } + } + + w_ie = 0; + if ((r.mode.read() != PRV_M) || r.mie.read()) { + w_ie = 1; + } + + if (!i_nrst.read()) { + v.mtvec = 0; + v.mscratch = 0; + v.mbadaddr = 0; + v.mode = PRV_M; + v.uie = 0; + v.mie = 0; + v.mpie = 0; + v.mpp = 0; + v.mepc = 0; + v.trap_code = 0; + v.trap_irq = 0; + } + + + o_rdata = wb_rdata; + o_ie = w_ie; + o_mode = r.mode; + o_mtvec = r.mtvec.read()(BUS_ADDR_WIDTH - 1, 0); + o_dport_rdata = wb_dport_rdata; +} + +void CsrRegs::registers() { + r = v; +} + +} // namespace debugger +
/core/csr.h
1,8 → 1,17
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief CSR registers module.
/*
* Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* 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.
*/
 
#ifndef __DEBUGGER_RIVERLIB_CSR_H__
/core/decoder.cpp
35,6 → 35,7
sc_trace(o_vcd, o_isa_type, "/top/proc0/dec0/o_isa_type");
sc_trace(o_vcd, o_instr_vec, "/top/proc0/dec0/o_instr_vec");
sc_trace(o_vcd, o_exception, "/top/proc0/dec0/o_exception");
sc_trace(o_vcd, o_compressed, "/top/proc0/dec0/o_compressed");
}
}
 
43,352 → 44,617
 
bool w_o_valid;
bool w_error = false;
bool w_compressed = false;
sc_uint<32> wb_instr = i_f_instr.read();
sc_uint<5> wb_opcode1 = wb_instr(6, 2);
sc_uint<3> wb_opcode2 = wb_instr(14, 12);
sc_uint<32> wb_instr_out;
sc_uint<5> wb_opcode1;
sc_uint<3> wb_opcode2;
sc_bv<Instr_Total> wb_dec = 0;
sc_bv<ISA_Total> wb_isa_type = 0;
 
if (wb_instr(1, 0) != 0x3) {
w_error = true;
}
 
switch (wb_opcode1) {
case OPCODE_ADD:
wb_isa_type[ISA_R_type] = 1;
switch (wb_opcode2) {
case 0:
if (wb_instr(31, 25) == 0x00) {
wb_dec[Instr_ADD] = 1;
} else if (wb_instr(31, 25) == 0x01) {
wb_dec[Instr_MUL] = 1;
} else if (wb_instr(31, 25) == 0x20) {
wb_dec[Instr_SUB] = 1;
} else {
w_error = true;
w_compressed = 1;
wb_opcode1 = (wb_instr(15, 13), wb_instr(1, 0));
wb_instr_out = 0x00000003;
switch (wb_opcode1) {
case OPCODE_C_ADDI4SPN:
wb_isa_type[ISA_I_type] = 1;
wb_dec[Instr_ADDI] = 1;
wb_instr_out(11, 7) = 0x8 | wb_instr(4, 2); // rd
wb_instr_out(19, 15) = 0x2; // rs1 = sp
wb_instr_out(29, 22) =
(wb_instr(10, 7), wb_instr(12, 11), wb_instr[5], wb_instr[6]);
break;
case OPCODE_C_NOP_ADDI:
wb_isa_type[ISA_I_type] = 1;
wb_dec[Instr_ADDI] = 1;
wb_instr_out(11, 7) = wb_instr(11, 7); // rd
wb_instr_out(19, 15) = wb_instr(11, 7); // rs1
wb_instr_out(24, 20) = wb_instr(6, 2); // imm
if (wb_instr[12]) {
wb_instr_out(31, 25) = ~0;
}
break;
case 0x1:
wb_dec[Instr_SLL] = 1;
case OPCODE_C_SLLI:
wb_isa_type[ISA_I_type] = 1;
wb_dec[Instr_SLLI] = 1;
wb_instr_out(11, 7) = wb_instr(11, 7); // rd
wb_instr_out(19, 15) = wb_instr(11, 7); // rs1
wb_instr_out(25, 20) = (wb_instr[12], wb_instr(6, 2)); // shamt
break;
case 0x2:
wb_dec[Instr_SLT] = 1;
case OPCODE_C_JAL_ADDIW:
// JAL is the RV32C only instruction
wb_isa_type[ISA_I_type] = 1;
wb_dec[Instr_ADDIW] = 1;
wb_instr_out(11, 7) = wb_instr(11, 7); // rd
wb_instr_out(19, 15) = wb_instr(11, 7); // rs1
wb_instr_out(24, 20) = wb_instr(6, 2); // imm
if (wb_instr[12]) {
wb_instr_out(31, 25) = ~0;
}
break;
case 0x3:
wb_dec[Instr_SLTU] = 1;
case OPCODE_C_LW:
wb_isa_type[ISA_I_type] = 1;
wb_dec[Instr_LW] = 1;
wb_instr_out(11, 7) = 0x8 | wb_instr(4, 2); // rd
wb_instr_out(19, 15) = 0x8 | wb_instr(9, 7); // rs1
wb_instr_out(26, 22) =
(wb_instr[5], wb_instr(12, 10), wb_instr[6]);
break;
case 0x4:
if (wb_instr(31, 25) == 0x00) {
wb_dec[Instr_XOR] = 1;
} else if (wb_instr(31, 25) == 0x01) {
wb_dec[Instr_DIV] = 1;
} else {
w_error = true;
case OPCODE_C_LI: // ADDI rd = r0 + imm
wb_isa_type[ISA_I_type] = 1;
wb_dec[Instr_ADDI] = 1;
wb_instr_out(11, 7) = wb_instr(11, 7); // rd
wb_instr_out(24, 20) = wb_instr(6, 2); // imm
if (wb_instr[12]) {
wb_instr_out(31, 25) = ~0;
}
break;
case 0x5:
if (wb_instr(31, 25) == 0x00) {
wb_dec[Instr_SRL] = 1;
} else if (wb_instr(31, 25) == 0x01) {
wb_dec[Instr_DIVU] = 1;
} else if (wb_instr(31, 25) == 0x20) {
wb_dec[Instr_SRA] = 1;
case OPCODE_C_LWSP:
wb_isa_type[ISA_I_type] = 1;
wb_dec[Instr_LW] = 1;
wb_instr_out(11, 7) = wb_instr(11, 7); // rd
wb_instr_out(19, 15) = 0x2; // rs1 = sp
wb_instr_out(27, 22) =
(wb_instr(3, 2), wb_instr[12], wb_instr(6, 4));
break;
case OPCODE_C_LD:
wb_isa_type[ISA_I_type] = 1;
wb_dec[Instr_LD] = 1;
wb_instr_out(11, 7) = 0x8 | wb_instr(4, 2); // rd
wb_instr_out(19, 15) = 0x8 | wb_instr(9, 7); // rs1
wb_instr_out(27, 23) =
(wb_instr[6], wb_instr[5], wb_instr(12, 10));
break;
case OPCODE_C_ADDI16SP_LUI:
if (wb_instr(11, 7) == 0x2) {
wb_isa_type[ISA_I_type] = 1;
wb_dec[Instr_ADDI] = 1;
wb_instr_out(11, 7) = 0x2; // rd = sp
wb_instr_out(19, 15) = 0x2; // rs1 = sp
wb_instr_out(28, 24) =
(wb_instr(4, 3), wb_instr[5], wb_instr[2], wb_instr[6]);
if (wb_instr[12]) {
wb_instr_out(31, 29) = ~0;
}
} else {
w_error = true;
wb_isa_type[ISA_U_type] = 1;
wb_dec[Instr_LUI] = 1;
wb_instr_out(11, 7) = wb_instr(11, 7); // rd
wb_instr_out(16, 12) = wb_instr(6, 2);
if (wb_instr[12]) {
wb_instr_out(31, 17) = ~0;
}
}
break;
case 0x6:
if (wb_instr(31, 25) == 0x00) {
wb_dec[Instr_OR] = 1;
} else if (wb_instr(31, 25) == 0x01) {
wb_dec[Instr_REM] = 1;
case OPCODE_C_LDSP:
wb_isa_type[ISA_I_type] = 1;
wb_dec[Instr_LD] = 1;
wb_instr_out(11, 7) = wb_instr(11, 7); // rd
wb_instr_out(19, 15) = 0x2; // rs1 = sp
wb_instr_out(28, 23) =
(wb_instr(4, 2), wb_instr[12], wb_instr(6, 5));
break;
case OPCODE_C_MATH:
if (wb_instr(11, 10) == 0) {
wb_isa_type[ISA_I_type] = 1;
wb_dec[Instr_SRLI] = 1;
wb_instr_out(11, 7) = 0x8 | wb_instr(9, 7); // rd
wb_instr_out(19, 15) = 0x8 | wb_instr(9, 7); // rs1
wb_instr_out(25, 20) = (wb_instr[12], wb_instr(6, 2)); // shamt
} else if (wb_instr(11, 10) == 1) {
wb_isa_type[ISA_I_type] = 1;
wb_dec[Instr_SRAI] = 1;
wb_instr_out(11, 7) = 0x8 | wb_instr(9, 7); // rd
wb_instr_out(19, 15) = 0x8 | wb_instr(9, 7); // rs1
wb_instr_out(25, 20) = (wb_instr[12], wb_instr(6, 2)); // shamt
} else if (wb_instr(11, 10) == 2) {
wb_isa_type[ISA_I_type] = 1;
wb_dec[Instr_ANDI] = 1;
wb_instr_out(11, 7) = 0x8 | wb_instr(9, 7); // rd
wb_instr_out(19, 15) = 0x8 | wb_instr(9, 7); // rs1
wb_instr_out(24, 20) = wb_instr(6, 2); // imm
if (wb_instr[12]) {
wb_instr_out(31, 25) = ~0;
}
} else if (wb_instr[12] == 0) {
wb_isa_type[ISA_R_type] = 1;
wb_instr_out(11, 7) = 0x8 | wb_instr(9, 7); // rd
wb_instr_out(19, 15) = 0x8 | wb_instr(9, 7); // rs1
wb_instr_out(24, 20) = 0x8 | wb_instr(4, 2); // rs2
switch (wb_instr(6, 5)) {
case 0:
wb_dec[Instr_SUB] = 1;
break;
case 1:
wb_dec[Instr_XOR] = 1;
break;
case 2:
wb_dec[Instr_OR] = 1;
break;
default:
wb_dec[Instr_AND] = 1;
}
} else {
w_error = true;
wb_isa_type[ISA_R_type] = 1;
wb_instr_out(11, 7) = 0x8 | wb_instr(9, 7); // rd
wb_instr_out(19, 15) = 0x8 | wb_instr(9, 7); // rs1
wb_instr_out(24, 20) = 0x8 | wb_instr(4, 2); // rs2
switch (wb_instr(6, 5)) {
case 0:
wb_dec[Instr_SUBW] = 1;
break;
case 1:
wb_dec[Instr_ADDW] = 1;
break;
default:
w_error = true;
}
}
break;
case 0x7:
if (wb_instr(31, 25) == 0x00) {
wb_dec[Instr_AND] = 1;
} else if (wb_instr(31, 25) == 0x01) {
wb_dec[Instr_REMU] = 1;
case OPCODE_C_JR_MV_EBREAK_JALR_ADD:
wb_isa_type[ISA_I_type] = 1;
if (wb_instr[12] == 0) {
if (wb_instr(6, 2) == 0) {
wb_dec[Instr_JALR] = 1;
wb_instr_out(19, 15) = wb_instr(11, 7); // rs1
} else {
wb_dec[Instr_ADDI] = 1;
wb_instr_out(11, 7) = wb_instr(11, 7); // rd
wb_instr_out(19, 15) = wb_instr(6, 2); // rs1
}
} else {
w_error = true;
if (wb_instr(11, 7) == 0 && wb_instr(6, 2) == 0) {
wb_dec[Instr_EBREAK] = 1;
} else if (wb_instr(6, 2) == 0) {
wb_dec[Instr_JALR] = 1;
wb_instr_out(11, 7) = 0x1; // rd = ra
wb_instr_out(19, 15) = wb_instr(11, 7); // rs1
} else {
wb_dec[Instr_ADD] = 1;
wb_isa_type[ISA_R_type] = 1;
wb_instr_out(11, 7) = wb_instr(11, 7); // rd
wb_instr_out(19, 15) = wb_instr(11, 7); // rs1
wb_instr_out(24, 20) = wb_instr(6, 2); // rs2
}
}
break;
default:
w_error = true;
}
break;
case OPCODE_ADDI:
wb_isa_type[ISA_I_type] = 1;
switch (wb_opcode2) {
case 0:
wb_dec[Instr_ADDI] = 1;
case OPCODE_C_J: // JAL with rd = 0
wb_isa_type[ISA_UJ_type] = 1;
wb_dec[Instr_JAL] = 1;
wb_instr_out[20] = wb_instr[12]; // imm11
wb_instr_out(23, 21) = wb_instr(5, 3); // imm10_1(3:1)
wb_instr_out[24] = wb_instr[11]; // imm10_1(4)
wb_instr_out[25] = wb_instr[2]; // imm10_1(5)
wb_instr_out[26] = wb_instr[7]; // imm10_1(6)
wb_instr_out[27] = wb_instr[6]; // imm10_1(7)
wb_instr_out(29, 28) = wb_instr(10, 9); // imm10_1(9:8)
wb_instr_out[30] = wb_instr[8]; // imm10_1(10)
if (wb_instr[12]) {
wb_instr_out(19, 12) = ~0; // imm19_12
wb_instr_out[31] = 1; // imm20
}
break;
case 0x1:
wb_dec[Instr_SLLI] = 1;
case OPCODE_C_SW:
wb_isa_type[ISA_S_type] = 1;
wb_dec[Instr_SW] = 1;
wb_instr_out(24, 20) = 0x8 | wb_instr(4, 2); // rs2
wb_instr_out(19, 15) = 0x8 | wb_instr(9, 7); // rs1
wb_instr_out(11, 9) = (wb_instr(11, 10), wb_instr[6]);
wb_instr_out(26, 25) = (wb_instr[5] , wb_instr[12]);
break;
case 0x2:
wb_dec[Instr_SLTI] = 1;
case OPCODE_C_BEQZ:
wb_isa_type[ISA_SB_type] = 1;
wb_dec[Instr_BEQ] = 1;
wb_instr_out(19, 15) = 0x8 | wb_instr(9, 7); // rs1
wb_instr_out(11, 8) = (wb_instr(11, 10), wb_instr(4, 3));
wb_instr_out(27, 25) = (wb_instr(6, 5), wb_instr[2]);
if (wb_instr[12]) {
wb_instr_out(30, 28) = ~0;
wb_instr_out[7] = 1;
wb_instr_out[31] = 1;
}
break;
case 0x3:
wb_dec[Instr_SLTIU] = 1;
case OPCODE_C_SWSP:
wb_isa_type[ISA_S_type] = 1;
wb_dec[Instr_SW] = 1;
wb_instr_out(24, 20) = wb_instr(6, 2); // rs2
wb_instr_out(19, 15) = 0x2; // rs1 = sp
wb_instr_out(11, 9) = wb_instr(11, 9);
wb_instr_out(27, 25) = (wb_instr(8, 7), wb_instr[12]);
break;
case 0x4:
wb_dec[Instr_XORI] = 1;
case OPCODE_C_SD:
wb_isa_type[ISA_S_type] = 1;
wb_dec[Instr_SD] = 1;
wb_instr_out(24, 20) = 0x8 | wb_instr(4, 2); // rs2
wb_instr_out(19, 15) = 0x8 | wb_instr(9, 7); // rs1
wb_instr_out(11, 10) = wb_instr(11, 10);
wb_instr_out(27, 25) = (wb_instr(6, 5), wb_instr[12]);
break;
case 0x5:
if (wb_instr(31, 26) == 0x00) {
wb_dec[Instr_SRLI] = 1;
} else if (wb_instr(31, 26) == 0x10) {
wb_dec[Instr_SRAI] = 1;
} else {
w_error = true;
case OPCODE_C_BNEZ:
wb_isa_type[ISA_SB_type] = 1;
wb_dec[Instr_BNE] = 1;
wb_instr_out(19, 15) = 0x8 | wb_instr(9, 7); // rs1
wb_instr_out(11, 8) = (wb_instr(11, 10), wb_instr(4, 3));
wb_instr_out(27, 25) = (wb_instr(6, 5), wb_instr[2]);
if (wb_instr[12]) {
wb_instr_out(30, 28) = ~0;
wb_instr_out[7] = 1;
wb_instr_out[31] = 1;
}
break;
case 0x6:
wb_dec[Instr_ORI] = 1;
case OPCODE_C_SDSP:
wb_isa_type[ISA_S_type] = 1;
wb_dec[Instr_SD] = 1;
wb_instr_out(24, 20) = wb_instr(6, 2); // rs2
wb_instr_out(19, 15) = 0x2; // rs1 = sp
wb_instr_out(11, 10) = wb_instr(11, 10);
wb_instr_out(28, 25) = (wb_instr(9, 7), wb_instr[12]);
break;
case 7:
wb_dec[Instr_ANDI] = 1;
break;
default:
w_error = true;
}
break;
case OPCODE_ADDIW:
wb_isa_type[ISA_I_type] = 1;
switch (wb_opcode2) {
case 0:
wb_dec[Instr_ADDIW] = 1;
} else {
wb_opcode1 = wb_instr(6, 2);
wb_opcode2 = wb_instr(14, 12);
switch (wb_opcode1) {
case OPCODE_ADD:
wb_isa_type[ISA_R_type] = 1;
switch (wb_opcode2) {
case 0:
if (wb_instr(31, 25) == 0x00) {
wb_dec[Instr_ADD] = 1;
} else if (wb_instr(31, 25) == 0x01) {
wb_dec[Instr_MUL] = 1;
} else if (wb_instr(31, 25) == 0x20) {
wb_dec[Instr_SUB] = 1;
} else {
w_error = true;
}
break;
case 0x1:
wb_dec[Instr_SLL] = 1;
break;
case 0x2:
wb_dec[Instr_SLT] = 1;
break;
case 0x3:
wb_dec[Instr_SLTU] = 1;
break;
case 0x4:
if (wb_instr(31, 25) == 0x00) {
wb_dec[Instr_XOR] = 1;
} else if (wb_instr(31, 25) == 0x01) {
wb_dec[Instr_DIV] = 1;
} else {
w_error = true;
}
break;
case 0x5:
if (wb_instr(31, 25) == 0x00) {
wb_dec[Instr_SRL] = 1;
} else if (wb_instr(31, 25) == 0x01) {
wb_dec[Instr_DIVU] = 1;
} else if (wb_instr(31, 25) == 0x20) {
wb_dec[Instr_SRA] = 1;
} else {
w_error = true;
}
break;
case 0x6:
if (wb_instr(31, 25) == 0x00) {
wb_dec[Instr_OR] = 1;
} else if (wb_instr(31, 25) == 0x01) {
wb_dec[Instr_REM] = 1;
} else {
w_error = true;
}
break;
case 0x7:
if (wb_instr(31, 25) == 0x00) {
wb_dec[Instr_AND] = 1;
} else if (wb_instr(31, 25) == 0x01) {
wb_dec[Instr_REMU] = 1;
} else {
w_error = true;
}
break;
default:
w_error = true;
}
break;
case 0x1:
wb_dec[Instr_SLLIW] = 1;
case OPCODE_ADDI:
wb_isa_type[ISA_I_type] = 1;
switch (wb_opcode2) {
case 0:
wb_dec[Instr_ADDI] = 1;
break;
case 0x1:
wb_dec[Instr_SLLI] = 1;
break;
case 0x2:
wb_dec[Instr_SLTI] = 1;
break;
case 0x3:
wb_dec[Instr_SLTIU] = 1;
break;
case 0x4:
wb_dec[Instr_XORI] = 1;
break;
case 0x5:
if (wb_instr(31, 26) == 0x00) {
wb_dec[Instr_SRLI] = 1;
} else if (wb_instr(31, 26) == 0x10) {
wb_dec[Instr_SRAI] = 1;
} else {
w_error = true;
}
break;
case 0x6:
wb_dec[Instr_ORI] = 1;
break;
case 7:
wb_dec[Instr_ANDI] = 1;
break;
default:
w_error = true;
}
break;
case 0x5:
if (wb_instr(31, 25) == 0x00) {
wb_dec[Instr_SRLIW] = 1;
} else if (wb_instr(31, 25) == 0x20) {
wb_dec[Instr_SRAIW] = 1;
} else {
case OPCODE_ADDIW:
wb_isa_type[ISA_I_type] = 1;
switch (wb_opcode2) {
case 0:
wb_dec[Instr_ADDIW] = 1;
break;
case 0x1:
wb_dec[Instr_SLLIW] = 1;
break;
case 0x5:
if (wb_instr(31, 25) == 0x00) {
wb_dec[Instr_SRLIW] = 1;
} else if (wb_instr(31, 25) == 0x20) {
wb_dec[Instr_SRAIW] = 1;
} else {
w_error = true;
}
break;
default:
w_error = true;
}
break;
default:
w_error = true;
}
break;
case OPCODE_ADDW:
wb_isa_type[ISA_R_type] = 1;
switch (wb_opcode2) {
case 0:
if (wb_instr(31, 25) == 0x00) {
wb_dec[Instr_ADDW] = 1;
} else if (wb_instr(31, 25) == 0x01) {
wb_dec[Instr_MULW] = 1;
} else if (wb_instr(31, 25) == 0x20) {
wb_dec[Instr_SUBW] = 1;
} else {
case OPCODE_ADDW:
wb_isa_type[ISA_R_type] = 1;
switch (wb_opcode2) {
case 0:
if (wb_instr(31, 25) == 0x00) {
wb_dec[Instr_ADDW] = 1;
} else if (wb_instr(31, 25) == 0x01) {
wb_dec[Instr_MULW] = 1;
} else if (wb_instr(31, 25) == 0x20) {
wb_dec[Instr_SUBW] = 1;
} else {
w_error = true;
}
break;
case 0x1:
wb_dec[Instr_SLLW] = 1;
break;
case 0x4:
if (wb_instr(31, 25) == 0x01) {
wb_dec[Instr_DIVW] = 1;
} else {
w_error = true;
}
break;
case 0x5:
if (wb_instr(31, 25) == 0x00) {
wb_dec[Instr_SRLW] = 1;
} else if (wb_instr(31, 25) == 0x01) {
wb_dec[Instr_DIVUW] = 1;
} else if (wb_instr(31, 25) == 0x20) {
wb_dec[Instr_SRAW] = 1;
} else {
w_error = true;
}
break;
case 0x6:
if (wb_instr(31, 25) == 0x01) {
wb_dec[Instr_REMW] = 1;
} else {
w_error = true;
}
break;
case 0x7:
if (wb_instr(31, 25) == 0x01) {
wb_dec[Instr_REMUW] = 1;
} else {
w_error = true;
}
break;
default:
w_error = true;
}
break;
case 0x1:
wb_dec[Instr_SLLW] = 1;
case OPCODE_AUIPC:
wb_isa_type[ISA_U_type] = 1;
wb_dec[Instr_AUIPC] = 1;
break;
case 0x4:
if (wb_instr(31, 25) == 0x01) {
wb_dec[Instr_DIVW] = 1;
} else {
case OPCODE_BEQ:
wb_isa_type[ISA_SB_type] = 1;
switch (wb_opcode2) {
case 0:
wb_dec[Instr_BEQ] = 1;
break;
case 1:
wb_dec[Instr_BNE] = 1;
break;
case 4:
wb_dec[Instr_BLT] = 1;
break;
case 5:
wb_dec[Instr_BGE] = 1;
break;
case 6:
wb_dec[Instr_BLTU] = 1;
break;
case 7:
wb_dec[Instr_BGEU] = 1;
break;
default:
w_error = true;
}
break;
case 0x5:
if (wb_instr(31, 25) == 0x00) {
wb_dec[Instr_SRLW] = 1;
} else if (wb_instr(31, 25) == 0x01) {
wb_dec[Instr_DIVUW] = 1;
} else if (wb_instr(31, 25) == 0x20) {
wb_dec[Instr_SRAW] = 1;
} else {
case OPCODE_JAL:
wb_isa_type[ISA_UJ_type] = 1;
wb_dec[Instr_JAL] = 1;
break;
case OPCODE_JALR:
wb_isa_type[ISA_I_type] = 1;
switch (wb_opcode2) {
case 0:
wb_dec[Instr_JALR] = 1;
break;
default:
w_error = true;
}
break;
case 0x6:
if (wb_instr(31, 25) == 0x01) {
wb_dec[Instr_REMW] = 1;
} else {
case OPCODE_LB:
wb_isa_type[ISA_I_type] = 1;
switch (wb_opcode2) {
case 0:
wb_dec[Instr_LB] = 1;
break;
case 1:
wb_dec[Instr_LH] = 1;
break;
case 2:
wb_dec[Instr_LW] = 1;
break;
case 3:
wb_dec[Instr_LD] = 1;
break;
case 4:
wb_dec[Instr_LBU] = 1;
break;
case 5:
wb_dec[Instr_LHU] = 1;
break;
case 6:
wb_dec[Instr_LWU] = 1;
break;
default:
w_error = true;
}
break;
case 0x7:
if (wb_instr(31, 25) == 0x01) {
wb_dec[Instr_REMUW] = 1;
} else {
case OPCODE_LUI:
wb_isa_type[ISA_U_type] = 1;
wb_dec[Instr_LUI] = 1;
break;
case OPCODE_SB:
wb_isa_type[ISA_S_type] = 1;
switch (wb_opcode2) {
case 0:
wb_dec[Instr_SB] = 1;
break;
case 1:
wb_dec[Instr_SH] = 1;
break;
case 2:
wb_dec[Instr_SW] = 1;
break;
case 3:
wb_dec[Instr_SD] = 1;
break;
default:
w_error = true;
}
break;
default:
w_error = true;
}
break;
case OPCODE_AUIPC:
wb_isa_type[ISA_U_type] = 1;
wb_dec[Instr_AUIPC] = 1;
break;
case OPCODE_BEQ:
wb_isa_type[ISA_SB_type] = 1;
switch (wb_opcode2) {
case 0:
wb_dec[Instr_BEQ] = 1;
case OPCODE_CSRR:
wb_isa_type[ISA_I_type] = 1;
switch (wb_opcode2) {
case 0:
if (wb_instr == 0x00000073) {
wb_dec[Instr_ECALL] = 1;
} else if (wb_instr == 0x00100073) {
wb_dec[Instr_EBREAK] = 1;
} else if (wb_instr == 0x00200073) {
wb_dec[Instr_URET] = 1;
} else if (wb_instr == 0x10200073) {
wb_dec[Instr_SRET] = 1;
} else if (wb_instr == 0x20200073) {
wb_dec[Instr_HRET] = 1;
} else if (wb_instr == 0x30200073) {
wb_dec[Instr_MRET] = 1;
} else {
w_error = true;
}
break;
case 1:
wb_dec[Instr_CSRRW] = 1;
break;
case 2:
wb_dec[Instr_CSRRS] = 1;
break;
case 3:
wb_dec[Instr_CSRRC] = 1;
break;
case 5:
wb_dec[Instr_CSRRWI] = 1;
break;
case 6:
wb_dec[Instr_CSRRSI] = 1;
break;
case 7:
wb_dec[Instr_CSRRCI] = 1;
break;
default:
w_error = true;
}
break;
case 1:
wb_dec[Instr_BNE] = 1;
break;
case 4:
wb_dec[Instr_BLT] = 1;
break;
case 5:
wb_dec[Instr_BGE] = 1;
break;
case 6:
wb_dec[Instr_BLTU] = 1;
break;
case 7:
wb_dec[Instr_BGEU] = 1;
break;
default:
w_error = true;
}
break;
case OPCODE_JAL:
wb_isa_type[ISA_UJ_type] = 1;
wb_dec[Instr_JAL] = 1;
break;
case OPCODE_JALR:
wb_isa_type[ISA_I_type] = 1;
switch (wb_opcode2) {
case 0:
wb_dec[Instr_JALR] = 1;
break;
default:
w_error = true;
}
break;
case OPCODE_LB:
wb_isa_type[ISA_I_type] = 1;
switch (wb_opcode2) {
case 0:
wb_dec[Instr_LB] = 1;
break;
case 1:
wb_dec[Instr_LH] = 1;
break;
case 2:
wb_dec[Instr_LW] = 1;
break;
case 3:
wb_dec[Instr_LD] = 1;
break;
case 4:
wb_dec[Instr_LBU] = 1;
break;
case 5:
wb_dec[Instr_LHU] = 1;
break;
case 6:
wb_dec[Instr_LWU] = 1;
break;
default:
w_error = true;
}
break;
case OPCODE_LUI:
wb_isa_type[ISA_U_type] = 1;
wb_dec[Instr_LUI] = 1;
break;
case OPCODE_SB:
wb_isa_type[ISA_S_type] = 1;
switch (wb_opcode2) {
case 0:
wb_dec[Instr_SB] = 1;
break;
case 1:
wb_dec[Instr_SH] = 1;
break;
case 2:
wb_dec[Instr_SW] = 1;
break;
case 3:
wb_dec[Instr_SD] = 1;
break;
default:
w_error = true;
}
break;
case OPCODE_CSRR:
wb_isa_type[ISA_I_type] = 1;
switch (wb_opcode2) {
case 0:
if (wb_instr == 0x00000073) {
wb_dec[Instr_ECALL] = 1;
} else if (wb_instr == 0x00100073) {
wb_dec[Instr_EBREAK] = 1;
} else if (wb_instr == 0x00200073) {
wb_dec[Instr_URET] = 1;
} else if (wb_instr == 0x10200073) {
wb_dec[Instr_SRET] = 1;
} else if (wb_instr == 0x20200073) {
wb_dec[Instr_HRET] = 1;
} else if (wb_instr == 0x30200073) {
wb_dec[Instr_MRET] = 1;
} else {
case OPCODE_FENCE:
switch (wb_opcode2) {
case 0:
wb_dec[Instr_FENCE] = 1;
break;
case 1:
wb_dec[Instr_FENCE_I] = 1;
break;
default:
w_error = true;
}
break;
case 1:
wb_dec[Instr_CSRRW] = 1;
break;
case 2:
wb_dec[Instr_CSRRS] = 1;
break;
case 3:
wb_dec[Instr_CSRRC] = 1;
break;
case 5:
wb_dec[Instr_CSRRWI] = 1;
break;
case 6:
wb_dec[Instr_CSRRSI] = 1;
break;
case 7:
wb_dec[Instr_CSRRCI] = 1;
break;
 
default:
w_error = true;
}
break;
case OPCODE_FENCE:
switch (wb_opcode2) {
case 0:
wb_dec[Instr_FENCE] = 1;
break;
case 1:
wb_dec[Instr_FENCE_I] = 1;
break;
default:
w_error = true;
}
break;
wb_instr_out = wb_instr;
} // compressed/!compressed
 
default:
w_error = true;
}
 
 
if (i_f_valid.read()) {
v.valid = 1;
v.pc = i_f_pc;
v.instr = wb_instr;
v.instr = wb_instr_out;
v.compressed = w_compressed;
 
v.isa_type = wb_isa_type;
v.instr_vec = wb_dec;
437,6 → 703,7
v.memop_size = MEMOP_1B;
v.unsigned_op = 0;
v.rv32 = 0;
v.compressed = 0;
 
v.instr_unimplemented = !wb_dec.or_reduce();
}
450,6 → 717,7
o_memop_size = r.memop_size;
o_unsigned_op = r.unsigned_op;
o_rv32 = r.rv32;
o_compressed = r.compressed;
o_isa_type = r.isa_type;
o_instr_vec = r.instr_vec;
o_exception = r.instr_unimplemented;
/core/decoder.h
26,6 → 26,26
const uint8_t OPCODE_JALR = 0x19; // 11001: JALR
const uint8_t OPCODE_JAL = 0x1B; // 11011: JAL
const uint8_t OPCODE_CSRR = 0x1C; // 11100: CSRRC, CSRRCI, CSRRS, CSRRSI, CSRRW, CSRRWI, URET, SRET, HRET, MRET
// Compressed instruction set
const uint8_t OPCODE_C_ADDI4SPN = 0x00;
const uint8_t OPCODE_C_NOP_ADDI = 0x01;
const uint8_t OPCODE_C_SLLI = 0x02;
const uint8_t OPCODE_C_JAL_ADDIW = 0x05;
const uint8_t OPCODE_C_LW = 0x08;
const uint8_t OPCODE_C_LI = 0x09;
const uint8_t OPCODE_C_LWSP = 0x0A;
const uint8_t OPCODE_C_LD = 0x0C;
const uint8_t OPCODE_C_ADDI16SP_LUI = 0xD;
const uint8_t OPCODE_C_LDSP = 0x0E;
const uint8_t OPCODE_C_MATH = 0x11;
const uint8_t OPCODE_C_JR_MV_EBREAK_JALR_ADD = 0x12;
const uint8_t OPCODE_C_J = 0x15;
const uint8_t OPCODE_C_SW = 0x18;
const uint8_t OPCODE_C_BEQZ = 0x19;
const uint8_t OPCODE_C_SWSP = 0x1A;
const uint8_t OPCODE_C_SD = 0x1C;
const uint8_t OPCODE_C_BNEZ = 0x1D;
const uint8_t OPCODE_C_SDSP = 0x1E;
 
SC_MODULE(InstrDecoder) {
sc_in<bool> i_clk;
43,6 → 63,7
sc_out<bool> o_memop_sign_ext; // Load memory value with sign extending
sc_out<sc_uint<2>> o_memop_size; // Memory transaction size
sc_out<bool> o_rv32; // 32-bits instruction
sc_out<bool> o_compressed; // C-type instruction
sc_out<bool> o_unsigned_op; // Unsigned operands
sc_out<sc_bv<ISA_Total>> o_isa_type; // Instruction format accordingly with ISA
sc_out<sc_bv<Instr_Total>> o_instr_vec; // One bit per decoded instruction bus
70,6 → 91,7
sc_signal<sc_uint<2>> memop_size;
sc_signal<bool> unsigned_op;
sc_signal<bool> rv32;
sc_signal<bool> compressed;
 
sc_signal<bool> instr_unimplemented;
} v, r;
/core/execute.cpp
1,8 → 1,17
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief CPU Instruction Execution stage.
/*
* Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* 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"
18,44 → 27,65
sensitive << i_d_pc;
sensitive << i_d_instr;
sensitive << i_wb_done;
sensitive << i_memop_store;
sensitive << i_memop_load;
sensitive << i_memop_store;
sensitive << i_memop_sign_ext;
sensitive << i_memop_size;
sensitive << i_unsigned_op;
sensitive << i_rv32;;
sensitive << i_rv32;
sensitive << i_compressed;
sensitive << i_isa_type;
sensitive << i_ivec;
sensitive << i_rdata1;
sensitive << i_rdata2;
sensitive << i_csr_rdata;
sensitive << i_ext_irq;
sensitive << i_ie;
sensitive << i_mtvec;
sensitive << i_mode;
sensitive << i_break_mode;
sensitive << i_unsup_exception;
sensitive << i_ext_irq;
sensitive << i_dport_npc_write;
sensitive << i_dport_npc;
sensitive << i_rdata1;
sensitive << i_rdata2;
sensitive << i_csr_rdata;
sensitive << r.d_valid;
sensitive << r.pc;
sensitive << r.npc;
sensitive << r.hazard_depth;
sensitive << r.hazard_addr0;
sensitive << r.hazard_addr1;
sensitive << r.instr;
sensitive << r.res_val;
sensitive << r.memop_load;
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_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.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.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_DIV];
sensitive << w_arith_valid[Multi_MUL];
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_sllw;
sensitive << wb_srl;
191,6 → 221,7
sc_uint<2> wb_memop_size;
sc_uint<BUS_ADDR_WIDTH> wb_memop_addr;
sc_bv<Instr_Total> wv;
int opcode_len;
 
bool w_pc_valid;
bool w_d_acceptable;
337,27 → 368,32
 
// Relative Branch on some condition:
w_pc_branch = 0;
if ((wv[Instr_BEQ] & (wb_sub64 == 0))
|| (wv[Instr_BGE] & (wb_sub64[63] == 0))
|| (wv[Instr_BGEU] & (w_gr_equal))
|| (wv[Instr_BLT] & (wb_sub64[63] == 1))
|| (wv[Instr_BLTU] & (w_less))
|| (wv[Instr_BNE] & (wb_sub64 != 0))) {
if ((wv[Instr_BEQ].to_bool() & (wb_sub64 == 0))
|| (wv[Instr_BGE].to_bool() & (wb_sub64[63] == 0))
|| (wv[Instr_BGEU].to_bool() & (w_gr_equal))
|| (wv[Instr_BLT].to_bool() & (wb_sub64[63] == 1))
|| (wv[Instr_BLTU].to_bool() & (w_less))
|| (wv[Instr_BNE].to_bool() & (wb_sub64 != 0))) {
w_pc_branch = 1;
}
 
opcode_len = 4;
if (i_compressed.read()) {
opcode_len = 2;
}
 
if (w_pc_branch) {
wb_npc = i_d_pc.read() + wb_off(BUS_ADDR_WIDTH-1, 0);
} 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);
} 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[0] = 0;
} else if ((wv[Instr_MRET] | wv[Instr_URET]).to_bool()) {
wb_res = i_d_pc.read() + 4;
w_xret = i_d_valid;
wb_res = i_d_pc.read() + opcode_len;
w_xret = i_d_valid.read() && w_pc_valid;
w_csr_wena = 0;
if (wv[Instr_URET].to_bool()) {
wb_csr_addr = CSR_uepc;
367,7 → 403,7
wb_npc = i_csr_rdata;
} else {
// 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) {
403,8 → 439,9
}
 
w_exception = w_d_acceptable
& (i_unsup_exception.read() || w_exception_load || w_exception_store
|| w_exception_xret || wv[Instr_ECALL] || wv[Instr_EBREAK]);
& ((i_unsup_exception.read() & w_pc_valid) || w_exception_load
|| w_exception_store || w_exception_xret
|| wv[Instr_ECALL] || wv[Instr_EBREAK]);
 
/** Default number of cycles per instruction = 0 (1 clock per instr)
* If instruction is multicycle then modify this value.
521,7 → 558,8
wb_exception_code = 0;
if (i_ext_irq & i_ie & !r.ext_irq_pulser) { // Maskable traps (interrupts)
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)
wb_exception_code[4] = 0;
if (w_exception_load) {
/core/execute.h
1,8 → 1,17
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief CPU Instruction Execution stage.
/*
* Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* 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.
*/
 
#ifndef __DEBUGGER_RIVERLIB_EXECUTE_H__
30,6 → 39,7
sc_in<sc_uint<2>> i_memop_size; // Memory transaction size
sc_in<bool> i_unsigned_op; // Unsigned operands
sc_in<bool> i_rv32; // 32-bits instruction
sc_in<bool> i_compressed; // C-extension (2-bytes length)
sc_in<sc_bv<ISA_Total>> i_isa_type; // Type of the instruction's structure (ISA spec.)
sc_in<sc_bv<Instr_Total>> i_ivec; // One pulse per supported instruction.
sc_in<bool> i_ie; // Interrupt enable bit
/core/fetch.cpp
77,7 → 77,7
 
w_predict_miss = 1;
if (i_e_npc == r.pc_z1
|| i_e_npc == i_predict_npc || i_e_npc == r.raddr_not_resp_yet) {
|| i_e_npc == r.raddr_not_resp_yet) {
w_predict_miss = 0;
}
 
/core/proc.cpp
71,6 → 71,7
dec0->o_memop_size(w.d.memop_size);
dec0->o_unsigned_op(w.d.unsigned_op);
dec0->o_rv32(w.d.rv32);
dec0->o_compressed(w.d.compressed);
dec0->o_isa_type(w.d.isa_type);
dec0->o_instr_vec(w.d.instr_vec);
dec0->o_exception(w.d.exception);
89,6 → 90,7
exec0->i_memop_size(w.d.memop_size);
exec0->i_unsigned_op(w.d.unsigned_op);
exec0->i_rv32(w.d.rv32);
exec0->i_compressed(w.d.compressed);
exec0->i_isa_type(w.d.isa_type);
exec0->i_ivec(w.d.instr_vec);
exec0->i_ie(csr.ie);
287,9 → 289,7
iregs0->generateVCD(i_vcd, o_vcd);
}
 
 
void Processor::comb() {
 
w_fetch_pipeline_hold = w.e.pipeline_hold | w.m.pipeline_hold | dbg.halt;
w_any_pipeline_hold = w.f.pipeline_hold | w.e.pipeline_hold
| w.m.pipeline_hold | dbg.halt;
323,10 → 323,9
int sz;
if (w.m.valid.read()) {
uint64_t line_cnt = dbg.executed_cnt.read() + 1;
sz = RISCV_sprintf(tstr, sizeof(tstr), "%8" RV_PRI64 "d [%08x] %08x: ",
sz = RISCV_sprintf(tstr, sizeof(tstr), "%8" RV_PRI64 "d [%08x]: ",
line_cnt,
w.m.pc.read().to_int(),
w.m.instr.read().to_int());
w.m.pc.read().to_int());
uint64_t prev_val = iregs0->r.mem[w.w.waddr.read().to_int()].to_int64();
uint64_t cur_val = w.w.wdata.read().to_int64();
if (w.w.waddr.read() == 0 || prev_val == cur_val) {
/core/proc.h
94,6 → 94,7
sc_signal<bool> memop_sign_ext;
sc_signal<sc_uint<2>> memop_size;
sc_signal<bool> rv32; // 32-bits instruction
sc_signal<bool> compressed; // C-extension
sc_signal<bool> unsigned_op; // Unsigned operands
sc_signal<sc_bv<ISA_Total>> isa_type;
sc_signal<sc_bv<Instr_Total>> instr_vec;
/river_cfg.h
1,8 → 1,17
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief "River" CPU configuration parameters
/*
* Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* 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.
*/
 
#ifndef __DEBUGGER_RIVER_CFG_H__
23,7 → 32,7
static const uint8_t MEMOP_2B = 1;
static const uint8_t MEMOP_1B = 0;
 
static const uint64_t RESET_VECTOR = 0x1000;
static const uint64_t RESET_VECTOR = 0x0040;
static const int DBG_FETCH_TRACE_SIZE = 4;
 
/** Number of elements each 2*CFG_ADDR_WIDTH in stack trace buffer: */
/river_top.cpp
1,8 → 1,17
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief "River" CPU Top level.
/*
* Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* 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 "river_top.h"
/river_top.h
1,8 → 1,17
/**
* @file
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief "River" CPU Top level.
/*
* Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* 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.
*/
 
#ifndef __DEBUGGER_RIVER_TOP_H__
39,7 → 48,6
sc_out<bool> o_dport_ready; // Response is ready
sc_out<sc_uint<RISCV_ARCH>> o_dport_rdata; // Response value
 
 
RiverTop(sc_module_name name_);
virtual ~RiverTop();
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.