verilator/test_regress/t/t_gate_tree.py
2024-09-08 13:00:03 -04:00

122 lines
4.5 KiB
Python
Executable File

#!/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()