// m4 doesn't work on the rest of this file with the usual quotes
// because these are used by verilog defines.
// change the quotes to very unlikely characters.
// also have to undefine define.
//
// commented out the m4 stuff because eagle's vpp does not support m4
//undefine(`define')
//undefine(`ifdef')
//changequote( )
module sastasks
;
//reg Mtask.complete.fold_comp;
reg psr_initialized
;
reg [31:0] sas_cmp_flag
;
integer Im_here
;
integer fpu_trap_flag
;
integer trap_flag
;
integer count_3_cycles
;
integer instr_count
;
integer mismatch_count
;
integer max_mismatch
;
integer num_ins_completed
;
integer iu_flds_done
;
parameter cycle = 20;
// new for FPU sas verilog
integer head
;
integer tail
;
integer num_fpdone
;
integer starting_fpop
;
integer fold_1st
;
reg fpopdone
;
reg[31:0] pc_que
[10:0];
reg[31:0] instr_que
[10:0];
reg[1:0] loop_count
;
// end of new add for FPU sas verilog
reg status
;
reg SAS
;
reg sas_verbose
;
reg trap_event_case
;
reg trap_happen
;
reg[55:0] sas_char
;
reg[31:0] comp_pc
, fpu_comp_pc
;
reg[31:0] comp_instr
, fpu_comp_instr
;
reg annul_flag
;
reg [31:0] tbr_value
;
integer s_sim
;
integer s_dmp
;
integer s_cmp
;
integer mike_i
;
event event_trap_completed;
event trap_complete_event;
event iu_flds_complete_event;
event fpop_complete_event;
function isfload;
input[31:0] instr;
begin
if (instr[31:30] == 2'b11)
begin
case (instr[24:19])
6'b100000, // ldf
6'b100011, // lddf
6'b100001: // ldfsr
isfload = 1;
default:
isfload = 0;
endcase
end
else
isfload = 0;
end endfunction
function isfstore;
input[31:0] instr;
begin
if (instr[31:30] == 2'b11)
begin
case (instr[24:19])
6'b100100, 6'b100111, 6'b100101, 6'b100110:
isfstore = 1;
default:
isfstore = 0;
endcase
end
else
isfstore = 0;
end endfunction
function isfpop;
input[31:0] instr;
begin
if (instr[31:30] == 2'b10)
begin
case (instr[24:19])
6'b110100, 6'b110101:
isfpop = 1;
default:
isfpop = 0;
endcase
end
else
isfpop = 0;
end endfunction
function isanullbranchalways;
input[31:0] instr;
isanullbranchalways = ({instr[31:30],
instr[29],
instr[28:25],
instr[24:22]}==10'b00_1_1000_010) ||
({instr[31:30],
instr[29],
instr[28:25],
instr[24:22]}==10'b00_1_1000_110);
endfunction
function isanullbranch;
input[31:0] instr;
isanullbranch = (({instr[31:30],
instr[29],
instr[24:22]}==6'b00_1_010) ||
({instr[31:30],
instr[29],
instr[24:22]}==6'b00_1_110) ||
({instr[31:30],
instr[29],
instr[24:22]}==6'b00_1_111));
endfunction
function [7:0] phys_adr;
input [2:0] window; // this is the window number
input [4:0] log_adr; // this is the relative register within the
// rg+24 = in, rg+16 = local, rg+8 = out, 0
reg [2:0] window_;
reg [3:0] windowp1_;
reg [2:0] windowmm1_;
reg [4:0] in_blk, local_blk, out_blk, global_blk;
reg [3:0] rg;
reg [2:0] cwp;
begin
window_ = ~window;
windowp1_ = ({1'b0,window_}) + 4'b0001;
// windowp1_ = ~(window == 6 ? 3'b0 : window + 1);
// windowmm1_ = ~(window + 1);
in_blk = (window_ == 3'b0) ? {1'b1,window_,1'b0} : {1'b0,window_,1'b0};
local_blk = {1'b0,window_,1'b1};
out_blk = {windowp1_,1'b0};
global_blk = 0;
case ({log_adr[4], log_adr[3]})
2'b00: phys_adr = {global_blk, log_adr[2:0]};
2'b01: phys_adr = {out_blk, log_adr[2:0]};
2'b10: phys_adr = {local_blk, log_adr[2:0]};
2'b11: phys_adr = {in_blk, log_adr[2:0]};
default: phys_adr = {4'bxxxx, log_adr[2:0]};
endcase
end
endfunction
always @(posedge `BOARD.SYS_CLK)
#(cycle - 2) if (Mtask.trace.trace)
begin :main_loop
iu_flds_done = 0;
fold_1st = 0;
if (Mtask.complete.fold_comp || (Mtask.complete.fold_in_r && Mtask.complete.r_cycle_trap))
loop_count = 2;
else
loop_count = 1;
while (loop_count > 0)
begin
if (Mtask.complete.r_cycle_trap && (loop_count == 1))
begin
$allow_cmp_tbr();
if (fpusas_sig.fpu_trap)
begin
fpu_trap_flag = 1;
end
trap_flag = 1;
comp_pc = Mtask.complete.r_pc;
comp_instr = Mtask.complete.r_decode_inst;
num_ins_completed = 1;
trap_event_case = 1;
@(event_trap_completed);
->trap_complete_event;
if (fpu_trap_flag)
tail = head;
fpu_trap_flag = 0;
trap_flag = 0;
end
else if ((!Mtask.complete.hold_pipe && (Mtask.complete.result_compare || annul_flag || (Mtask.complete.fold_in_r && Mtask.complete.fold_annul_r) || Mtask.complete.fold_comp)) || (Mtask.complete.fold_in_r && Mtask.complete.r_cycle_trap))
begin
num_ins_completed = 1;
if (loop_count == 1)
begin
comp_pc = Mtask.complete.r_pc;
if (Mtask.complete.fold_in_r && Mtask.complete.fold_annul_r)
begin
comp_instr = Mtask.complete.fold_rir;
->iu_flds_complete_event;
end else
begin
comp_instr = Mtask.complete.r_decode_inst;
if (isfpop(Mtask.complete.r_decode_inst))
begin
if (!annul_flag)
begin
pc_que[tail] = Mtask.complete.r_pc;
instr_que[tail] = Mtask.complete.r_decode_inst;
tail = tail + 1;
if (tail > 10)
tail = 0;
dis_fpq_msg;
end
if (SAS)
sas_simulate;
end
else
begin
if (!annul_flag)
->iu_flds_complete_event;
else
if (SAS)
sas_simulate;
end
end
end
else
begin
fold_1st = 1;
->iu_flds_complete_event;
end
if (!(Mtask.complete.fold_in_r && Mtask.complete.fold_annul_r) && ((loop_count == 1) && (isanullbranchalways(Mtask.complete.r_decode_inst) || (isanullbranch(Mtask.complete.r_decode_inst) && !( (Mtask.complete.r_bicc_taken && (Mtask.complete.r_decode_inst[24:22]==3'b010)) || (Mtask.complete.r_fcc_taken && (Mtask.complete.r_decode_inst[24:22]==3'b110)) )))))
begin
if(annul_flag)
annul_flag = 0;
else
annul_flag = 1;
end
else
begin
annul_flag = 0;
end
end
if (loop_count == 1)
begin
if (fpusas_sig.fpop_done > 0)
begin
->fpop_complete_event;
end
end
if (fold_1st)
wait (iu_flds_done);
loop_count = loop_count - 1;
fold_1st = 0;
end // end while
end // end main_loop
always @(posedge `BOARD.SYS_CLK)
begin
if (!Mtask.complete.hold_pipe && (trap_event_case))
begin
trap_happen = 1;
trap_event_case = 0;
end
end
always @(posedge `BOARD.SYS_CLK)
begin
#(cycle - 2);
if (loop_count == 1)
begin
// FPU compares while IU is taking an
// unrelated trap
// if ((fpusas_sig.fpop_done > 0) && (trap_happen || Mtask.complete.r_cycle_trap))
// begin
// ->fpop_complete_event;
// end
if (!Mtask.complete.hold_pipe && (trap_happen)) // count 3 cycles for trap
begin
count_3_cycles = count_3_cycles + 1;
if (count_3_cycles == 3)
begin
trap_happen = 0;
count_3_cycles = 0;
-> event_trap_completed;
end
end
end
end
always @(fpop_complete_event)
begin
if ( SAS )
begin
for (num_fpdone = fpusas_sig.fpop_done; num_fpdone > 0; num_fpdone = num_fpdone - 1)
begin
if (tail == head) begin
$display(
"Warning: There are no fpops in fpc queue when done is asserted");
end
else begin
fpu_comp_pc = pc_que[head];
fpu_comp_instr = instr_que[head];
fpop_sas_simulate;
end
end
fpusas_sig.fpop_done = 0 ;
if (! fpusas_sig.fpop_deferred) begin // have to compare later
// $display("fpop_complete_event: comparing fpu state");
sas_fpu_dump_state;
compare_fpu_state;
end
end
end
always @(trap_complete_event)
begin
dis_trap_msg;
if ( SAS )
begin
sas_set_irl;
sas_simulate;
sas_dump_state;
sas_compare_state;
if ((! fpusas_sig.fpop_deferred) && // defer fpu compare
(fpu_trap_flag != 0)) begin // don't compare fpu for non-fp trap
// $display("trap_complete_event: comparing fpu state");
sas_fpu_dump_state;
compare_fpu_state;
end
sas_unset_irl;
end
end
always @(iu_flds_complete_event)
begin
dis_msg;
if ( SAS )
begin
sas_simulate;
if (loop_count == 0)
begin
sas_dump_state;
sas_compare_state;
if (isfload(Mtask.complete.r_decode_inst) && !fpusas_sig.fpop_deferred &&
!fpusas_sig.fpop_done) // cmp later
begin
// $display("iu_flds_complete_event: comparing fpu state");
sas_fpu_dump_state; // compare after fload
compare_fpu_state;
end
end
else begin
if ($sas_dump_inst(Mtask.complete.fold_rir))
$display("%d *** Error : in $sas_dump_inst",Mclocks.cycle_count);
if ($sas_dump_pc(Mtask.complete.r_pc-4))
$display("%d *** Error : in $sas_dump_pc",Mclocks.cycle_count);
sas_compare_fold_state;
end
if (Mtask.complete.fold_in_r && Mtask.complete.fold_annul_r)
sas_simulate;
end
iu_flds_done = 1;
end
task fpop_sas_simulate;
begin
begin
dis_fpu_msg;
if ($sas_command("focus fpu"))
begin
$display("%d *** Error : in $sas_command",Mclocks.cycle_count);
$stop;
end
if ($sas_command("finish_fpop"))
begin
$display("%d *** Error : in $sas_command",Mclocks.cycle_count);
$stop;
end
if ($sas_command("focus cpu"))
begin
$display("%d *** Error : in $sas_command",Mclocks.cycle_count);
$stop;
end
end
end
endtask
task sas_fpu_dump_state;
reg [31:0] value;
integer i;
reg pipe_qne ;
begin
for (i=0;i<16;i=i+1) begin
value = `FPUREG.fp_regfile.rf_even[i] ;
if ($sas_data_append(value)) begin
$display("%d *** Error : in $sas_data_append %d",Mclocks.cycle_count,i);
// board.clocks.xstop;
disable sas_fpu_dump_state ;
end
value = `FPUREG.fp_regfile.rf_odd[i] ;
if ($sas_data_append(value)) begin
$display("%d *** Error : in $sas_data_append %d",Mclocks.cycle_count,i);
// board.clocks.xstop;
disable sas_fpu_dump_state ;
end
end
value[31:14] = fpusas_sig.fsr[31:14] ;
value[13] = fpusas_sig.qne_r & ((tail != head) || !fpusas_sig.exemode);
value[12:0] = fpusas_sig.fsr[12:0] ;
if ($sas_data_append(value))
begin
$display("%d *** Error : in $sas_data_append %d",Mclocks.cycle_count,i);
disable sas_fpu_dump_state ;
end
end
endtask
task compare_fpu_state;
begin
if ($start_compare_fpu(Mclocks.cycle_count))
begin
if ( mismatch_count < 0 )
mismatch_count = 0;
mismatch_count = mismatch_count + 1;
if ( (mismatch_count > 0 ) &&
( mismatch_count >= max_mismatch))
Mclocks.print_error("FPU mismatch against SAS") ;
end
end
endtask
task sas_simulate;
integer i;
begin
// MPSas will give you the 'fetched pc' when you do print pc
// but verilog will give 'execute pc' when we get inst_comp
// so save current pc and compare after in the PLI
s_sim = s_sim + 1;
if ($sas_save_pc())
begin
$display("%d *** Error : in $sas_save_pc",Mclocks.cycle_count);
end
for (i=0; i<num_ins_completed; i=i+1)
begin
instr_count = instr_count + 1;
if ($sas_command("run"))
begin
$display("%d *** Error : in $sas_command",
Mclocks.cycle_count);
$stop;
end
end
end
endtask
task dis_fpu_msg;
begin
$display;
$fwrite(Mccdisp.allvec_mcd, "// ") ;
$fwrite(Mccdisp.allvec_tto_mcd, "%0d\t:: FPOP completed ",
Mclocks.cycle_count);
$fwrite(Mccdisp.allvec_tto_mcd, "%h %h ", fpu_comp_pc, fpu_comp_instr);
if ($disassemble(fpu_comp_instr,32'b0))
$fdisplay(Mccdisp.allvec_tto_mcd, "disassemble error");
if (head == 10)
head = 0;
else
head = head + 1;
$fdisplay(Mccdisp.allvec_mcd) ;
end
endtask
task dis_trap_msg;
begin
$display;
$fwrite(Mccdisp.allvec_mcd, "// ") ;
$fwrite(Mccdisp.allvec_tto_mcd, "%0d\t:: Trap occured ",
Mclocks.cycle_count );
$fwrite(Mccdisp.allvec_tto_mcd, "%h %h ", comp_pc, comp_instr);
if ($disassemble(comp_instr,32'b0))
$fdisplay(Mccdisp.allvec_tto_mcd, "disassemble error");
$fdisplay(Mccdisp.allvec_mcd) ;
end
endtask
task dis_fpq_msg;
begin
$display;
$fwrite(Mccdisp.allvec_mcd, "// ") ;
$fwrite(Mccdisp.allvec_tto_mcd, "%0d\t:: FPOP Instr queued ", Mclocks.cycle_count);
$fwrite(Mccdisp.allvec_tto_mcd, "%h %h ", comp_pc, comp_instr);
if ($disassemble(comp_instr,32'b0))
$fdisplay(Mccdisp.allvec_tto_mcd, "disassemble error");
$fdisplay(Mccdisp.allvec_mcd) ;
end
endtask
task dis_msg;
begin
$display;
$fwrite(Mccdisp.allvec_mcd, "// ") ;
$fwrite(Mccdisp.allvec_tto_mcd, "%0d\t:: Instr trace ",
Mclocks.cycle_count);
if (loop_count == 2)
begin
$fwrite(Mccdisp.allvec_tto_mcd, "%h %h folded ", Mtask.complete.r_pc-4,Mtask.complete.fold_rir);
if ($disassemble(Mtask.complete.fold_rir,32'b0))
$fdisplay(Mccdisp.allvec_tto_mcd, "disassemble error");
end
else if (Mtask.complete.fold_in_r && Mtask.complete.fold_annul_r)
begin
$fwrite(Mccdisp.allvec_tto_mcd, "%h %h folded branch and annulled delay slot ", Mtask.complete.r_pc,Mtask.complete.fold_rir);
if ($disassemble(Mtask.complete.fold_rir,32'b0))
$fdisplay(Mccdisp.allvec_tto_mcd, "disassemble error");
end
else
begin
$fwrite(Mccdisp.allvec_tto_mcd, "%h %h ", comp_pc, comp_instr);
if ($disassemble(comp_instr,32'b0))
$fdisplay(Mccdisp.allvec_tto_mcd, "disassemble error");
end
$fdisplay(Mccdisp.allvec_mcd) ;
end
endtask
task sas_compare_state;
begin
s_cmp = s_cmp + 1;
if ($sas_data_compare(Mclocks.cycle_count))
begin
if ( mismatch_count < 0 )
mismatch_count = 0;
mismatch_count = mismatch_count + 1;
if ( (mismatch_count > 0 ) &&
( mismatch_count >= max_mismatch))
Mclocks.print_error("IU mismatch against SAS") ;
end
end
endtask
task sas_compare_fold_state;
begin
s_cmp = s_cmp + 1;
if ($sas_compare_inst_pc(Mclocks.cycle_count))
begin
if ( mismatch_count < 0 )
mismatch_count = 0;
mismatch_count = mismatch_count + 1;
if ( (mismatch_count > 0 ) &&
( mismatch_count >= max_mismatch))
Mclocks.print_error("IU mismatch against SAS") ;
end
end
endtask
task sas_dump_state;
reg [31:0] value;
integer i;
integer window;
integer bank;
begin
s_dmp = s_dmp + 1;
// g0
value = 0;
if ($sas_data_append(value)) begin
$display("%d *** Error : in $sas_data_append 0",Mclocks.cycle_count);
disable sas_dump_state ;
end
// g1 - g7
for (i=1;i<8;i=i+1)
begin
value = `Mregfile.rf_ram.memory_array[phys_adr(3'h0,i)] ;
if ($sas_data_append(value))
begin
$display("%d *** Error : in $sas_data_append GLOBALS",Mclocks.cycle_count);
disable sas_dump_state ;
end
end
//
//(outs followed by locals, 8 windows: 8x16=128+8=136)
//
for(window = 0; window < 8; window = window + 1)
begin
for(i=8; i < 16; i = i + 1) // OUTS
begin
// $display("OUTS window = %x , phys_adr(window) %x : %x",
// window, phys_adr(window,i),i);
value = `Mregfile.rf_ram.memory_array[phys_adr(window,i)] ;
if ($sas_data_append(value))
begin
$display("%d *** Error : in $sas_data_append OUTS",Mclocks.cycle_count);
disable sas_dump_state ;
end
end
for(i=16; i < 24; i = i + 1) // LOCALS
begin
// $display("LOCALS window = %x , phys_adr(window) %x : %x",
// window, phys_adr(window,i),i);
value = `Mregfile.rf_ram.memory_array[phys_adr(window,i)] ;
if ($sas_data_append(value))
begin
$display("%d *** Error : in $sas_data_append LOCALS",Mclocks.cycle_count);
disable sas_dump_state ;
end
end
end
// psr
// small hack here to avoid mpsas miscompares at startup
if ( ^Mtask.complete.r_psr === 1'bx )
begin
if ( psr_initialized === 1'b0 )
value = 32'h040000c0 ;
else
value = Mtask.complete.r_psr ;
end
else
begin
psr_initialized = 1'b1 ;
value = Mtask.complete.r_psr ;
end
if ($sas_data_append(value)) begin
$display("%d *** Error : in $sas_data_append psr",Mclocks.cycle_count);
disable sas_dump_state ;
end
// tbr
value = Mtask.complete.trap_base_reg;
//if (!tbr_written) value[11:4] = 8'hfb ;
if ($sas_data_append(value)) begin
$display("%d *** Error : in $sas_data_append tbr",Mclocks.cycle_count);
disable sas_dump_state ;
end
// wim
value = Mtask.complete.w_invalid_mask ;
if ($sas_data_append(value)) begin
$display("%d *** Error : in $sas_data_append wim",Mclocks.cycle_count);
disable sas_dump_state ;
end
// y
value = Mtask.complete.y_reg ;
if ($sas_data_append(value)) begin
$display("%d *** Error : in $sas_data_append y",Mclocks.cycle_count);
disable sas_dump_state ;
end
// inst
value = comp_instr;
if ($sas_data_append(value)) begin
$display("%d *** Error : in $sas_data_append instruction",Mclocks.cycle_count);
disable sas_dump_state ;
end
// pc
value = comp_pc;
if ($sas_data_append(value)) begin
$display("%d *** Error : in $sas_data_append pc",Mclocks.cycle_count);
disable sas_dump_state ;
end
end
endtask
task sas_set_irl;
integer sas_cmd_stat;
begin
tbr_value = Mtask.complete.trap_base_reg;
if ( (tbr_value > 16) && (tbr_value < 32) )
begin
sas_cmd_stat = 0;
case (tbr_value)
32'd17: sas_cmd_stat = $sas_command("set irl 1");
32'd18: sas_cmd_stat = $sas_command("set irl 2");
32'd19: sas_cmd_stat = $sas_command("set irl 3");
32'd20: sas_cmd_stat = $sas_command("set irl 4");
32'd21: sas_cmd_stat = $sas_command("set irl 5");
32'd22: sas_cmd_stat = $sas_command("set irl 6");
32'd23: sas_cmd_stat = $sas_command("set irl 7");
32'd24: sas_cmd_stat = $sas_command("set irl 8");
32'd25: sas_cmd_stat = $sas_command("set irl 9");
32'd26: sas_cmd_stat = $sas_command("set irl 10");
32'd27: sas_cmd_stat = $sas_command("set irl 11");
32'd28: sas_cmd_stat = $sas_command("set irl 12");
32'd29: sas_cmd_stat = $sas_command("set irl 13");
32'd30: sas_cmd_stat = $sas_command("set irl 14");
32'd31: sas_cmd_stat = $sas_command("set irl 15");
default: begin
$display("*** Error : in sastasks: task sas_set_irl\n");
$display("switch didn't evalute properly %0d",tbr_value);
$stop;
end
endcase
if ( sas_cmd_stat )
begin
$display("%d *** Error : in $sas_command",
Mclocks.cycle_count);
$stop;
end
end
end
endtask
task sas_unset_irl;
begin
if ($sas_command("set irl 0"))
begin
$display("%d *** Error : in $sas_command", Mclocks.cycle_count);
$stop;
end
end
endtask
always @Mclocks.new_working_dir sas_init ;
task sas_init;
begin
// Initialize state variables
annul_flag = 0;
count_3_cycles = 0;
fpopdone = 0;
trap_event_case = 0;
head = 0;
tail = 0;
num_fpdone = 0;
starting_fpop = 0;
trap_happen = 0;
mismatch_count = -1;
instr_count = 0;
if (sas_cmp_flag == 1) begin
// Disable a verilog block that may be waiting for an
// event in a previous simulation.
disable main_loop ;
// Kill the old sas if we've started one
if (SAS) begin
$display("Quitting sas process") ;
if ($sas_command("quit"))
$display("%d *** Error : in $sas_command", Mclocks.cycle_count);
end
// Start a new one
$display("Starting sas process") ;
$sas_verbose(sas_verbose);
if ($sas_init({Mclocks.working_dir}))
begin
$display("%d *** Error : error in $sas_init",Mclocks.cycle_count);
// disable sas_init;
$finish;
end
SAS = 1;
end else
SAS = 0;
end
endtask
initial
begin
psr_initialized = 1'b0 ;
s_sim = 0;
s_dmp = 0;
s_cmp = 0;
$GetEnv("sas_cmp",sas_cmp_flag);
Im_here = 1;
if (sas_cmp_flag == 1)
max_mismatch = 1;
else
max_mismatch = 0;
SAS = 0;
sas_verbose = 0;
end
endmodule
| This page: |
Created: | Thu Aug 19 12:03:36 1999 |
| From: |
../../../sparc_v8/env/rtl/sastasks.vpp
|