Reset behavior with miter equivalence checking - yosys

I'm trying to prove equivalence using miter and sat for a sequential circuit. Essentially, the behavior of the two circuits should be identical as soon as they are reset. I cannot figure out how to tell yosys this though. I have tried reseting the designs with -set in_reset 0 -set-at 0 in_reset 1. Here is an example circuit (a shift register) and yosys script that illustrate what I'm trying to do:
module shift_reg(
input clock,
input reset,
input in,
output out
);
reg [7:0] r;
assign out = r[7];
always #(posedge clock) begin
if (reset)
r <= 0;
else
r <= {r[6:0], in};
end
endmodule
My Yosys commands:
read_verilog shift_reg.v
rename shift_reg shift_reg_2
read_verilog shift_reg.v
prep; proc; opt; memory
miter -equiv -flatten shift_reg shift_reg_2 miter
hierarchy -top miter
sat -verify -tempinduct -prove trigger 0 -set in_reset 0 -set-at 0 in_reset 1 -seq 0 miter
If I add -set-init-zero it works, but that defeats the purpose because I'm trying to test reset behavior. I can also change -seq 0 to -seq 8 but that also defeats the purpose because I'm trying to check that the circuits are equivalent as soon as they are reset.
How do I tell equivalence checking to reset the circuits before checking?

Simply use the following SAT command:
sat -verify -tempinduct -prove trigger 0 \
-set in_reset 0 -set-at 1 in_reset 1 -seq 1 miter
Changes compared to your script:
The "sat" command numbers steps starting with 1. So the -set-at option needs 1 as first argument for resetting in the first cycle.
The "-seq 1" will disable checking of properties in the first cycle. This make sense because the reset will only have taken effect in the 2nd cycle, so the two modules might indeed produce different outputs in cycle 1.

Related

Is there any alternative to (* keep *) in Verilog using ABC implementation?

I am using yosys to synthesize using the synth_ice40 command which calls ABC as well. In my Verilog code, I have used (* keep *) wire wire_1; Yosys does not optimize this but when it comes to ABC, it removes these unused wires. Is there anything equivalent to (* keep *) which could be used in Verilog which ABC does not optimize and remove the certain wires?
Any help would be appreciated.
Thanks,
Log:
`.44.2. Continuing TECHMAP pass.
No more expansions possible.
Removed 0 unused cells and 3 unused wires.
2.45. Executing OPT_LUT pass (optimize LUTs).
Discovering LUTs.
Number of LUTs: 1
2-LUT 1
Eliminating LUTs.
Number of LUTs: 1
2-LUT 1
Combining LUTs.
Number of LUTs: 1
2-LUT 1
Eliminated 0 LUTs.
Combined 0 LUTs.
<suppressed ~2 debug messages>
2.46. Executing TECHMAP pass (map to technology primitives).
2.46.1. Executing Verilog-2005 frontend: /usr/local/bin/../share/yosys/ice40/cells_map.v
Parsing Verilog input from /usr/local/bin/../share/yosys/ice40/cells_map.v' to AST representation. Generating RTLIL representation for module $lut'.
Successfully finished Verilog frontend.
2.46.2. Continuing TECHMAP pass.
Using template $paramod$lut\WIDTH=2\LUT=4'1000 for cells of type $lut.
No more expansions possible.
<suppressed ~14 debug messages>
Removed 0 unused cells and 2 unused wires.`

Can I avoid opt_merge from removing a BUF? (Yosys tri-state workaround)

I know yosys has limited tri-state support, but I'm looking for a possible workaround.
The following circuit:
module TBUF2
(
inout SALIDA1,
inout SALIDA2,
input OE,
output C);
assign SALIDA1=OE ? 1'b0 : 1'bZ;
assign SALIDA2=OE ? 1'b0 : 1'bZ;
wire e;
assign e=SALIDA1 & SALIDA2;
assign C=e;
endmodule
Is interpreted as:
TBUF2 parsed tree
Note that when OE is 0 C=SALIDA1 and SALIDA2.
During the opt pass, the opt_merge pass removes $2 mux and generates:
TBUF2 optimized
This breaks the circuit (when OE is 0 then C=SALIDA1). I realize this is because yosys/ABC doesn't really understand the consequences of the "1'z" input.
Is it possible to keep muxes that meet the following criteria?:
1) At least one input is 1'Z
2) Its output drives an inout pin
Here is the script to reproduce it:
read_verilog tbuf2.v
proc
show -format dot -prefix tbuf2_01
opt
show -format dot -prefix tbuf2_02
Convert the tristate buffer $mux cells to $tribuf cells by running the tribuf command after proc and before running any opt commands.

Yosys logic loop falsely detected

