temp commit

Signed-off-by: liangkangnan <liangkangnan@163.com>
pull/4/head
liangkangnan 2021-03-31 15:25:22 +08:00
parent 9322b595bc
commit c070f0b49d
7 changed files with 1256 additions and 610 deletions

View File

@ -1,2 +1,6 @@
更新计划:
1.增加指令trace功能
2.总线优化;
3.取指、访存优化;
4.jtag优化

View File

@ -1,44 +1,45 @@
+incdir+../rtl/core
../rtl/core/clint.sv
../rtl/core/csr_reg.sv
../rtl/core/defines.sv
../rtl/core/divider.sv
../rtl/core/exu.sv
../rtl/core/exu_alu_datapath.sv
../rtl/core/exu_commit.sv
../rtl/core/exu_dispatch.sv
../rtl/core/exu_mem.sv
../rtl/core/exu_muldiv.sv
../rtl/core/gpr_reg.sv
../rtl/core/idu.sv
../rtl/core/idu_exu.sv
../rtl/core/ifu.sv
../rtl/core/ifu_idu.sv
../rtl/core/pipe_ctrl.sv
../rtl/core/rst_ctrl.sv
../rtl/core/tinyriscv_core.sv
../rtl/debug/jtag_dm.sv
../rtl/debug/jtag_driver.sv
../rtl/debug/jtag_top.sv
../rtl/perips/gpio.sv
../rtl/perips/ram.sv
../rtl/perips/rom.sv
../rtl/perips/timer.sv
../rtl/perips/uart.sv
../rtl/sys_bus/rib.sv
../rtl/top/tinyriscv_soc_top.sv
../rtl/utils/full_handshake_rx.sv
../rtl/utils/full_handshake_tx.sv
../rtl/utils/gen_buf.sv
../rtl/utils/gen_dff.sv
../rtl/utils/gen_ram.sv
../rtl/utils/vld_rdy.sv
+incdir+../rtl/core
../rtl/core/clint.sv
../rtl/core/csr_reg.sv
../rtl/core/defines.sv
../rtl/core/divider.sv
../rtl/core/exu.sv
../rtl/core/exu_alu_datapath.sv
../rtl/core/exu_commit.sv
../rtl/core/exu_dispatch.sv
../rtl/core/exu_mem.sv
../rtl/core/exu_muldiv.sv
../rtl/core/gpr_reg.sv
../rtl/core/idu.sv
../rtl/core/idu_exu.sv
../rtl/core/ifu.sv
../rtl/core/ifu_idu.sv
../rtl/core/pipe_ctrl.sv
../rtl/core/rst_ctrl.sv
../rtl/core/tinyriscv_core.sv
../rtl/core/tracer.sv
../rtl/debug/jtag_dm.sv
../rtl/debug/jtag_driver.sv
../rtl/debug/jtag_top.sv
../rtl/perips/gpio.sv
../rtl/perips/ram.sv
../rtl/perips/rom.sv
../rtl/perips/timer.sv
../rtl/perips/uart.sv
../rtl/sys_bus/rib.sv
../rtl/top/tinyriscv_soc_top.sv
../rtl/utils/full_handshake_rx.sv
../rtl/utils/full_handshake_tx.sv
../rtl/utils/gen_buf.sv
../rtl/utils/gen_dff.sv
../rtl/utils/gen_ram.sv
../rtl/utils/vld_rdy.sv

View File

