#!/usr/bin/env python3 # DESCRIPTION: Verilator: Verilog Test driver/expect definition # # Copyright 2024 by Wilson Snyder. This program is free software; you # can redistribute it and/or modify it under the terms of either the GNU # Lesser General Public License Version 3 or the Perl Artistic License # Version 2.0. # SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 import vltest_bootstrap import collections import math test.scenarios('simulator') test.top_filename = test.obj_dir + "/t_gate_tree.v" test.cycles = (1000000 if test.benchmark else 100) test.sim_time = test.cycles * 10 + 1000 width = 64 * int(test.getenv_def("VERILATOR_TEST_WIDTH", "4")) nvars = 64 def gen(filename): with open(filename, 'w', encoding="utf8") as fh: fh.write("// Generated by t_gate_tree.py\n") fh.write("module t (clk);\n") fh.write(" input clk;\n") fh.write("\n") fh.write(" integer cyc=0;\n") fh.write(" reg reset;\n") fh.write("\n") tree = collections.defaultdict(dict) fanin = 8 stages = int(math.log(nvars) / math.log(fanin) + 0.99999) + 1 result = 0 for n in range(0, nvars): result += max(n, 1) if 0 not in tree: tree[0] = {} if n not in tree[0]: tree[0][n] = {} tree[0][n][n] = True nl = n for stage in range(1, stages): lastn = nl nl = int(nl / fanin) if stage not in tree: tree[stage] = {} if nl not in tree[stage]: tree[stage][nl] = {} tree[stage][nl][lastn] = True # pprint(tree) fh.write("\n") workingset = 0 for stage in sorted(tree.keys()): for n in sorted(tree[stage].keys()): fh.write(" reg [" + str(width - 1) + ":0] v" + str(stage) + "_" + str(n) + ";\n") workingset += int(width / 8 + 7) fh.write("\n") fh.write(" always @ (posedge clk) begin\n") fh.write(" cyc <= cyc + 1;\n") fh.write("`ifdef TEST_VERBOSE\n") fh.write(" $write(\"[%0t] rst=%0x v0_0=%0x v1_0=%0x result=%0x\\n\"" ", $time, reset, v0_0, v1_0, v" + str(stages - 1) + "_0);\n") fh.write("`endif\n") fh.write(" if (cyc==0) begin\n") fh.write(" reset <= 1;\n") fh.write(" end\n") fh.write(" else if (cyc==10) begin\n") fh.write(" reset <= 0;\n") fh.write(" end\n") fh.write("`ifndef SIM_CYCLES\n") fh.write(" `define SIM_CYCLES 99\n") fh.write("`endif\n") fh.write(" else if (cyc==`SIM_CYCLES) begin\n") fh.write(" if (v" + str(stages - 1) + "_0 != " + str(width) + "'d" + str(result) + ") $stop;\n") fh.write(" $write(\"VARS=" + str(nvars) + " WIDTH=" + str(width) + " WORKINGSET=" + str(int(workingset / 1024)) + "KB\\n\");\n") fh.write(' $write("*-* All Finished *-*\\n");' + "\n") fh.write(' $finish;' + "\n") fh.write(" end\n") fh.write(" end\n") fh.write("\n") for n in range(0, nvars): fh.write(" always @ (posedge clk)" + " v0_" + str(n) + " <= reset ? " + str(width) + "'d" + str(max(n, 1)) + " : v0_" + str((int(n / fanin) * fanin) + ((n + 1) % fanin)) + ";\n") for stage in sorted(tree.keys()): if stage == 0: continue fh.write("\n") for n in sorted(tree[stage].keys()): fh.write(" always @ (posedge clk) v" + str(stage) + "_" + str(n) + " <=") op = "" for ni in sorted(tree[stage][n].keys()): fh.write(op + " v" + str(stage - 1) + "_" + str(ni)) op = " +" fh.write(";\n") fh.write("endmodule\n") gen(test.top_filename) test.compile(v_flags2=["+define+SIM_CYCLES=" + str(test.cycles)], verilator_flags2=["--stats --x-assign fast --x-initial fast", "-Wno-UNOPTTHREADS"]) test.execute(all_run_flags=[ "+verilator+prof+exec+start+100", " +verilator+prof+exec+window+2", " +verilator+prof+exec+file+" + test.obj_dir + "/profile_exec.dat", " +verilator+prof+vlt+file+" + test.obj_dir + "/profile.vlt"]) # yapf:disable test.passes()