$display("%0d miscompares found", err_count) ;
end
endtask
// Task to ss_save verilog and mpsas state.
// variable 'Im_here' tells us if sas is running or not.
// if Im_here is 1, then i-i compare is on, if it's
// 0 then we are not using i-i compare.
reg saved
; initial saved
= 0;
reg restored
; initial restored
= 0;
task ss_save;
begin
if (saved == 0) begin
$display("Full save . . .");
saved=1;
// Save mpsas state.
if (sastasks.Im_here == 1) begin
$display("Dumping mpsas state . . .");
$sas_display("state dump mpsas");
if ($sas_command("quit")) begin
$display("Could not quit mpsas on save.");
end
sastasks.SAS=0;
disable sastasks.main_loop;
end
$display("Saving verilog state in file vimag");
// $ss_save("vimag");
if (sastasks.Im_here == 1) begin
sastasks.sas_init;
$sas_display("state restore mpsas");
// Doing a full save, remove old incremental.
$display("removing old incremental snapshosts.");
$system({"rm -rf vimag.inc mpsas.inc"});
end
end
else if (saved == 1) begin
$display("Incremental save . . .");
if (sastasks.Im_here == 1) begin
// Save mpsas state.
$sas_display("state dump mpsas.inc");
if ($sas_command("quit")) begin
$display("Could not quit mpsas on save.");
end
sastasks.SAS=0;
disable sastasks.main_loop;
end
$display("Saving verilog state in file vimag.inc");
// $ss_incsave("vimag.inc");
if (sastasks.Im_here == 1) begin
sastasks.sas_init;
$sas_display("state restore mpsas.inc");
end
end
end
endtask
// task ss_increstore will restore verilog and mpsas back to
// the last increment found in the current directory.
task ss_increstore;
begin
if (sastasks.Im_here == 1) begin
if ($sas_command("quit")) begin
$display("Could not quit mpsas on restore.");
end
end
// $ss_restart("vimag.inc");
if (sastasks.Im_here == 1) begin
sastasks.sas_init;
$sas_display("state restore mpsas");
end
end
endtask
// task ss_restore will restore verilog and mpsas back to
// the last full saved state.
task ss_restore;
begin
if (sastasks.Im_here == 1) begin
if ($sas_command("quit")) begin
$display("Could not quit mpsas on restore.");
end
end
// $ss_restart("vimag");
if (sastasks.Im_here == 1) begin
sastasks.sas_init;
$sas_display("state restore mpsas");
end
end
endtask
// Instantiate IU display module
Mdisplay iudisp() ;
// The following code provides for optional interrupts
// at random times.
// This switch turns on the interrupt test
reg irl_test
; initial irl_test
= 0;
reg irl_ext
; initial irl_ext
= 0 ;
reg irl_lev15
; initial irl_lev15
= 1 ;
integer irl_active
;
integer irl_passive
;
integer irl_ctr
;
integer irl_seed
;
integer irl_rate
; initial irl_rate
= 5 ;
reg [3:0] irl_drive
; // copy of value last sent to irl
reg [3:0] irl
;
/*
irl lines are now driven from interrupt priority model.
assign Msystem.irl = irl ;
*/
always @ (posedge Msystem.clock) #1 begin
// Initialize random state on reset, for determinism
if (`SS_SCOPE.reset) begin
irl_active = 0;
irl_passive = 100 ; // need a few cycles after reset
irl_ctr = 14;
irl_seed = 2571;
irl_drive = 0 ;
irl = 0 ;
end
// else if (!irl_test) begin
// if (! irl_ext) irl = 0 ;
// end
else if (irl_test) // if random ints enb
begin
if(irl_active > 0) begin
if (irl_drive < 15)
begin
irl_drive = irl_ctr ;
irl = irl_drive ;
end
irl_active = irl_active - 1;
if(irl_active <= 0) begin
irl_passive =
$dist_normal(irl_seed, irl_rate, 1);
if(irl_passive < 0)
irl_passive = 32'h0 - irl_passive;
end
end
else begin
if (irl_drive < 15)
begin
irl_drive = 0 ;
irl = 0 ;
end
irl_passive = irl_passive - 1;
if(irl_passive <= 0) begin
irl_active = $dist_normal(irl_seed, 3, 1);
if(irl_active < 0)
irl_active = 32'h0 - irl_active;
if (irl_active > 0) begin
irl_ctr = irl_ctr - 1;
if(irl_ctr <= 0) begin
irl_ctr = 14;
end
end
end
end
end
end
/*
Force sw_reset sequence to within a practical range for simulation. Prints timer value
to verilog.log if count is non-zero.
3-12-97
*/
always @(posedge Msystem.ssparc.ssparc_core.ssparc_pcic.interrupts.sys_rst_cntl.pci_clk)
begin
if(Msystem.ssparc.ssparc_core.ssparc_pcic.interrupts.sys_rst_cntl.sw_rst_tmr[14:0] != 0)
$display("sw_rst_tmr = %h",Msystem.ssparc.ssparc_core.ssparc_pcic.interrupts.sys_rst_cntl.sw_rst_tmr[14:0]);
if(Msystem.ssparc.ssparc_core.ssparc_pcic.interrupts.sys_rst_cntl.sw_rst_tmr[14:0] === 15'h00f0)
begin
#1 force `Msystem.ssparc.ssparc_core.ssparc_pcic.interrupts.sys_rst_cntl.sw_rst_tmr_in = 'h7bf0;
$display("Force software reset timer 0x7bf0");
@(posedge Msystem.ssparc.ssparc_core.ssparc_pcic.interrupts.sys_rst_cntl.pci_clk)
begin
#1 release `Msystem.ssparc.ssparc_core.ssparc_pcic.interrupts.sys_rst_cntl.sw_rst_tmr_in ;
end
end
if(Msystem.ssparc.ssparc_core.ssparc_pcic.interrupts.sys_rst_cntl.sw_rst_tmr[14:0] === 15'h7fc0)
begin
#1 force `Msystem.ssparc.ssparc_core.ssparc_pcic.interrupts.sys_rst_cntl.sw_rst_tmr_in = 'h7ff0;
$display("Force software reset timer 0x7ff0");
@(posedge Msystem.ssparc.ssparc_core.ssparc_pcic.interrupts.sys_rst_cntl.pci_clk)
begin
#1 release `Msystem.ssparc.ssparc_core.ssparc_pcic.interrupts.sys_rst_cntl.sw_rst_tmr_in ;
end
end
end
/*
* monitor state of MMU level 15 interrupt request & drive IRL
*/
/*
Level 15 interrupt is now driven in join_sb.v to one of the interrupt
priority model input pins.
always
@(`SS_SCOPE.cp_stat_l[0])
if (irl_lev15) // if enabled, loop back request
begin
irl_drive = ! `SS_SCOPE.cp_stat_l[0] ? 'hF :
irl_test && irl_active > 0 ? irl_ctr : 'h0 ;
irl = irl_drive ;
end
*/
// Monitor for standby mode
// These count sbclk cycles
//
// Use GCLK instead of sbus clock - Sandeep 6/21/96
// Use PCI clock instead of GCLK - Sandeep 7/15/96
//
integer standby_asserted
;
integer standby_clocks_off
;
// This counts positive edges on the standby pin
integer standby_periods
;
initial begin
standby_asserted = 0 ;
standby_clocks_off = 0 ;
standby_periods = 0 ;
end
// assign the internal standby port on ssparc to the external standby
// register since the standby pin has been deleted.
assign Msystem.ssparc.w_standby = Msystem.standby;
always @(posedge Msystem.standby)
standby_periods = standby_periods + 1 ;
Mflipflop_noop sds_ff(standby_dsbl_sysclk
,
`misc.standby_dsbl_sysclk_a1,
//`ssparc_core.sbclk0) ;
//`ssparc_core.w_gclk);
`SS_SCOPE.pci_clk0);
//always @(posedge `ssparc_core.sbclk0) begin
//always @(posedge `ssparc_core.w_gclk) begin
always @(posedge `SS_SCOPE.pci_clk0) begin
if (Msystem.standby===1'b1)
standby_asserted = standby_asserted + 1 ;
if (standby_dsbl_sysclk===1'b1)
standby_clocks_off = standby_clocks_off + 1 ;
end
task standby_report ;
//$display("standby pin asserted %0d times, %0d sbclk cycles; clocks off %0d sbclk cycles",
//$display("standby pin asserted %0d times, %0d gclk cycles; clocks off %0d gclk cycles",
$display("standby pin asserted %0d times, %0d pciclk cycles; clocks off %0d pciclk cycles",
standby_periods, standby_asserted, standby_clocks_off) ;
endtask
// Random standby mode: toggle the standby input pin, based on a
// random number generator. The integer standby_t contains a
// random number between 1 and (standby_max); it represents the
// number of sbclk cycles between toggles of standby.
reg [31:0] standby_max
; initial standby_max
= 67 ; // Prime number
reg [31:0] standby_t
;
reg [31:0] standby_seed
; initial standby_seed
= 0 ;
reg enbl_random_standby
;
initial begin
# 10 ; // delay to make the standby mode triggered
$GetEnv("standby_mode",enbl_random_standby);
$display("\n INFO: standby mode == %b", enbl_random_standby);
end
always @enbl_random_standby
begin
if ( enbl_random_standby === 1'b1)
$display("\n INFO: Random STANDBY MODE assertions in simulation");
while (enbl_random_standby===1'b1) begin
standby_t = ($random(standby_seed) % standby_max) + 1 ;
//repeat(standby_t) @(posedge `ssparc_core.sbclk0) #0 ;
//repeat(standby_t) @(posedge `ssparc_core.w_gclk) #0 ;
repeat(standby_t) @(posedge `SS_SCOPE.pci_clk0) #0 ;
// Print warning if the system has not yet responded to
// the last toggle.
if (standby_dsbl_sysclk ^ Msystem.standby) begin
//$display( "\n### %0d warning: standby_dsbl_sysclk=%b, %0d sbclks after standby <- %b",
//$display( "\n### %0d warning: standby_dsbl_sysclk=%b, %0d gclks after standby <- %b",
$display( "\n### %0d warning: standby_dsbl_sysclk=%b, %0d pciclks after standby <- %b",
Mclocks.cycle_count_s,
standby_dsbl_sysclk,
standby_t,
Msystem.standby) ;
$display( "### dc_standby_w=%b, ic_standby_f=%b, pcic_idle=%b, mm_hold_rst=%b, memif_idle=%b",
`misc.dc_standby_w, `misc.ic_standby_f, `misc.pcic_idle,
`misc.mm_hold_rst, `misc.memif_idle
) ;
Mclocks.warning_count = Mclocks.warning_count + 1 ;
end
#1 Msystem.standby = (Msystem.standby===1'b0) ;
$display("\n%0d: standby <- %b",
Mclocks.cycle_count, Msystem.standby) ;
end
end
// This signal is used below
Mflipflop_noop hold_ff(hold_d1
, `Mhold_control.hold, Msystem
.clock) ;
// Random ICache Miss
reg enbl_random_imiss
; initial enbl_random_imiss
= 0 ;
reg random_imiss
; initial random_imiss
= 0 ;
// These define the probability of forcing a miss on an access
integer imiss_num
; initial imiss_num
= 1 ;
integer imiss_denom
; initial imiss_denom
= 3 ;
// This is the seed used by $random
integer imiss_seed
; initial imiss_seed
= 0 ;
// Each time we do an ITag check, compute whether we should force an
// imiss on the *next* ITag check.
// Constraint from MMU: don't force any miss that would cause assertion of
// ic_miss in the cycle after hold is active.
wire itag_check_f
= `SSPARC_CORE.enbl_itag_match_f & ~`SSPARC_CORE.iwait_f
& ~(`SSPARC_CORE.ic_idle & hold_d1) ;
always @(posedge enbl_random_imiss) begin
$display("%0d: Enabling random I-Cache miss", Mclocks.cycle_count) ;
$display(" Forcing miss on %0d/%0d of all ITag accesses",
imiss_num, imiss_denom) ;
while (enbl_random_imiss)
@(posedge Msystem.clock) if (itag_check_f)
#1 random_imiss = (($random(imiss_seed)%imiss_denom)<imiss_num) ;
$display("%0d: Disabling random I-Cache miss", Mclocks.cycle_count) ;
random_imiss = 0 ;
end
// Effectively AND ~force_imiss_f into itag_hit ;
wire force_imiss_f
= itag_check_f & random_imiss ;
assign (supply1,supply0) `SSPARC_CORE.it_hit_f = force_imiss_f ? 1'b0 : 1'bz ;
// Random DCache Miss
reg enbl_random_dmiss
; initial enbl_random_dmiss
= 0 ;
reg random_dmiss
; initial random_dmiss
= 0 ;
// These define the probability of forcing a miss on an access
integer dmiss_num
; initial dmiss_num
= 1 ;
integer dmiss_denom
; initial dmiss_denom
= 3 ;
// This is the seed used by $random
integer dmiss_seed
; initial dmiss_seed
= 0 ;
// Each time we do a DTag check, compute whether we should force a
// dmiss on the *next* DTag check.
// Constraint from MMU: don't force any miss that would cause assertion of
// dc_miss in the cycle after hold is active.
wire dtag_check_w
= `SSPARC_CORE.enbl_dtag_match_w & ~`SSPARC_CORE.dwait_w
& ~(`SSPARC_CORE.dcc_idle & hold_d1) ;
always @(posedge enbl_random_dmiss) begin
$display("%0d: Enabling random D-Cache miss", Mclocks.cycle_count) ;
$display(" Forcing miss on %0d/%0d of all DTag accesses",
dmiss_num, dmiss_denom) ;
while (enbl_random_dmiss)
@(posedge Msystem.clock) if (dtag_check_w)
#1 random_dmiss = (($random(dmiss_seed)%dmiss_denom)<dmiss_num) ;
$display("%0d: Disabling random D-Cache miss", Mclocks.cycle_count) ;
random_dmiss = 0 ;
end
// Effectively AND ~force_dmiss_w into dtag_hit ;
wire force_dmiss_w
= dtag_check_w & random_dmiss ;
assign (supply1,supply0) `SSPARC_CORE.dt_hit_w = force_dmiss_w ? 1'b0 : 1'bz ;
// Leverage from P200 team
// IU pipeline display:
`ifdef IU_RTL
wire d_help =`IU.iuchip.decode.pipec_im_id.d_opcode[10];
wire [1:0] d_op =`IU.iuchip.decode.pipec_im_id.d_opcode[9:8];
wire [2:0] d_op2 =`IU.iuchip.decode.pipec_im_id.d_opcode[7:5];
wire [5:0] d_op3 =`IU.iuchip.decode.pipec_im_id.d_opcode[7:2];
wire e_help =`IU.iuchip.decode.pipec_im_id.e_opcode[10];
wire [1:0] e_op =`IU.iuchip.decode.pipec_im_id.e_opcode[9:8];
wire [2:0] e_op2 =`IU.iuchip.decode.pipec_im_id.e_opcode[7:5];
wire [5:0] e_op3 =`IU.iuchip.decode.pipec_im_id.e_opcode[7:2];
wire w_help =`IU.iuchip.decode.pipec_im_id.w_opcode[10];
wire [1:0] w_op =`IU.iuchip.decode.pipec_im_id.w_opcode[9:8];
wire [2:0] w_op2 =`IU.iuchip.decode.pipec_im_id.w_opcode[7:5];
wire [5:0] w_op3 =`IU.iuchip.decode.pipec_im_id.w_opcode[7:2];
wire r_help =`IU.iuchip.decode.ir_control.r_opcode[10];
wire [1:0] r_op =`IU.iuchip.decode.ir_control.r_opcode[9:8];
wire [2:0] r_op2 =`IU.iuchip.decode.ir_control.r_opcode[7:5];
wire [5:0] r_op3 =`IU.iuchip.decode.ir_control.r_opcode[7:2];
wire [63:0] d_opcode_dis =
disasm(d_help, d_op, d_op2, d_op3);
wire [63:0] e_opcode_dis =
disasm(e_help, e_op, e_op2, e_op3);
wire [63:0] w_opcode_dis =
disasm(w_help, w_op, w_op2, w_op3);
wire [63:0] r_opcode_dis =
disasm(r_help, r_op, r_op2, r_op3);
function [63:0] disasm;
input help;
input [1:0] op;
input [2:0] op2;
input [5:0] op3;
if ((help ^ (^op) ^ (^op2) ^ (^op3)) === 1'bx)
disasm = "x ";
else if (help)
disasm = "helpinst";
else if (op == 2'b00)
case (op2)
3'b100: disasm = "SETHI ";
3'b010: disasm = "Bicc ";
3'b110: disasm = "FBfcc ";
3'b111: disasm = "CBccc ";
3'b000: disasm = "UNIMP ";
endcase
else if (op == 2'b01)
disasm = "CALL ";
else if (op == 2'b10)
case (op3)
6'b000001: disasm = "AND ";
6'b010001: disasm = "ANDcc ";
6'b000101: disasm = "ANDN ";
6'b010101: disasm = "ANDNcc ";
6'b000010: disasm = "OR ";
6'b010010: disasm = "ORcc ";
6'b000110: disasm = "ORN ";
6'b010110: disasm = "ORNcc ";
6'b000011: disasm = "XOR ";
6'b010011: disasm = "XORcc ";
6'b000111: disasm = "XNOR ";
6'b010111: disasm = "XNORcc ";
6'b100101: disasm = "SLL ";
6'b100110: disasm = "SRL ";
6'b100111: disasm = "SRA ";
6'b000000: disasm = "ADD ";
6'b010000: disasm = "ADDcc ";
6'b001000: disasm = "ADDX ";
6'b011000: disasm = "ADDXcc ";
6'b100000: disasm = "TADDcc ";
6'b100010: disasm = "TADDccTV";
6'b000100: disasm = "SUB ";
6'b010100: disasm = "SUBcc ";
6'b001100: disasm = "SUBX ";
6'b011100: disasm = "SUBXcc ";
6'b100001: disasm = "TSUBcc ";
6'b100011: disasm = "TSUBccTV";
6'b100100: disasm = "MULScc ";
6'b001010: disasm = "UMUL ";
6'b001011: disasm = "SMUL ";
6'b011010: disasm = "UMULcc ";
6'b011011: disasm = "SMULcc ";
6'b001110: disasm = "UDIV ";
6'b001111: disasm = "SDIV ";
6'b011110: disasm = "UDIVcc ";
6'b011111: disasm = "SDIVcc ";
6'b111100: disasm = "SAVE ";
6'b111101: disasm = "RESTORE ";
6'b111000: disasm = "JMPL ";
6'b111001: disasm = "RETT ";
6'b111010: disasm = "Ticc ";
6'b101000: disasm = "RDY/ASR ";
6'b101001: disasm = "RDPSR ";
6'b101010: disasm = "RDWIM ";
6'b101011: disasm = "RDTBR ";
6'b110000: disasm = "WRY/ASR ";
6'b110001: disasm = "WRPSR ";
6'b110010: disasm = "WRWIM ";
6'b110011: disasm = "WRTBR ";
6'b101000: disasm = "STBAR ";
6'b111011: disasm = "FLUSH ";
6'b110100: disasm = "FPop1 ";
6'b110101: disasm = "FPop2 ";
6'b110110: disasm = "CPop1 ";
6'b110111: disasm = "CPop2 ";
endcase
else if (op == 2'b11)
case (op3)
6'b001001: disasm = "LDSB ";
6'b001010: disasm = "LDSH ";
6'b000001: disasm = "LDUB ";
6'b000010: disasm = "LDUH ";
6'b000000: disasm = "LD ";
6'b000011: disasm = "LDD ";
6'b011001: disasm = "LDSBA ";
6'b011010: disasm = "LDSHA ";
6'b010001: disasm = "LDUBA ";
6'b010010: disasm = "LDUHA ";
6'b010000: disasm = "LDA ";
6'b010011: disasm = "LDDA ";
6'b100000: disasm = "LDF ";
6'b100011: disasm = "LDDF ";
6'b100001: disasm = "LDFSR ";
6'b110000: disasm = "LDC ";
6'b110011: disasm = "LDDC ";
6'b110001: disasm = "LDCSR ";
6'b000101: disasm = "STB ";
6'b000110: disasm = "STH ";
6'b000100: disasm = "ST ";
6'b000111: disasm = "STD ";
6'b010101: disasm = "STBA ";
6'b010110: disasm = "STHA ";
6'b010100: disasm = "STA ";
6'b010111: disasm = "STDA ";
6'b100100: disasm = "STF ";
6'b100111: disasm = "STDF ";
6'b100101: disasm = "STFSR ";
6'b100110: disasm = "STDFQ ";
6'b110100: disasm = "STC ";
6'b110111: disasm = "STDC ";
6'b110101: disasm = "STCSR ";
6'b110110: disasm = "STDCQ ";
6'b001101: disasm = "LDSTUB ";
6'b011101: disasm = "LDSTUBA ";
6'b001111: disasm = "SWAP ";
6'b011111: disasm = "SWAPA ";
endcase
endfunction
`endif
// Trace modules for I-I sas support
reg trace_trap_handlers
; initial trace_trap_handlers
= 1;
Mcomplete complete(inst_complete
, end_diagnostic
,
Msystem.clock, `Mhold_control.hold, Msystem.ss_scan_mode);
Mtrace trace(inst_complete, `Mpc.tpc, end_diagnostic,
Msystem.clock, `Mhold_control.hold, Msystem.ss_scan_mode);
// Some IU functions
//--------------------------------------------------------------------------
// function to convert a physical register file address to a logical
// one. It returns a concatenation of the 3-bit CWP with the 5-bit
// register number. For GLOBALS cwp is set to 7.
// This routine always returns the OUT register CWP and register number
// rather than the (equivalent) IN.
function [7:0] phy2log;
input [6:0] paddr; // physical register file address
reg [2:0] cwp;
reg local; // 1 if register is a local
begin
local = 0;
if(paddr[6:3]==4'd00) begin // global
cwp = 7;
end
else begin // window register
local = ~paddr[3];
cwp = ~paddr[6:4];
end
if(local)
phy2log = {cwp, 2'b10, paddr[2:0]}; // LOCAL
else if (cwp==3'h7)
phy2log = {cwp, 2'b00, paddr[2:0]}; // GLOBAL
else
phy2log = {cwp, 2'b01, paddr[2:0]}; // OUT
end
endfunction
// task to display a logical address as derived with the function above
task disp_laddr;
input [7:0] phy2log;
begin
if(phy2log[7:5]==3'h7) // GLOBAL
$write("G_%x ", phy2log[2:0]);
else if(phy2log[4:3]==2'h2) // LOCAL
$write("W%d_L%x ", phy2log[7:5], phy2log[2:0]);
else // OUT
$write("W%d_O%x ", phy2log[7:5], phy2log[2:0]);
end
endtask
endmodule
This page: |
Created: | Thu Aug 19 12:00:49 1999 |
| From: |
../../../sparc_v8/env/rtl/task.v
|