447 lines
11 KiB
Verilog
447 lines
11 KiB
Verilog
/*Copyright 2020-2021 T-Head Semiconductor Co., Ltd.
|
|
|
|
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.
|
|
*/
|
|
`define E906
|
|
`define SOC_TOP tb.x_soc
|
|
`define RTL_MEM tb.x_soc.x_smem_ctrl
|
|
`define ISA_MEM tb.x_pa_isa
|
|
`define JTAG_5
|
|
|
|
`define IAHB_LITE
|
|
`ifdef IAHB_LITE
|
|
`define RTL_IAHBL_MEM tb.x_soc.x_cpu_sub_system_ahb.x_iahb_mem_ctrl
|
|
`else
|
|
`define RTL_IAHBL_MEM tb.x_soc.x_imem_ctrl
|
|
`endif
|
|
|
|
`define DAHB_LITE
|
|
`ifdef DAHB_LITE
|
|
`define RTL_DAHBL_MEM tb.x_soc.x_cpu_sub_system_ahb.x_dahb_mem_ctrl
|
|
`else
|
|
`define RTL_DAHBL_MEM tb.x_soc.x_dmem_ctrl
|
|
`endif
|
|
|
|
//clock period
|
|
`define CLK_PERIOD 10
|
|
`define TCLK_PERIOD 33
|
|
`define MAX_RUN_TIME 700000000
|
|
`define clk tb.clk
|
|
`define rst_b tb.rst_b
|
|
// `include "../cpu/environment.h"
|
|
`timescale 1ns/100ps
|
|
|
|
module tb();
|
|
reg clk;
|
|
reg jclk;
|
|
reg rst_b;
|
|
reg jrst_b;
|
|
reg nrst_b;
|
|
reg jtap_en;
|
|
//wire jtag2_sel;
|
|
wire jtg_tms;
|
|
wire jtg_tdi;
|
|
wire jtg_tdo;
|
|
|
|
wire uart0_sin;
|
|
wire [7:0]b_pad_gpio_porta;
|
|
static integer FILE;
|
|
//Clock Generator
|
|
initial
|
|
begin
|
|
clk =0;
|
|
forever begin
|
|
#(`CLK_PERIOD/2) clk = ~clk;
|
|
end
|
|
end
|
|
|
|
initial
|
|
begin
|
|
jclk = 0;
|
|
forever begin
|
|
#(`TCLK_PERIOD/2) jclk = ~jclk;
|
|
end
|
|
end
|
|
|
|
//Reset Generater
|
|
initial
|
|
begin
|
|
rst_b = 1;
|
|
#100;
|
|
rst_b = 0;
|
|
#100;
|
|
rst_b = 1;
|
|
end
|
|
|
|
initial
|
|
begin
|
|
jrst_b = 1;
|
|
#100;
|
|
jrst_b = 0;
|
|
#100;
|
|
jrst_b = 1;
|
|
end
|
|
|
|
initial
|
|
begin
|
|
nrst_b = 1;
|
|
#100;
|
|
nrst_b = 0;
|
|
#100;
|
|
nrst_b = 1;
|
|
end
|
|
|
|
///////////////////////////////////////
|
|
// Memory Initialization
|
|
///////////////////////////////////////
|
|
integer i;
|
|
reg [31:0] mem_data_size;
|
|
reg [31:0] mem_inst_size;
|
|
|
|
reg [31:0] mem_inst_temp [65536];
|
|
reg [31:0] mem_data_temp [65536];
|
|
|
|
initial
|
|
begin
|
|
$display("\t******START TO LOAD PROGRAM******\n");
|
|
$readmemh("./case.pat", mem_inst_temp);
|
|
$readmemh("./data.pat", mem_data_temp);
|
|
|
|
|
|
for(i=0;i<65536;i=i+1)
|
|
begin
|
|
`RTL_IAHBL_MEM.ram0.mem[i][7:0] = ((^mem_inst_temp[i][31:24]) === 1'bx ) ? 8'b0:mem_inst_temp[i][31:24];
|
|
`RTL_IAHBL_MEM.ram1.mem[i][7:0] = ((^mem_inst_temp[i][23:16]) === 1'bx ) ? 8'b0:mem_inst_temp[i][23:16];
|
|
`RTL_IAHBL_MEM.ram2.mem[i][7:0] = ((^mem_inst_temp[i][15: 8]) === 1'bx ) ? 8'b0:mem_inst_temp[i][15: 8];
|
|
`RTL_IAHBL_MEM.ram3.mem[i][7:0] = ((^mem_inst_temp[i][ 7: 0]) === 1'bx ) ? 8'b0:mem_inst_temp[i][ 7: 0];
|
|
end
|
|
|
|
for(i=0;i<=65536;i=i+1)
|
|
begin
|
|
`RTL_DAHBL_MEM.ram0.mem[i][7:0] = 8'b0;
|
|
`RTL_DAHBL_MEM.ram1.mem[i][7:0] = 8'b0;
|
|
`RTL_DAHBL_MEM.ram2.mem[i][7:0] = 8'b0;
|
|
`RTL_DAHBL_MEM.ram3.mem[i][7:0] = 8'b0;
|
|
end
|
|
for(i=0;i<=65536;i=i+1)
|
|
begin
|
|
`RTL_DAHBL_MEM.ram4.mem[i][7:0] = 8'b0;
|
|
`RTL_DAHBL_MEM.ram5.mem[i][7:0] = 8'b0;
|
|
`RTL_DAHBL_MEM.ram6.mem[i][7:0] = 8'b0;
|
|
`RTL_DAHBL_MEM.ram7.mem[i][7:0] = 8'b0;
|
|
end
|
|
|
|
|
|
end
|
|
///////////////////////////////////////
|
|
// Finish Condition Control
|
|
///////////////////////////////////////
|
|
|
|
// Reaching the max simulation time.
|
|
reg [31:0] ins_counter;
|
|
initial
|
|
begin
|
|
#`MAX_RUN_TIME;
|
|
$display("**********************************************");
|
|
$display("* meeting max simulation time, stop! *");
|
|
$display("**********************************************");
|
|
FILE = $fopen("run_case.report","w");
|
|
$fdisplay(FILE,"TEST FAIL");
|
|
$finish;
|
|
end
|
|
// No instrunction retired in the last `LAST_CYCLE cycles
|
|
reg [31:0] retire_inst_in_period;
|
|
reg [31:0] cycle_count;
|
|
`define LAST_CYCLE 5000
|
|
always @(posedge clk or negedge rst_b)
|
|
begin
|
|
if(!rst_b)
|
|
cycle_count[31:0] <= 32'b1;
|
|
else
|
|
cycle_count[31:0] <= cycle_count[31:0] + 1'b1;
|
|
end
|
|
|
|
|
|
always @(posedge clk or negedge rst_b)
|
|
begin
|
|
if(!rst_b) //reset to zero
|
|
retire_inst_in_period[31:0] <= 32'b0;
|
|
else if( (cycle_count[31:0] % `LAST_CYCLE) == 0)//check and reset retire_inst_in_period every 50000 cycles
|
|
begin
|
|
if(retire_inst_in_period[31:0] == 0)begin
|
|
$display("*************************************************************");
|
|
$display("* Error: There is no instructions retired in the last %d cycles! *", `LAST_CYCLE);
|
|
$display("* Simulation Fail and Finished! *");
|
|
$display("*************************************************************");
|
|
#10;
|
|
FILE = $fopen("run_case.report","w");
|
|
$fdisplay(FILE,"TEST FAIL");
|
|
|
|
$finish;
|
|
end
|
|
retire_inst_in_period[31:0] <= 32'b0;
|
|
end
|
|
else if(tb.x_soc.x_cpu_sub_system_ahb.biu_pad_retire)
|
|
retire_inst_in_period[31:0] <= retire_inst_in_period[31:0] + 1'b1;
|
|
end
|
|
|
|
|
|
//Finish control with address 32'h0
|
|
reg [31:0] cpu_addr;
|
|
reg [1:0] cpu_trans;
|
|
reg cpu_write;
|
|
wire [31:0] cpu_wdata;
|
|
always @(posedge clk)
|
|
begin
|
|
cpu_trans[1:0] <= `SOC_TOP.biu_pad_htrans[1:0];
|
|
cpu_addr[31:0] <= `SOC_TOP.biu_pad_haddr[31:0];
|
|
cpu_write <= `SOC_TOP.biu_pad_hwrite;
|
|
end
|
|
assign cpu_wdata[31:0] = `SOC_TOP.biu_pad_hwdata[31:0];
|
|
always @(posedge clk)
|
|
begin
|
|
if((cpu_trans[1:0] == 2'b10) &&
|
|
(cpu_addr[31:0] == 32'h6000fff8) &&
|
|
cpu_write &&
|
|
(cpu_wdata[31:0] == 12'hfff || cpu_wdata[31:0] == 32'hffff0000))
|
|
begin
|
|
$display("\n**********************************************");
|
|
$display("* simulation finished successfully *");
|
|
$display("**********************************************");
|
|
#10;
|
|
FILE = $fopen("run_case.report","w");
|
|
$fdisplay(FILE,"TEST PASS");
|
|
|
|
$finish;
|
|
end
|
|
else if((cpu_trans[1:0] == 2'b10) &&
|
|
(cpu_addr[31:0] == 32'h6000fff8) &&
|
|
cpu_write &&
|
|
(cpu_wdata[31:0] == 12'heee || cpu_wdata[31:0] == 32'heeee0000))
|
|
begin
|
|
$display("**********************************************");
|
|
$display("* simulation finished with error *");
|
|
$display("**********************************************");
|
|
#10;
|
|
FILE = $fopen("run_case.report","w");
|
|
$fdisplay(FILE,"TEST FAIL");
|
|
|
|
$finish;
|
|
end
|
|
else if((cpu_trans[1:0] == 2'b10) &&
|
|
(cpu_addr[31:0] == 32'h6000fff8) &&
|
|
cpu_write)
|
|
begin
|
|
// $write("begin to display:");
|
|
$write("%c", cpu_wdata[7:0]);
|
|
end
|
|
end
|
|
|
|
//Dumping Control
|
|
`ifndef NO_DUMP
|
|
initial
|
|
begin
|
|
`ifdef NC_SIM
|
|
$dumpfile("test.vcd");
|
|
$dumpvars;
|
|
`else
|
|
`ifdef IVERILOG_SIM
|
|
$dumpfile("test.vcd");
|
|
$dumpvars;
|
|
`else
|
|
$fsdbDumpvars();
|
|
`endif
|
|
`endif
|
|
end
|
|
`endif
|
|
|
|
//Monitor
|
|
`ifndef NO_MONITOR
|
|
mnt x_mnt();
|
|
`endif
|
|
uart_mnt x_uart_mnt();
|
|
assign jtg_tdi = 1'b0;
|
|
|
|
assign uart0_sin = 1'b1;
|
|
|
|
//instantiate soc
|
|
soc x_soc(
|
|
.i_pad_clk ( clk ),
|
|
.i_pad_uart0_sin ( uart0_sin ),
|
|
.o_pad_uart0_sout ( uart0_sout ),
|
|
.i_pad_jtg_tclk ( jclk ),
|
|
.i_pad_jtg_trst_b ( jrst_b ),
|
|
.i_pad_jtg_nrst_b ( nrst_b ),
|
|
.b_pad_gpio_porta ( b_pad_gpio_porta ),
|
|
`ifdef JTAG_5
|
|
.i_pad_jtg_tdi ( jtg_tdi ),
|
|
.o_pad_jtg_tdo ( jtg_tdo ),
|
|
`endif
|
|
.i_pad_jtg_tms ( jtg_tms ),
|
|
`ifdef RST_ACTIVE_HIGH
|
|
.i_pad_rst ( !rst_b )
|
|
`else
|
|
.i_pad_rst_b ( rst_b )
|
|
`endif
|
|
);
|
|
|
|
|
|
`ifdef PG_SIM
|
|
|
|
`define MAX_ARCH_STRLEN 100
|
|
|
|
function supply_on;
|
|
//input string pad_name;
|
|
input [8*`MAX_ARCH_STRLEN : 1] pad_name;
|
|
input real value;
|
|
begin
|
|
supply_on = $mvsim_supply_on(pad_name, value);
|
|
end
|
|
endfunction
|
|
|
|
function supply_off;
|
|
//input string pad_name;
|
|
input [8*`MAX_ARCH_STRLEN : 1] pad_name;
|
|
begin
|
|
supply_off = $mvsim_supply_off(pad_name);
|
|
end
|
|
endfunction
|
|
|
|
real sp_on_vdd;
|
|
real sp_on_vss;
|
|
|
|
|
|
initial
|
|
begin
|
|
sp_on_vdd = supply_on("VDD", 1.2);
|
|
sp_on_vss = supply_on("VSS", 0);
|
|
|
|
// #1000
|
|
// force tb.x_soc.pad_cpu_rst_b = 1'b0;
|
|
// #20
|
|
// force tb.x_soc.x_cpu_sub_system_ahb.x_ck803s.pmu_corec_isolation = 1'b1;
|
|
// #20
|
|
// force tb.x_soc.x_cpu_sub_system_ahb.x_ck803s.pmu_corec_sleep_in = 1'b1;
|
|
//
|
|
// #500
|
|
//
|
|
// release tb.x_soc.x_cpu_sub_system_ahb.x_ck803s.pmu_corec_sleep_in ;
|
|
// #20
|
|
// release tb.x_soc.x_cpu_sub_system_ahb.x_ck803s.pmu_corec_isolation;
|
|
// #20
|
|
// release tb.x_soc.pad_cpu_rst_b ;
|
|
|
|
end
|
|
|
|
initial
|
|
begin
|
|
$deposit(tb.x_soc.x_cpu_sub_system_ahb.pmu_corec_sleep_in, 1'b0);
|
|
$deposit(tb.x_soc.x_cpu_sub_system_ahb.pmu_corec_isolation, 1'b0);
|
|
$deposit(tb.x_soc.x_cpu_sub_system_ahb.corec_pmu_sleep_out, 1'b0);
|
|
end
|
|
|
|
`endif
|
|
|
|
`ifdef E902
|
|
`define CPU_TOP tb.x_soc.x_cpu_sub_system_ahb.x_e902
|
|
`elsif E906
|
|
`define CPU_TOP tb.x_soc.x_cpu_sub_system_ahb.x_e906_top
|
|
`else
|
|
`define CPU_TOP tb.x_soc.x_cpu_sub_system_ahb.x_ck803s
|
|
`endif
|
|
|
|
`define CPU_CLK `CPU_TOP.pll_core_cpuclk
|
|
`define CPU_RST `CPU_TOP.pad_cpu_rst_b
|
|
|
|
`ifdef E902
|
|
`define VIRTUAL_READ `CPU_TOP.x_cr_tcipif_top.x_cr_tcipif_dbus.dummy_addr_cmplt
|
|
`elsif E906
|
|
`define VIRTUAL_READ `CPU_TOP.x_pa_tcipif_top.x_pa_tcipif_dbus.dummy_addr_cmplt
|
|
`else
|
|
`define VIRTUAL_READ `CPU_TOP.x_vg_tcip_top.x_nm_tcipif_dbus.dummy_addr_cmplt
|
|
`endif
|
|
`ifdef E902
|
|
`define VIRTUAL_TIME `CPU_TOP.x_cr_tcipif_top.x_cr_tcipif_dbus.tcipif_rd_data[31:0]
|
|
`elsif E906
|
|
`define VIRTUAL_TIME `CPU_TOP.x_pa_tcipif_top.x_pa_tcipif_dbus.tcipif_bmu_dbus_data[31:0]
|
|
`else
|
|
`define VIRTUAL_TIME `CPU_TOP.x_vg_tcip_top.x_nm_tcipif_dbus.tcipif_dbus_rd_data[31:0]
|
|
`endif
|
|
|
|
reg [31:0] virtual_counter;
|
|
|
|
always @(posedge `CPU_CLK or negedge `CPU_RST)
|
|
begin
|
|
if(!`CPU_RST)
|
|
virtual_counter[31:0] <= 32'b0;
|
|
else if(virtual_counter[31:0]==32'hffffffff)
|
|
virtual_counter[31:0] <= virtual_counter[31:0];
|
|
else
|
|
virtual_counter[31:0] <= virtual_counter[31:0] +1'b1;
|
|
end
|
|
|
|
initial
|
|
begin
|
|
#1;
|
|
wait (`VIRTUAL_READ==1'b1);
|
|
force `VIRTUAL_TIME = virtual_counter[31:0];
|
|
@(posedge `CPU_CLK);
|
|
release `VIRTUAL_TIME;
|
|
#1;
|
|
|
|
wait (`VIRTUAL_READ==1'b1);
|
|
force `VIRTUAL_TIME = virtual_counter[31:0];
|
|
@(posedge `CPU_CLK);
|
|
release `VIRTUAL_TIME;
|
|
#1;
|
|
|
|
wait (`VIRTUAL_READ==1'b1);
|
|
force `VIRTUAL_TIME = virtual_counter[31:0];
|
|
@(posedge `CPU_CLK);
|
|
release `VIRTUAL_TIME;
|
|
#1;
|
|
|
|
wait (`VIRTUAL_READ==1'b1);
|
|
force `VIRTUAL_TIME = virtual_counter[31:0];
|
|
@(posedge `CPU_CLK);
|
|
release `VIRTUAL_TIME;
|
|
|
|
#1;
|
|
wait (`VIRTUAL_READ==1'b1);
|
|
force `VIRTUAL_TIME = virtual_counter[31:0];
|
|
@(posedge `CPU_CLK);
|
|
release `VIRTUAL_TIME;
|
|
|
|
#1;
|
|
wait (`VIRTUAL_READ==1'b1);
|
|
force `VIRTUAL_TIME = virtual_counter[31:0];
|
|
@(posedge `CPU_CLK);
|
|
release `VIRTUAL_TIME;
|
|
#1;
|
|
end
|
|
|
|
// count instruction number
|
|
always @(posedge `CPU_CLK or negedge `CPU_RST)
|
|
begin
|
|
if(!`CPU_RST)
|
|
ins_counter[31:0] <= 32'b0;
|
|
else if(`SOC_TOP.x_cpu_sub_system_ahb.biu_pad_retire &&
|
|
(`SOC_TOP.x_cpu_sub_system_ahb.biu_pad_retire_pc[31:0] > 32'had4))
|
|
ins_counter[31:0] <= ins_counter[31:0] + 1'b1;
|
|
else
|
|
ins_counter[31:0] <= ins_counter[31:0];
|
|
end
|
|
|
|
endmodule
|
|
|