10 def create_bram(dsc_f
, sim_f
, ref_f
, tb_f
, k1
, k2
, or_next
):
12 init
= 0 # random.randrange(2)
13 abits
= random
.randrange(1, 8)
14 dbits
= random
.randrange(1, 8)
15 groups
= random
.randrange(2, 5)
17 if random
.randrange(2):
18 abits
= 2 ** random
.randrange(1, 4)
19 if random
.randrange(2):
20 dbits
= 2 ** random
.randrange(1, 4)
23 wrmode
= [ random
.randrange(0, 2) for i
in range(groups
) ]
24 if wrmode
.count(1) == 0: continue
25 if wrmode
.count(0) == 0: continue
28 if random
.randrange(2):
34 clkpol
= random
.randrange(4)
38 def generate_enable(i
):
40 v
= 2 ** random
.randrange(0, 4)
41 while dbits
< v
or dbits
% v
!= 0:
46 def generate_transp(i
):
48 return random
.randrange(maxtransp
)
51 def generate_clkpol(i
):
54 return random
.randrange(maxpol
)
56 ports
= [ random
.randrange(1, 3) for i
in range(groups
) ]
57 enable
= [ generate_enable(i
) for i
in range(groups
) ]
58 transp
= [ generate_transp(i
) for i
in range(groups
) ]
59 clocks
= [ random
.randrange(maxclocks
)+1 for i
in range(groups
) ]
60 clkpol
= [ generate_clkpol(i
) for i
in range(groups
) ]
63 print("bram bram_%02d_%02d" % (k1
, k2
), file=dsc_f
)
64 print(" init %d" % init
, file=dsc_f
)
65 print(" abits %d" % abits
, file=dsc_f
)
66 print(" dbits %d" % dbits
, file=dsc_f
)
67 print(" groups %d" % groups
, file=dsc_f
)
68 print(" ports %s" % " ".join(["%d" % i
for i
in ports
]), file=dsc_f
)
69 print(" wrmode %s" % " ".join(["%d" % i
for i
in wrmode
]), file=dsc_f
)
70 print(" enable %s" % " ".join(["%d" % i
for i
in enable
]), file=dsc_f
)
71 print(" transp %s" % " ".join(["%d" % i
for i
in transp
]), file=dsc_f
)
72 print(" clocks %s" % " ".join(["%d" % i
for i
in clocks
]), file=dsc_f
)
73 print(" clkpol %s" % " ".join(["%d" % i
for i
in clkpol
]), file=dsc_f
)
74 print("endbram", file=dsc_f
)
75 print("match bram_%02d_%02d" % (k1
, k2
), file=dsc_f
)
76 if random
.randrange(2):
77 non_zero_enables
= [chr(ord('A') + i
) for i
in range(len(enable
)) if enable
[i
]]
78 if len(non_zero_enables
):
79 print(" shuffle_enable %c" % random
.choice(non_zero_enables
), file=dsc_f
)
81 print(" or_next_if_better", file=dsc_f
)
82 print("endmatch", file=dsc_f
)
97 tb_addrlist
.append(random
.randrange(1048576))
99 t
= random
.randrange(1048576)
101 tb_addrlist
.append(t ^
(1 << i
))
103 v_stmts
.append("(* nomem2reg *) reg [%d:0] memory [0:%d];" % (dbits
-1, 2**abits
-1))
106 last_always_hdr
= (-1, "")
108 for p1
in range(groups
):
109 for p2
in range(ports
[p1
]):
110 pf
= "%c%d" % (chr(ord("A") + p1
), p2
+ 1)
113 v_stmts
.append("`ifndef SYNTHESIS")
114 v_stmts
.append(" event UPDATE_%s;" % pf
)
115 v_stmts
.append("`endif")
117 if clocks
[p1
] and not ("CLK%d" % clocks
[p1
]) in v_ports
:
118 v_ports
.add("CLK%d" % clocks
[p1
])
119 v_stmts
.append("input CLK%d;" % clocks
[p1
])
120 tb_decls
.append("reg CLK%d = 0;" % clocks
[p1
])
121 tb_clocks
.append("CLK%d" % clocks
[p1
])
123 v_ports
.add("%sADDR" % pf
)
124 v_stmts
.append("input [%d:0] %sADDR;" % (abits
-1, pf
))
126 v_stmts
.append("reg [%d:0] %sADDR_Q;" % (abits
-1, pf
))
127 tb_decls
.append("reg [%d:0] %sADDR;" % (abits
-1, pf
))
128 tb_addr
.append("%sADDR" % pf
)
130 v_ports
.add("%sDATA" % pf
)
131 v_stmts
.append("%s [%d:0] %sDATA;" % ("input" if wrmode
[p1
] else "output reg", dbits
-1, pf
))
134 tb_decls
.append("reg [%d:0] %sDATA;" % (dbits
-1, pf
))
135 tb_din
.append("%sDATA" % pf
)
137 tb_decls
.append("wire [%d:0] %sDATA;" % (dbits
-1, pf
))
138 tb_decls
.append("wire [%d:0] %sDATA_R;" % (dbits
-1, pf
))
139 tb_dout
.append("%sDATA" % pf
)
141 if wrmode
[p1
] and enable
[p1
]:
142 v_ports
.add("%sEN" % pf
)
143 v_stmts
.append("input [%d:0] %sEN;" % (enable
[p1
]-1, pf
))
144 tb_decls
.append("reg [%d:0] %sEN;" % (enable
[p1
]-1, pf
))
145 tb_din
.append("%sEN" % pf
)
149 always_hdr
= "always @* begin"
151 elif clkpol
[p1
] == 0:
152 always_hdr
= "always @(negedge CLK%d) begin" % clocks
[p1
]
153 elif clkpol
[p1
] == 1:
154 always_hdr
= "always @(posedge CLK%d) begin" % clocks
[p1
]
156 if not ("CP", clkpol
[p1
]) in states
:
157 v_stmts
.append("parameter CLKPOL%d = 0;" % clkpol
[p1
])
158 states
.add(("CP", clkpol
[p1
]))
159 if not ("CPW", clocks
[p1
], clkpol
[p1
]) in states
:
160 v_stmts
.append("wire CLK%d_CLKPOL%d = CLK%d == CLKPOL%d;" % (clocks
[p1
], clkpol
[p1
], clocks
[p1
], clkpol
[p1
]))
161 states
.add(("CPW", clocks
[p1
], clkpol
[p1
]))
162 always_hdr
= "always @(posedge CLK%d_CLKPOL%d) begin" % (clocks
[p1
], clkpol
[p1
])
164 if last_always_hdr
[1] != always_hdr
:
165 last_always_hdr
= (portindex
, always_hdr
)
166 v_always
[last_always_hdr
] = list()
169 for i
in range(enable
[p1
]):
170 enrange
= "[%d:%d]" % ((i
+1)*dbits
/enable
[p1
]-1, i
*dbits
/enable
[p1
])
171 v_always
[last_always_hdr
].append((portindex
, pf
, "if (%sEN[%d]) memory[%sADDR]%s = %sDATA%s;" % (pf
, i
, pf
, enrange
, pf
, enrange
)))
173 v_always
[last_always_hdr
].append((sum(ports
)+1, pf
, "%sADDR_Q %s %sADDR;" % (pf
, assign_op
, pf
)))
174 v_stmts
.append("always @* %sDATA = memory[%sADDR_Q];" % (pf
, pf
))
176 v_always
[last_always_hdr
].append((0, pf
, "%sDATA %s memory[%sADDR];" % (pf
, assign_op
, pf
)))
178 for always_hdr
in sorted(v_always
):
179 v_stmts
.append(always_hdr
[1])
180 triggered_events
= set()
182 v_always
[always_hdr
].sort()
183 for t
, p
, s
in v_always
[always_hdr
]:
184 if time_cursor
!= t
or not p
in triggered_events
:
185 v_stmts
.append(" `ifndef SYNTHESIS")
188 stmt
+= " #%d;" % (t
-time_cursor
)
190 if not p
in triggered_events
:
191 stmt
+= (" -> UPDATE_%s;" % p
)
192 triggered_events
.add(p
)
193 v_stmts
.append(" %s" % stmt
)
194 v_stmts
.append(" `endif")
195 v_stmts
.append(" %s" % s
)
196 v_stmts
.append("end")
198 print("module bram_%02d_%02d(%s);" % (k1
, k2
, ", ".join(v_ports
)), file=sim_f
)
200 print(" %s" % stmt
, file=sim_f
)
201 print("endmodule", file=sim_f
)
203 print("module bram_%02d_%02d_ref(%s);" % (k1
, k2
, ", ".join(v_ports
)), file=ref_f
)
205 print(" %s" % stmt
, file=ref_f
)
206 print("endmodule", file=ref_f
)
208 print("module bram_%02d_%02d_tb;" % (k1
, k2
), file=tb_f
)
209 for stmt
in tb_decls
:
210 print(" %s" % stmt
, file=tb_f
)
211 print(" bram_%02d_%02d uut (" % (k1
, k2
), file=tb_f
)
212 print(" " + ",\n ".join([".%s(%s)" % (p
, p
) for p
in (tb_clocks
+ tb_addr
+ tb_din
+ tb_dout
)]), file=tb_f
)
213 print(" );", file=tb_f
)
214 print(" bram_%02d_%02d_ref ref (" % (k1
, k2
), file=tb_f
)
215 print(" " + ",\n ".join([".%s(%s)" % (p
, p
) for p
in (tb_clocks
+ tb_addr
+ tb_din
)]) + ",", file=tb_f
)
216 print(" " + ",\n ".join([".%s(%s_R)" % (p
, p
) for p
in tb_dout
]), file=tb_f
)
217 print(" );", file=tb_f
)
219 expr_dout
= "{%s}" % ", ".join(tb_dout
)
220 expr_dout_ref
= "{%s}" % ", ".join(i
+ "_R" for i
in tb_dout
)
222 print(" wire error = %s !== %s;" % (expr_dout
, expr_dout_ref
), file=tb_f
)
224 print(" initial begin", file=tb_f
)
227 print(" $dumpfile(`vcd_file);", file=tb_f
)
228 print(" $dumpvars(0, bram_%02d_%02d_tb);" % (k1
, k2
), file=tb_f
)
229 print(" #%d;" % (1000 + k2
), file=tb_f
)
231 for p
in (tb_clocks
+ tb_addr
+ tb_din
):
233 print(" %s <= ~0;" % p
, file=tb_f
)
235 print(" %s <= 0;" % p
, file=tb_f
)
236 print(" #1000;", file=tb_f
)
238 for v
in [1, 0, 1, 0]:
240 print(" %s = %d;" % (p
, v
), file=tb_f
)
241 print(" #1000;", file=tb_f
)
243 for i
in range(20 if debug_mode
else 100):
245 c
= random
.choice(tb_clocks
)
246 print(" %s = !%s;" % (c
, c
), file=tb_f
)
247 print(" #100;", file=tb_f
)
248 print(" $display(\"bram_%02d_%02d %3d: %%b %%b %%s\", %s, %s, error ? \"ERROR\" : \"OK\");" %
249 (k1
, k2
, i
, expr_dout
, expr_dout_ref
), file=tb_f
)
251 print(" %s <= %d;" % (p
, random
.randrange(1048576)), file=tb_f
)
253 print(" %s <= %d;" % (p
, random
.choice(tb_addrlist
)), file=tb_f
)
254 print(" #900;", file=tb_f
)
256 print(" end", file=tb_f
)
257 print("endmodule", file=tb_f
)
259 parser
= argparse
.ArgumentParser(formatter_class
= argparse
.ArgumentDefaultsHelpFormatter
)
260 parser
.add_argument('-S', '--seed', type = int, help = 'seed for PRNG')
261 parser
.add_argument('-c', '--count', type = int, default
= 5, help = 'number of test cases to generate')
262 parser
.add_argument('-d', '--debug', action
='store_true')
263 args
= parser
.parse_args()
265 debug_mode
= args
.debug
267 if args
.seed
is not None:
270 seed
= (int(os
.times()[4]*100) + os
.getpid()) % 900000 + 100000
272 print("PRNG seed: %d" % seed
)
275 for k1
in range(args
.count
):
276 dsc_f
= open("temp/brams_%02d.txt" % k1
, "w")
277 sim_f
= open("temp/brams_%02d.v" % k1
, "w")
278 ref_f
= open("temp/brams_%02d_ref.v" % k1
, "w")
279 tb_f
= open("temp/brams_%02d_tb.v" % k1
, "w")
281 for f
in [sim_f
, ref_f
, tb_f
]:
282 print("`timescale 1 ns / 1 ns", file=f
)
284 lenk2
= 1 if debug_mode
else 10
285 for k2
in range(lenk2
):
286 create_bram(dsc_f
, sim_f
, ref_f
, tb_f
, k1
, k2
, random
.randrange(2 if k2
+1 < lenk2
else 1))