/******************************************************************************/
/* */
/* Copyright (c) 1999 Sun Microsystems, Inc. All rights reserved. */
/* */
/* The contents of this file are subject to the current version of the Sun */
/* Community Source License, microSPARCII ("the License"). You may not use */
/* this file except in compliance with the License. You may obtain a copy */
/* of the License by searching for "Sun Community Source License" on the */
/* World Wide Web at http://www.sun.com. See the License for the rights, */
/* obligations, and limitations governing use of the contents of this file. */
/* */
/* Sun Microsystems, Inc. has intellectual property rights relating to the */
/* technology embodied in these files. In particular, and without limitation, */
/* these intellectual property rights may include one or more U.S. patents, */
/* foreign patents, or pending applications. */
/* */
/* Sun, Sun Microsystems, the Sun logo, all Sun-based trademarks and logos, */
/* Solaris, Java and all Java-based trademarks and logos are trademarks or */
/* registered trademarks of Sun Microsystems, Inc. in the United States and */
/* other countries. microSPARC is a trademark or registered trademark of */
/* SPARC International, Inc. All SPARC trademarks are used under license and */
/* are trademarks or registered trademarks of SPARC International, Inc. in */
/* the United States and other countries. Products bearing SPARC trademarks */
/* are based upon an architecture developed by Sun Microsystems, Inc. */
/* */
/******************************************************************************/
`define C `CYCLETIME
`define hC (`C/2)
`define Cstop (`C-3)
module Mclocks
(
clock
) ;
output clock
;
reg clock ;
integer phase
; // Current phase of clock (between 0 and `C-1)
reg STOP
; // flag used to indicate the end of an
// interactive task
reg RST_TMO
; // flag used to reset the timeout checkers
/*wire*/ reg RESET_IN
; // This is forced during simulation to initiate reset
// Changed wire to reg for Chronologic
reg [31:0] cycle_count
; // cycle counter
// 'Slave' copy of cycle_count, delayed by #1 so it can be sampled at
// the rising edge of clock.
reg [31:0] cycle_count_s
;
initial cycle_count_s = 0 ;
always @cycle_count #1 cycle_count_s = cycle_count ;
// value of cycle_count at which mux select compares will begin
reg [31:0] compare_threshold
;
initial compare_threshold = 9999999 ;
// trigger used by mux select compare code
event compare_trigger ;
// trigger the mux select compare logic for every cycle after
// cycle_count has exceeded compare_threshold
always @(posedge clock) begin
if (cycle_count > compare_threshold) begin
#(`CYCLETIME - 3) -> compare_trigger ;
end
end
reg reset_clears_count
; // When set, RESET will clear cycle_count
reg [31:0] sample_count
; // Counter for dcc samples
reg end_run
; // Flag set when diagnostic finishes
reg end_run_error
; // Flag set when diag signals failure
reg ignore_end_run
; // When set, ignore end_run
initial ignore_end_run = 0 ;
reg scan_operation
; // Flag set when doing a scan/debug operation
initial scan_operation = 0 ;
reg [31:0] trace_mcd
; // File descriptor used for trace file
reg [31:0] breakpoint
; // 32 independent breakpoint flags
// Mask of breakpoints for which clocking should continue after the
// breakpoint hits - used by vsh @bp.
reg [31:0] bp_continue
;
// Breakpoint test values from previous cycle
reg [63:0] lastbreak
[0:31] ; // Can compare up to 64 bits
reg dsbl_breakpoints
; // Useful during reset sequences
event breaktest ; // Breakpoints are evaluated @breaktest
event samplesig ; // dcc samples are taken @samplesig
event vecsig ; // vector samples are taken @vecsig
event piggy_isig ; // Apply piggyback inputs
event piggy_osig ; // Test piggyback outputs
event piggy_mcsig ; // Test piggyback clock outputs at midcycle
// This register is a counter for error messages. It should be incremented
// by any code which prints a '***' message. It is useful as an object
// to be tested by a vfront breakpoint.
reg [31:0] error_count
; initial error_count
= 0 ;
// Another one for warning messages.
reg [31:0] warning_count
; initial warning_count
= 0 ;
event bpdisp ; // Display a breakpoint
reg [31:0] bpdispnum
; // Which loop to trigger for display
event killtest ; // Kills a loop
reg [31:0] killnum
; // Which one to kill
reg enbl_icon
; initial enbl_icon
=0 ;
reg [2047:0] icon_dir
;
// In vsh mode, append <del><nl> to end of $write strings.
reg [15:0] vsh_nl
; initial vsh_nl
= 0 ;
// String which holds the name of the working directory for the
// current simulation run. Use when opening files.
reg [2047:0] working_dir
; // Big enough for 256 chars.
// Activate this event whenever we change working_dir;
// code may use this as a signal to close old files and
// open new ones.
event new_working_dir ;
initial begin
clock = 0;
phase = `Cstop ;
STOP = 0;
RST_TMO = 0;
cycle_count = 0;
sample_count = 0;
reset_clears_count = 0 ;
breakpoint = 0;
bp_continue = 0;
dsbl_breakpoints = 0;
working_dir = "." ;
stop; // enable the stop task
end
// task to stop simulation whenever STOP is wiggled
task stop;
forever @STOP begin
$stop(0);
// Flush the VCD buffer
$dumpflush ;
end
endtask
// Task to execute, with no clocks
task sim;
input [31:0] n;
begin
RST_TMO = ~RST_TMO ;
#n STOP = ~STOP;
end
endtask
// This prevents simulation from 'running off the end'
// and terminating verilog
// If RST_TMO is not toggled within 1000 time units,
// this code triggers a $stop.
always @(posedge RST_TMO) begin :timeout1
disable timeout0 ;
#(2*`C)
$display("Timeout");
STOP = ~STOP ;
#0 RST_TMO = ~RST_TMO ;
end
always @(negedge RST_TMO) begin :timeout0
disable timeout1 ;
#(2*`C)
$display("Timeout");
STOP = ~STOP ;
#0 RST_TMO = ~RST_TMO ;
end
task toggle_clock ;
begin
clock = ~clock ;
// Zero the cycle count on startup reset, but not
// error reset
if (clock) begin
phase = 0 ;
if (reset_clears_count && RESET_IN) begin
cycle_count = 0 ;
sample_count = 0 ;
end
else cycle_count = cycle_count + 1;
end
else phase = `hC ;
end
endtask
// Piggyback inputs are applied at #2 into the cycle (since all
// FFs have #1 Clk->Q and all gates have #0 delay).
// Piggyback clock outputs are tested at #1 before the next negedge
// clock.
// Piggyback outputs are tested at #1 before the next posedge clock;
// vector capture happens at the same time.
always @(posedge clock) fork
#2 -> piggy_isig ;
#((`C>>1)-1) -> piggy_mcsig ;
#(`C-1) begin
-> piggy_osig ;
-> vecsig ;
end
join
// The above code doesn't get kicked for the very first cycle -
// apply the inputs at #1 after initial, and test the outputs at
// #1 before the first posedge clock.
initial fork
#1 -> piggy_isig ;
#(`C-`Cstop-1) begin
-> piggy_osig ;
-> vecsig ;
end
join
// Note: piggy_isig is also activated at the start of the 'cycles'
// task.
task change_icon ;
input [1023:0] icon ;
$write("]I%0s/%0s\\%0s", icon_dir, icon, vsh_nl) ;
endtask
// Task to issue clocks, stopping at a breakpoint
// or end of diagnostic.
task cycles ;
input [31:0] n; // Iteration count
input [31:0] nticks; // Time units per iteration
input [31:0] nzeros; // Number of zero-delay samples per iteration
input [31:0] disp_each_iter;
input fastmode ; // dummy for scan debugger - see clocks_scan.v
integer nextedge ;
reg [7:0] ch ;
begin
// Disable stop task so that displays won't stop simulation
if(disp_each_iter==1) disable stop;
end_run = 0; // clear flags which stops simulation
end_run_error = 0 ;
breakpoint = 0 ;
// Update the dcc samples and piggyback inputs to reflect any
// changes that were made interactively.
#0 ->samplesig ; ->piggy_isig ;
// Change icon for this window
if (enbl_icon) change_icon("vfront.icon") ;
while (
(n>0) && (((end_run & ~ignore_end_run) | breakpoint)==0)
) begin
n=n-1;
RST_TMO = ~RST_TMO ;
// Compute time to next clock edge
// This expression always gives a number between 1 and `hC.
nextedge = `hC-(phase%`hC) ;
// Simulate for the required amount of time
// Two clock transitions:
if (nticks>=(nextedge+`hC)) begin
#nextedge toggle_clock ;
#`hC toggle_clock ;
#(nticks-nextedge-`hC) ;
phase = phase + (nticks-nextedge-`hC) ;
end
// One clock transition:
else if (nticks>=nextedge) begin
#nextedge toggle_clock ;
#(nticks-nextedge) ;
phase = phase + (nticks-nextedge) ;
end
// No clock transitions:
// Don't do a #0 if nticks==0 - we do one below.
else if (nticks > 0) begin
#nticks ;
phase = phase + nticks ;
end
repeat (nzeros) begin
// Now display something, if specified
case (disp_each_iter)
// The 2 is vestigial from Sunup
2: begin
ch =
((cycle_count%10)==0)
? ("0"+((cycle_count/10)%10)) : (
(phase==`Cstop) ? "." : (
",") ) ;
// If a multiple of 100, print the whole
// cycle count at beginning of line.
if (ch=="0")
$write("\n%0d%0s", cycle_count, vsh_nl) ;
else
$write("%c%0s", ch, vsh_nl) ;
end
endcase
// Do a dcc sample
sample_count = sample_count + 1 ;
#0 // Wait for Mccdisp.cidx to be updated
->samplesig ;
#0 ;
end
// Trigger breakpoint test event
if (!dsbl_breakpoints) ->breaktest ;
#0 ; // Wait for breakpoints to be set before loop test
end
// Trigger piggyback output test, so we'll see this cycle's
// mismatches before the prompt (we'll see them again
// if we resume simulation).
-> piggy_osig ;
// Done with loop - print messages.
if (disp_each_iter==2) $display("");
// Print explanatory messages
// If we hit only @bp breakpoints in vsh, print a line
// which will cause vsh to do the remaining clocks.
if ((breakpoint&bp_continue) && !(breakpoint&~bp_continue))
$display("\033@@Mclocks.cycles(%0d,%0d,%0d,%0d,%0d);.",
n,nticks,nzeros,disp_each_iter,fastmode) ;
else begin
if (breakpoint!=0) $write("Breakpoint: ") ;
if (end_run & ~ignore_end_run) begin
if (end_run_error)
$write("******Diagnostic failed: ") ;
else
$write("Diagnostic completed: ") ;
// $sas_verbose(1);
if (sastasks.SAS == 1)
if ($sas_command("quit"))
$display("Could not quit mpsas on stop.");
end
end
$write("Clocks stopped at cycle %0d",cycle_count) ;
if ((nticks!=`C) || (phase!=`Cstop) )
$write(" (phase=%0d/%0d)", phase, `C) ;
if (cycle_count != sample_count)
$write(", sample %0d", sample_count) ;
$display("") ;
if (enbl_icon)
change_icon(
(end_run & ~ignore_end_run)
? "vfront_done.icon"
: (breakpoint ? "vfront_break.icon"
: "vfront_stop.icon")
) ;
#0 ;
if(disp_each_iter==1) // re-enable stop task
// and trigger it in parallel
fork
stop;
STOP = ~STOP;
join
else STOP = ~STOP; // trigger stop
end
endtask
// Task to display a breakpoint
task dispbp ;
input [31:0] n ;
begin
// Trigger display loop (n+100)
bpdispnum = n+100 ;
->bpdisp;
// Wait for it to finish
#0 ;
end
endtask
// Convert number to 10-digit verilog string (decimal representation).
// Suppress leading zeros.
function [79:0] dec_str ;
input [31:0] n ;
if (^n===1'bx) dec_str = "xxxxxxxxxx" ;
else if (n==0) dec_str = "0" << 72 ;
else begin
dec_str = 0 ; // Initialize to all nulls
while (n != 0) begin
dec_str = (dec_str >> 8) | (("0"+(n%10)) << 72) ;
n = n/10 ;
end
end
endfunction
reg saved
; initial saved
= 0 ;
task save ;
begin
$display("Saving simulation state at cycle %0d in file save_%0d . . .", cycle_count, sample_count) ;
// Copy the trace.v file
if (trace_mcd==0) begin
$system({"echo 'no trace file' > ",
Mclocks.working_dir,
"/save_", dec_str(sample_count), ".trace"}) ;
end
else begin
$system({"cp ", Mclocks.working_dir, "/trace.v ",
Mclocks.working_dir,
"/save_", dec_str(sample_count), ".trace"}) ;
end
// Copy the dcc.log file
// Make one if it doesn't exist
$system({"cat /dev/null>>", Mclocks.working_dir,"/dcc.log"});
$system({"cp ",Mclocks.working_dir,"/dcc.log ",
Mclocks.working_dir,
"/save_", dec_str(sample_count), ".dcc"}) ;
// Now do the $save
if (saved)
$incsave({Mclocks.working_dir,"/save_", dec_str(sample_count)}) ;
else $save({Mclocks.working_dir,"/save_", dec_str(sample_count)}) ;
/*----- Simulation will resume here after a $restart ------*/
saved = 1 ;
$display("Continuing simulation at cycle %0d", cycle_count) ;
end
endtask
// Task to change working_dir and signal the change.
// If new_log is true, close the verilog.log file and open a new one
// in the new directory.
task chdir ;
input [2047:0] new_dir ;
input [2047:0] new_log ;
begin
if (new_log) begin
$display("Opening new log file %0s/%0s", new_dir, new_log) ;
$log({new_dir, "/", new_log}) ;
end
$display("Previous working_dir was %0s", working_dir) ;
working_dir = new_dir ;
// Set up a symbolic link within the directory we were
// started up in (the link is used by I-I sas).
$system({"rm -f working_dir; ln -s ",
working_dir, " working_dir"}) ;
$display("New working_dir is %0s", working_dir) ;
-> new_working_dir ;
end
endtask
// Print a value as exactly n binary digits
task print_bits ;
input [31:0] n ;
input [63:0] x ;
integer i ;
for (i=n-1 ; i>=0 ; i=i-1) $write("%b", x[i]) ;
endtask
task print_error ;
input [2047:0] string ;
begin
$display("\n*** %0d: %0s", cycle_count_s, string) ;
error_count = error_count + 1 ;
end
endtask
endmodule
This page: |
Created: | Thu Aug 19 11:57:52 1999 |
| From: |
../../../sparc_v8/system/rtl/clocks.v
|