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

View File

@ -1,318 +1,324 @@
/* /*
Copyright 2019 Blue Liang, liangkangnan@163.com Copyright 2019 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
`include "defines.sv" `include "defines.sv"
// tinyriscv处理器核顶层模块 // tinyriscv处理器核顶层模块
module tinyriscv_core( module tinyriscv_core(
input wire clk, input wire clk,
input wire rst_n, input wire rst_n,
output wire[31:0] dbus_addr_o, output wire[31:0] dbus_addr_o,
input wire[31:0] dbus_data_i, input wire[31:0] dbus_data_i,
output wire[31:0] dbus_data_o, output wire[31:0] dbus_data_o,
output wire[3:0] dbus_sel_o, output wire[3:0] dbus_sel_o,
output wire dbus_we_o, output wire dbus_we_o,
output wire dbus_req_valid_o, output wire dbus_req_valid_o,
input wire dbus_req_ready_i, input wire dbus_req_ready_i,
input wire dbus_rsp_valid_i, input wire dbus_rsp_valid_i,
output wire dbus_rsp_ready_o, output wire dbus_rsp_ready_o,
output wire[31:0] ibus_addr_o, // 取指地址 output wire[31:0] ibus_addr_o, // 取指地址
input wire[31:0] ibus_data_i, // 取到的指令内容 input wire[31:0] ibus_data_i, // 取到的指令内容
output wire[31:0] ibus_data_o, output wire[31:0] ibus_data_o,
output wire[3:0] ibus_sel_o, output wire[3:0] ibus_sel_o,
output wire ibus_we_o, output wire ibus_we_o,
output wire ibus_req_valid_o, output wire ibus_req_valid_o,
input wire ibus_req_ready_i, input wire ibus_req_ready_i,
input wire ibus_rsp_valid_i, input wire ibus_rsp_valid_i,
output wire ibus_rsp_ready_o, output wire ibus_rsp_ready_o,
input wire jtag_halt_i, input wire jtag_halt_i,
input wire[`INT_WIDTH-1:0] int_i // 中断输入信号 input wire[`INT_WIDTH-1:0] int_i // 中断输入信号
); );
// ifu模块输出信号 // ifu模块输出信号
wire[31:0] ifetch_inst_o; wire[31:0] ifetch_inst_o;
wire[31:0] ifetch_pc_o; wire[31:0] ifetch_pc_o;
wire ifetch_inst_valid_o; wire ifetch_inst_valid_o;
// ifu_idu模块输出信号 // ifu_idu模块输出信号
wire[31:0] if_inst_o; wire[31:0] if_inst_o;
wire[31:0] if_inst_addr_o; wire[31:0] if_inst_addr_o;
wire[`INT_WIDTH-1:0] if_int_flag_o; wire[`INT_WIDTH-1:0] if_int_flag_o;
// idu模块输出信号 // idu模块输出信号
wire[31:0] id_inst_o; wire[31:0] id_inst_o;
wire[31:0] id_inst_addr_o; wire[31:0] id_inst_addr_o;
wire[`DECINFO_WIDTH-1:0] id_dec_info_bus_o; wire[`DECINFO_WIDTH-1:0] id_dec_info_bus_o;
wire[31:0] id_dec_imm_o; wire[31:0] id_dec_imm_o;
wire[31:0] id_dec_pc_o; wire[31:0] id_dec_pc_o;
wire[4:0] id_rs1_raddr_o; wire[4:0] id_rs1_raddr_o;
wire[4:0] id_rs2_raddr_o; wire[4:0] id_rs2_raddr_o;
wire[4:0] id_rd_waddr_o; wire[4:0] id_rd_waddr_o;
wire id_rd_we_o; wire id_rd_we_o;
wire id_stall_o; wire id_stall_o;
wire[31:0] id_rs1_rdata_o; wire[31:0] id_rs1_rdata_o;
wire[31:0] id_rs2_rdata_o; wire[31:0] id_rs2_rdata_o;
// idu_exu模块输出信号 // idu_exu模块输出信号
wire[31:0] ie_inst_o; wire[31:0] ie_inst_o;
wire[31:0] ie_inst_addr_o; wire[31:0] ie_inst_addr_o;
wire[`DECINFO_WIDTH-1:0] ie_dec_info_bus_o; wire[`DECINFO_WIDTH-1:0] ie_dec_info_bus_o;
wire[31:0] ie_dec_imm_o; wire[31:0] ie_dec_imm_o;
wire[31:0] ie_dec_pc_o; wire[31:0] ie_dec_pc_o;
wire[31:0] ie_rs1_rdata_o; wire[31:0] ie_rs1_rdata_o;
wire[31:0] ie_rs2_rdata_o; wire[31:0] ie_rs2_rdata_o;
wire[4:0] ie_rd_waddr_o; wire[4:0] ie_rd_waddr_o;
wire ie_rd_we_o; wire ie_rd_we_o;
// exu模块输出信号 // exu模块输出信号
wire[31:0] ex_mem_wdata_o; wire[31:0] ex_mem_wdata_o;
wire[31:0] ex_mem_addr_o; wire[31:0] ex_mem_addr_o;
wire ex_mem_we_o; wire ex_mem_we_o;
wire[3:0] ex_mem_sel_o; wire[3:0] ex_mem_sel_o;
wire ex_mem_req_valid_o; wire ex_mem_req_valid_o;
wire ex_mem_rsp_ready_o; wire ex_mem_rsp_ready_o;
wire ex_mem_access_misaligned_o; wire ex_mem_access_misaligned_o;
wire[31:0] ex_reg_wdata_o; wire[31:0] ex_reg_wdata_o;
wire ex_reg_we_o; wire ex_reg_we_o;
wire[4:0] ex_reg_waddr_o; wire[4:0] ex_reg_waddr_o;
wire ex_hold_flag_o; wire ex_hold_flag_o;
wire ex_jump_flag_o; wire ex_jump_flag_o;
wire[31:0] ex_jump_addr_o; wire[31:0] ex_jump_addr_o;
wire[31:0] ex_csr_wdata_o; wire[31:0] ex_csr_wdata_o;
wire ex_csr_we_o; wire ex_csr_we_o;
wire[31:0] ex_csr_waddr_o; wire[31:0] ex_csr_waddr_o;
wire[31:0] ex_csr_raddr_o; wire[31:0] ex_csr_raddr_o;
wire ex_inst_ecall_o; wire ex_inst_ecall_o;
wire ex_inst_ebreak_o; wire ex_inst_ebreak_o;
wire ex_inst_mret_o; wire ex_inst_mret_o;
// gpr_reg模块输出信号 // gpr_reg模块输出信号
wire[31:0] regs_rdata1_o; wire[31:0] regs_rdata1_o;
wire[31:0] regs_rdata2_o; wire[31:0] regs_rdata2_o;
// csr_reg模块输出信号 // csr_reg模块输出信号
wire[31:0] csr_ex_data_o; wire[31:0] csr_ex_data_o;
wire[31:0] csr_clint_data_o; wire[31:0] csr_clint_data_o;
wire[31:0] csr_mtvec_o; wire[31:0] csr_mtvec_o;
wire[31:0] csr_mepc_o; wire[31:0] csr_mepc_o;
wire[31:0] csr_mstatus_o; wire[31:0] csr_mstatus_o;
// pipe_ctrl模块输出信号 // pipe_ctrl模块输出信号
wire[31:0] ctrl_flush_addr_o; wire[31:0] ctrl_flush_addr_o;
wire ctrl_flush_o; wire ctrl_flush_o;
wire[`STALL_WIDTH-1:0] ctrl_stall_o; wire[`STALL_WIDTH-1:0] ctrl_stall_o;
// clint模块输出信号 // clint模块输出信号
wire clint_csr_we_o; wire clint_csr_we_o;
wire[31:0] clint_csr_waddr_o; wire[31:0] clint_csr_waddr_o;
wire[31:0] clint_csr_wdata_o; wire[31:0] clint_csr_wdata_o;
wire clint_stall_flag_o; wire clint_stall_flag_o;
wire[31:0] clint_int_addr_o; wire[31:0] clint_int_addr_o;
wire clint_int_assert_o; wire clint_int_assert_o;
assign dbus_addr_o = ex_mem_addr_o; assign dbus_addr_o = ex_mem_addr_o;
assign dbus_data_o = ex_mem_wdata_o; assign dbus_data_o = ex_mem_wdata_o;
assign dbus_we_o = ex_mem_we_o; assign dbus_we_o = ex_mem_we_o;
assign dbus_sel_o = ex_mem_sel_o; assign dbus_sel_o = ex_mem_sel_o;
assign dbus_req_valid_o = ex_mem_req_valid_o; assign dbus_req_valid_o = ex_mem_req_valid_o;
assign dbus_rsp_ready_o = ex_mem_rsp_ready_o; assign dbus_rsp_ready_o = ex_mem_rsp_ready_o;
ifu u_ifu( ifu u_ifu(
.clk(clk), .clk(clk),
.rst_n(rst_n), .rst_n(rst_n),
.flush_addr_i(ctrl_flush_addr_o), .flush_addr_i(ctrl_flush_addr_o),
.stall_i(ctrl_stall_o), .stall_i(ctrl_stall_o),
.flush_i(ctrl_flush_o), .flush_i(ctrl_flush_o),
.jtag_halt_i(jtag_halt_i), .jtag_halt_i(jtag_halt_i),
.inst_o(ifetch_inst_o), .inst_o(ifetch_inst_o),
.pc_o(ifetch_pc_o), .pc_o(ifetch_pc_o),
.inst_valid_o(ifetch_inst_valid_o), .inst_valid_o(ifetch_inst_valid_o),
.ibus_addr_o(ibus_addr_o), .ibus_addr_o(ibus_addr_o),
.ibus_data_i(ibus_data_i), .ibus_data_i(ibus_data_i),
.ibus_data_o(ibus_data_o), .ibus_data_o(ibus_data_o),
.ibus_sel_o(ibus_sel_o), .ibus_sel_o(ibus_sel_o),
.ibus_we_o(ibus_we_o), .ibus_we_o(ibus_we_o),
.req_valid_o(ibus_req_valid_o), .req_valid_o(ibus_req_valid_o),
.req_ready_i(ibus_req_ready_i), .req_ready_i(ibus_req_ready_i),
.rsp_valid_i(ibus_rsp_valid_i), .rsp_valid_i(ibus_rsp_valid_i),
.rsp_ready_o(ibus_rsp_ready_o) .rsp_ready_o(ibus_rsp_ready_o)
); );
pipe_ctrl u_pipe_ctrl( pipe_ctrl u_pipe_ctrl(
.clk(clk), .clk(clk),
.rst_n(rst_n), .rst_n(rst_n),
.stall_from_id_i(id_stall_o), .stall_from_id_i(id_stall_o),
.stall_from_ex_i(ex_hold_flag_o), .stall_from_ex_i(ex_hold_flag_o),
.stall_from_jtag_i(1'b0), .stall_from_jtag_i(1'b0),
.stall_from_clint_i(clint_stall_flag_o), .stall_from_clint_i(clint_stall_flag_o),
.jump_assert_i(ex_jump_flag_o), .jump_assert_i(ex_jump_flag_o),
.jump_addr_i(ex_jump_addr_o), .jump_addr_i(ex_jump_addr_o),
.flush_o(ctrl_flush_o), .flush_o(ctrl_flush_o),
.stall_o(ctrl_stall_o), .stall_o(ctrl_stall_o),
.flush_addr_o(ctrl_flush_addr_o) .flush_addr_o(ctrl_flush_addr_o)
); );
gpr_reg u_gpr_reg( gpr_reg u_gpr_reg(
.clk(clk), .clk(clk),
.rst_n(rst_n), .rst_n(rst_n),
.we_i(ex_reg_we_o), .we_i(ex_reg_we_o),
.waddr_i(ex_reg_waddr_o), .waddr_i(ex_reg_waddr_o),
.wdata_i(ex_reg_wdata_o), .wdata_i(ex_reg_wdata_o),
.raddr1_i(id_rs1_raddr_o), .raddr1_i(id_rs1_raddr_o),
.rdata1_o(regs_rdata1_o), .rdata1_o(regs_rdata1_o),
.raddr2_i(id_rs2_raddr_o), .raddr2_i(id_rs2_raddr_o),
.rdata2_o(regs_rdata2_o) .rdata2_o(regs_rdata2_o)
); );
csr_reg u_csr_reg( csr_reg u_csr_reg(
.clk(clk), .clk(clk),
.rst_n(rst_n), .rst_n(rst_n),
.exu_we_i(ex_csr_we_o), .exu_we_i(ex_csr_we_o),
.exu_raddr_i(ex_csr_raddr_o), .exu_raddr_i(ex_csr_raddr_o),
.exu_waddr_i(ex_csr_waddr_o), .exu_waddr_i(ex_csr_waddr_o),
.exu_wdata_i(ex_csr_wdata_o), .exu_wdata_i(ex_csr_wdata_o),
.exu_rdata_o(csr_ex_data_o), .exu_rdata_o(csr_ex_data_o),
.clint_we_i(clint_csr_we_o), .clint_we_i(clint_csr_we_o),
.clint_waddr_i(clint_csr_waddr_o), .clint_waddr_i(clint_csr_waddr_o),
.clint_wdata_i(clint_csr_wdata_o), .clint_wdata_i(clint_csr_wdata_o),
.mtvec_o(csr_mtvec_o), .mtvec_o(csr_mtvec_o),
.mepc_o(csr_mepc_o), .mepc_o(csr_mepc_o),
.mstatus_o(csr_mstatus_o) .mstatus_o(csr_mstatus_o)
); );
ifu_idu u_ifu_idu( ifu_idu u_ifu_idu(
.clk(clk), .clk(clk),
.rst_n(rst_n), .rst_n(rst_n),
.inst_i(ifetch_inst_o), .inst_i(ifetch_inst_o),
.inst_addr_i(ifetch_pc_o), .inst_addr_i(ifetch_pc_o),
.stall_i(ctrl_stall_o), .stall_i(ctrl_stall_o),
.flush_i(ctrl_flush_o), .flush_i(ctrl_flush_o),
.inst_valid_i(ifetch_inst_valid_o), .inst_valid_i(ifetch_inst_valid_o),
.inst_o(if_inst_o), .inst_o(if_inst_o),
.inst_addr_o(if_inst_addr_o) .inst_addr_o(if_inst_addr_o)
); );
idu u_idu( idu u_idu(
.clk(clk), .clk(clk),
.rst_n(rst_n), .rst_n(rst_n),
.inst_i(if_inst_o), .inst_i(if_inst_o),
.rs1_rdata_i(regs_rdata1_o), .rs1_rdata_i(regs_rdata1_o),
.rs2_rdata_i(regs_rdata2_o), .rs2_rdata_i(regs_rdata2_o),
.inst_o(id_inst_o), .inst_o(id_inst_o),
.inst_addr_i(if_inst_addr_o), .inst_addr_i(if_inst_addr_o),
.rs1_rdata_o(id_rs1_rdata_o), .rs1_rdata_o(id_rs1_rdata_o),
.rs2_rdata_o(id_rs2_rdata_o), .rs2_rdata_o(id_rs2_rdata_o),
.stall_o(id_stall_o), .stall_o(id_stall_o),
.dec_info_bus_o(id_dec_info_bus_o), .dec_info_bus_o(id_dec_info_bus_o),
.dec_imm_o(id_dec_imm_o), .dec_imm_o(id_dec_imm_o),
.dec_pc_o(id_dec_pc_o), .dec_pc_o(id_dec_pc_o),
.rs1_raddr_o(id_rs1_raddr_o), .rs1_raddr_o(id_rs1_raddr_o),
.rs2_raddr_o(id_rs2_raddr_o), .rs2_raddr_o(id_rs2_raddr_o),
.rd_waddr_o(id_rd_waddr_o), .rd_waddr_o(id_rd_waddr_o),
.rd_we_o(id_rd_we_o) .rd_we_o(id_rd_we_o)
); );
idu_exu u_idu_exu( idu_exu u_idu_exu(
.clk(clk), .clk(clk),
.rst_n(rst_n), .rst_n(rst_n),
.inst_i(id_inst_o), .inst_i(id_inst_o),
.stall_i(ctrl_stall_o), .stall_i(ctrl_stall_o),
.flush_i(ctrl_flush_o), .flush_i(ctrl_flush_o),
.dec_info_bus_i(id_dec_info_bus_o), .dec_info_bus_i(id_dec_info_bus_o),
.dec_imm_i(id_dec_imm_o), .dec_imm_i(id_dec_imm_o),
.dec_pc_i(id_dec_pc_o), .dec_pc_i(id_dec_pc_o),
.rs1_rdata_i(id_rs1_rdata_o), .rs1_rdata_i(id_rs1_rdata_o),
.rs2_rdata_i(id_rs2_rdata_o), .rs2_rdata_i(id_rs2_rdata_o),
.rd_waddr_i(id_rd_waddr_o), .rd_waddr_i(id_rd_waddr_o),
.rd_we_i(id_rd_we_o), .rd_we_i(id_rd_we_o),
.inst_o(ie_inst_o), .inst_o(ie_inst_o),
.dec_info_bus_o(ie_dec_info_bus_o), .dec_info_bus_o(ie_dec_info_bus_o),
.dec_imm_o(ie_dec_imm_o), .dec_imm_o(ie_dec_imm_o),
.dec_pc_o(ie_dec_pc_o), .dec_pc_o(ie_dec_pc_o),
.rs1_rdata_o(ie_rs1_rdata_o), .rs1_rdata_o(ie_rs1_rdata_o),
.rs2_rdata_o(ie_rs2_rdata_o), .rs2_rdata_o(ie_rs2_rdata_o),
.rd_waddr_o(ie_rd_waddr_o), .rd_waddr_o(ie_rd_waddr_o),
.rd_we_o(ie_rd_we_o) .rd_we_o(ie_rd_we_o)
); );
exu u_exu( exu u_exu(
.clk(clk), .clk(clk),
.rst_n(rst_n), .rst_n(rst_n),
.reg1_rdata_i(ie_rs1_rdata_o), .reg1_rdata_i(ie_rs1_rdata_o),
.reg2_rdata_i(ie_rs2_rdata_o), .reg2_rdata_i(ie_rs2_rdata_o),
.mem_rdata_i(dbus_data_i), .mem_rdata_i(dbus_data_i),
.mem_req_ready_i(dbus_req_ready_i), .mem_req_ready_i(dbus_req_ready_i),
.mem_rsp_valid_i(dbus_rsp_valid_i), .mem_rsp_valid_i(dbus_rsp_valid_i),
.mem_wdata_o(ex_mem_wdata_o), .mem_wdata_o(ex_mem_wdata_o),
.mem_addr_o(ex_mem_addr_o), .mem_addr_o(ex_mem_addr_o),
.mem_we_o(ex_mem_we_o), .mem_we_o(ex_mem_we_o),
.mem_sel_o(ex_mem_sel_o), .mem_sel_o(ex_mem_sel_o),
.mem_req_valid_o(ex_mem_req_valid_o), .mem_req_valid_o(ex_mem_req_valid_o),
.mem_rsp_ready_o(ex_mem_rsp_ready_o), .mem_rsp_ready_o(ex_mem_rsp_ready_o),
.mem_access_misaligned_o(ex_mem_access_misaligned_o), .mem_access_misaligned_o(ex_mem_access_misaligned_o),
.reg_wdata_o(ex_reg_wdata_o), .reg_wdata_o(ex_reg_wdata_o),
.reg_we_o(ex_reg_we_o), .reg_we_o(ex_reg_we_o),
.reg_waddr_o(ex_reg_waddr_o), .reg_waddr_o(ex_reg_waddr_o),
.hold_flag_o(ex_hold_flag_o), .hold_flag_o(ex_hold_flag_o),
.jump_flag_o(ex_jump_flag_o), .jump_flag_o(ex_jump_flag_o),
.jump_addr_o(ex_jump_addr_o), .jump_addr_o(ex_jump_addr_o),
.int_assert_i(clint_int_assert_o), .int_assert_i(clint_int_assert_o),
.int_addr_i(clint_int_addr_o), .int_addr_i(clint_int_addr_o),
.inst_ecall_o(ex_inst_ecall_o), .inst_ecall_o(ex_inst_ecall_o),
.inst_ebreak_o(ex_inst_ebreak_o), .inst_ebreak_o(ex_inst_ebreak_o),
.inst_mret_o(ex_inst_mret_o), .inst_mret_o(ex_inst_mret_o),
.int_stall_i(clint_stall_flag_o), .int_stall_i(clint_stall_flag_o),
.csr_raddr_o(ex_csr_raddr_o), .csr_raddr_o(ex_csr_raddr_o),
.csr_rdata_i(csr_ex_data_o), .csr_rdata_i(csr_ex_data_o),
.csr_wdata_o(ex_csr_wdata_o), .csr_wdata_o(ex_csr_wdata_o),
.csr_we_o(ex_csr_we_o), .csr_we_o(ex_csr_we_o),
.csr_waddr_o(ex_csr_waddr_o), .csr_waddr_o(ex_csr_waddr_o),
.dec_info_bus_i(ie_dec_info_bus_o), .dec_info_bus_i(ie_dec_info_bus_o),
.dec_imm_i(ie_dec_imm_o), .dec_imm_i(ie_dec_imm_o),
.dec_pc_i(ie_dec_pc_o), .dec_pc_i(ie_dec_pc_o),
.next_pc_i(if_inst_addr_o), .next_pc_i(if_inst_addr_o),
.rd_waddr_i(ie_rd_waddr_o), .rd_waddr_i(ie_rd_waddr_o),
.rd_we_i(ie_rd_we_o) .rd_we_i(ie_rd_we_o)
); );
clint u_clint( clint u_clint(
.clk(clk), .clk(clk),
.rst_n(rst_n), .rst_n(rst_n),
.int_flag_i(int_i), .int_flag_i(int_i),
.inst_ecall_i(ex_inst_ecall_o), .inst_ecall_i(ex_inst_ecall_o),
.inst_ebreak_i(ex_inst_ebreak_o), .inst_ebreak_i(ex_inst_ebreak_o),
.inst_mret_i(ex_inst_mret_o), .inst_mret_i(ex_inst_mret_o),
.inst_addr_i(ie_dec_pc_o), .inst_addr_i(ie_dec_pc_o),
.jump_flag_i(ex_jump_flag_o), .jump_flag_i(ex_jump_flag_o),
.mem_access_misaligned_i(ex_mem_access_misaligned_o), .mem_access_misaligned_i(ex_mem_access_misaligned_o),
.csr_mtvec_i(csr_mtvec_o), .csr_mtvec_i(csr_mtvec_o),
.csr_mepc_i(csr_mepc_o), .csr_mepc_i(csr_mepc_o),
.csr_mstatus_i(csr_mstatus_o), .csr_mstatus_i(csr_mstatus_o),
.csr_we_o(clint_csr_we_o), .csr_we_o(clint_csr_we_o),
.csr_waddr_o(clint_csr_waddr_o), .csr_waddr_o(clint_csr_waddr_o),
.csr_wdata_o(clint_csr_wdata_o), .csr_wdata_o(clint_csr_wdata_o),
.stall_flag_o(clint_stall_flag_o), .stall_flag_o(clint_stall_flag_o),
.int_addr_o(clint_int_addr_o), .int_addr_o(clint_int_addr_o),
.int_assert_o(clint_int_assert_o) .int_assert_o(clint_int_assert_o)
); );
endmodule `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 := ../sdk/examples/simple/simple.mem
PROG_DIR := $(shell dirname $(PROG)) PROG_DIR := $(shell dirname $(PROG))
MAKE := make MAKE := make
VERILATOR := verilator VERILATOR := verilator
VERI_FLAGS += +vcd VERI_FLAGS += +vcd
VERI_CFLAGS += VERI_CFLAGS +=
VERI_VFLAGS += -DRVFI VERI_VFLAGS += -DTRACE_ENABLED
TRACE_ENABLE := 1 RTL_FILES = ../rtl.flist
RTL_FILES = ../rtl.flist VERI_OBJ_DIR := cobj_dir
VERI_OBJ_DIR := cobj_dir ifeq ($(findstring +vcd,$(VERI_FLAGS)),+vcd)
VERI_TRACE = "--trace"
ifeq ($(findstring +vcd,$(VERI_FLAGS)),+vcd) VERI_CFLAGS += "-DVCD_TRACE"
VERI_TRACE = "--trace" else
VERI_CFLAGS += "-DVCD_TRACE" VERI_TRACE =
else endif
VERI_TRACE =
endif SIM_SRC := sim_jtag.sv
SIM_SRC := sim_jtag.sv SIM_SRC += tb_top_verilator.sv \
tb_top_verilator.cpp
SIM_SRC += tb_top_verilator.sv \
tb_top_verilator.cpp SIM_TOP_MODULE := tb_top_verilator
SIM_TOP_MODULE := tb_top_verilator .DEFAULT_GOAL := sim
all: sim
.DEFAULT_GOAL := sim
all: sim .PHONY: recompile
recompile:
.PHONY: recompile rm -rf $(VERI_OBJ_DIR) testbench_verilator
recompile: $(MAKE) -C ./remote_bitbang clean
rm -rf $(VERI_OBJ_DIR) testbench_verilator $(MAKE) -C $(PROG_DIR) clean
$(MAKE) -C ./remote_bitbang clean $(MAKE) compile
$(MAKE) -C $(PROG_DIR) clean
$(MAKE) compile .PHONY: compile
compile: remote_bitbang/librbs.so $(PROG) testbench_verilator
.PHONY: compile
compile: remote_bitbang/librbs.so $(PROG) testbench_verilator testbench_verilator:
$(VERILATOR) --cc --sv --exe \
testbench_verilator: $(VERI_TRACE) \
$(VERILATOR) --cc --sv --exe \ --Wno-lint --Wno-UNOPTFLAT \
$(VERI_TRACE) \ --Wno-MODDUP --top-module \
--Wno-lint --Wno-UNOPTFLAT \ $(SIM_TOP_MODULE) \
--Wno-MODDUP --top-module \ -f $(RTL_FILES) \
$(SIM_TOP_MODULE) \ $(SIM_SRC) \
-f $(RTL_FILES) \ --Mdir $(VERI_OBJ_DIR) \
$(SIM_SRC) \ $(VERI_VFLAGS) \
--Mdir $(VERI_OBJ_DIR) \ -LDFLAGS "-L../remote_bitbang \
$(VERI_VFLAGS) \ -Wl,--enable-new-dtags -Wl,-rpath,remote_bitbang -lrbs" \
-LDFLAGS "-L../remote_bitbang \ -CFLAGS "-std=gnu++11 $(VERI_CFLAGS)"
-Wl,--enable-new-dtags -Wl,-rpath,remote_bitbang -lrbs" \ $(MAKE) -C $(VERI_OBJ_DIR) -f V$(SIM_TOP_MODULE).mk
-CFLAGS "-std=gnu++11 $(VERI_CFLAGS)" cp $(VERI_OBJ_DIR)/V$(SIM_TOP_MODULE) testbench_verilator
$(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
remote_bitbang/librbs.so:
$(MAKE) -C ./remote_bitbang all $(PROG):
$(MAKE) -C $(PROG_DIR)
$(PROG):
$(MAKE) -C $(PROG_DIR) .PHONY: run
run:
.PHONY: run ./testbench_verilator "+firmware=$(PROG)"
run:
./testbench_verilator "+firmware=$(PROG)" .PHONY: sim
sim: recompile run
.PHONY: sim
sim: recompile run .PHONY: clean
clean:
.PHONY: clean rm -rf $(VERI_OBJ_DIR) testbench_verilator *.log *.vcd
clean: $(MAKE) -C ./remote_bitbang clean
rm -rf $(VERI_OBJ_DIR) testbench_verilator *.log *.vcd $(MAKE) -C $(PROG_DIR) clean
$(MAKE) -C ./remote_bitbang clean
$(MAKE) -C $(PROG_DIR) clean .PHONY: help
help:
.PHONY: help @echo 'rebuild all:'
help: @echo 'make PROG=/path/file.mem recompile'
@echo 'rebuild all:' @echo 'run directly:'
@echo 'make PROG=/path/file.mem recompile' @echo 'make PROG=/path/file.mem run'
@echo 'run directly:' @echo 'rebuild & run:'
@echo 'make PROG=/path/file.mem run' @echo 'make PROG=/path/file.mem sim'
@echo 'rebuild & run:' @echo 'clean obj files:'
@echo 'make PROG=/path/file.mem sim' @echo 'make PROG=/path/file.mem clean'
@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> // Copyright 2018 Robert Balas <balasr@student.ethz.ch>
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // http://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
// Top level wrapper for a verilator RI5CY testbench // Top level wrapper for a verilator RI5CY testbench
// Contributor: Robert Balas <balasr@student.ethz.ch> // Contributor: Robert Balas <balasr@student.ethz.ch>
#include "svdpi.h" #include "svdpi.h"
#include "Vtb_top_verilator__Dpi.h" #include "Vtb_top_verilator__Dpi.h"
#include "Vtb_top_verilator.h" #include "Vtb_top_verilator.h"
#include "verilated_vcd_c.h" #include "verilated_vcd_c.h"
#include "verilated.h" #include "verilated.h"
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
#include <fstream> #include <fstream>
#include <exception> #include <exception>
#include <cstdio> #include <cstdio>
#include <cstdint> #include <cstdint>
#include <cerrno> #include <cerrno>
//void dump_memory(); //void dump_memory();
double sc_time_stamp(); double sc_time_stamp();
static vluint64_t t = 0; static vluint64_t t = 0;
Vtb_top_verilator *top; Vtb_top_verilator *top;
int main(int argc, char **argv, char **env) int main(int argc, char **argv, char **env)
{ {
Verilated::commandArgs(argc, argv); Verilated::commandArgs(argc, argv);
Verilated::traceEverOn(true); Verilated::traceEverOn(true);
top = new Vtb_top_verilator(); top = new Vtb_top_verilator();
//svSetScope(svGetScopeFromName( //svSetScope(svGetScopeFromName(
// "TOP.tb_top_verilator.u_ram.ram")); // "TOP.tb_top_verilator.u_ram.ram"));
//Verilated::scopesDump(); //Verilated::scopesDump();
#ifdef VCD_TRACE #ifdef VCD_TRACE
VerilatedVcdC *tfp = new VerilatedVcdC; VerilatedVcdC *tfp = new VerilatedVcdC;
top->trace(tfp, 99); top->trace(tfp, 99);
tfp->open("verilator_tb.vcd"); tfp->open("verilator_tb.vcd");
#endif #endif
top->fetch_enable_i = 1; top->clk_i = 0;
top->clk_i = 0; top->rst_ni = 0;
top->rst_ni = 0;
top->eval();
top->eval(); //dump_memory();
//dump_memory();
while (!Verilated::gotFinish()) {
while (!Verilated::gotFinish()) { if (t > 40)
if (t > 40) top->rst_ni = 1;
top->rst_ni = 1; top->clk_i = !top->clk_i;
top->clk_i = !top->clk_i; top->eval();
top->eval(); #ifdef VCD_TRACE
#ifdef VCD_TRACE tfp->dump(t);
tfp->dump(t); #endif
#endif t += 5;
t += 5; //if (t > 5000)
if (t > 1000) // break;
break; }
} #ifdef VCD_TRACE
#ifdef VCD_TRACE tfp->close();
tfp->close(); #endif
#endif delete top;
delete top; exit(0);
exit(0); }
}
double sc_time_stamp()
double sc_time_stamp() {
{ return t;
return t; }
} /*
/* void dump_memory()
void dump_memory() {
{ errno = 0;
errno = 0; std::ofstream mem_file;
std::ofstream mem_file; svLogicVecVal addr = {0};
svLogicVecVal addr = {0};
mem_file.exceptions(std::ofstream::failbit | std::ofstream::badbit);
mem_file.exceptions(std::ofstream::failbit | std::ofstream::badbit); try {
try { mem_file.open("memory_dump.bin");
mem_file.open("memory_dump.bin"); for (size_t i = 0; i < 1048576; i++) {
for (size_t i = 0; i < 1048576; i++) { addr.aval = i;
addr.aval = i; uint32_t val = read_byte(&addr);
uint32_t val = read_byte(&addr); mem_file << std::setfill('0') << std::setw(2) << std::hex << val
mem_file << std::setfill('0') << std::setw(2) << std::hex << val << std::endl;
<< std::endl; }
} mem_file.close();
mem_file.close();
std::cout << "finished dumping memory" << std::endl;
std::cout << "finished dumping memory" << std::endl;
} catch (std::ofstream::failure e) {
} catch (std::ofstream::failure e) { std::cerr << "exception opening/reading/closing file memory_dump.bin\n";
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 2018 Robert Balas <balasr@student.ethz.ch>
// Copyright and related rights are licensed under the Solderpad Hardware // Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in // 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 // 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 // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under // or agreed to in writing, software, hardware and materials distributed under
// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // 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 // CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License. // specific language governing permissions and limitations under the License.
// Top level wrapper for a verilator RI5CY testbench // Top level wrapper for a verilator RI5CY testbench
// Contributor: Robert Balas <balasr@student.ethz.ch> // Contributor: Robert Balas <balasr@student.ethz.ch>
module tb_top_verilator #( module tb_top_verilator #(
) ( ) (
input clk_i, input clk_i,
input rst_ni, input rst_ni
input fetch_enable_i );
);
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;
initial begin: load_prog
automatic logic [1023:0] firmware; if($value$plusargs("firmware=%s", firmware)) begin
//if($test$plusargs("verbose"))
if($value$plusargs("firmware=%s", firmware)) begin $display("[TESTBENCH] %t: loading firmware %0s ...",
//if($test$plusargs("verbose")) $time, firmware);
$display("[TESTBENCH] %t: loading firmware %0s ...", $readmemh (firmware, u_tinyriscv_soc_top.u_rom.u_gen_ram.ram);
$time, firmware); end else begin
$readmemh (firmware, u_tinyriscv_soc_top.u_rom.u_gen_ram.ram); $display("No firmware specified");
//$display("mem[0x80]=0x%x", u_ram.ram.mem[32]); end
//$display("mem[0x84]=0x%x", u_ram.ram.mem[33]); end
end else begin
$display("No firmware specified"); always @(posedge clk_i or negedge rst_ni) begin
end if (!rst_ni) begin
end
end else begin
if (x26 == 32'b1) begin
tinyriscv_soc_top u_tinyriscv_soc_top( if (x27 == 32'b1) begin
.clk(clk_i), $display("~~~~~~~~~~~~~~~~~~~ TEST_PASS ~~~~~~~~~~~~~~~~~~~");
.rst_ext_i(rst_ni) $display("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
); $display("~~~~~~~~~ ##### ## #### #### ~~~~~~~~~");
$display("~~~~~~~~~ # # # # # # ~~~~~~~~~");
endmodule // tb_top_verilator $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