Contents

  1. Remove 'X' propagation in gate level simulation
    1. Abstract
    2. Detail 'X' causes
    3. GofCall script
    4. Run the script
    5. Use the files in simulation
    6. Note

Remove 'X' propagation in gate level simulation

Abstract

The most difficult part in gate level simulation (GLS) is 'X' propagation debug. 'X' propagation in GLS is mostly caused by 'X' pessimism, so it is practical to suppress them and focus on the main purpose of GLS.

This use case shows how to suppress 'X' propagations in GLS while retain the capability to catch 'X' optimism issue.

Detail 'X' causes

'X' propagations have these root causes in GLS:

  1. Non-resettable flops and latches
  2. RAMs
  3. First stage flops in synchronizers
  4. Setup/hold timing violations
  5. Library modeling
  6. Uninitialized input ports
  7. Other special cases

Suppressing 'X' in item 1,2,3 is covered in this topic, and item 4 is the real problem to catch in GLS, while users need to do 'X' tracing and debug for item 5,6,7.

The method to handle item 1,2 is different from the way to handle item 3. For item 1 and 2, the flops/latches/RAMs should be forced to known value, either 0 or 1, before reset is done. In GLS, these force statements can be put into a file, and included in simulation. For item 3, a complete synchronizer list should be created, and the first stage flop instances have timing check disabled.

The script below shows how to collect all uninitialized flops/latches/RAMs and put them into a verilog initialization file, "force_memory_elements.v".

And the script collects full list of synchronizer and put the first stage flops timing check disable statements into a TCL do file, "disable_sync_timing.do", which can be included in run command during simulation.

GofCall script

The purpose of this script is to generate two files.

  1. Verilog file, "force_memory_elements.v", has collection of all uninitialized flops/latches/RAMs which are forced to known value. The value can be random 0 or 1 to mimic real silicon, so that they will have different values in every run, and 'X' optimistic RTL bugs may be caught during simulations. The delay time, currently it's 150ns, can be adjusted to start the force during reset period
  2. TCL do file, "disable_sync_timing.do", has collection of all first stage of synchronizer flops which should have specific naming convention, like 'DONTTOUCH_sync_u0'. The do file is for QuestaSim in this example.
## Script name: initialize_registers_disable_sync_timing.pl
## Click on get_cells/get_pins/get_ref for detail API usage
open(FOUT, ">force_memory_elements.v");
my $path = "tb.udut.myinstance";

##
## Initialize memories, the following example is for Virage Memories
##
my @rams = get_cells("-hier", "-dotpath", "-type", "ram");
foreach my $ram (@rams){
  my $ref = get_ref($ram);
  my ($depth, $size) = ($ref =~ m/(\d+)[x_](\d+)/);
  print FOUT "defparam $path.$ram.uut.DataX = 0;\n";
  print FOUT "defparam $path.$ram.uut.DataZ = 0;\n";
}

print FOUT "initial begin\n  \$display(\"Force memory elements to known states\");\n";
print FOUT "  #150ns;\n"; # Adjust the delay to start the force during reset period
foreach my $ram (@rams){
  my $ref = get_ref($ram);
  my ($depth, $size) = ($ref =~ m/(\d+)[x_](\d+)/);
  print FOUT "  for(int i=0;i<$depth;i=i+1) begin\n";
  print FOUT "     $path.$ram.uut.mem_core_array[i] = 0;\n";
  print FOUT "  end\n";
}

##
## Find all flops and force all non-resettable flops to 0 or 1
##
my @cells = get_cells("-hier", "-dotpath", "-type", "ff");
my @release = ();
my @clocks;
foreach my $cell (@cells){
  my $ref = get_ref($cell);
  my @reset = get_pins($ref, "-reset");
  # Only work on non-resettable flops
  if(scalar(@reset)==0){
    my @clks = get_pins($ref, "-clock");
    my @datas = get_pins($ref, "-data");
    
    if(@datas){
      foreach my $data (@datas){
	# \$random can be replaced by 1'b0 for simple handling
        print FOUT "  force $path.$cell.$data = \$random;\n"; 
        push @release, "$cell.$data";
      }
    }
    push @clocks, "$cell.$clks[0]";
    push @release, "$cell.$clks[0]";
  }
}

##
## Find all latches and force them to 0 or 1
##
my @latches = get_cells("-hier", "-dotpath", "-type", "latch");
foreach my $latch (@latches){
  my $ref = get_ref($latch);
  my @clks = get_pins($ref, "-clock");
  my @datas = get_pins($ref, "-data");
  foreach my $data (@datas){
    print FOUT "  force $path.$latch.$data = \$random;\n";
    push @release, "$latch.$data";
  }
  push @release, "$latch.$clks[0]";
  push @clocks, "$latch.$clks[0]";
}

print FOUT "  force $path.$_ = 0;\n" foreach @clocks;
print FOUT "  #1ps;\n";
print FOUT "  force $path.$_ = 1;\n" foreach @clocks;
print FOUT "  #1ps;\n";
print FOUT "  force $path.$_ = 0;\n" foreach @clocks;

##
## Release all force signals
## 
print FOUT "  #1ps;\n";
foreach my $rel (@release){
  print FOUT "  release $path.$rel;\n";
}

print FOUT "  \$display(\"Done forcing memory elements\");\n";
print FOUT "end\n";
close(FOUT);

##
## The second part is to find the first stage flop of synchronizer
##
my @sync0 = get_cells("-hier", "DONTTOUCH_sync_u0");
open(FOUT, ">disable_sync_timing.do");
foreach my $flop (@sync0){
  print FOUT "  tcheck_set $path/$flop off\n";
}
print FOUT "run -all\n";
close(FOUT);
print "The end of the script, please check the two created files\n";
exit;

Run the script

The script can be run by the command line:

gof -lib tsmc.lib design.v -run initialize_registers_disable_sync_timing.pl

Two files mentioned above will be created at the end.

Use the files in simulation

Include the force file, 'force_memory_elements.v' in simulation

module tb;
...
`include 'force_memory_elements.v'

... endmodule

Add TCL do file in simulation command line.

vsim -do disable_sync_timing.do ...

Simulation flow diagram

Note

This script flow has been used in tens IC projects. However it may need tune-up in new project, please contact us if you need support.


Follow us:
© 2024 NanDigits Design Automation. All rights reserved.