ecp5: Add simulation equivalence check for Diamond FF implementations
authorDavid Shah <dave@ds0.me>
Fri, 30 Aug 2019 12:25:55 +0000 (13:25 +0100)
committerDavid Shah <dave@ds0.me>
Fri, 30 Aug 2019 12:27:36 +0000 (13:27 +0100)
Signed-off-by: David Shah <dave@ds0.me>
techlibs/ecp5/cells_sim.v
techlibs/ecp5/tests/.gitignore [new file with mode: 0644]
techlibs/ecp5/tests/test_diamond_ffs.py [new file with mode: 0644]

index ba5b9c715616efa1fca3c680fc583a074f79c0e5..75a1aad1f48b884192fce737a3f9c47d525d8598 100644 (file)
@@ -693,5 +693,9 @@ module DP16KD(
        parameter INITVAL_3F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
 endmodule
 
+`ifndef NO_INCLUDES
+
 `include "cells_ff.vh"
 `include "cells_io.vh"
+
+`endif
diff --git a/techlibs/ecp5/tests/.gitignore b/techlibs/ecp5/tests/.gitignore
new file mode 100644 (file)
index 0000000..0e18132
--- /dev/null
@@ -0,0 +1 @@
+work_*
diff --git a/techlibs/ecp5/tests/test_diamond_ffs.py b/techlibs/ecp5/tests/test_diamond_ffs.py
new file mode 100644 (file)
index 0000000..1ed85ce
--- /dev/null
@@ -0,0 +1,82 @@
+import os
+import subprocess
+
+if not os.path.exists("work_ff"):
+       os.mkdir("work_ff")
+
+modules = []
+
+with open("../cells_ff.vh", "r") as f:
+       with open("work_ff/cells_ff_gate.v", "w") as g:
+               for line in f:
+                       if not line.startswith("module"):
+                               g.write(line)
+                               continue
+                       else:
+                               spidx = line.find(" ")
+                               bridx = line.find("(")
+                               modname = line[spidx+1 : bridx]
+                               g.write("module %s_gate" % modname)
+                               g.write(line[bridx:])
+                               inpidx = line.find("input ")
+                               outpidx = line.find(", output")
+                               modules.append((modname, [x.strip() for x in line[inpidx+6:outpidx].split(",")]))
+
+with open("work_ff/testbench.v", "w") as f:
+       print("""
+`timescale 1ns/ 1ps
+
+module testbench;
+reg pur = 0, clk, rst, cen, d;
+
+// Needed for Diamond sim models
+GSR GSR_INST (.GSR(1'b1));
+PUR PUR_INST (.PUR(pur));
+
+
+initial begin
+       $dumpfile("work_ff/ffs.vcd");
+       $dumpvars(0, testbench);
+       #5;
+       pur = 1;
+       #95;
+       repeat (2500) begin
+               {clk, rst, cen, d} = $random;
+               #10;
+               check_outputs;
+               #1;
+       end
+       $finish;
+end
+       """, file=f)
+
+       for modname, inputs in modules:
+               print("    wire %s_gold_q, %s_gate_q;"  % (modname, modname), file=f)
+               portconns = []
+               for inp in inputs:
+                       if inp in ("SCLK", "CK"):
+                               portconns.append(".%s(clk)" % inp)
+                       elif inp in ("CD", "PD"):
+                               portconns.append(".%s(rst)" % inp)
+                       elif inp == "SP":
+                               portconns.append(".%s(cen)" % inp)
+                       elif inp == "D":
+                               portconns.append(".%s(d)" % inp)
+                       else:
+                               assert False
+               portconns.append(".Q(%s_gold_q)" % modname)
+               print("    %s %s_gold_i (%s);" % (modname, modname, ", ".join(portconns)), file=f)
+               portconns[-1] = (".Q(%s_gate_q)" % modname)
+               print("    %s_gate %s_gate_i (%s);" % (modname, modname, ", ".join(portconns)), file=f)
+               print("", file=f)
+       print("    task check_outputs;", file=f)
+       print("        begin", file=f)
+       print("             if (%s_gold_q != %s_gate_q) $display(\"MISMATCH at %%1t:  %s_gold_q=%%b, %s_gate_q=%%b\", $time, %s_gold_q, %s_gate_q);" %
+                       (modname, modname, modname, modname, modname, modname), file=f)
+       print("        end", file=f)
+       print("    endtask", file=f)
+       print("endmodule", file=f)
+
+diamond_models = "/usr/local/diamond/3.10_x64/cae_library/simulation/verilog/ecp5u"
+subprocess.call(["iverilog", "-s", "testbench", "-o", "work_ff/testbench", "-Dmixed_hdl", "-DNO_INCLUDES", "-y", diamond_models, "work_ff/cells_ff_gate.v", "../cells_sim.v", "work_ff/testbench.v"])
+subprocess.call(["vvp", "work_ff/testbench"])