1#!/usr/bin/env python3 2 3import argparse 4import sys 5import random 6from contextlib import contextmanager 7 8@contextmanager 9def redirect_stdout(new_target): 10 old_target, sys.stdout = sys.stdout, new_target 11 try: 12 yield new_target 13 finally: 14 sys.stdout = old_target 15 16def random_expression(depth = 3, maxparam = 0): 17 def recursion(): 18 return random_expression(depth = depth-1, maxparam = maxparam) 19 if depth == 0: 20 if maxparam != 0 and random.randint(0, 1) != 0: 21 return 'p%02d' % random.randint(0, maxparam-1) 22 return random.choice([ '%e', '%f', '%g' ]) % random.uniform(-2, +2) 23 if random.randint(0, 4) == 0: 24 return recursion() + random.choice([ ' < ', ' <= ', ' == ', ' != ', ' >= ', ' > ' ]) + recursion() + ' ? ' + recursion() + ' : ' + recursion() 25 op_prefix = [ '+(', '-(' ] 26 op_infix = [ ' + ', ' - ', ' * ', ' / ' ] 27 op_func1 = [ '$ln', '$log10', '$exp', '$sqrt', '$floor', '$ceil', '$sin', '$cos', '$tan', '$asin', '$acos', '$atan', '$sinh', '$cosh', '$tanh', '$asinh', '$acosh', '$atanh' ] 28 op_func2 = [ '$pow', '$atan2', '$hypot' ] 29 op = random.choice(op_prefix + op_infix + op_func1 + op_func2) 30 if op in op_prefix: 31 return op + recursion() + ')' 32 if op in op_infix: 33 return '(' + recursion() + op + recursion() + ')' 34 if op in op_func1: 35 return op + '(' + recursion() + ')' 36 if op in op_func2: 37 return op + '(' + recursion() + ', ' + recursion() + ')' 38 raise 39 40parser = argparse.ArgumentParser(formatter_class = argparse.ArgumentDefaultsHelpFormatter) 41parser.add_argument('-S', '--seed', type = int, help = 'seed for PRNG') 42parser.add_argument('-c', '--count', type = int, default = 100, help = 'number of test cases to generate') 43args = parser.parse_args() 44 45if args.seed is not None: 46 print("PRNG seed: %d" % args.seed) 47 random.seed(args.seed) 48 49for idx in range(args.count): 50 with open('temp/uut_%05d.v' % idx, 'w') as f: 51 with redirect_stdout(f): 52 print('module uut_%05d(output [63:0] %s);\n' % (idx, ', '.join(['y%02d' % i for i in range(100)]))) 53 for i in range(30): 54 if idx < 10: 55 print('localparam p%02d = %s;' % (i, random_expression())) 56 else: 57 print('localparam%s p%02d = %s;' % (random.choice(['', ' real', ' integer']), i, random_expression())) 58 for i in range(30, 60): 59 if idx < 10: 60 print('localparam p%02d = %s;' % (i, random_expression(maxparam = 30))) 61 else: 62 print('localparam%s p%02d = %s;' % (random.choice(['', ' real', ' integer']), i, random_expression(maxparam = 30))) 63 for i in range(100): 64 print('assign y%02d = 65536 * (%s);' % (i, random_expression(maxparam = 60))) 65 print('endmodule') 66 with open('temp/uut_%05d.ys' % idx, 'w') as f: 67 with redirect_stdout(f): 68 print('read_verilog uut_%05d.v' % idx) 69 print('rename uut_%05d uut_%05d_syn' % (idx, idx)) 70 print('write_verilog uut_%05d_syn.v' % idx) 71 with open('temp/uut_%05d_tb.v' % idx, 'w') as f: 72 with redirect_stdout(f): 73 print('module uut_%05d_tb;\n' % idx) 74 print('wire [63:0] %s;' % (', '.join(['r%02d' % i for i in range(100)]))) 75 print('wire [63:0] %s;' % (', '.join(['s%02d' % i for i in range(100)]))) 76 print('uut_%05d ref(%s);' % (idx, ', '.join(['r%02d' % i for i in range(100)]))) 77 print('uut_%05d_syn syn(%s);' % (idx, ', '.join(['s%02d' % i for i in range(100)]))) 78 print('task compare_ref_syn;') 79 print(' input [7:0] i;') 80 print(' input [63:0] r, s;') 81 print(' reg [64*8-1:0] buffer;') 82 print(' integer j;') 83 print(' begin') 84 print(' if (-1 <= $signed(r-s) && $signed(r-s) <= +1) begin') 85 print(' // $display("%d: %b %b", i, r, s);') 86 print(' end else if (r === s) begin ') 87 print(' // $display("%d: %b %b", i, r, s);') 88 print(' end else begin ') 89 print(' for (j = 0; j < 64; j = j+1)') 90 print(' buffer[j*8 +: 8] = r[j] !== s[j] ? "^" : " ";') 91 print(' $display("\\n%3d: %b %b", i, r, s);') 92 print(' $display(" %s %s", buffer, buffer);') 93 print(' end') 94 print(' end') 95 print('endtask') 96 print('initial begin #1;') 97 for i in range(100): 98 print(' compare_ref_syn(%2d, r%02d, s%02d);' % (i, i, i)) 99 print('end') 100 print('endmodule') 101 102