// 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 [1:0 ]; logic [ 4:0] wb_dest [1:0 ]; logic [31:0] wb_data [1:0 ]; wire [63:0] WriteData; string abi_reg [ 32]; // ABI register names assign WriteData = rvsoc.lsu_hwdata; 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 = write && laddr == MAILBOX_ADDR; 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; 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.swerv.dec.tlu.minstretl[31:0], rvsoc.rvtop.swerv.dec.tlu.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[1:0] <= '{ rvsoc.rvtop.swerv.dec.dec_i1_wen_wb, rvsoc.rvtop.swerv.dec.dec_i0_wen_wb }; wb_dest[1:0] <= '{ rvsoc.rvtop.swerv.dec.dec_i1_waddr_wb, rvsoc.rvtop.swerv.dec.dec_i0_waddr_wb }; wb_data[1:0] <= '{ rvsoc.rvtop.swerv.dec.dec_i1_wdata_wb, rvsoc.rvtop.swerv.dec.dec_i0_wdata_wb }; if (rvsoc.trace_rv_i_valid_ip !== 0) begin $fwrite(tp, "%b,%h,%h,%0h,%0h,3,%b,%h,%h,%b\n", rvsoc.trace_rv_i_valid_ip, rvsoc.trace_rv_i_address_ip[63:32], rvsoc.trace_rv_i_address_ip[31:0], rvsoc.trace_rv_i_insn_ip[63:32], rvsoc.trace_rv_i_insn_ip[31:0], 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 for (int i = 0; i < 2; i++) if (rvsoc.trace_rv_i_valid_ip[i] == 1) begin commit_count++; $fwrite(el, "%10d : %8s %0d %h %h%13s ; %s\n", cycleCnt, $sformatf( "#%0d", commit_count), 0, rvsoc.trace_rv_i_address_ip[31+i*32-:32], rvsoc.trace_rv_i_insn_ip[31+i*32-:32], (wb_dest[i] != 0 && wb_valid[i]) ? $sformatf( "%s=%h", abi_reg[wb_dest[i]], wb_data[i]) : " ", dasm( rvsoc.trace_rv_i_insn_ip[31+i*32-:32], rvsoc.trace_rv_i_address_ip[31+i*32-:32], wb_dest[i] & {5{wb_valid[i]}}, wb_data[i] )); end end if (rvsoc.rvtop.swerv.dec.dec_nonblock_load_wen) begin $fwrite(el, "%10d : %10d%22s=%h ; nbL\n", cycleCnt, 0, abi_reg[rvsoc.rvtop.swerv.dec.dec_nonblock_load_waddr], rvsoc.rvtop.swerv.dec.lsu_nonblock_load_data); soc_sim.gpr[0][rvsoc.rvtop.swerv.dec.dec_nonblock_load_waddr] = rvsoc.rvtop.swerv.dec.lsu_nonblock_load_data; end 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"); $fwrite( el, "// Cycle : #inst hart pc opcode reg=value ; mnemonic\n"); $fwrite( el, "//---------------------------------------------------------------\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