1#!/usr/bin/env python3
2
3import sys, os, re, shutil
4import numpy as np
5
6max_span_hack = True
7
8pins = np.random.permutation("""
9    1 2 3 4 7 8 9 10 11 12 19 22 23 24 25 26 28 29 31 32 33 34
10    37 38 41 42 43 44 45 47 48 52 56 58 60 61 62 63 64
11    73 74 75 76 78 79 80 81 87 88 90 91 95 96 97 98 101 102 104 105 106 107
12    112 113 114 115 116 117 118 119 120 121 122 134 135 136 137 138 139 141 142 143 144
13""".split())
14
15io_names = None
16mode = sys.argv[1]
17
18with open("%s.v" % sys.argv[1], "w") as f:
19    if mode == "test0":
20        io_names = [ "clk", "i0", "o0", "o1", "o2" ]
21        print("module top(input clk, i0, output o0, o1, o2);", file=f)
22        print("  reg [31:0] state;", file=f)
23        print("  always @(posedge clk) state <= ((state << 5) + state) ^ i0;", file=f)
24        print("  assign o0 = ^state, o1 = |state, o2 = state[31:16] + state[15:0];", file=f)
25        print("endmodule", file=f)
26    if mode == "test1":
27        io_names = [ "clk", "i0", "i1", "i2", "i3", "o0", "o1", "o2", "o3" ]
28        print("module top(input clk, i0, i1, i2, i3, output o0, o1, o2, o3);", file=f)
29        print("  reg [15:0] din, dout;", file=f)
30        print("  always @(posedge clk) din <= {din, i3, i2, i1, i0};", file=f)
31        print("  always @(posedge clk) dout <= din + {din[7:0], din[15:8]};", file=f)
32        print("  assign {o3, o2, o1, o0} = dout >> din;", file=f)
33        print("endmodule", file=f)
34    if mode == "test2":
35        io_names = [ "clk", "i0", "i1", "i2", "i3", "o0", "o1", "o2", "o3" ]
36        print("""
37          module top(input clk, i0, i1, i2, i3, output reg o0, o1, o2, o3);
38            reg [7:0] raddr, waddr, rdata, wdata;
39            reg [7:0] memory [0:255];
40            always @(posedge clk) begin
41              case ({i0, i1, i2})
42                0: raddr <= {raddr, i3};
43                1: waddr <= {waddr, i3};
44                2: wdata <= {wdata, i3};
45                3: rdata <= memory[raddr];
46                4: memory[waddr] <= wdata;
47                5: {o0, o1, o2, o3} <= rdata[3:0];
48                6: {o0, o1, o2, o3} <= rdata[7:4];
49              endcase
50            end
51          endmodule
52        """, file=f)
53    if mode == "test3":
54        io_names = [ "clk", "i0", "i1", "i2", "i3", "o0", "o1", "o2", "o3", "o4" ]
55        print("""
56          module top(input clk, i0, i1, i2, i3, output reg o0, o1, o2, o3, o4);
57            reg [9:0] raddr, waddr, rdata, wdata;
58            reg [9:0] memory [0:1023];
59            always @(posedge clk) begin
60              case ({i0, i1, i2})
61                0: raddr <= {raddr, i3};
62                1: waddr <= {waddr, i3};
63                2: wdata <= {wdata, i3};
64                3: rdata <= memory[raddr];
65                4: memory[waddr] <= wdata;
66                5: rdata <= memory[waddr];
67                6: {o0, o1, o2, o3, o4} <= rdata[4:0];
68                7: {o0, o1, o2, o3, o4} <= rdata[9:5];
69              endcase
70            end
71          endmodule
72        """, file=f)
73    if mode == "test4":
74        io_names = [ "clk", "i", "s", "o" ]
75        print("""
76          module top(input clk, i, s, output reg o);
77            reg re1, rclke1, we1, wclke1;
78            reg [7:0] raddr1, waddr1;
79            reg [15:0] rdata1, wdata1, mask1;
80            wire [15:0] rdata1_unreg;
81
82            reg re2, rclke2, we2, wclke2;
83            reg [7:0] raddr2, waddr2;
84            reg [15:0] rdata2, wdata2, mask2;
85            wire [15:0] rdata2_unreg;
86
87            always @(posedge clk) begin
88              o <= rdata1[15];
89              {rdata1, rdata2} <= {rdata1, rdata2} << 1;
90              {raddr1, waddr1, wdata1, mask1, re1, rclke1, we1, wclke1,
91               raddr2, waddr2, wdata2, mask2, re2, rclke2, we2, wclke2} <=
92                ({raddr1, waddr1, wdata1, mask1, re1, rclke1, we1, wclke1,
93                  raddr2, waddr2, wdata2, mask2, re2, rclke2, we2, wclke2} << 1) | i;
94              if (s) begin
95                rdata1 <= rdata1_unreg;
96                rdata2 <= rdata2_unreg;
97              end
98            end
99
100            SB_RAM40_4K mem1 (
101              .RDATA(rdata1_unreg),
102              .RCLK(clk),
103              .RCLKE(rclke1),
104              .RE(re1),
105              .RADDR(raddr1),
106              .WCLK(clk),
107              .WCLKE(wclke1),
108              .WE(we1),
109              .WADDR(waddr1),
110              .MASK(mask1),
111              .WDATA(wdata1)
112            );
113
114            SB_RAM40_4K mem2 (
115              .RDATA(rdata2_unreg),
116              .RCLK(clk),
117              .RCLKE(rclke2),
118              .RE(re2),
119              .RADDR(raddr1), // <- cascade
120              .WCLK(clk),
121              .WCLKE(wclke2),
122              .WE(we2),
123              .WADDR(waddr1), // <- cascade
124              .MASK(mask2),
125              .WDATA(wdata2)
126            );
127          endmodule
128        """, file=f)
129
130with open("%s.pcf" % sys.argv[1], "w") as f:
131    for i, name in enumerate(io_names):
132        print("set_io %s %s" % (name, pins[i]), file=f)
133
134with open("%s.ys" % sys.argv[1], "w") as f:
135    print("echo on", file=f)
136    print("read_verilog -lib cells.v", file=f)
137    print("read_verilog %s_ref.v" % sys.argv[1], file=f)
138    print("read_verilog %s_out.v" % sys.argv[1], file=f)
139    print("prep", file=f)
140    print("equiv_make top chip equiv", file=f)
141    print("# check -assert", file=f)
142    print("cd equiv", file=f)
143    print("script %s.lc" % sys.argv[1], file=f)
144    print("rename -hide w:N_*", file=f)
145    print("equiv_struct -maxiter 100", file=f)
146    print("opt_clean -purge", file=f)
147    print("write_ilang %s.il" % sys.argv[1], file=f)
148    print("equiv_status -assert", file=f)
149
150assert os.system("bash ../icefuzz/icecube.sh %s.v" % sys.argv[1]) == 0
151os.rename("%s.v" % sys.argv[1], "%s_in.v" % sys.argv[1])
152
153if False:
154    assert os.system("python3 ../icebox/icebox_explain.py %s.asc > %s.ex" % (sys.argv[1], sys.argv[1])) == 0
155
156with open("%s_ref.v" % sys.argv[1], "w") as f:
157    for line in open("%s.vsb" % sys.argv[1], "r"):
158        if re.match(r" *defparam .*\.(IO_STANDARD|PULLUP|INIT_.|WRITE_MODE|READ_MODE)=", line):
159            continue
160
161        line = line.replace(" Span4Mux_s0_h ",   " Span4Mux_h4 "  if max_span_hack else " Span4Mux_h0 ")
162        line = line.replace(" Span4Mux_s1_h ",   " Span4Mux_h4 "  if max_span_hack else " Span4Mux_h1 ")
163        line = line.replace(" Span4Mux_s2_h ",   " Span4Mux_h4 "  if max_span_hack else " Span4Mux_h2 ")
164        line = line.replace(" Span4Mux_s3_h ",   " Span4Mux_h4 "  if max_span_hack else " Span4Mux_h3 ")
165        line = line.replace(" Span4Mux_h ",      " Span4Mux_h4 "  if max_span_hack else " Span4Mux_h4 ")
166
167        line = line.replace(" Span4Mux_s0_v ",   " Span4Mux_v4 "  if max_span_hack else " Span4Mux_v0 ")
168        line = line.replace(" Span4Mux_s1_v ",   " Span4Mux_v4 "  if max_span_hack else " Span4Mux_v1 ")
169        line = line.replace(" Span4Mux_s2_v ",   " Span4Mux_v4 "  if max_span_hack else " Span4Mux_v2 ")
170        line = line.replace(" Span4Mux_s3_v ",   " Span4Mux_v4 "  if max_span_hack else " Span4Mux_v3 ")
171        line = line.replace(" Span4Mux_v ",      " Span4Mux_v4 "  if max_span_hack else " Span4Mux_v4 ")
172        line = line.replace(" Span4Mux ",        " Span4Mux_v4 "  if max_span_hack else " Span4Mux_v4 ")
173
174        line = line.replace(" Span12Mux_s0_h ",  " Span12Mux_h12 " if max_span_hack else " Span12Mux_h0 ")
175        line = line.replace(" Span12Mux_s1_h ",  " Span12Mux_h12 " if max_span_hack else " Span12Mux_h1 ")
176        line = line.replace(" Span12Mux_s2_h ",  " Span12Mux_h12 " if max_span_hack else " Span12Mux_h2 ")
177        line = line.replace(" Span12Mux_s3_h ",  " Span12Mux_h12 " if max_span_hack else " Span12Mux_h3 ")
178        line = line.replace(" Span12Mux_s4_h ",  " Span12Mux_h12 " if max_span_hack else " Span12Mux_h4 ")
179        line = line.replace(" Span12Mux_s5_h ",  " Span12Mux_h12 " if max_span_hack else " Span12Mux_h5 ")
180        line = line.replace(" Span12Mux_s6_h ",  " Span12Mux_h12 " if max_span_hack else " Span12Mux_h6 ")
181        line = line.replace(" Span12Mux_s7_h ",  " Span12Mux_h12 " if max_span_hack else " Span12Mux_h7 ")
182        line = line.replace(" Span12Mux_s8_h ",  " Span12Mux_h12 " if max_span_hack else " Span12Mux_h8 ")
183        line = line.replace(" Span12Mux_s9_h ",  " Span12Mux_h12 " if max_span_hack else " Span12Mux_h9 ")
184        line = line.replace(" Span12Mux_s10_h ", " Span12Mux_h12 " if max_span_hack else " Span12Mux_h10 ")
185        line = line.replace(" Span12Mux_s11_h ", " Span12Mux_h12 " if max_span_hack else " Span12Mux_h11 ")
186        line = line.replace(" Span12Mux ",       " Span12Mux_h12 " if max_span_hack else " Span12Mux_h12 ")
187
188        line = line.replace(" Span12Mux_s0_v ",  " Span12Mux_v12 " if max_span_hack else " Span12Mux_v0 ")
189        line = line.replace(" Span12Mux_s1_v ",  " Span12Mux_v12 " if max_span_hack else " Span12Mux_v1 ")
190        line = line.replace(" Span12Mux_s2_v ",  " Span12Mux_v12 " if max_span_hack else " Span12Mux_v2 ")
191        line = line.replace(" Span12Mux_s3_v ",  " Span12Mux_v12 " if max_span_hack else " Span12Mux_v3 ")
192        line = line.replace(" Span12Mux_s4_v ",  " Span12Mux_v12 " if max_span_hack else " Span12Mux_v4 ")
193        line = line.replace(" Span12Mux_s5_v ",  " Span12Mux_v12 " if max_span_hack else " Span12Mux_v5 ")
194        line = line.replace(" Span12Mux_s6_v ",  " Span12Mux_v12 " if max_span_hack else " Span12Mux_v6 ")
195        line = line.replace(" Span12Mux_s7_v ",  " Span12Mux_v12 " if max_span_hack else " Span12Mux_v7 ")
196        line = line.replace(" Span12Mux_s8_v ",  " Span12Mux_v12 " if max_span_hack else " Span12Mux_v8 ")
197        line = line.replace(" Span12Mux_s9_v ",  " Span12Mux_v12 " if max_span_hack else " Span12Mux_v9 ")
198        line = line.replace(" Span12Mux_s10_v ", " Span12Mux_v12 " if max_span_hack else " Span12Mux_v10 ")
199        line = line.replace(" Span12Mux_s11_v ", " Span12Mux_v12 " if max_span_hack else " Span12Mux_v11 ")
200        line = line.replace(" Span12Mux_v ",     " Span12Mux_v12 " if max_span_hack else " Span12Mux_v12 ")
201
202        f.write(line)
203
204assert os.system("yosys -qp 'select -write %s.lc t:LogicCell40' %s_ref.v" % (sys.argv[1], sys.argv[1])) == 0
205assert os.system(r"sed -i -r 's,.*/(.*)LC_(.*),equiv_add -try -cell \1LC_\2_gold lc40_\2_gate,' %s.lc" % sys.argv[1]) == 0
206
207os.remove("%s.bin" % sys.argv[1])
208os.remove("%s.vsb" % sys.argv[1])
209os.remove("%s.glb" % sys.argv[1])
210os.remove("%s.psb" % sys.argv[1])
211os.remove("%s.sdf" % sys.argv[1])
212shutil.rmtree("%s.tmp" % sys.argv[1])
213
214