I've been testing yosys for some use cases.
Version: Yosys 0.7+200 (git sha1 155a80d, gcc-6.3 6.3.0 -fPIC -Os)
I wrote a simple block which converts gray code to binary:
module gray2bin (gray, bin);
parameter WDT = 3;
input [WDT-1:0] gray;
output [WDT-1:0] bin;
assign bin = {gray[WDT-1], bin[WDT-1:1]^gray[WDT-2:0]};
endmodule
This is an acceptable and valid code in verilog, and there is no loop in it.
It passes compilation and synthesis without any warnings in other tools.
But, when I run in yosys the next commands:
read_verilog gray2bin.v
scc
I get that a logic loop was found:
Found an SCC: $xor$gray2bin.v:11$1
Found 1 SCCs in module gray2bin.
Found 1 SCCs.
The next code, which is equivalent, pass the check:
module gray2bin2 (
gray,
bin
);
parameter WDT = 3;
input [WDT-1:0] gray;
output [WDT-1:0] bin;
assign bin[WDT-1] = gray[WDT-1];
genvar i;
generate
for (i = WDT-2; i>=0; i=i-1) begin : gen_serial_xor
assign bin[i] = bin[i+1]^gray[i];
end
endgenerate
endmodule
Am I missing a flag or synthesis option of some kind?
Using word-wide operators this circuit clearly has a loop (generated with yosys -p 'prep; show' gray2bin.v):
You have to synthesize the circuit to a gate-level representation to get a loop-free version (generated with yosys -p 'synth; splitnets -ports; show' gray2bin.v, the call to splitnets is just there for better visualization):
The answer given by CliffordVienna indeed gives a solution, but I also want to clarify that that it's not suitable to all purposes.
My analysis was done for the purpose of formal verification. Since I replaced the prep to synth to solve the falsely identified logic loops, my formal code got optimized. Wires which I've created that were driven only by the assume property pragma, were removed - this made many assertions redundant.
It's not correct to reduce any logic for the purpose of behavioral verification.
Therefore, if the purpose is to prepare a verification database, I suggest not to use the synth command, but to use a subset of commands the synth command executes.
You can find those commands under:
http://www.clifford.at/yosys/cmd_synth.html
In general, I've used all the commands specified in the above link that do not optimize logic:
hierarchy -check
proc
check
wreduce
alumacc
fsm
memory -nomap
memory_map
techmap
abc -fast
hierarchy -check
stat
check
And everything works as expected.

Is it possible to remove clock input variable from the AIGER output?

Consider the example:
read_verilog ./tests/simple/fsm.v
synth -flatten -top fsm_test
abc -g AND
write_aiger -ascii -symbols hoho.aag
The resulting AIGER file contains input variable clk, which is dangling.
Is it possible to avoid introducing such clock input into AIGER?
Thanks.
Not automatically. The following options exist:
Simply use the SystemVerilog $global_clock feature to avoid having a clock input at all. Use always #($global_clock) instead of always #(posedge clk) and then remove the clk input from your design.
Remove the clock input near the end of your synthesis script. I.e. right before calling write_aiger call something like delete -input fsm_test/clk. This will turn the clock signal into a dangling wire internal to the module. You should avoid doing that before running a lot of optimization commands, or you risk Yosys optimizing away all your FFs. But doing that near the end of your script should be fine.
You can combine 2. with mapping your FFs to $ff/$_FF_ cells (the kind of FF cells generated by $global_clock-blocks). The advantage of this approach is that it makes the clk wire truly unused, so there is no risk of optimizations messing with your FFs because they have an undriven clock input. I've now added a dff2ff.v techmap file in commit e7a984a that simplifies this a bit.
Script for option 2:
read_verilog ./tests/simple/fsm.v
synth -flatten -top fsm_test
abc -g AND
delete -input fsm_test/clk
write_aiger -ascii -symbols hoho.aag
Script for option 3 (requires Yosys git commit e7a984a or later):
read_verilog ./tests/simple/fsm.v
hierarchy -top fsm_test
proc
techmap -map +/dff2ff.v
delete fsm_test/clk
synth -flatten
abc -g AND
write_aiger -ascii -symbols hoho.aag

LLVM ScalarEvolution Pass Cannot Compute Exit Count for Loop Vectorizer

I'm trying to figure out how to run LLVM's built-in loop vectorizer. I have a small program containing an extremely simple loop (I had some output at one point which is why stdio.h is still being included despite never being used):
1 #include <stdio.h>
2
3 unsigned NUM_ELS = 10000;
4
5 int main() {
6 int A[NUM_ELS];
7
8 #pragma clang loop vectorize(enable)
9 for (int i = 0; i < NUM_ELS; ++i) {
10 A[i] = i*2;
11 }
12
13 return 0;
14 }
As you can see, it does nothing at all useful; I just need the for loop to be vectorizable. I'm compiling it to LLVM bytecode with
clang -emit-llvm -O0 -c loop1.c -o loop1.bc
llvm-dis -f loop1.bc
Then I'm applying the vectorizer with
opt -loop-vectorize -force-vector-width=4 -S -debug loop1.ll
However, the debug output gives me this:
LV: Checking a loop in "main" from loop1.bc
LV: Loop hints: force=? width=4 unroll=0
LV: Found a loop: for.cond
LV: SCEV could not compute the loop exit count.
LV: Not vectorizing: Cannot prove legality.
I've dug around in the LLVM source a bit, and it looks like SCEV comes from the ScalarEvolution pass, which has the task of (among other things) counting the number of back edges back to the loop condition, which in this case (if I'm not mistaken) should be the trip count minus the first trip (so 9,999 in this case). I've run this pass on a much larger benchmark and it gives me the exact same error at every loop, so I'm guessing it isn't the loop itself, but that I'm not giving it enough information.
I've spent quite a bit of time combing through the documentation and Google results to find an example of a full opt command using this transformation, but have been unsuccessful so far; I'd appreciate any hints as to what I may be missing (I'm new to vectorizing code so it could be something very obvious).
Thank you,
Stephen
vectorization depends on number of other optimization which needs to be run before. They are not run at all at -O0, therefore you cannot expect that your code would be 'just' vectorized there.
Adding -O2 before -loop-vectorize in opt cmdline would help here (make sure your 'A' array is external / used somehow, otherwise everything will be optimized away).