quasar/soc/soc_sim.sv

417 lines
18 KiB
Systemverilog

// SPDX-License-Identifier: Apache-2.0
// Copyright 2020 Western Digital Corporation or its affiliates.
//
// 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 soc_sim (
input bit core_clk
);
logic rst_l;
logic dbg_rst_l;
wire jtag_tdo;
wire jtag_tck;
wire jtag_tms;
wire jtag_tdi;
wire jtag_trst_n;
bit [31:0] cycleCnt;
logic mailbox_data_val;
int commit_count;
logic wb_valid;
logic [ 4:0] wb_dest;
logic [31:0] wb_data;
wire [63:0] WriteData;
string abi_reg [32]; // ABI register names
assign WriteData = rvsoc.lsu_axi_wdata;
assign mailbox_data_val = WriteData[7:0] > 8'h5 && WriteData[7:0] < 8'h7f;
parameter MAILBOX_ADDR = 32'hD0580000;
logic write;
logic [31:0] laddr;
wire mailbox_write = rvsoc.lmem_axi_awvalid && rvsoc.lsu_axi_awaddr == MAILBOX_ADDR && rst_l;
always @(posedge core_clk or negedge rst_l) begin
if (~rst_l) begin
laddr <= 32'b0;
write <= 1'b0;
end else begin
if (rvsoc.lsu_hready) begin
laddr <= rvsoc.lsu_haddr;
write <= rvsoc.lsu_hwrite & |rvsoc.lsu_htrans;
end
end
end
parameter MAX_CYCLES = 10_000_000_0;
integer fd, tp, el, pic, lsu, ifu, dec, exu;
always @(posedge core_clk) begin
cycleCnt <= cycleCnt + 1;
if (cycleCnt == MAX_CYCLES) begin
$display("Hit max cycle count (%0d) .. stopping", cycleCnt);
$finish;
end
if (mailbox_data_val & mailbox_write) begin
$fwrite(fd, "%c", WriteData[7:0]);
$write("%c", WriteData[7:0]);
end
if (mailbox_write && WriteData[7:0] == 8'hff) begin
$display("\nFinished : minstret = %0d, mcycle = %0d",
rvsoc.rvtop.core.dec.tlu.csr.minstretl[31:0],
rvsoc.rvtop.core.dec.tlu.csr.mcyclel[31:0]);
$display(
"See \"exec.log\" for execution trace with register updates..\n");
$display("TEST_PASSED");
$finish;
end else if (mailbox_write && WriteData[7:0] == 8'h1) begin
$display("TEST_FAILED");
$finish;
end
end
// trace monitor
always @(posedge core_clk) begin
wb_valid <= rvsoc.rvtop.core.dec.decode_io_dec_i0_wen_r;
wb_dest <= rvsoc.rvtop.core.dec.decode_io_dec_i0_waddr_r;
wb_data <= rvsoc.rvtop.core.dec.decode_io_dec_i0_wdata_r;
if (rvsoc.trace_rv_i_valid_ip) begin
$fwrite(tp, "%b,%h,%h,%0h,%0h,3,%b,%h,%h,%b\n", rvsoc.trace_rv_i_valid_ip,
0, rvsoc.trace_rv_i_address_ip, 0, rvsoc.trace_rv_i_insn_ip,
rvsoc.trace_rv_i_exception_ip, rvsoc.trace_rv_i_ecause_ip,
rvsoc.trace_rv_i_tval_ip, rvsoc.trace_rv_i_interrupt_ip);
// Basic trace - no exception register updates
// #1 0 ee000000 b0201073 c 0b02 00000000
commit_count++;
$fwrite(el, "%10d : %8s 0 %h %h%13s ; %s\n", cycleCnt, $sformatf(
"#%0d", commit_count), rvsoc.trace_rv_i_address_ip,
rvsoc.trace_rv_i_insn_ip, (wb_dest != 0 && wb_valid) ? $sformatf(
"%s=%h", abi_reg[wb_dest], wb_data) : " ", dasm(
rvsoc.trace_rv_i_insn_ip,
rvsoc.trace_rv_i_address_ip,
wb_dest & {5{wb_valid}},
wb_data
));
end
if (rvsoc.rvtop.core.dec.decode_io_dec_nonblock_load_wen)
$fwrite(el, "%10d : %32s=%h ; nbL\n", cycleCnt,
abi_reg[rvsoc.rvtop.core.dec.decode_io_dec_nonblock_load_waddr],
rvsoc.rvtop.core.dec.io_lsu_nonblock_load_data);
if (rvsoc.rvtop.core.dec.io_exu_div_wren)
$fwrite(el, "%10d : %32s=%h ; nbD\n", cycleCnt,
abi_reg[rvsoc.rvtop.core.dec.decode_io_div_waddr_wb],
rvsoc.rvtop.core.dec.io_exu_div_result);
end
//////////////////////////////////////////////////pic tracer///////////////////////////////////////////////////////
always @(posedge core_clk) begin
if (rvsoc.rvtop.core.pic_ctrl_inst.io_lsu_pic_picm_wren == 1) begin
$fwrite(pic, "%0d,%0d,%h\t",
rvsoc.rvtop.core.pic_ctrl_inst.io_lsu_pic_picm_wren,
rvsoc.rvtop.core.pic_ctrl_inst.io_lsu_pic_picm_wraddr,
rvsoc.rvtop.core.pic_ctrl_inst.io_lsu_pic_picm_wr_data);
end else if (rvsoc.rvtop.core.pic_ctrl_inst.io_lsu_pic_picm_rden == 1)
$fwrite(pic, "x\tx\tx\t");
if (rvsoc.rvtop.core.pic_ctrl_inst.io_lsu_pic_picm_rden == 1) begin
$fwrite(pic, "%0d,%0d,%h\n",
rvsoc.rvtop.core.pic_ctrl_inst.io_lsu_pic_picm_rden,
rvsoc.rvtop.core.pic_ctrl_inst.io_lsu_pic_picm_rdaddr,
rvsoc.rvtop.core.pic_ctrl_inst.io_lsu_pic_picm_rd_data);
end else if (rvsoc.rvtop.core.pic_ctrl_inst.io_lsu_pic_picm_wren == 1)
$fwrite(pic, "x\tx\tx\t\n");
end
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////LSU tracer///////////////////////////////////////////////////////
always @(posedge core_clk) begin
if (rvsoc.rvtop.core.lsu.io_dccm_wren == 1) begin
$fwrite(lsu, "%0h,%0h,%0h,%0h,%0h\t", rvsoc.rvtop.core.lsu.io_dccm_wren,
rvsoc.rvtop.core.lsu.io_dccm_wr_addr_hi,
rvsoc.rvtop.core.lsu.io_dccm_wr_addr_lo,
rvsoc.rvtop.core.lsu.io_dccm_wr_data_hi,
rvsoc.rvtop.core.lsu.io_dccm_wr_data_lo);
end
else if(rvsoc.rvtop.core.lsu.io_dccm_rden == 1 || rvsoc.rvtop.core.lsu.io_lsu_dma_dma_dccm_ctl_dccm_dma_rvalid)
$fwrite(lsu, "x\tx\tx\tx\tx\t");
if (rvsoc.rvtop.core.lsu.io_dccm_rden == 1) begin
$fwrite(lsu, "%0h,%0h,%0h,%0h,%0h\t", rvsoc.rvtop.core.lsu.io_dccm_rden,
rvsoc.rvtop.core.lsu.io_dccm_rd_addr_hi,
rvsoc.rvtop.core.lsu.io_dccm_rd_addr_lo,
rvsoc.rvtop.core.lsu.io_dccm_rd_data_hi,
rvsoc.rvtop.core.lsu.io_dccm_rd_data_lo);
end
else if(rvsoc.rvtop.core.lsu.io_dccm_wren == 1 || rvsoc.rvtop.core.lsu.io_lsu_dma_dma_dccm_ctl_dccm_dma_rvalid)
$fwrite(lsu, "x\tx\tx\tx\tx\t");
if (rvsoc.rvtop.core.lsu.io_lsu_dma_dma_dccm_ctl_dccm_dma_rvalid == 1) begin
$fwrite(lsu, "%0h,%0h\n",
rvsoc.rvtop.core.lsu.io_lsu_dma_dma_dccm_ctl_dccm_dma_rvalid,
rvsoc.rvtop.core.lsu.io_lsu_dma_dma_dccm_ctl_dccm_dma_rdata);
end
else if (rvsoc.rvtop.core.lsu.io_dccm_wren == 1 || rvsoc.rvtop.core.lsu.io_dccm_rden== 1)
$fwrite(lsu, "x\tx\n");
end
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////IFU tracer////////////////////////////////////////////////////////
always @(posedge core_clk) begin
if (rvsoc.rvtop.core.ifu.aln_ctl_io_dec_aln_aln_ib_ifu_i0_valid == 1 && cycleCnt != 0) begin
$fwrite(ifu, "%5d,%0h,%0h,%0h\t", cycleCnt,
rvsoc.rvtop.core.ifu.aln_ctl_io_dec_aln_aln_ib_ifu_i0_valid,
rvsoc.rvtop.core.ifu.aln_ctl_io_dec_aln_aln_ib_ifu_i0_instr,
rvsoc.rvtop.core.ifu.aln_ctl_io_dec_aln_aln_ib_ifu_i0_pc);
end
else if((rvsoc.rvtop.core.ifu.io_iccm_wren == 1 || rvsoc.rvtop.core.ifu.io_iccm_rden==1 || rvsoc.rvtop.core.ifu.io_ic_wr_en !==0 || rvsoc.rvtop.core.ifu.io_ic_rd_en ==1 || rvsoc.rvtop.core.ifu.io_iccm_dma_rvalid == 1) && cycleCnt != 0)
$fwrite(ifu, "%5d,x\tx\tx\t", cycleCnt);
if (rvsoc.rvtop.core.ifu.io_iccm_wren == 1 && cycleCnt != 0) begin
$fwrite(ifu, "%0h,%0h,%0h\t", rvsoc.rvtop.core.ifu.io_iccm_wren,
rvsoc.rvtop.core.ifu.io_iccm_rw_addr,
rvsoc.rvtop.core.ifu.io_iccm_wr_data);
end
else if((rvsoc.rvtop.core.ifu.aln_ctl_io_dec_aln_aln_ib_ifu_i0_valid == 1 || rvsoc.rvtop.core.ifu.io_iccm_rden==1 || rvsoc.rvtop.core.ifu.io_ic_wr_en !==0 || rvsoc.rvtop.core.ifu.io_ic_rd_en ==1 || rvsoc.rvtop.core.ifu.io_iccm_dma_rvalid == 1) && cycleCnt != 0)
$fwrite(ifu, "\tx\tx\tx\t");
if (rvsoc.rvtop.core.ifu.io_iccm_rden == 1 && cycleCnt != 0) begin
$fwrite(ifu, "%0h,%0h,%0h\t", rvsoc.rvtop.core.ifu.io_iccm_rden,
rvsoc.rvtop.core.ifu.io_iccm_rw_addr,
rvsoc.rvtop.core.ifu.io_iccm_rd_data_ecc);
end
else if((rvsoc.rvtop.core.ifu.aln_ctl_io_dec_aln_aln_ib_ifu_i0_valid == 1 || rvsoc.rvtop.core.ifu.io_iccm_wren==1 || rvsoc.rvtop.core.ifu.io_ic_wr_en !==0 || rvsoc.rvtop.core.ifu.io_ic_rd_en ==1 || rvsoc.rvtop.core.ifu.io_iccm_dma_rvalid == 1)&& cycleCnt != 0)
$fwrite(ifu, "\tx\tx\tx\t");
if (rvsoc.rvtop.core.ifu.io_ic_wr_en !== 0 && cycleCnt != 0) begin
$fwrite(ifu, "%0h,%0h,%0h\t", rvsoc.rvtop.core.ifu.io_ic_wr_en,
rvsoc.rvtop.core.ifu.io_ic_rw_addr,
rvsoc.rvtop.core.ifu.io_ic_wr_data_0,
rvsoc.rvtop.core.ifu.io_ic_wr_data_1);
end
else if((rvsoc.rvtop.core.ifu.aln_ctl_io_dec_aln_aln_ib_ifu_i0_valid == 1 || rvsoc.rvtop.core.ifu.io_iccm_wren==1 || rvsoc.rvtop.core.ifu.io_iccm_rden ==1 || rvsoc.rvtop.core.ifu.io_ic_rd_en ==1 || rvsoc.rvtop.core.ifu.io_iccm_dma_rvalid == 1)&& cycleCnt != 0)
$fwrite(ifu, "\tx\tx\tx\tx\t");
if (rvsoc.rvtop.core.ifu.io_ic_rd_en == 1 && cycleCnt != 0) begin
$fwrite(ifu, "%0h,%0h,%0h\t", rvsoc.rvtop.core.ifu.io_ic_rd_en,
rvsoc.rvtop.core.ifu.io_ic_rw_addr,
rvsoc.rvtop.core.ifu.io_ic_rd_data);
end
else if((rvsoc.rvtop.core.ifu.aln_ctl_io_dec_aln_aln_ib_ifu_i0_valid == 1 || rvsoc.rvtop.core.ifu.io_iccm_wren==1 || rvsoc.rvtop.core.ifu.io_iccm_rden ==1 || rvsoc.rvtop.core.ifu.io_ic_wr_en !== 0 ||rvsoc.rvtop.core.ifu.io_iccm_dma_rvalid == 1)&& cycleCnt != 0)
$fwrite(ifu, "\tx\tx\tx\t");
if (rvsoc.rvtop.core.ifu.io_iccm_dma_rvalid == 1 && cycleCnt != 0) begin
$fwrite(ifu, "%h,%0h\n", rvsoc.rvtop.core.ifu.io_iccm_dma_rvalid,
rvsoc.rvtop.core.ifu.io_iccm_dma_rdata);
end
else if((rvsoc.rvtop.core.ifu.aln_ctl_io_dec_aln_aln_ib_ifu_i0_valid == 1 || rvsoc.rvtop.core.ifu.io_iccm_wren==1 || rvsoc.rvtop.core.ifu.io_iccm_rden ==1 || rvsoc.rvtop.core.ifu.io_ic_wr_en !== 0 || rvsoc.rvtop.core.ifu.io_ic_rd_en)&& cycleCnt != 0)
$fwrite(ifu, "\tx\tx\n");
end
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////DEC tracer////////////////////////////////////////////////////////
always @(posedge core_clk) begin
if (rvsoc.rvtop.core.dma_ctrl.io_dma_dbg_cmd_done == 1) begin
$fwrite(dec, "%5d,\t%0h,%0h\t", cycleCnt,
rvsoc.rvtop.core.dma_ctrl.io_dma_dbg_cmd_done,
rvsoc.rvtop.core.dec.io_dec_dbg_rddata);
end
else if(rvsoc.rvtop.core.dec.io_dec_exu_dec_alu_dec_i0_alu_decode_d == 1 || rvsoc.rvtop.core.dec.decode_io_dec_csr_wen_r==1)
$fwrite(dec, "%5d,\tx\tx\t", cycleCnt);
if (rvsoc.rvtop.core.dec.io_dec_exu_dec_alu_dec_i0_alu_decode_d == 1) begin
$fwrite(dec, "%0h,%0h,%0h,%0h,%0h,%0h\t",
rvsoc.rvtop.core.dec.io_dec_exu_dec_alu_dec_i0_alu_decode_d,
rvsoc.rvtop.core.dec.decode_io_decode_exu_dec_i0_rs1_en_d,
rvsoc.rvtop.core.exu.i0_rs1_d,
rvsoc.rvtop.core.dec.decode_io_decode_exu_dec_i0_rs2_en_d,
rvsoc.rvtop.core.exu.i0_rs2_d,
rvsoc.rvtop.core.exu.io_dec_exu_decode_exu_exu_i0_result_x);
end
else if(rvsoc.rvtop.core.dma_ctrl.io_dma_dbg_cmd_done == 1 || rvsoc.rvtop.core.dec.decode_io_dec_csr_wen_r==1)
$fwrite(dec, "x\t,x\t,x\t,x\tx\tx\t");
if (rvsoc.rvtop.core.dec.decode_io_dec_csr_wen_r == 1) begin
$fwrite(dec, "%0h,%0h,%0h,%0h,%0h\n",
rvsoc.rvtop.core.dec.decode_io_dec_csr_wen_r,
rvsoc.rvtop.core.dec.decode_io_dec_csr_wraddr_r,
rvsoc.rvtop.core.dec.decode_io_dec_csr_wrdata_r,
rvsoc.rvtop.core.dec.decode_io_dec_csr_rdaddr_d,
rvsoc.rvtop.core.dec.decode_io_dec_csr_rddata_d);
end
else if(rvsoc.rvtop.core.dma_ctrl.io_dma_dbg_cmd_done == 1 || rvsoc.rvtop.core.dec.io_dec_exu_dec_alu_dec_i0_alu_decode_d == 1 )
$fwrite(dec, "x\t,x\t,x\t,x\t,x\n");
end
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////exu tracer///////////////////////////////////////////////////
always @(posedge core_clk) begin
if (rvsoc.rvtop.core.exu.io_exu_div_wren == 1) begin
$fwrite(exu, "%5d,\t%0h,%0h,%0h,%0h,%0h\t", cycleCnt,
rvsoc.rvtop.core.exu.io_exu_div_wren,
rvsoc.rvtop.core.exu.io_exu_div_result,
rvsoc.rvtop.core.exu.i_div.io_dividend,
rvsoc.rvtop.core.exu.i_div.io_divisor,
rvsoc.rvtop.core.exu.i_div.io_exu_div_result);
end
else if(rvsoc.rvtop.core.exu.i0_rs1_bypass_en_d == 1 || rvsoc.rvtop.core.exu.i0_rs2_bypass_en_d == 1)
$fwrite(exu, "%5d,\tx\tx\tx\tx\tx,\t", cycleCnt);
if (rvsoc.rvtop.core.exu.i0_rs1_bypass_en_d == 1) begin
$fwrite(exu, "\t%0h,%0h\t", rvsoc.rvtop.core.exu.i0_rs1_bypass_en_d,
rvsoc.rvtop.core.exu.i0_rs1_bypass_data_d);
end
else if(rvsoc.rvtop.core.exu.io_exu_div_wren == 1 || rvsoc.rvtop.core.exu.i0_rs2_bypass_en_d == 1)
$fwrite(exu, "\tx\tx\t");
if (rvsoc.rvtop.core.exu.i0_rs2_bypass_en_d == 1) begin
$fwrite(exu, "\t%0h,%0h\n", rvsoc.rvtop.core.exu.i0_rs2_bypass_en_d,
rvsoc.rvtop.core.exu.i0_rs2_bypass_data_d);
end
else if(rvsoc.rvtop.core.exu.io_exu_div_wren == 1 || rvsoc.rvtop.core.exu.i0_rs1_bypass_en_d == 1)
$fwrite(exu, "\tx\tx\n");
end
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
initial begin
abi_reg[0] = "zero";
abi_reg[1] = "ra";
abi_reg[2] = "sp";
abi_reg[3] = "gp";
abi_reg[4] = "tp";
abi_reg[5] = "t0";
abi_reg[6] = "t1";
abi_reg[7] = "t2";
abi_reg[8] = "s0";
abi_reg[9] = "s1";
abi_reg[10] = "a0";
abi_reg[11] = "a1";
abi_reg[12] = "a2";
abi_reg[13] = "a3";
abi_reg[14] = "a4";
abi_reg[15] = "a5";
abi_reg[16] = "a6";
abi_reg[17] = "a7";
abi_reg[18] = "s2";
abi_reg[19] = "s3";
abi_reg[20] = "s4";
abi_reg[21] = "s5";
abi_reg[22] = "s6";
abi_reg[23] = "s7";
abi_reg[24] = "s8";
abi_reg[25] = "s9";
abi_reg[26] = "s10";
abi_reg[27] = "s11";
abi_reg[28] = "t3";
abi_reg[29] = "t4";
abi_reg[30] = "t5";
abi_reg[31] = "t6";
tp = $fopen("trace_port.csv", "w");
el = $fopen("exec.log", "w");
//////////////////////////////////////////////////////////////////
pic = $fopen("pic.log", "w");
$fwrite(pic,
" write enable, write addr , write data ,read enable, read address, read data \n");
///////////////////////////////////////////////////////////////////
lsu = $fopen("lsu.log", "w");
$fwrite(lsu,
"write en, write addrs hi,write addrs lo, write data hi,write data lo, read_en, read addrs hi,read addrs lo, read data hi,read data lo, dma valid, dma read data \n");
/////////////////////////////////////////////////////////////////////////
ifu = $fopen("ifu.log", "w");
$fwrite(ifu,
"cycleCnt,inst_valid,inst,inst_pc\ticcm wen,iccm waddr,iccm wdata, iccm ren,iccm raddr, iccm rdata\tic wen,ic waddr,ic wdata0,ic wdata1\tic ren,ic raddr,ic rdata\ticcm dma rvalid,iccm dma rdata\n");
///////////////////////////////////////////////////////////////////////////
dec = $fopen("dec.log", "w");
$fwrite(dec,
"clock cycle dbg cmd, dbg rd data\talu decode, rs1 en, rs1, rs2 en, rs2, result, csr wen, csr wr addr, csr wrdata, csr rd addr, csr rd data\n");
///////////////////////////////////////////////////////////////////////////
exu = $fopen("exu.log", "w");
$fwrite(exu,
"clock cycle div enable, div result, dividend, divisor, out\t,rs1 bypassen, rs1 bypassdata\t, rs2 bypassen, rs2 bypassdata\n");
$fwrite(el, "//Cycle : #inst 0 pc opcode reg regnum value\n");
fd = $fopen("console.log", "w");
commit_count = 0;
end
assign rst_l = cycleCnt > 5;
assign dbg_rst_l = cycleCnt > 2;
soc_top rvsoc (
.clk(core_clk),
.rst(rst_l),
.dbg_rst(dbg_rst_l),
.jtag_tdo(jtag_tdo),
.jtag_tck(jtag_tck),
.jtag_tms(jtag_tms),
.jtag_tdi(jtag_tdi),
.jtag_trst_n(jtag_trst_n)
);
jtagdpi jtagdpi (
.clk_i (core_clk),
.rst_ni(rst_l),
.jtag_tck(jtag_tck),
.jtag_tms(jtag_tms),
.jtag_tdi(jtag_tdi),
.jtag_tdo(jtag_tdo),
.jtag_trst_n(jtag_trst_n),
.jtag_srst_n()
);
`define DRAM(bank) \
rvsoc.rvtop.mem.Gen_dccm_enable.dccm.mem_bank[bank].dccm_bank.ram_core
`define ICCM_PATH `RV_TOP.mem.iccm
`define IRAM0(bk) `ICCM_PATH.mem_bank[bk].iccm_bank_lo0.ram_core
`define IRAM1(bk) `ICCM_PATH.mem_bank[bk].iccm_bank_lo1.ram_core
`define IRAM2(bk) `ICCM_PATH.mem_bank[bk].iccm_bank_hi0.ram_core
`define IRAM3(bk) `ICCM_PATH.mem_bank[bk].iccm_bank_hi1.ram_core
/* verilator lint_off WIDTH */
/* verilator lint_off CASEINCOMPLETE */
`include "dasm.svi"
/* verilator lint_on CASEINCOMPLETE */
/* verilator lint_on WIDTH */
endmodule