@ -1,318 +1,324 @@
/*
Copyright 2019 Blue Liang, liangkangnan@163.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 "defines.sv"
// tinyriscv处理器核顶层模块
module tinyriscv_core(
input wire clk,
input wire rst_n,
output wire[31:0] dbus_addr_o,
input wire[31:0] dbus_data_i,
output wire[31:0] dbus_data_o,
output wire[3:0] dbus_sel_o,
output wire dbus_we_o,
output wire dbus_req_valid_o,
input wire dbus_req_ready_i,
input wire dbus_rsp_valid_i,
output wire dbus_rsp_ready_o,
output wire[31:0] ibus_addr_o, // 取指地址
input wire[31:0] ibus_data_i, // 取到的指令内容
output wire[31:0] ibus_data_o,
output wire[3:0] ibus_sel_o,
output wire ibus_we_o,
output wire ibus_req_valid_o,
input wire ibus_req_ready_i,
input wire ibus_rsp_valid_i,
output wire ibus_rsp_ready_o,
input wire jtag_halt_i,
input wire[`INT_WIDTH-1:0] int_i // 中断输入信号
);
// ifu模块输出信号
wire[31:0] ifetch_inst_o;
wire[31:0] ifetch_pc_o;
wire ifetch_inst_valid_o;
// ifu_idu模块输出信号
wire[31:0] if_inst_o;
wire[31:0] if_inst_addr_o;
wire[`INT_WIDTH-1:0] if_int_flag_o;
// idu模块输出信号
wire[31:0] id_inst_o;
wire[31:0] id_inst_addr_o;
wire[`DECINFO_WIDTH-1:0] id_dec_info_bus_o;
wire[31:0] id_dec_imm_o;
wire[31:0] id_dec_pc_o;
wire[4:0] id_rs1_raddr_o;
wire[4:0] id_rs2_raddr_o;
wire[4:0] id_rd_waddr_o;
wire id_rd_we_o;
wire id_stall_o;
wire[31:0] id_rs1_rdata_o;
wire[31:0] id_rs2_rdata_o;
// idu_exu模块输出信号
wire[31:0] ie_inst_o;
wire[31:0] ie_inst_addr_o;
wire[`DECINFO_WIDTH-1:0] ie_dec_info_bus_o;
wire[31:0] ie_dec_imm_o;
wire[31:0] ie_dec_pc_o;
wire[31:0] ie_rs1_rdata_o;
wire[31:0] ie_rs2_rdata_o;
wire[4:0] ie_rd_waddr_o;
wire ie_rd_we_o;
// exu模块输出信号
wire[31:0] ex_mem_wdata_o;
wire[31:0] ex_mem_addr_o;
wire ex_mem_we_o;
wire[3:0] ex_mem_sel_o;
wire ex_mem_req_valid_o;
wire ex_mem_rsp_ready_o;
wire ex_mem_access_misaligned_o;
wire[31:0] ex_reg_wdata_o;
wire ex_reg_we_o;
wire[4:0] ex_reg_waddr_o;
wire ex_hold_flag_o;
wire ex_jump_flag_o;
wire[31:0] ex_jump_addr_o;
wire[31:0] ex_csr_wdata_o;
wire ex_csr_we_o;
wire[31:0] ex_csr_waddr_o;
wire[31:0] ex_csr_raddr_o;
wire ex_inst_ecall_o;
wire ex_inst_ebreak_o;
wire ex_inst_mret_o;
// gpr_reg模块输出信号
wire[31:0] regs_rdata1_o;
wire[31:0] regs_rdata2_o;
// csr_reg模块输出信号
wire[31:0] csr_ex_data_o;
wire[31:0] csr_clint_data_o;
wire[31:0] csr_mtvec_o;
wire[31:0] csr_mepc_o;
wire[31:0] csr_mstatus_o;
// pipe_ctrl模块输出信号
wire[31:0] ctrl_flush_addr_o;
wire ctrl_flush_o;
wire[`STALL_WIDTH-1:0] ctrl_stall_o;
// clint模块输出信号
wire clint_csr_we_o;
wire[31:0] clint_csr_waddr_o;
wire[31:0] clint_csr_wdata_o;
wire clint_stall_flag_o;
wire[31:0] clint_int_addr_o;
wire clint_int_assert_o;
assign dbus_addr_o = ex_mem_addr_o;
assign dbus_data_o = ex_mem_wdata_o;
assign dbus_we_o = ex_mem_we_o;
assign dbus_sel_o = ex_mem_sel_o;
assign dbus_req_valid_o = ex_mem_req_valid_o;
assign dbus_rsp_ready_o = ex_mem_rsp_ready_o;
ifu u_ifu(
.clk(clk),
.rst_n(rst_n),
.flush_addr_i(ctrl_flush_addr_o),
.stall_i(ctrl_stall_o),
.flush_i(ctrl_flush_o),
.jtag_halt_i(jtag_halt_i),
.inst_o(ifetch_inst_o),
.pc_o(ifetch_pc_o),
.inst_valid_o(ifetch_inst_valid_o),
.ibus_addr_o(ibus_addr_o),
.ibus_data_i(ibus_data_i),
.ibus_data_o(ibus_data_o),
.ibus_sel_o(ibus_sel_o),
.ibus_we_o(ibus_we_o),
.req_valid_o(ibus_req_valid_o),
.req_ready_i(ibus_req_ready_i),
.rsp_valid_i(ibus_rsp_valid_i),
.rsp_ready_o(ibus_rsp_ready_o)
);
pipe_ctrl u_pipe_ctrl(
.clk(clk),
.rst_n(rst_n),
.stall_from_id_i(id_stall_o),
.stall_from_ex_i(ex_hold_flag_o),
.stall_from_jtag_i(1'b0),
.stall_from_clint_i(clint_stall_flag_o),
.jump_assert_i(ex_jump_flag_o),
.jump_addr_i(ex_jump_addr_o),
.flush_o(ctrl_flush_o),
.stall_o(ctrl_stall_o),
.flush_addr_o(ctrl_flush_addr_o)
);
gpr_reg u_gpr_reg(
.clk(clk),
.rst_n(rst_n),
.we_i(ex_reg_we_o),
.waddr_i(ex_reg_waddr_o),
.wdata_i(ex_reg_wdata_o),
.raddr1_i(id_rs1_raddr_o),
.rdata1_o(regs_rdata1_o),
.raddr2_i(id_rs2_raddr_o),
.rdata2_o(regs_rdata2_o)
);
csr_reg u_csr_reg(
.clk(clk),
.rst_n(rst_n),
.exu_we_i(ex_csr_we_o),
.exu_raddr_i(ex_csr_raddr_o),
.exu_waddr_i(ex_csr_waddr_o),
.exu_wdata_i(ex_csr_wdata_o),
.exu_rdata_o(csr_ex_data_o),
.clint_we_i(clint_csr_we_o),
.clint_waddr_i(clint_csr_waddr_o),
.clint_wdata_i(clint_csr_wdata_o),
.mtvec_o(csr_mtvec_o),
.mepc_o(csr_mepc_o),
.mstatus_o(csr_mstatus_o)
);
ifu_idu u_ifu_idu(
.clk(clk),
.rst_n(rst_n),
.inst_i(ifetch_inst_o),
.inst_addr_i(ifetch_pc_o),
.stall_i(ctrl_stall_o),
.flush_i(ctrl_flush_o),
.inst_valid_i(ifetch_inst_valid_o),
.inst_o(if_inst_o),
.inst_addr_o(if_inst_addr_o)
);
idu u_idu(
.clk(clk),
.rst_n(rst_n),
.inst_i(if_inst_o),
.rs1_rdata_i(regs_rdata1_o),
.rs2_rdata_i(regs_rdata2_o),
.inst_o(id_inst_o),
.inst_addr_i(if_inst_addr_o),
.rs1_rdata_o(id_rs1_rdata_o),
.rs2_rdata_o(id_rs2_rdata_o),
.stall_o(id_stall_o),
.dec_info_bus_o(id_dec_info_bus_o),
.dec_imm_o(id_dec_imm_o),
.dec_pc_o(id_dec_pc_o),
.rs1_raddr_o(id_rs1_raddr_o),
.rs2_raddr_o(id_rs2_raddr_o),
.rd_waddr_o(id_rd_waddr_o),
.rd_we_o(id_rd_we_o)
);
idu_exu u_idu_exu(
.clk(clk),
.rst_n(rst_n),
.inst_i(id_inst_o),
.stall_i(ctrl_stall_o),
.flush_i(ctrl_flush_o),
.dec_info_bus_i(id_dec_info_bus_o),
.dec_imm_i(id_dec_imm_o),
.dec_pc_i(id_dec_pc_o),
.rs1_rdata_i(id_rs1_rdata_o),
.rs2_rdata_i(id_rs2_rdata_o),
.rd_waddr_i(id_rd_waddr_o),
.rd_we_i(id_rd_we_o),
.inst_o(ie_inst_o),
.dec_info_bus_o(ie_dec_info_bus_o),
.dec_imm_o(ie_dec_imm_o),
.dec_pc_o(ie_dec_pc_o),
.rs1_rdata_o(ie_rs1_rdata_o),
.rs2_rdata_o(ie_rs2_rdata_o),
.rd_waddr_o(ie_rd_waddr_o),
.rd_we_o(ie_rd_we_o)
);
exu u_exu(
.clk(clk),
.rst_n(rst_n),
.reg1_rdata_i(ie_rs1_rdata_o),
.reg2_rdata_i(ie_rs2_rdata_o),
.mem_rdata_i(dbus_data_i),
.mem_req_ready_i(dbus_req_ready_i),
.mem_rsp_valid_i(dbus_rsp_valid_i),
.mem_wdata_o(ex_mem_wdata_o),
.mem_addr_o(ex_mem_addr_o),
.mem_we_o(ex_mem_we_o),
.mem_sel_o(ex_mem_sel_o),
.mem_req_valid_o(ex_mem_req_valid_o),
.mem_rsp_ready_o(ex_mem_rsp_ready_o),
.mem_access_misaligned_o(ex_mem_access_misaligned_o),
.reg_wdata_o(ex_reg_wdata_o),
.reg_we_o(ex_reg_we_o),
.reg_waddr_o(ex_reg_waddr_o),
.hold_flag_o(ex_hold_flag_o),
.jump_flag_o(ex_jump_flag_o),
.jump_addr_o(ex_jump_addr_o),
.int_assert_i(clint_int_assert_o),
.int_addr_i(clint_int_addr_o),
.inst_ecall_o(ex_inst_ecall_o),
.inst_ebreak_o(ex_inst_ebreak_o),
.inst_mret_o(ex_inst_mret_o),
.int_stall_i(clint_stall_flag_o),
.csr_raddr_o(ex_csr_raddr_o),
.csr_rdata_i(csr_ex_data_o),
.csr_wdata_o(ex_csr_wdata_o),
.csr_we_o(ex_csr_we_o),
.csr_waddr_o(ex_csr_waddr_o),
.dec_info_bus_i(ie_dec_info_bus_o),
.dec_imm_i(ie_dec_imm_o),
.dec_pc_i(ie_dec_pc_o),
.next_pc_i(if_inst_addr_o),
.rd_waddr_i(ie_rd_waddr_o),
.rd_we_i(ie_rd_we_o)
);
clint u_clint(
.clk(clk),
.rst_n(rst_n),
.int_flag_i(int_i),
.inst_ecall_i(ex_inst_ecall_o),
.inst_ebreak_i(ex_inst_ebreak_o),
.inst_mret_i(ex_inst_mret_o),
.inst_addr_i(ie_dec_pc_o),
.jump_flag_i(ex_jump_flag_o),
.mem_access_misaligned_i(ex_mem_access_misaligned_o),
.csr_mtvec_i(csr_mtvec_o),
.csr_mepc_i(csr_mepc_o),
.csr_mstatus_i(csr_mstatus_o),
.csr_we_o(clint_csr_we_o),
.csr_waddr_o(clint_csr_waddr_o),
.csr_wdata_o(clint_csr_wdata_o),
.stall_flag_o(clint_stall_flag_o),
.int_addr_o(clint_int_addr_o),
.int_assert_o(clint_int_assert_o)
);
endmodule
/*
Copyright 2019 Blue Liang, liangkangnan@163.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 "defines.sv"
// tinyriscv处理器核顶层模块
module tinyriscv_core(
input wire clk,
input wire rst_n,
output wire[31:0] dbus_addr_o,
input wire[31:0] dbus_data_i,
output wire[31:0] dbus_data_o,
output wire[3:0] dbus_sel_o,
output wire dbus_we_o,
output wire dbus_req_valid_o,
input wire dbus_req_ready_i,
input wire dbus_rsp_valid_i,
output wire dbus_rsp_ready_o,
output wire[31:0] ibus_addr_o, // 取指地址
input wire[31:0] ibus_data_i, // 取到的指令内容
output wire[31:0] ibus_data_o,
output wire[3:0] ibus_sel_o,
output wire ibus_we_o,
output wire ibus_req_valid_o,
input wire ibus_req_ready_i,
input wire ibus_rsp_valid_i,
output wire ibus_rsp_ready_o,
input wire jtag_halt_i,
input wire[`INT_WIDTH-1:0] int_i // 中断输入信号
);
// ifu模块输出信号
wire[31:0] ifetch_inst_o;
wire[31:0] ifetch_pc_o;
wire ifetch_inst_valid_o;
// ifu_idu模块输出信号
wire[31:0] if_inst_o;
wire[31:0] if_inst_addr_o;
wire[`INT_WIDTH-1:0] if_int_flag_o;
// idu模块输出信号
wire[31:0] id_inst_o;
wire[31:0] id_inst_addr_o;
wire[`DECINFO_WIDTH-1:0] id_dec_info_bus_o;
wire[31:0] id_dec_imm_o;
wire[31:0] id_dec_pc_o;
wire[4:0] id_rs1_raddr_o;
wire[4:0] id_rs2_raddr_o;
wire[4:0] id_rd_waddr_o;
wire id_rd_we_o;
wire id_stall_o;
wire[31:0] id_rs1_rdata_o;
wire[31:0] id_rs2_rdata_o;
// idu_exu模块输出信号
wire[31:0] ie_inst_o;
wire[31:0] ie_inst_addr_o;
wire[`DECINFO_WIDTH-1:0] ie_dec_info_bus_o;
wire[31:0] ie_dec_imm_o;
wire[31:0] ie_dec_pc_o;
wire[31:0] ie_rs1_rdata_o;
wire[31:0] ie_rs2_rdata_o;
wire[4:0] ie_rd_waddr_o;
wire ie_rd_we_o;
// exu模块输出信号
wire[31:0] ex_mem_wdata_o;
wire[31:0] ex_mem_addr_o;
wire ex_mem_we_o;
wire[3:0] ex_mem_sel_o;
wire ex_mem_req_valid_o;
wire ex_mem_rsp_ready_o;
wire ex_mem_access_misaligned_o;
wire[31:0] ex_reg_wdata_o;
wire ex_reg_we_o;
wire[4:0] ex_reg_waddr_o;
wire ex_hold_flag_o;
wire ex_jump_flag_o;
wire[31:0] ex_jump_addr_o;
wire[31:0] ex_csr_wdata_o;
wire ex_csr_we_o;
wire[31:0] ex_csr_waddr_o;
wire[31:0] ex_csr_raddr_o;
wire ex_inst_ecall_o;
wire ex_inst_ebreak_o;
wire ex_inst_mret_o;
// gpr_reg模块输出信号
wire[31:0] regs_rdata1_o;
wire[31:0] regs_rdata2_o;
// csr_reg模块输出信号
wire[31:0] csr_ex_data_o;
wire[31:0] csr_clint_data_o;
wire[31:0] csr_mtvec_o;
wire[31:0] csr_mepc_o;
wire[31:0] csr_mstatus_o;
// pipe_ctrl模块输出信号
wire[31:0] ctrl_flush_addr_o;
wire ctrl_flush_o;
wire[`STALL_WIDTH-1:0] ctrl_stall_o;
// clint模块输出信号
wire clint_csr_we_o;
wire[31:0] clint_csr_waddr_o;
wire[31:0] clint_csr_wdata_o;
wire clint_stall_flag_o;
wire[31:0] clint_int_addr_o;
wire clint_int_assert_o;
assign dbus_addr_o = ex_mem_addr_o;
assign dbus_data_o = ex_mem_wdata_o;
assign dbus_we_o = ex_mem_we_o;
assign dbus_sel_o = ex_mem_sel_o;
assign dbus_req_valid_o = ex_mem_req_valid_o;
assign dbus_rsp_ready_o = ex_mem_rsp_ready_o;
ifu u_ifu(
.clk(clk),
.rst_n(rst_n),
.flush_addr_i(ctrl_flush_addr_o),
.stall_i(ctrl_stall_o),
.flush_i(ctrl_flush_o),
.jtag_halt_i(jtag_halt_i),
.inst_o(ifetch_inst_o),
.pc_o(ifetch_pc_o),
.inst_valid_o(ifetch_inst_valid_o),
.ibus_addr_o(ibus_addr_o),
.ibus_data_i(ibus_data_i),
.ibus_data_o(ibus_data_o),
.ibus_sel_o(ibus_sel_o),
.ibus_we_o(ibus_we_o),
.req_valid_o(ibus_req_valid_o),
.req_ready_i(ibus_req_ready_i),
.rsp_valid_i(ibus_rsp_valid_i),
.rsp_ready_o(ibus_rsp_ready_o)
);
pipe_ctrl u_pipe_ctrl(
.clk(clk),
.rst_n(rst_n),
.stall_from_id_i(id_stall_o),
.stall_from_ex_i(ex_hold_flag_o),
.stall_from_jtag_i(1'b0),
.stall_from_clint_i(clint_stall_flag_o),
.jump_assert_i(ex_jump_flag_o),
.jump_addr_i(ex_jump_addr_o),
.flush_o(ctrl_flush_o),
.stall_o(ctrl_stall_o),
.flush_addr_o(ctrl_flush_addr_o)
);
gpr_reg u_gpr_reg(
.clk(clk),
.rst_n(rst_n),
.we_i(ex_reg_we_o),
.waddr_i(ex_reg_waddr_o),
.wdata_i(ex_reg_wdata_o),
.raddr1_i(id_rs1_raddr_o),
.rdata1_o(regs_rdata1_o),
.raddr2_i(id_rs2_raddr_o),
.rdata2_o(regs_rdata2_o)
);
csr_reg u_csr_reg(
.clk(clk),
.rst_n(rst_n),
.exu_we_i(ex_csr_we_o),
.exu_raddr_i(ex_csr_raddr_o),
.exu_waddr_i(ex_csr_waddr_o),
.exu_wdata_i(ex_csr_wdata_o),
.exu_rdata_o(csr_ex_data_o),
.clint_we_i(clint_csr_we_o),
.clint_waddr_i(clint_csr_waddr_o),
.clint_wdata_i(clint_csr_wdata_o),
.mtvec_o(csr_mtvec_o),
.mepc_o(csr_mepc_o),
.mstatus_o(csr_mstatus_o)
);
ifu_idu u_ifu_idu(
.clk(clk),
.rst_n(rst_n),
.inst_i(ifetch_inst_o),
.inst_addr_i(ifetch_pc_o),
.stall_i(ctrl_stall_o),
.flush_i(ctrl_flush_o),
.inst_valid_i(ifetch_inst_valid_o),
.inst_o(if_inst_o),
.inst_addr_o(if_inst_addr_o)
);
idu u_idu(
.clk(clk),
.rst_n(rst_n),
.inst_i(if_inst_o),
.rs1_rdata_i(regs_rdata1_o),
.rs2_rdata_i(regs_rdata2_o),
.inst_o(id_inst_o),
.inst_addr_i(if_inst_addr_o),
.rs1_rdata_o(id_rs1_rdata_o),
.rs2_rdata_o(id_rs2_rdata_o),
.stall_o(id_stall_o),
.dec_info_bus_o(id_dec_info_bus_o),
.dec_imm_o(id_dec_imm_o),
.dec_pc_o(id_dec_pc_o),
.rs1_raddr_o(id_rs1_raddr_o),
.rs2_raddr_o(id_rs2_raddr_o),
.rd_waddr_o(id_rd_waddr_o),
.rd_we_o(id_rd_we_o)
);
idu_exu u_idu_exu(
.clk(clk),
.rst_n(rst_n),
.inst_i(id_inst_o),
.stall_i(ctrl_stall_o),
.flush_i(ctrl_flush_o),
.dec_info_bus_i(id_dec_info_bus_o),
.dec_imm_i(id_dec_imm_o),
.dec_pc_i(id_dec_pc_o),
.rs1_rdata_i(id_rs1_rdata_o),
.rs2_rdata_i(id_rs2_rdata_o),
.rd_waddr_i(id_rd_waddr_o),
.rd_we_i(id_rd_we_o),
.inst_o(ie_inst_o),
.dec_info_bus_o(ie_dec_info_bus_o),
.dec_imm_o(ie_dec_imm_o),
.dec_pc_o(ie_dec_pc_o),
.rs1_rdata_o(ie_rs1_rdata_o),
.rs2_rdata_o(ie_rs2_rdata_o),
.rd_waddr_o(ie_rd_waddr_o),
.rd_we_o(ie_rd_we_o)
);
exu u_exu(
.clk(clk),
.rst_n(rst_n),
.reg1_rdata_i(ie_rs1_rdata_o),
.reg2_rdata_i(ie_rs2_rdata_o),
.mem_rdata_i(dbus_data_i),
.mem_req_ready_i(dbus_req_ready_i),
.mem_rsp_valid_i(dbus_rsp_valid_i),
.mem_wdata_o(ex_mem_wdata_o),
.mem_addr_o(ex_mem_addr_o),
.mem_we_o(ex_mem_we_o),
.mem_sel_o(ex_mem_sel_o),
.mem_req_valid_o(ex_mem_req_valid_o),
.mem_rsp_ready_o(ex_mem_rsp_ready_o),
.mem_access_misaligned_o(ex_mem_access_misaligned_o),
.reg_wdata_o(ex_reg_wdata_o),
.reg_we_o(ex_reg_we_o),
.reg_waddr_o(ex_reg_waddr_o),
.hold_flag_o(ex_hold_flag_o),
.jump_flag_o(ex_jump_flag_o),
.jump_addr_o(ex_jump_addr_o),
.int_assert_i(clint_int_assert_o),
.int_addr_i(clint_int_addr_o),
.inst_ecall_o(ex_inst_ecall_o),
.inst_ebreak_o(ex_inst_ebreak_o),
.inst_mret_o(ex_inst_mret_o),
.int_stall_i(clint_stall_flag_o),
.csr_raddr_o(ex_csr_raddr_o),
.csr_rdata_i(csr_ex_data_o),
.csr_wdata_o(ex_csr_wdata_o),
.csr_we_o(ex_csr_we_o),
.csr_waddr_o(ex_csr_waddr_o),
.dec_info_bus_i(ie_dec_info_bus_o),
.dec_imm_i(ie_dec_imm_o),
.dec_pc_i(ie_dec_pc_o),
.next_pc_i(if_inst_addr_o),
.rd_waddr_i(ie_rd_waddr_o),
.rd_we_i(ie_rd_we_o)
);
clint u_clint(
.clk(clk),
.rst_n(rst_n),
.int_flag_i(int_i),
.inst_ecall_i(ex_inst_ecall_o),
.inst_ebreak_i(ex_inst_ebreak_o),
.inst_mret_i(ex_inst_mret_o),
.inst_addr_i(ie_dec_pc_o),
.jump_flag_i(ex_jump_flag_o),
.mem_access_misaligned_i(ex_mem_access_misaligned_o),
.csr_mtvec_i(csr_mtvec_o),
.csr_mepc_i(csr_mepc_o),
.csr_mstatus_i(csr_mstatus_o),
.csr_we_o(clint_csr_we_o),
.csr_waddr_o(clint_csr_waddr_o),
.csr_wdata_o(clint_csr_wdata_o),
.stall_flag_o(clint_stall_flag_o),
.int_addr_o(clint_int_addr_o),
.int_assert_o(clint_int_assert_o)
);
`ifdef TRACE_ENABLED
tracer u_tracer(
);
`endif
endmodule

612
rtl/core/tracer.sv Normal file
View File

@ -0,0 +1,612 @@
/*
Copyright 2021 Blue Liang, liangkangnan@163.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.
*/
module tracer(
input logic clk,
input logic rst_n,
input logic[31:0] inst_i,
input logic[31:0] pc_i,
input logic inst_valid_i
);
typedef enum logic [6:0] {
OPCODE_LOAD = 7'h03,
OPCODE_MISC_MEM = 7'h0f,
OPCODE_OP_IMM = 7'h13,
OPCODE_AUIPC = 7'h17,
OPCODE_STORE = 7'h23,
OPCODE_OP = 7'h33,
OPCODE_LUI = 7'h37,
OPCODE_BRANCH = 7'h63,
OPCODE_JALR = 7'h67,
OPCODE_JAL = 7'h6f,
OPCODE_SYSTEM = 7'h73
} opcode_e;
// instruction masks (for tracer)
parameter logic [31:0] INSN_LUI = { 25'h?, {OPCODE_LUI } };
parameter logic [31:0] INSN_AUIPC = { 25'h?, {OPCODE_AUIPC} };
parameter logic [31:0] INSN_JAL = { 25'h?, {OPCODE_JAL } };
parameter logic [31:0] INSN_JALR = { 17'h?, 3'b000, 5'h?, {OPCODE_JALR } };
// BRANCH
parameter logic [31:0] INSN_BEQ = { 17'h?, 3'b000, 5'h?, {OPCODE_BRANCH} };
parameter logic [31:0] INSN_BNE = { 17'h?, 3'b001, 5'h?, {OPCODE_BRANCH} };
parameter logic [31:0] INSN_BLT = { 17'h?, 3'b100, 5'h?, {OPCODE_BRANCH} };
parameter logic [31:0] INSN_BGE = { 17'h?, 3'b101, 5'h?, {OPCODE_BRANCH} };
parameter logic [31:0] INSN_BLTU = { 17'h?, 3'b110, 5'h?, {OPCODE_BRANCH} };
parameter logic [31:0] INSN_BGEU = { 17'h?, 3'b111, 5'h?, {OPCODE_BRANCH} };
// OPIMM
parameter logic [31:0] INSN_ADDI = { 17'h?, 3'b000, 5'h?, {OPCODE_OP_IMM} };
parameter logic [31:0] INSN_SLTI = { 17'h?, 3'b010, 5'h?, {OPCODE_OP_IMM} };
parameter logic [31:0] INSN_SLTIU = { 17'h?, 3'b011, 5'h?, {OPCODE_OP_IMM} };
parameter logic [31:0] INSN_XORI = { 17'h?, 3'b100, 5'h?, {OPCODE_OP_IMM} };
parameter logic [31:0] INSN_ORI = { 17'h?, 3'b110, 5'h?, {OPCODE_OP_IMM} };
parameter logic [31:0] INSN_ANDI = { 17'h?, 3'b111, 5'h?, {OPCODE_OP_IMM} };
parameter logic [31:0] INSN_SLLI = { 7'b0000000, 10'h?, 3'b001, 5'h?, {OPCODE_OP_IMM} };
parameter logic [31:0] INSN_SRLI = { 7'b0000000, 10'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
parameter logic [31:0] INSN_SRAI = { 7'b0100000, 10'h?, 3'b101, 5'h?, {OPCODE_OP_IMM} };
// OP
parameter logic [31:0] INSN_ADD = { 7'b0000000, 10'h?, 3'b000, 5'h?, {OPCODE_OP} };
parameter logic [31:0] INSN_SUB = { 7'b0100000, 10'h?, 3'b000, 5'h?, {OPCODE_OP} };
parameter logic [31:0] INSN_SLL = { 7'b0000000, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
parameter logic [31:0] INSN_SLT = { 7'b0000000, 10'h?, 3'b010, 5'h?, {OPCODE_OP} };
parameter logic [31:0] INSN_SLTU = { 7'b0000000, 10'h?, 3'b011, 5'h?, {OPCODE_OP} };
parameter logic [31:0] INSN_XOR = { 7'b0000000, 10'h?, 3'b100, 5'h?, {OPCODE_OP} };
parameter logic [31:0] INSN_SRL = { 7'b0000000, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
parameter logic [31:0] INSN_SRA = { 7'b0100000, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
parameter logic [31:0] INSN_OR = { 7'b0000000, 10'h?, 3'b110, 5'h?, {OPCODE_OP} };
parameter logic [31:0] INSN_AND = { 7'b0000000, 10'h?, 3'b111, 5'h?, {OPCODE_OP} };
// SYSTEM
parameter logic [31:0] INSN_CSRRW = { 17'h?, 3'b001, 5'h?, {OPCODE_SYSTEM} };
parameter logic [31:0] INSN_CSRRS = { 17'h?, 3'b010, 5'h?, {OPCODE_SYSTEM} };
parameter logic [31:0] INSN_CSRRC = { 17'h?, 3'b011, 5'h?, {OPCODE_SYSTEM} };
parameter logic [31:0] INSN_CSRRWI = { 17'h?, 3'b101, 5'h?, {OPCODE_SYSTEM} };
parameter logic [31:0] INSN_CSRRSI = { 17'h?, 3'b110, 5'h?, {OPCODE_SYSTEM} };
parameter logic [31:0] INSN_CSRRCI = { 17'h?, 3'b111, 5'h?, {OPCODE_SYSTEM} };
parameter logic [31:0] INSN_ECALL = { 12'b000000000000, 13'b0, {OPCODE_SYSTEM} };
parameter logic [31:0] INSN_EBREAK = { 12'b000000000001, 13'b0, {OPCODE_SYSTEM} };
parameter logic [31:0] INSN_MRET = { 12'b001100000010, 13'b0, {OPCODE_SYSTEM} };
parameter logic [31:0] INSN_DRET = { 12'b011110110010, 13'b0, {OPCODE_SYSTEM} };
parameter logic [31:0] INSN_WFI = { 12'b000100000101, 13'b0, {OPCODE_SYSTEM} };
// RV32M
parameter logic [31:0] INSN_MUL = { 7'b0000001, 10'h?, 3'b000, 5'h?, {OPCODE_OP} };
parameter logic [31:0] INSN_MULH = { 7'b0000001, 10'h?, 3'b001, 5'h?, {OPCODE_OP} };
parameter logic [31:0] INSN_MULHSU = { 7'b0000001, 10'h?, 3'b010, 5'h?, {OPCODE_OP} };
parameter logic [31:0] INSN_MULHU = { 7'b0000001, 10'h?, 3'b011, 5'h?, {OPCODE_OP} };
parameter logic [31:0] INSN_DIV = { 7'b0000001, 10'h?, 3'b100, 5'h?, {OPCODE_OP} };
parameter logic [31:0] INSN_DIVU = { 7'b0000001, 10'h?, 3'b101, 5'h?, {OPCODE_OP} };
parameter logic [31:0] INSN_REM = { 7'b0000001, 10'h?, 3'b110, 5'h?, {OPCODE_OP} };
parameter logic [31:0] INSN_REMU = { 7'b0000001, 10'h?, 3'b111, 5'h?, {OPCODE_OP} };
// LOAD & STORE
parameter logic [31:0] INSN_LOAD = {25'h?, {OPCODE_LOAD } };
parameter logic [31:0] INSN_STORE = {25'h?, {OPCODE_STORE} };
// MISC-MEM
parameter logic [31:0] INSN_FENCE = { 17'h?, 3'b000, 5'h?, {OPCODE_MISC_MEM} };
parameter logic [31:0] INSN_FENCEI = { 17'h0, 3'b001, 5'h0, {OPCODE_MISC_MEM} };
// Get a CSR name for a CSR address.
function automatic string get_csr_name(input logic [11:0] csr_addr);
unique case (csr_addr)
12'd0: return "ustatus";
12'd4: return "uie";
12'd5: return "utvec";
12'd64: return "uscratch";
12'd65: return "uepc";
12'd66: return "ucause";
12'd67: return "utval";
12'd68: return "uip";
12'd1: return "fflags";
12'd2: return "frm";
12'd3: return "fcsr";
12'd3072: return "cycle";
12'd3073: return "time";
12'd3074: return "instret";
12'd3075: return "hpmcounter3";
12'd3076: return "hpmcounter4";
12'd3077: return "hpmcounter5";
12'd3078: return "hpmcounter6";
12'd3079: return "hpmcounter7";
12'd3080: return "hpmcounter8";
12'd3081: return "hpmcounter9";
12'd3082: return "hpmcounter10";
12'd3083: return "hpmcounter11";
12'd3084: return "hpmcounter12";
12'd3085: return "hpmcounter13";
12'd3086: return "hpmcounter14";
12'd3087: return "hpmcounter15";
12'd3088: return "hpmcounter16";
12'd3089: return "hpmcounter17";
12'd3090: return "hpmcounter18";
12'd3091: return "hpmcounter19";
12'd3092: return "hpmcounter20";
12'd3093: return "hpmcounter21";
12'd3094: return "hpmcounter22";
12'd3095: return "hpmcounter23";
12'd3096: return "hpmcounter24";
12'd3097: return "hpmcounter25";
12'd3098: return "hpmcounter26";
12'd3099: return "hpmcounter27";
12'd3100: return "hpmcounter28";
12'd3101: return "hpmcounter29";
12'd3102: return "hpmcounter30";
12'd3103: return "hpmcounter31";
12'd3200: return "cycleh";
12'd3201: return "timeh";
12'd3202: return "instreth";
12'd3203: return "hpmcounter3h";
12'd3204: return "hpmcounter4h";
12'd3205: return "hpmcounter5h";
12'd3206: return "hpmcounter6h";
12'd3207: return "hpmcounter7h";
12'd3208: return "hpmcounter8h";
12'd3209: return "hpmcounter9h";
12'd3210: return "hpmcounter10h";
12'd3211: return "hpmcounter11h";
12'd3212: return "hpmcounter12h";
12'd3213: return "hpmcounter13h";
12'd3214: return "hpmcounter14h";
12'd3215: return "hpmcounter15h";
12'd3216: return "hpmcounter16h";
12'd3217: return "hpmcounter17h";
12'd3218: return "hpmcounter18h";
12'd3219: return "hpmcounter19h";
12'd3220: return "hpmcounter20h";
12'd3221: return "hpmcounter21h";
12'd3222: return "hpmcounter22h";
12'd3223: return "hpmcounter23h";
12'd3224: return "hpmcounter24h";
12'd3225: return "hpmcounter25h";
12'd3226: return "hpmcounter26h";
12'd3227: return "hpmcounter27h";
12'd3228: return "hpmcounter28h";
12'd3229: return "hpmcounter29h";
12'd3230: return "hpmcounter30h";
12'd3231: return "hpmcounter31h";
12'd256: return "sstatus";
12'd258: return "sedeleg";
12'd259: return "sideleg";
12'd260: return "sie";
12'd261: return "stvec";
12'd262: return "scounteren";
12'd320: return "sscratch";
12'd321: return "sepc";
12'd322: return "scause";
12'd323: return "stval";
12'd324: return "sip";
12'd384: return "satp";
12'd3857: return "mvendorid";
12'd3858: return "marchid";
12'd3859: return "mimpid";
12'd3860: return "mhartid";
12'd768: return "mstatus";
12'd769: return "misa";
12'd770: return "medeleg";
12'd771: return "mideleg";
12'd772: return "mie";
12'd773: return "mtvec";
12'd774: return "mcounteren";
12'd832: return "mscratch";
12'd833: return "mepc";
12'd834: return "mcause";
12'd835: return "mtval";
12'd836: return "mip";
12'd928: return "pmpcfg0";
12'd929: return "pmpcfg1";
12'd930: return "pmpcfg2";
12'd931: return "pmpcfg3";
12'd944: return "pmpaddr0";
12'd945: return "pmpaddr1";
12'd946: return "pmpaddr2";
12'd947: return "pmpaddr3";
12'd948: return "pmpaddr4";
12'd949: return "pmpaddr5";
12'd950: return "pmpaddr6";
12'd951: return "pmpaddr7";
12'd952: return "pmpaddr8";
12'd953: return "pmpaddr9";
12'd954: return "pmpaddr10";
12'd955: return "pmpaddr11";
12'd956: return "pmpaddr12";
12'd957: return "pmpaddr13";
12'd958: return "pmpaddr14";
12'd959: return "pmpaddr15";
12'd2816: return "mcycle";
12'd2818: return "minstret";
12'd2819: return "mhpmcounter3";
12'd2820: return "mhpmcounter4";
12'd2821: return "mhpmcounter5";
12'd2822: return "mhpmcounter6";
12'd2823: return "mhpmcounter7";
12'd2824: return "mhpmcounter8";
12'd2825: return "mhpmcounter9";
12'd2826: return "mhpmcounter10";
12'd2827: return "mhpmcounter11";
12'd2828: return "mhpmcounter12";
12'd2829: return "mhpmcounter13";
12'd2830: return "mhpmcounter14";
12'd2831: return "mhpmcounter15";
12'd2832: return "mhpmcounter16";
12'd2833: return "mhpmcounter17";
12'd2834: return "mhpmcounter18";
12'd2835: return "mhpmcounter19";
12'd2836: return "mhpmcounter20";
12'd2837: return "mhpmcounter21";
12'd2838: return "mhpmcounter22";
12'd2839: return "mhpmcounter23";
12'd2840: return "mhpmcounter24";
12'd2841: return "mhpmcounter25";
12'd2842: return "mhpmcounter26";
12'd2843: return "mhpmcounter27";
12'd2844: return "mhpmcounter28";
12'd2845: return "mhpmcounter29";
12'd2846: return "mhpmcounter30";
12'd2847: return "mhpmcounter31";
12'd2944: return "mcycleh";
12'd2946: return "minstreth";
12'd2947: return "mhpmcounter3h";
12'd2948: return "mhpmcounter4h";
12'd2949: return "mhpmcounter5h";
12'd2950: return "mhpmcounter6h";
12'd2951: return "mhpmcounter7h";
12'd2952: return "mhpmcounter8h";
12'd2953: return "mhpmcounter9h";
12'd2954: return "mhpmcounter10h";
12'd2955: return "mhpmcounter11h";
12'd2956: return "mhpmcounter12h";
12'd2957: return "mhpmcounter13h";
12'd2958: return "mhpmcounter14h";
12'd2959: return "mhpmcounter15h";
12'd2960: return "mhpmcounter16h";
12'd2961: return "mhpmcounter17h";
12'd2962: return "mhpmcounter18h";
12'd2963: return "mhpmcounter19h";
12'd2964: return "mhpmcounter20h";
12'd2965: return "mhpmcounter21h";
12'd2966: return "mhpmcounter22h";
12'd2967: return "mhpmcounter23h";
12'd2968: return "mhpmcounter24h";
12'd2969: return "mhpmcounter25h";
12'd2970: return "mhpmcounter26h";
12'd2971: return "mhpmcounter27h";
12'd2972: return "mhpmcounter28h";
12'd2973: return "mhpmcounter29h";
12'd2974: return "mhpmcounter30h";
12'd2975: return "mhpmcounter31h";
12'd803: return "mhpmevent3";
12'd804: return "mhpmevent4";
12'd805: return "mhpmevent5";
12'd806: return "mhpmevent6";
12'd807: return "mhpmevent7";
12'd808: return "mhpmevent8";
12'd809: return "mhpmevent9";
12'd810: return "mhpmevent10";
12'd811: return "mhpmevent11";
12'd812: return "mhpmevent12";
12'd813: return "mhpmevent13";
12'd814: return "mhpmevent14";
12'd815: return "mhpmevent15";
12'd816: return "mhpmevent16";
12'd817: return "mhpmevent17";
12'd818: return "mhpmevent18";
12'd819: return "mhpmevent19";
12'd820: return "mhpmevent20";
12'd821: return "mhpmevent21";
12'd822: return "mhpmevent22";
12'd823: return "mhpmevent23";
12'd824: return "mhpmevent24";
12'd825: return "mhpmevent25";
12'd826: return "mhpmevent26";
12'd827: return "mhpmevent27";
12'd828: return "mhpmevent28";
12'd829: return "mhpmevent29";
12'd830: return "mhpmevent30";
12'd831: return "mhpmevent31";
12'd1952: return "tselect";
12'd1953: return "tdata1";
12'd1954: return "tdata2";
12'd1955: return "tdata3";
12'd1968: return "dcsr";
12'd1969: return "dpc";
12'd1970: return "dscratch";
12'd512: return "hstatus";
12'd514: return "hedeleg";
12'd515: return "hideleg";
12'd516: return "hie";
12'd517: return "htvec";
12'd576: return "hscratch";
12'd577: return "hepc";
12'd578: return "hcause";
12'd579: return "hbadaddr";
12'd580: return "hip";
12'd896: return "mbase";
12'd897: return "mbound";
12'd898: return "mibase";
12'd899: return "mibound";
12'd900: return "mdbase";
12'd901: return "mdbound";
12'd800: return "mcountinhibit";
default: return $sformatf("0x%x", csr_addr);
endcase
endfunction
int unsigned cycle;
string decoded_str;
int file_handle;
string file_name;
logic[4:0] rd_addr = inst_i[11:7];
logic[4:0] rs1_addr = inst_i[19:15];
logic[4:0] rs2_addr = inst_i[24:20];
function automatic void decode_u_insn(input string mnemonic);
decoded_str = $sformatf("%s\tx%0d,0x%0x", mnemonic, rd_addr, {inst_i[31:12]});
endfunction
function automatic void decode_j_insn(input string mnemonic);
decoded_str = $sformatf("%s\tx%0d,%0x", mnemonic, rd_addr,
{{12{inst_i[31]}}, inst_i[19:12], inst_i[20], inst_i[30:21], 1'b0});
endfunction
function automatic void decode_i_jalr_insn(input string mnemonic);
decoded_str = $sformatf("%s\tx%0d,%0d(x%0d)", mnemonic, rd_addr,
$signed({{20 {inst_i[31]}}, inst_i[31:20]}), rs1_addr);
endfunction
function automatic void decode_b_insn(input string mnemonic);
logic [31:0] branch_target;
logic [31:0] imm;
// We cannot use rvfi_pc_wdata for conditional jumps.
imm = $signed({ {19 {inst_i[31]}}, inst_i[31], inst_i[7],
inst_i[30:25], inst_i[11:8], 1'b0 });
branch_target = pc_i + imm;
decoded_str = $sformatf("%s\tx%0d,x%0d,%0x", mnemonic, rs1_addr, rs2_addr, branch_target);
endfunction
function automatic void decode_i_insn(input string mnemonic);
decoded_str = $sformatf("%s\tx%0d,x%0d,%0d", mnemonic, rd_addr, rs1_addr,
$signed({{20 {inst_i[31]}}, inst_i[31:20]}));
endfunction
function automatic void decode_i_shift_insn(input string mnemonic);
logic [4:0] shamt;
shamt = {inst_i[24:20]};
decoded_str = $sformatf("%s\tx%0d,x%0d,0x%0x", mnemonic, rd_addr, rs1_addr, shamt);
endfunction
function automatic void decode_r_insn(input string mnemonic);
decoded_str = $sformatf("%s\tx%0d,x%0d,x%0d", mnemonic, rd_addr, rs1_addr, rs2_addr);
endfunction
function automatic void decode_csr_insn(input string mnemonic);
logic [11:0] csr;
string csr_name;
csr = inst_i[31:20];
csr_name = get_csr_name(csr);
if (!inst_i[14]) begin
decoded_str = $sformatf("%s\tx%0d,%s,x%0d", mnemonic, rd_addr, csr_name, rs1_addr);
end else begin
decoded_str = $sformatf("%s\tx%0d,%s,%0d", mnemonic, rd_addr, csr_name, { 27'b0, inst_i[19:15]});
end
endfunction
function automatic void decode_mnemonic(input string mnemonic);
decoded_str = mnemonic;
endfunction
function automatic void decode_load_insn();
string mnemonic;
logic [2:0] size;
size = inst_i[14:12];
if (size == 3'b000) begin
mnemonic = "lb";
end else if (size == 3'b001) begin
mnemonic = "lh";
end else if (size == 3'b010) begin
mnemonic = "lw";
end else if (size == 3'b100) begin
mnemonic = "lbu";
end else if (size == 3'b101) begin
mnemonic = "lhu";
end else begin
decode_mnemonic("INVALID");
return;
end
decoded_str = $sformatf("%s\tx%0d,%0d(x%0d)", mnemonic, rd_addr,
$signed({{20 {inst_i[31]}}, inst_i[31:20]}), rs1_addr);
endfunction
function automatic void decode_store_insn();
string mnemonic;
if (inst_i[13:12] == 2'b00) begin
mnemonic = "sb";
end else if (inst_i[13:12] == 2'b01) begin
mnemonic = "sh";
end else if (inst_i[13:12] == 2'b10) begin
mnemonic = "sw";
end else begin
decode_mnemonic("INVALID");
return;
end
if (!inst_i[14]) begin
decoded_str = $sformatf("%s\tx%0d,%0d(x%0d)", mnemonic, rs2_addr,
$signed({ {20 {inst_i[31]}}, inst_i[31:25], inst_i[11:7] }), rs1_addr);
end else begin
decode_mnemonic("INVALID");
end
endfunction
function automatic string get_fence_description(logic [3:0] bits);
string desc = "";
if (bits[3]) begin
desc = {desc, "i"};
end
if (bits[2]) begin
desc = {desc, "o"};
end
if (bits[1]) begin
desc = {desc, "r"};
end
if (bits[0]) begin
desc = {desc, "w"};
end
return desc;
endfunction
function automatic void decode_fence();
string predecessor;
string successor;
predecessor = get_fence_description(inst_i[27:24]);
successor = get_fence_description(inst_i[23:20]);
decoded_str = $sformatf("fence\t%s,%s", predecessor, successor);
endfunction
always_comb begin
decoded_str = "";
unique casez (inst_i)
INSN_LUI: decode_u_insn("lui");
INSN_AUIPC: decode_u_insn("auipc");
INSN_JAL: decode_j_insn("jal");
INSN_JALR: decode_i_jalr_insn("jalr");
// BRANCH
INSN_BEQ: decode_b_insn("beq");
INSN_BNE: decode_b_insn("bne");
INSN_BLT: decode_b_insn("blt");
INSN_BGE: decode_b_insn("bge");
INSN_BLTU: decode_b_insn("bltu");
INSN_BGEU: decode_b_insn("bgeu");
// OPIMM
INSN_ADDI: begin
if (inst_i == 32'h00_00_00_13) begin
// TODO: objdump doesn't decode this as nop currently, even though it would be helpful
// Decide what to do here: diverge from objdump, or make the trace less readable to
// users.
//decode_mnemonic("nop");
decode_i_insn("addi");
end else begin
decode_i_insn("addi");
end
end
INSN_SLTI: decode_i_insn("slti");
INSN_SLTIU: decode_i_insn("sltiu");
INSN_XORI: decode_i_insn("xori");
INSN_ORI: decode_i_insn("ori");
INSN_ANDI: decode_i_insn("andi");
INSN_SLLI: decode_i_shift_insn("slli");
INSN_SRLI: decode_i_shift_insn("srli");
INSN_SRAI: decode_i_shift_insn("srai");
// OP
INSN_ADD: decode_r_insn("add");
INSN_SUB: decode_r_insn("sub");
INSN_SLL: decode_r_insn("sll");
INSN_SLT: decode_r_insn("slt");
INSN_SLTU: decode_r_insn("sltu");
INSN_XOR: decode_r_insn("xor");
INSN_SRL: decode_r_insn("srl");
INSN_SRA: decode_r_insn("sra");
INSN_OR: decode_r_insn("or");
INSN_AND: decode_r_insn("and");
// SYSTEM (CSR manipulation)
INSN_CSRRW: decode_csr_insn("csrrw");
INSN_CSRRS: decode_csr_insn("csrrs");
INSN_CSRRC: decode_csr_insn("csrrc");
INSN_CSRRWI: decode_csr_insn("csrrwi");
INSN_CSRRSI: decode_csr_insn("csrrsi");
INSN_CSRRCI: decode_csr_insn("csrrci");
// SYSTEM (others)
INSN_ECALL: decode_mnemonic("ecall");
INSN_EBREAK: decode_mnemonic("ebreak");
INSN_MRET: decode_mnemonic("mret");
INSN_DRET: decode_mnemonic("dret");
INSN_WFI: decode_mnemonic("wfi");
// RV32M
INSN_MUL: decode_r_insn("mul");
INSN_MULH: decode_r_insn("mulh");
INSN_MULHSU: decode_r_insn("mulhsu");
INSN_MULHU: decode_r_insn("mulhu");
INSN_DIV: decode_r_insn("div");
INSN_DIVU: decode_r_insn("divu");
INSN_REM: decode_r_insn("rem");
INSN_REMU: decode_r_insn("remu");
// LOAD & STORE
INSN_LOAD: decode_load_insn();
INSN_STORE: decode_store_insn();
// MISC-MEM
INSN_FENCE: decode_fence();
INSN_FENCEI: decode_mnemonic("fence.i");
default: decode_mnemonic("INVALID");
endcase
end
initial begin
string file_name_base = "trace_core";
$sformat(file_name, "%s.log", file_name_base);
$display("Writing execution trace to %s", file_name);
file_handle = $fopen(file_name, "w");
$fwrite(file_handle, "Time\tCycle\tPC\tInsn\tDecoded instruction\n");
end
function automatic void printbuffer_dumpline();
$fwrite(file_handle, "%15t\t%d\t%h\t%s\t%s", $time, cycle, pc_i, inst_i, decoded_str);
$fwrite(file_handle, "\n");
endfunction
// log execution
always @(posedge clk) begin
if (inst_valid_i) begin
printbuffer_dumpline();
end
end
// cycle counter
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
cycle <= 0;
end else begin
cycle <= cycle + 1;
end
end
endmodule

View File

@ -1,90 +1,88 @@
PROG := ../sdk/examples/simple/simple.mem
PROG_DIR := $(shell dirname $(PROG))
MAKE := make
VERILATOR := verilator
VERI_FLAGS += +vcd
VERI_CFLAGS +=
VERI_VFLAGS += -DRVFI
TRACE_ENABLE := 1
RTL_FILES = ../rtl.flist
VERI_OBJ_DIR := cobj_dir
ifeq ($(findstring +vcd,$(VERI_FLAGS)),+vcd)
VERI_TRACE = "--trace"
VERI_CFLAGS += "-DVCD_TRACE"
else
VERI_TRACE =
endif
SIM_SRC := sim_jtag.sv
SIM_SRC += tb_top_verilator.sv \
tb_top_verilator.cpp
SIM_TOP_MODULE := tb_top_verilator
.DEFAULT_GOAL := sim
all: sim
.PHONY: recompile
recompile:
rm -rf $(VERI_OBJ_DIR) testbench_verilator
$(MAKE) -C ./remote_bitbang clean
$(MAKE) -C $(PROG_DIR) clean
$(MAKE) compile
.PHONY: compile
compile: remote_bitbang/librbs.so $(PROG) testbench_verilator
testbench_verilator:
$(VERILATOR) --cc --sv --exe \
$(VERI_TRACE) \
--Wno-lint --Wno-UNOPTFLAT \
--Wno-MODDUP --top-module \
$(SIM_TOP_MODULE) \
-f $(RTL_FILES) \
$(SIM_SRC) \
--Mdir $(VERI_OBJ_DIR) \
$(VERI_VFLAGS) \
-LDFLAGS "-L../remote_bitbang \
-Wl,--enable-new-dtags -Wl,-rpath,remote_bitbang -lrbs" \
-CFLAGS "-std=gnu++11 $(VERI_CFLAGS)"
$(MAKE) -C $(VERI_OBJ_DIR) -f V$(SIM_TOP_MODULE).mk
cp $(VERI_OBJ_DIR)/V$(SIM_TOP_MODULE) testbench_verilator
remote_bitbang/librbs.so:
$(MAKE) -C ./remote_bitbang all
$(PROG):
$(MAKE) -C $(PROG_DIR)
.PHONY: run
run:
./testbench_verilator "+firmware=$(PROG)"
.PHONY: sim
sim: recompile run
.PHONY: clean
clean:
rm -rf $(VERI_OBJ_DIR) testbench_verilator *.log *.vcd
$(MAKE) -C ./remote_bitbang clean
$(MAKE) -C $(PROG_DIR) clean
.PHONY: help
help:
@echo 'rebuild all:'
@echo 'make PROG=/path/file.mem recompile'
@echo 'run directly:'
@echo 'make PROG=/path/file.mem run'
@echo 'rebuild & run:'
@echo 'make PROG=/path/file.mem sim'
@echo 'clean obj files:'
@echo 'make PROG=/path/file.mem clean'
PROG := ../sdk/examples/simple/simple.mem
PROG_DIR := $(shell dirname $(PROG))
MAKE := make
VERILATOR := verilator
VERI_FLAGS += +vcd
VERI_CFLAGS +=
VERI_VFLAGS += -DTRACE_ENABLED
RTL_FILES = ../rtl.flist
VERI_OBJ_DIR := cobj_dir
ifeq ($(findstring +vcd,$(VERI_FLAGS)),+vcd)
VERI_TRACE = "--trace"
VERI_CFLAGS += "-DVCD_TRACE"
else
VERI_TRACE =
endif
SIM_SRC := sim_jtag.sv
SIM_SRC += tb_top_verilator.sv \
tb_top_verilator.cpp
SIM_TOP_MODULE := tb_top_verilator
.DEFAULT_GOAL := sim
all: sim
.PHONY: recompile
recompile:
rm -rf $(VERI_OBJ_DIR) testbench_verilator
$(MAKE) -C ./remote_bitbang clean
$(MAKE) -C $(PROG_DIR) clean
$(MAKE) compile
.PHONY: compile
compile: remote_bitbang/librbs.so $(PROG) testbench_verilator
testbench_verilator:
$(VERILATOR) --cc --sv --exe \
$(VERI_TRACE) \
--Wno-lint --Wno-UNOPTFLAT \
--Wno-MODDUP --top-module \
$(SIM_TOP_MODULE) \
-f $(RTL_FILES) \
$(SIM_SRC) \
--Mdir $(VERI_OBJ_DIR) \
$(VERI_VFLAGS) \
-LDFLAGS "-L../remote_bitbang \
-Wl,--enable-new-dtags -Wl,-rpath,remote_bitbang -lrbs" \
-CFLAGS "-std=gnu++11 $(VERI_CFLAGS)"
$(MAKE) -C $(VERI_OBJ_DIR) -f V$(SIM_TOP_MODULE).mk
cp $(VERI_OBJ_DIR)/V$(SIM_TOP_MODULE) testbench_verilator
remote_bitbang/librbs.so:
$(MAKE) -C ./remote_bitbang all
$(PROG):
$(MAKE) -C $(PROG_DIR)
.PHONY: run
run:
./testbench_verilator "+firmware=$(PROG)"
.PHONY: sim
sim: recompile run
.PHONY: clean
clean:
rm -rf $(VERI_OBJ_DIR) testbench_verilator *.log *.vcd
$(MAKE) -C ./remote_bitbang clean
$(MAKE) -C $(PROG_DIR) clean
.PHONY: help
help:
@echo 'rebuild all:'
@echo 'make PROG=/path/file.mem recompile'
@echo 'run directly:'
@echo 'make PROG=/path/file.mem run'
@echo 'rebuild & run:'
@echo 'make PROG=/path/file.mem sim'
@echo 'clean obj files:'
@echo 'make PROG=/path/file.mem clean'

View File

@ -1,108 +1,107 @@
// Copyright 2018 Robert Balas <balasr@student.ethz.ch>
//
// 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.
// Top level wrapper for a verilator RI5CY testbench
// Contributor: Robert Balas <balasr@student.ethz.ch>
#include "svdpi.h"
#include "Vtb_top_verilator__Dpi.h"
#include "Vtb_top_verilator.h"
#include "verilated_vcd_c.h"
#include "verilated.h"
#include <iostream>
#include <iomanip>
#include <fstream>
#include <exception>
#include <cstdio>
#include <cstdint>
#include <cerrno>
//void dump_memory();
double sc_time_stamp();
static vluint64_t t = 0;
Vtb_top_verilator *top;
int main(int argc, char **argv, char **env)
{
Verilated::commandArgs(argc, argv);
Verilated::traceEverOn(true);
top = new Vtb_top_verilator();
//svSetScope(svGetScopeFromName(
// "TOP.tb_top_verilator.u_ram.ram"));
//Verilated::scopesDump();
#ifdef VCD_TRACE
VerilatedVcdC *tfp = new VerilatedVcdC;
top->trace(tfp, 99);
tfp->open("verilator_tb.vcd");
#endif
top->fetch_enable_i = 1;
top->clk_i = 0;
top->rst_ni = 0;
top->eval();
//dump_memory();
while (!Verilated::gotFinish()) {
if (t > 40)
top->rst_ni = 1;
top->clk_i = !top->clk_i;
top->eval();
#ifdef VCD_TRACE
tfp->dump(t);
#endif
t += 5;
if (t > 1000)
break;
}
#ifdef VCD_TRACE
tfp->close();
#endif
delete top;
exit(0);
}
double sc_time_stamp()
{
return t;
}
/*
void dump_memory()
{
errno = 0;
std::ofstream mem_file;
svLogicVecVal addr = {0};
mem_file.exceptions(std::ofstream::failbit | std::ofstream::badbit);
try {
mem_file.open("memory_dump.bin");
for (size_t i = 0; i < 1048576; i++) {
addr.aval = i;
uint32_t val = read_byte(&addr);
mem_file << std::setfill('0') << std::setw(2) << std::hex << val
<< std::endl;
}
mem_file.close();
std::cout << "finished dumping memory" << std::endl;
} catch (std::ofstream::failure e) {
std::cerr << "exception opening/reading/closing file memory_dump.bin\n";
}
}
*/
// Copyright 2018 Robert Balas <balasr@student.ethz.ch>
//
// 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.
// Top level wrapper for a verilator RI5CY testbench
// Contributor: Robert Balas <balasr@student.ethz.ch>
#include "svdpi.h"
#include "Vtb_top_verilator__Dpi.h"
#include "Vtb_top_verilator.h"
#include "verilated_vcd_c.h"
#include "verilated.h"
#include <iostream>
#include <iomanip>
#include <fstream>
#include <exception>
#include <cstdio>
#include <cstdint>
#include <cerrno>
//void dump_memory();
double sc_time_stamp();
static vluint64_t t = 0;
Vtb_top_verilator *top;
int main(int argc, char **argv, char **env)
{
Verilated::commandArgs(argc, argv);
Verilated::traceEverOn(true);
top = new Vtb_top_verilator();
//svSetScope(svGetScopeFromName(
// "TOP.tb_top_verilator.u_ram.ram"));
//Verilated::scopesDump();
#ifdef VCD_TRACE
VerilatedVcdC *tfp = new VerilatedVcdC;
top->trace(tfp, 99);
tfp->open("verilator_tb.vcd");
#endif
top->clk_i = 0;
top->rst_ni = 0;
top->eval();
//dump_memory();
while (!Verilated::gotFinish()) {
if (t > 40)
top->rst_ni = 1;
top->clk_i = !top->clk_i;
top->eval();
#ifdef VCD_TRACE
tfp->dump(t);
#endif
t += 5;
//if (t > 5000)
// break;
}
#ifdef VCD_TRACE
tfp->close();
#endif
delete top;
exit(0);
}
double sc_time_stamp()
{
return t;
}
/*
void dump_memory()
{
errno = 0;
std::ofstream mem_file;
svLogicVecVal addr = {0};
mem_file.exceptions(std::ofstream::failbit | std::ofstream::badbit);
try {
mem_file.open("memory_dump.bin");
for (size_t i = 0; i < 1048576; i++) {
addr.aval = i;
uint32_t val = read_byte(&addr);
mem_file << std::setfill('0') << std::setw(2) << std::hex << val
<< std::endl;
}
mem_file.close();
std::cout << "finished dumping memory" << std::endl;
} catch (std::ofstream::failure e) {
std::cerr << "exception opening/reading/closing file memory_dump.bin\n";
}
}
*/

View File

@ -1,48 +1,74 @@
// Copyright 2018 Robert Balas <balasr@student.ethz.ch>
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this 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.
// Top level wrapper for a verilator RI5CY testbench
// Contributor: Robert Balas <balasr@student.ethz.ch>
module tb_top_verilator #(
) (
input clk_i,
input rst_ni,
input fetch_enable_i
);
initial begin: load_prog
automatic logic [1023:0] firmware;
if($value$plusargs("firmware=%s", firmware)) begin
//if($test$plusargs("verbose"))
$display("[TESTBENCH] %t: loading firmware %0s ...",
$time, firmware);
$readmemh (firmware, u_tinyriscv_soc_top.u_rom.u_gen_ram.ram);
//$display("mem[0x80]=0x%x", u_ram.ram.mem[32]);
//$display("mem[0x84]=0x%x", u_ram.ram.mem[33]);
end else begin
$display("No firmware specified");
end
end
tinyriscv_soc_top u_tinyriscv_soc_top(
.clk(clk_i),
.rst_ext_i(rst_ni)
);
endmodule // tb_top_verilator
// Copyright 2018 Robert Balas <balasr@student.ethz.ch>
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this 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.
// Top level wrapper for a verilator RI5CY testbench
// Contributor: Robert Balas <balasr@student.ethz.ch>
module tb_top_verilator #(
) (
input clk_i,
input rst_ni
);
wire[31:0] x26 = u_tinyriscv_soc_top.u_tinyriscv_core.u_gpr_reg.regs[26];
wire[31:0] x27 = u_tinyriscv_soc_top.u_tinyriscv_core.u_gpr_reg.regs[27];
initial begin: load_prog
automatic logic [1023:0] firmware;
if($value$plusargs("firmware=%s", firmware)) begin
//if($test$plusargs("verbose"))
$display("[TESTBENCH] %t: loading firmware %0s ...",
$time, firmware);
$readmemh (firmware, u_tinyriscv_soc_top.u_rom.u_gen_ram.ram);
end else begin
$display("No firmware specified");
end
end
always @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
end else begin
if (x26 == 32'b1) begin
if (x27 == 32'b1) begin
$display("~~~~~~~~~~~~~~~~~~~ TEST_PASS ~~~~~~~~~~~~~~~~~~~");
$display("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
$display("~~~~~~~~~ ##### ## #### #### ~~~~~~~~~");
$display("~~~~~~~~~ # # # # # # ~~~~~~~~~");
$display("~~~~~~~~~ # # # # #### #### ~~~~~~~~~");
$display("~~~~~~~~~ ##### ###### # #~~~~~~~~~");
$display("~~~~~~~~~ # # # # # # #~~~~~~~~~");
$display("~~~~~~~~~ # # # #### #### ~~~~~~~~~");
$display("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
end else begin
$display("~~~~~~~~~~~~~~~~~~~ TEST_FAIL ~~~~~~~~~~~~~~~~~~~~");
$display("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
$display("~~~~~~~~~~###### ## # # ~~~~~~~~~~");
$display("~~~~~~~~~~# # # # # ~~~~~~~~~~");
$display("~~~~~~~~~~##### # # # # ~~~~~~~~~~");
$display("~~~~~~~~~~# ###### # # ~~~~~~~~~~");
$display("~~~~~~~~~~# # # # # ~~~~~~~~~~");
$display("~~~~~~~~~~# # # # ######~~~~~~~~~~");
$display("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
end
$finish;
end
end
end
tinyriscv_soc_top u_tinyriscv_soc_top(
.clk(clk_i),
.rst_ext_i(rst_ni)
);
endmodule // tb_top_verilator