From c070f0b49d92818b1c92c9cdbfd28422ca32637e Mon Sep 17 00:00:00 2001 From: liangkangnan Date: Wed, 31 Mar 2021 15:25:22 +0800 Subject: [PATCH] temp commit Signed-off-by: liangkangnan --- README.md | 8 +- rtl.flist | 89 ++--- rtl/core/tinyriscv_core.sv | 642 +++++++++++++++++++------------------ rtl/core/tracer.sv | 612 +++++++++++++++++++++++++++++++++++ sim/Makefile | 178 +++++----- sim/tb_top_verilator.cpp | 215 +++++++------ sim/tb_top_verilator.sv | 122 ++++--- 7 files changed, 1256 insertions(+), 610 deletions(-) create mode 100644 rtl/core/tracer.sv diff --git a/README.md b/README.md index 139597f..977c208 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,6 @@ - - +更新计划: +1.增加指令trace功能; +2.总线优化; +3.取指、访存优化; +4.jtag优化; + diff --git a/rtl.flist b/rtl.flist index db251d4..26642d0 100644 --- a/rtl.flist +++ b/rtl.flist @@ -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 + + diff --git a/rtl/core/tinyriscv_core.sv b/rtl/core/tinyriscv_core.sv index d925b72..17fe970 100644 --- a/rtl/core/tinyriscv_core.sv +++ b/rtl/core/tinyriscv_core.sv @@ -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 diff --git a/rtl/core/tracer.sv b/rtl/core/tracer.sv new file mode 100644 index 0000000..570161d --- /dev/null +++ b/rtl/core/tracer.sv @@ -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 diff --git a/sim/Makefile b/sim/Makefile index 7548c8a..15466b6 100644 --- a/sim/Makefile +++ b/sim/Makefile @@ -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' diff --git a/sim/tb_top_verilator.cpp b/sim/tb_top_verilator.cpp index 53234cf..5e4ce47 100644 --- a/sim/tb_top_verilator.cpp +++ b/sim/tb_top_verilator.cpp @@ -1,108 +1,107 @@ -// Copyright 2018 Robert Balas -// -// 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 - -#include "svdpi.h" -#include "Vtb_top_verilator__Dpi.h" -#include "Vtb_top_verilator.h" -#include "verilated_vcd_c.h" -#include "verilated.h" - -#include -#include -#include -#include -#include -#include -#include - -//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 +// +// 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 + +#include "svdpi.h" +#include "Vtb_top_verilator__Dpi.h" +#include "Vtb_top_verilator.h" +#include "verilated_vcd_c.h" +#include "verilated.h" + +#include +#include +#include +#include +#include +#include +#include + +//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"; + } +} +*/ diff --git a/sim/tb_top_verilator.sv b/sim/tb_top_verilator.sv index 19f2200..0761e51 100644 --- a/sim/tb_top_verilator.sv +++ b/sim/tb_top_verilator.sv @@ -1,48 +1,74 @@ -// Copyright 2018 Robert Balas -// 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 - - -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 +// 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 + + +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