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
)
96 addrmask
= (1 << abits
) - 1
99 tb_addrlist
.append(random
.randrange(1048576) & addrmask
)
101 t
= random
.randrange(1048576)
103 tb_addrlist
.append((t ^
(1 << i
)) & addrmask
)
105 v_stmts
.append("(* nomem2reg *) reg [%d:0] memory [0:%d];" % (dbits
-1, 2**abits
-1))
108 last_always_hdr
= (-1, "")
112 for p1
in range(groups
):
113 for p2
in range(ports
[p1
]):
114 pf
= "%c%d" % (chr(ord("A") + p1
), p2
+ 1)
117 v_stmts
.append("`ifndef SYNTHESIS")
118 v_stmts
.append(" event UPDATE_%s;" % pf
)
119 v_stmts
.append("`endif")
121 if clocks
[p1
] and not ("CLK%d" % clocks
[p1
]) in v_ports
:
122 v_ports
.add("CLK%d" % clocks
[p1
])
123 v_stmts
.append("input CLK%d;" % clocks
[p1
])
124 tb_decls
.append("reg CLK%d = 0;" % clocks
[p1
])
125 tb_clocks
.append("CLK%d" % clocks
[p1
])
127 v_ports
.add("%sADDR" % pf
)
128 v_stmts
.append("input [%d:0] %sADDR;" % (abits
-1, pf
))
130 v_stmts
.append("reg [%d:0] %sADDR_Q;" % (abits
-1, pf
))
131 tb_decls
.append("reg [%d:0] %sADDR;" % (abits
-1, pf
))
132 tb_addr
.append("%sADDR" % pf
)
134 v_ports
.add("%sDATA" % pf
)
135 v_stmts
.append("%s [%d:0] %sDATA;" % ("input" if wrmode
[p1
] else "output reg", dbits
-1, pf
))
138 tb_decls
.append("reg [%d:0] %sDATA;" % (dbits
-1, pf
))
139 tb_din
.append("%sDATA" % pf
)
141 tb_decls
.append("wire [%d:0] %sDATA;" % (dbits
-1, pf
))
142 tb_decls
.append("wire [%d:0] %sDATA_R;" % (dbits
-1, pf
))
143 tb_dout
.append("%sDATA" % pf
)
145 if wrmode
[p1
] and enable
[p1
]:
146 v_ports
.add("%sEN" % pf
)
147 v_stmts
.append("input [%d:0] %sEN;" % (enable
[p1
]-1, pf
))
148 tb_decls
.append("reg [%d:0] %sEN;" % (enable
[p1
]-1, pf
))
149 tb_din
.append("%sEN" % pf
)
150 addr2en
["%sADDR" % pf
] = "%sEN" % pf
154 always_hdr
= "always @* begin"
156 elif clkpol
[p1
] == 0:
157 always_hdr
= "always @(negedge CLK%d) begin" % clocks
[p1
]
158 elif clkpol
[p1
] == 1:
159 always_hdr
= "always @(posedge CLK%d) begin" % clocks
[p1
]
161 if not ("CP", clkpol
[p1
]) in states
:
162 v_stmts
.append("parameter CLKPOL%d = 0;" % clkpol
[p1
])
163 states
.add(("CP", clkpol
[p1
]))
164 if not ("CPW", clocks
[p1
], clkpol
[p1
]) in states
:
165 v_stmts
.append("wire CLK%d_CLKPOL%d = CLK%d == CLKPOL%d;" % (clocks
[p1
], clkpol
[p1
], clocks
[p1
], clkpol
[p1
]))
166 states
.add(("CPW", clocks
[p1
], clkpol
[p1
]))
167 always_hdr
= "always @(posedge CLK%d_CLKPOL%d) begin" % (clocks
[p1
], clkpol
[p1
])
169 if last_always_hdr
[1] != always_hdr
:
170 last_always_hdr
= (portindex
, always_hdr
)
171 v_always
[last_always_hdr
] = list()
174 for i
in range(enable
[p1
]):
175 enrange
= "[%d:%d]" % ((i
+1)*dbits
/enable
[p1
]-1, i
*dbits
/enable
[p1
])
176 v_always
[last_always_hdr
].append((portindex
, pf
, "if (%sEN[%d]) memory[%sADDR]%s = %sDATA%s;" % (pf
, i
, pf
, enrange
, pf
, enrange
)))
178 v_always
[last_always_hdr
].append((sum(ports
)+1, pf
, "%sADDR_Q %s %sADDR;" % (pf
, assign_op
, pf
)))
179 v_stmts
.append("always @* %sDATA = memory[%sADDR_Q];" % (pf
, pf
))
181 v_always
[last_always_hdr
].append((0, pf
, "%sDATA %s memory[%sADDR];" % (pf
, assign_op
, pf
)))
183 for always_hdr
in sorted(v_always
):
184 v_stmts
.append(always_hdr
[1])
185 triggered_events
= set()
187 v_always
[always_hdr
].sort()
188 for t
, p
, s
in v_always
[always_hdr
]:
189 if time_cursor
!= t
or not p
in triggered_events
:
190 v_stmts
.append(" `ifndef SYNTHESIS")
193 stmt
+= " #%d;" % (t
-time_cursor
)
195 if not p
in triggered_events
:
196 stmt
+= (" -> UPDATE_%s;" % p
)
197 triggered_events
.add(p
)
198 v_stmts
.append(" %s" % stmt
)
199 v_stmts
.append(" `endif")
200 v_stmts
.append(" %s" % s
)
201 v_stmts
.append("end")
203 print("module bram_%02d_%02d(%s);" % (k1
, k2
, ", ".join(v_ports
)), file=sim_f
)
205 print(" %s" % stmt
, file=sim_f
)
206 print("endmodule", file=sim_f
)
208 print("module bram_%02d_%02d_ref(%s);" % (k1
, k2
, ", ".join(v_ports
)), file=ref_f
)
210 print(" %s" % stmt
, file=ref_f
)
211 print("endmodule", file=ref_f
)
213 print("module bram_%02d_%02d_tb;" % (k1
, k2
), file=tb_f
)
214 for stmt
in tb_decls
:
215 print(" %s" % stmt
, file=tb_f
)
216 print(" bram_%02d_%02d uut (" % (k1
, k2
), file=tb_f
)
217 print(" " + ",\n ".join([".%s(%s)" % (p
, p
) for p
in (tb_clocks
+ tb_addr
+ tb_din
+ tb_dout
)]), file=tb_f
)
218 print(" );", file=tb_f
)
219 print(" bram_%02d_%02d_ref ref (" % (k1
, k2
), file=tb_f
)
220 print(" " + ",\n ".join([".%s(%s)" % (p
, p
) for p
in (tb_clocks
+ tb_addr
+ tb_din
)]) + ",", file=tb_f
)
221 print(" " + ",\n ".join([".%s(%s_R)" % (p
, p
) for p
in tb_dout
]), file=tb_f
)
222 print(" );", file=tb_f
)
224 expr_dout
= "{%s}" % ", ".join(tb_dout
)
225 expr_dout_ref
= "{%s}" % ", ".join(i
+ "_R" for i
in tb_dout
)
227 print(" wire error = %s !== %s;" % (expr_dout
, expr_dout_ref
), file=tb_f
)
229 print(" initial begin", file=tb_f
)
232 print(" $dumpfile(`vcd_file);", file=tb_f
)
233 print(" $dumpvars(0, bram_%02d_%02d_tb);" % (k1
, k2
), file=tb_f
)
234 print(" #%d;" % (1000 + k2
), file=tb_f
)
236 for p
in (tb_clocks
+ tb_addr
+ tb_din
):
238 print(" %s <= ~0;" % p
, file=tb_f
)
240 print(" %s <= 0;" % p
, file=tb_f
)
241 print(" #1000;", file=tb_f
)
243 for v
in [1, 0, 1, 0]:
245 print(" %s = %d;" % (p
, v
), file=tb_f
)
246 print(" #1000;", file=tb_f
)
248 for i
in range(20 if debug_mode
else 100):
250 c
= random
.choice(tb_clocks
)
251 print(" %s = !%s;" % (c
, c
), file=tb_f
)
252 print(" #100;", file=tb_f
)
253 print(" $display(\"bram_%02d_%02d %3d: %%b %%b %%s\", %s, %s, error ? \"ERROR\" : \"OK\");" %
254 (k1
, k2
, i
, expr_dout
, expr_dout_ref
), file=tb_f
)
257 addr
= random
.choice(tb_addrlist
)
261 a2e
[addr
].append(addr2en
[p
])
262 print(" %s <= %d;" % (p
, addr
), file=tb_f
)
264 for v
in a2e
.values():
270 val
= 0 if p
in enzero
else random
.randrange(1048576)
271 print(" %s <= %d;" % (p
, val
), file=tb_f
)
272 print(" #900;", file=tb_f
)
274 print(" end", file=tb_f
)
275 print("endmodule", file=tb_f
)
277 parser
= argparse
.ArgumentParser(formatter_class
= argparse
.ArgumentDefaultsHelpFormatter
)
278 parser
.add_argument('-S', '--seed', type = int, help = 'seed for PRNG')
279 parser
.add_argument('-c', '--count', type = int, default
= 5, help = 'number of test cases to generate')
280 parser
.add_argument('-d', '--debug', action
='store_true')
281 args
= parser
.parse_args()
283 debug_mode
= args
.debug
285 if args
.seed
is not None:
288 seed
= (int(os
.times()[4]*100) + os
.getpid()) % 900000 + 100000
290 print("PRNG seed: %d" % seed
)
293 for k1
in range(args
.count
):
294 dsc_f
= open("temp/brams_%02d.txt" % k1
, "w")
295 sim_f
= open("temp/brams_%02d.v" % k1
, "w")
296 ref_f
= open("temp/brams_%02d_ref.v" % k1
, "w")
297 tb_f
= open("temp/brams_%02d_tb.v" % k1
, "w")
299 for f
in [sim_f
, ref_f
, tb_f
]:
300 print("`timescale 1 ns / 1 ns", file=f
)
302 lenk2
= 1 if debug_mode
else 10
303 for k2
in range(lenk2
):
304 create_bram(dsc_f
, sim_f
, ref_f
, tb_f
, k1
, k2
, random
.randrange(2 if k2
+1 < lenk2
else 1))