// 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. // `ifdef VERILATOR module soc_top ( input bit core_clk); `else module soc_top; bit core_clk; `endif logic rst_l; logic porst_l; logic nmi_int; logic [31:0] reset_vector; logic [31:0] nmi_vector; logic [31:1] jtag_id; logic [31:0] ic_haddr; logic [2:0] ic_hburst; logic ic_hmastlock; logic [3:0] ic_hprot; logic [2:0] ic_hsize; logic [1:0] ic_htrans; logic ic_hwrite; logic [63:0] ic_hrdata; logic ic_hready; logic ic_hresp; logic [31:0] lsu_haddr; logic [2:0] lsu_hburst; logic lsu_hmastlock; logic [3:0] lsu_hprot; logic [2:0] lsu_hsize; logic [1:0] lsu_htrans; logic lsu_hwrite; logic [63:0] lsu_hrdata; logic [63:0] lsu_hwdata; logic lsu_hready; logic lsu_hresp; logic [31:0] sb_haddr; logic [2:0] sb_hburst; logic sb_hmastlock; logic [3:0] sb_hprot; logic [2:0] sb_hsize; logic [1:0] sb_htrans; logic sb_hwrite; logic [63:0] sb_hrdata; logic [63:0] sb_hwdata; logic sb_hready; logic sb_hresp; logic [63:0] trace_rv_i_insn_ip; logic [63:0] trace_rv_i_address_ip; logic [2:0] trace_rv_i_valid_ip; logic [2:0] trace_rv_i_exception_ip; logic [4:0] trace_rv_i_ecause_ip; logic [2:0] trace_rv_i_interrupt_ip; logic [31:0] trace_rv_i_tval_ip; logic o_debug_mode_status; logic [1:0] dec_tlu_perfcnt0; logic [1:0] dec_tlu_perfcnt1; logic [1:0] dec_tlu_perfcnt2; logic [1:0] dec_tlu_perfcnt3; wire jtag_tdo; wire jtag_tck; wire jtag_tms; wire jtag_tdi; wire jtag_trst_n; logic o_cpu_halt_ack; logic o_cpu_halt_status; logic o_cpu_run_ack; logic mailbox_write; logic [63:0] dma_hrdata; logic [63:0] dma_hwdata; logic dma_hready; logic dma_hresp; logic mpc_debug_halt_req; logic mpc_debug_run_req; logic mpc_reset_run_req; logic mpc_debug_halt_ack; logic mpc_debug_run_ack; logic debug_brkpt_status; bit [31:0] cycleCnt; logic mailbox_data_val; wire dma_hready_out; 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 `define DEC rvtop.swerv.dec assign mailbox_write = lmem.mailbox_write; assign WriteData = lmem.WriteData; assign mailbox_data_val = WriteData[7:0] > 8'h5 && WriteData[7:0] < 8'h7f; parameter MAX_CYCLES = 10_000_000_0; integer fd, tp, el; always @(negedge core_clk) begin cycleCnt <= cycleCnt+1; // Test timeout monitor if(cycleCnt == MAX_CYCLES) begin $display ("Hit max cycle count (%0d) .. stopping",cycleCnt); $finish; end // cansol Monitor if( mailbox_data_val & mailbox_write) begin $fwrite(fd,"%c", WriteData[7:0]); $write("%c", WriteData[7:0]); end // End Of test monitor if(mailbox_write && WriteData[7:0] == 8'hff) begin $display("\nFinished : minstret = %0d, mcycle = %0d", `DEC.tlu.minstretl[31:0],`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] <= '{`DEC.dec_i1_wen_wb, `DEC.dec_i0_wen_wb}; wb_dest[1:0] <= '{`DEC.dec_i1_waddr_wb, `DEC.dec_i0_waddr_wb}; wb_data[1:0] <= '{`DEC.dec_i1_wdata_wb, `DEC.dec_i0_wdata_wb}; if (trace_rv_i_valid_ip !== 0) begin $fwrite(tp,"%b,%h,%h,%0h,%0h,3,%b,%h,%h,%b\n", trace_rv_i_valid_ip, trace_rv_i_address_ip[63:32], trace_rv_i_address_ip[31:0], trace_rv_i_insn_ip[63:32], trace_rv_i_insn_ip[31:0],trace_rv_i_exception_ip,trace_rv_i_ecause_ip, trace_rv_i_tval_ip,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 (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, trace_rv_i_address_ip[31+i*32 -:32], 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(trace_rv_i_insn_ip[31+i*32 -:32], trace_rv_i_address_ip[31+i*32-:32], wb_dest[i] & {5{wb_valid[i]}}, wb_data[i]) ); end end if(`DEC.dec_nonblock_load_wen) begin $fwrite (el, "%10d : %10d%22s=%h ; nbL\n", cycleCnt, 0, abi_reg[`DEC.dec_nonblock_load_waddr], `DEC.lsu_nonblock_load_data); soc_top.gpr[0][`DEC.dec_nonblock_load_waddr] = `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"; // tie offs jtag_id[31:28] = 4'b1; jtag_id[27:12] = '0; jtag_id[11:1] = 11'h45; reset_vector = 32'h0; nmi_vector = 32'hee000000; nmi_int = 0; $readmemh("program.hex", lmem.mem); $readmemh("program.hex", imem.mem); 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; preload_dccm(); preload_iccm(); `ifndef VERILATOR if($test$plusargs("dumpon")) $dumpvars; forever core_clk = #5 ~core_clk; `endif end assign rst_l = cycleCnt > 5; assign porst_l = cycleCnt >2; //=========================================================================- // RTL instance //=========================================================================- 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() ); swerv_wrapper rvtop ( .rst_l ( rst_l ), .dbg_rst_l ( porst_l ), .clk ( core_clk ), .rst_vec ( reset_vector[31:1]), .nmi_int ( nmi_int ), .nmi_vec ( nmi_vector[31:1]), .jtag_id ( jtag_id[31:1]), `ifdef RV_BUILD_AHB_LITE .haddr ( ic_haddr ), .hburst ( ic_hburst ), .hmastlock ( ic_hmastlock ), .hprot ( ic_hprot ), .hsize ( ic_hsize ), .htrans ( ic_htrans ), .hwrite ( ic_hwrite ), .hrdata ( ic_hrdata[63:0]), .hready ( ic_hready ), .hresp ( ic_hresp ), //--------------------------------------------------------------- // Debug AHB Master //--------------------------------------------------------------- .sb_haddr ( sb_haddr ), .sb_hburst ( sb_hburst ), .sb_hmastlock ( sb_hmastlock ), .sb_hprot ( sb_hprot ), .sb_hsize ( sb_hsize ), .sb_htrans ( sb_htrans ), .sb_hwrite ( sb_hwrite ), .sb_hwdata ( sb_hwdata ), .sb_hrdata ( sb_hrdata ), .sb_hready ( sb_hready ), .sb_hresp ( sb_hresp ), //--------------------------------------------------------------- // LSU AHB Master //--------------------------------------------------------------- .lsu_haddr ( lsu_haddr ), .lsu_hburst ( lsu_hburst ), .lsu_hmastlock ( lsu_hmastlock ), .lsu_hprot ( lsu_hprot ), .lsu_hsize ( lsu_hsize ), .lsu_htrans ( lsu_htrans ), .lsu_hwrite ( lsu_hwrite ), .lsu_hwdata ( lsu_hwdata ), .lsu_hrdata ( lsu_hrdata[63:0]), .lsu_hready ( lsu_hready ), .lsu_hresp ( lsu_hresp ), //--------------------------------------------------------------- // DMA Slave //--------------------------------------------------------------- .dma_haddr ( '0 ), .dma_hburst ( '0 ), .dma_hmastlock ( '0 ), .dma_hprot ( '0 ), .dma_hsize ( '0 ), .dma_htrans ( '0 ), .dma_hwrite ( '0 ), .dma_hwdata ( '0 ), .dma_hrdata ( dma_hrdata ), .dma_hresp ( dma_hresp ), .dma_hsel ( 1'b1 ), .dma_hreadyin ( dma_hready_out ), .dma_hreadyout ( dma_hready_out ), `endif .timer_int ( 1'b0 ), .extintsrc_req ( '0 ), .lsu_bus_clk_en ( 1'b1 ), .ifu_bus_clk_en ( 1'b1 ), .dbg_bus_clk_en ( 1'b1 ), .dma_bus_clk_en ( 1'b1 ), .trace_rv_i_insn_ip (trace_rv_i_insn_ip), .trace_rv_i_address_ip (trace_rv_i_address_ip), .trace_rv_i_valid_ip (trace_rv_i_valid_ip), .trace_rv_i_exception_ip(trace_rv_i_exception_ip), .trace_rv_i_ecause_ip (trace_rv_i_ecause_ip), .trace_rv_i_interrupt_ip(trace_rv_i_interrupt_ip), .trace_rv_i_tval_ip (trace_rv_i_tval_ip), .jtag_tck ( jtag_tck ), .jtag_tms ( jtag_tms ), .jtag_tdi ( jtag_tdi ), .jtag_trst_n ( jtag_trst_n ), .jtag_tdo ( jtag_tdo ), .mpc_debug_halt_ack ( mpc_debug_halt_ack), .mpc_debug_halt_req ( 1'b0), .mpc_debug_run_ack ( mpc_debug_run_ack), .mpc_debug_run_req ( 1'b1), .mpc_reset_run_req ( 1'b1), .debug_brkpt_status (debug_brkpt_status), .i_cpu_halt_req ( 1'b0 ), .o_cpu_halt_ack ( o_cpu_halt_ack ), .o_cpu_halt_status ( o_cpu_halt_status ), .i_cpu_run_req ( 1'b0 ), .o_debug_mode_status (o_debug_mode_status), .o_cpu_run_ack ( o_cpu_run_ack ), .dec_tlu_perfcnt0 (dec_tlu_perfcnt0), .dec_tlu_perfcnt1 (dec_tlu_perfcnt1), .dec_tlu_perfcnt2 (dec_tlu_perfcnt2), .dec_tlu_perfcnt3 (dec_tlu_perfcnt3), .scan_mode ( 1'b0 ), .mbist_mode ( 1'b0 ) ); //=========================================================================- // AHB I$ instance //=========================================================================- `ifdef RV_BUILD_AHB_LITE ahb_sif imem ( // Inputs .HWDATA(64'h0), .HCLK(core_clk), .HSEL(1'b1), .HPROT(ic_hprot), .HWRITE(ic_hwrite), .HTRANS(ic_htrans), .HSIZE(ic_hsize), .HREADY(ic_hready), .HRESETn(rst_l), .HADDR(ic_haddr), .HBURST(ic_hburst), // Outputs .HREADYOUT(ic_hready), .HRESP(ic_hresp), .HRDATA(ic_hrdata[63:0]) ); ahb_sif lmem ( // Inputs .HWDATA(lsu_hwdata), .HCLK(core_clk), .HSEL(1'b1), .HPROT(lsu_hprot), .HWRITE(lsu_hwrite), .HTRANS(lsu_htrans), .HSIZE(lsu_hsize), .HREADY(lsu_hready), .HRESETn(rst_l), .HADDR(lsu_haddr), .HBURST(lsu_hburst), // Outputs .HREADYOUT(lsu_hready), .HRESP(lsu_hresp), .HRDATA(lsu_hrdata[63:0]) ); `endif task preload_iccm; bit[31:0] data; bit[31:0] addr, eaddr, saddr; /* addresses: 0xfffffff0 - ICCM start address to load 0xfffffff4 - ICCM end address to load */ addr = 'hffff_fff0; saddr = {lmem.mem[addr+3],lmem.mem[addr+2],lmem.mem[addr+1],lmem.mem[addr]}; if ( (saddr < `RV_ICCM_SADR) || (saddr > `RV_ICCM_EADR)) return; `ifndef RV_ICCM_ENABLE $display("********************************************************"); $display("ICCM preload: there is no ICCM in SweRV, terminating !!!"); $display("********************************************************"); $finish; `endif addr += 4; eaddr = {lmem.mem[addr+3],lmem.mem[addr+2],lmem.mem[addr+1],lmem.mem[addr]}; $display("ICCM pre-load from %h to %h", saddr, eaddr); for(addr= saddr; addr <= eaddr; addr+=4) begin data = {imem.mem[addr+3],imem.mem[addr+2],imem.mem[addr+1],imem.mem[addr]}; slam_iccm_ram(addr, data == 0 ? 0 : {riscv_ecc32(data),data}); end endtask task preload_dccm; bit[31:0] data; bit[31:0] addr, saddr, eaddr; /* addresses: 0xffff_fff8 - DCCM start address to load 0xffff_fffc - DCCM end address to load */ addr = 'hffff_fff8; saddr = {lmem.mem[addr+3],lmem.mem[addr+2],lmem.mem[addr+1],lmem.mem[addr]}; if (saddr < `RV_DCCM_SADR || saddr > `RV_DCCM_EADR) return; `ifndef RV_DCCM_ENABLE $display("********************************************************"); $display("DCCM preload: there is no DCCM in SweRV, terminating !!!"); $display("********************************************************"); $finish; `endif addr += 4; eaddr = {lmem.mem[addr+3],lmem.mem[addr+2],lmem.mem[addr+1],lmem.mem[addr]}; $display("DCCM pre-load from %h to %h", saddr, eaddr); for(addr=saddr; addr <= eaddr; addr+=4) begin data = {lmem.mem[addr+3],lmem.mem[addr+2],lmem.mem[addr+1],lmem.mem[addr]}; slam_dccm_ram(addr, data == 0 ? 0 : {riscv_ecc32(data),data}); end endtask `define DRAM(bank) \ 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 task slam_iccm_ram(input [31:0] addr, input[38:0] data); int bank, indx; `ifdef RV_ICCM_ENABLE `ifdef RV_ICCM_NUM_BANKS_4 indx = int'(addr[`RV_ICCM_BITS-1:4]); bank = int'( addr[3:2]); `elsif RV_ICCM_NUM_BANKS_8 indx = int'(addr[`RV_ICCM_BITS-1:5]); bank = int'(addr[4:2]); `else indx = int'(addr[`RV_ICCM_BITS-1:6]); bank = int'( addr[5:2]); `endif case(bank) 0: `IRAM0(0)[indx] = data; 1: `IRAM1(0)[indx] = data; 2: `IRAM2(0)[indx] = data; 3: `IRAM3(0)[indx] = data; `ifdef RV_ICCM_NUM_BANKS_8 4: `IRAM0(1)[indx] = data; 5: `IRAM1(1)[indx] = data; 6: `IRAM2(1)[indx] = data; 7: `IRAM3(1)[indx] = data; `endif `ifdef RV_ICCM_NUM_BANKS_16 8: `IRAM0(2)[indx] = data; 9: `IRAM1(2)[indx] = data; 10: `IRAM2(2)[indx] = data; 11: `IRAM3(2)[indx] = data; 12: `IRAM0(3)[indx] = data; 13: `IRAM1(3)[indx] = data; 14: `IRAM2(3)[indx] = data; 15: `IRAM3(3)[indx] = data; `endif endcase `endif endtask task slam_dccm_ram(input [31:0] addr, input[38:0] data); int bank, indx; `ifdef RV_DCCM_ENABLE `ifdef RV_DCCM_NUM_BANKS_2 indx = int'(addr[`RV_DCCM_BITS-1:3]); bank = int'( addr[2]); `elsif RV_DCCM_NUM_BANKS_4 indx = int'(addr[`RV_DCCM_BITS-1:4]); bank = int'(addr[3:2]); `elsif RV_DCCM_NUM_BANKS_8 indx = int'(addr[`RV_DCCM_BITS-1:5]); bank = int'( addr[4:2]); `endif case(bank) 0: `DRAM(0)[indx] = data; 1: `DRAM(1)[indx] = data; `ifdef RV_DCCM_NUM_BANKS_4 2: `DRAM(2)[indx] = data; 3: `DRAM(3)[indx] = data; `endif `ifdef RV_DCCM_NUM_BANKS_8 2: `DRAM(2)[indx] = data; 3: `DRAM(3)[indx] = data; 4: `DRAM(4)[indx] = data; 5: `DRAM(5)[indx] = data; 6: `DRAM(6)[indx] = data; 7: `DRAM(7)[indx] = data; `endif endcase `endif endtask function[6:0] riscv_ecc32(input[31:0] data); reg[6:0] synd; synd[0] = ^(data & 32'h56aa_ad5b); synd[1] = ^(data & 32'h9b33_366d); synd[2] = ^(data & 32'he3c3_c78e); synd[3] = ^(data & 32'h03fc_07f0); synd[4] = ^(data & 32'h03ff_f800); synd[5] = ^(data & 32'hfc00_0000); synd[6] = ^{data, synd[5:0]}; return synd; endfunction /* verilator lint_off WIDTH */ /* verilator lint_off CASEINCOMPLETE */ `include "dasm.svi" /* verilator lint_on CASEINCOMPLETE */ /* verilator lint_on WIDTH */ endmodule