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.
'X' propagations have these root causes in GLS:
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.
The purpose of this script is to generate two files.
## 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;
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.
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
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.