Skip to content

Commit 370aa4b

Browse files
committed
Simplify Verilog export string formatting code. No functionality changes.
1 parent 18e0639 commit 370aa4b

File tree

1 file changed

+63
-69
lines changed

1 file changed

+63
-69
lines changed

pyrtl/importexport.py

Lines changed: 63 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,15 @@
2626
from pyrtl.wire import Const, Input, Output, Register, WireVector, next_tempvar_name
2727

2828
if TYPE_CHECKING:
29+
from pyrtl.core import LogicNet
2930
from pyrtl.simulation import SimulationTrace
3031

3132

32-
def _natural_sort_key(key):
33+
def _natural_sort_key(key: str) -> list:
3334
"""Convert the key into a form such that it will be sorted naturally, e.g. such that
3435
"tmp4" appears before "tmp18".
36+
37+
For example, given "a1b2" as input, this will return ['a', 1, 'b', 2, ''].
3538
"""
3639

3740
def convert(text):
@@ -40,7 +43,7 @@ def convert(text):
4043
return [convert(c) for c in re.split(r"(\d+)", key)]
4144

4245

43-
def _net_sorted(logic, name_mapper=lambda w: w.name):
46+
def _net_sorted(logic: set[LogicNet], name_mapper=lambda w: w.name) -> list[LogicNet]:
4447
# Sort nets based on the name of the destination wire, unless it's a memory write
4548
# net.
4649
def natural_keys(n):
@@ -55,7 +58,9 @@ def natural_keys(n):
5558
return sorted(logic, key=natural_keys)
5659

5760

58-
def _name_sorted(wires, name_mapper=lambda w: w.name):
61+
def _name_sorted(
62+
wires: set[WireVector], name_mapper=lambda w: w.name
63+
) -> list[WireVector]:
5964
return sorted(wires, key=lambda w: _natural_sort_key(name_mapper(w)))
6065

6166

@@ -780,7 +785,7 @@ def output_to_verilog(
780785
for wire in block.wirevector_set:
781786
internal_names.make_valid_string(wire.name)
782787

783-
def varname(wire):
788+
def varname(wire: WireVector) -> str:
784789
return internal_names[wire.name]
785790

786791
_to_verilog_header(file, block, varname, add_reset, initialize_registers)
@@ -826,12 +831,8 @@ def _extra_checks(self, str):
826831
) # not too long to be a Verilog id
827832

828833

829-
def _verilog_vector_size_decl(n):
830-
return "" if n == 1 else f"[{n - 1:d}:0]"
831-
832-
833-
def _verilog_vector_decl(w):
834-
return _verilog_vector_size_decl(len(w))
834+
def _verilog_vector_size_decl(n: int) -> str:
835+
return "" if n == 1 else f"[{n - 1}:0]"
835836

836837

837838
def _verilog_block_parts(block):
@@ -866,27 +867,28 @@ def name_list(wires):
866867
msg = 'input or output with name starting with "tmp" indicates unnamed IO'
867868
raise PyrtlError(msg)
868869
io_list_str = ", ".join(io_list)
869-
print(f"module toplevel({io_list_str:s});", file=file)
870+
print(f"module toplevel({io_list_str});", file=file)
870871

871872
# inputs and outputs
872873
print(" input clk;", file=file)
873874
if add_reset:
874875
print(" input rst;", file=file)
875876
for w in name_sorted(inputs):
876-
print(f" input{_verilog_vector_decl(w):s} {varname(w):s};", file=file)
877+
print(
878+
f" input{_verilog_vector_size_decl(w.bitwidth)} {varname(w)};", file=file
879+
)
877880
for w in name_sorted(outputs):
878881
print(
879-
f" output{_verilog_vector_decl(w):s} {varname(w):s};",
882+
f" output{_verilog_vector_size_decl(w.bitwidth)} {varname(w)};",
880883
file=file,
881884
)
882885
print(file=file)
883886

884887
# memories and registers
885888
for m in sorted(memories, key=lambda m: m.id):
886-
memwidth_str = _verilog_vector_size_decl(m.bitwidth)
887-
memsize_str = _verilog_vector_size_decl(1 << m.addrwidth)
888889
print(
889-
f" reg{memwidth_str:s} mem_{m.id}{memsize_str:s}; //{m.name}",
890+
f" reg{_verilog_vector_size_decl(m.bitwidth)} "
891+
f"mem_{m.id}{_verilog_vector_size_decl(1 << m.addrwidth)}; //{m.name}",
890892
file=file,
891893
)
892894
for reg in name_sorted(registers):
@@ -897,7 +899,7 @@ def name_list(wires):
897899
reset_value = reg.reset_value
898900
register_initialization = f" = {reg.bitwidth}'d{reset_value}"
899901
print(
900-
f" reg{_verilog_vector_decl(reg)} {varname(reg)}"
902+
f" reg{_verilog_vector_size_decl(reg.bitwidth)} {varname(reg)}"
901903
f"{register_initialization};",
902904
file=file,
903905
)
@@ -906,7 +908,9 @@ def name_list(wires):
906908

907909
# wires
908910
for w in name_sorted(wires):
909-
print(f" wire{_verilog_vector_decl(w):s} {varname(w):s};", file=file)
911+
print(
912+
f" wire{_verilog_vector_size_decl(w.bitwidth)} {varname(w)};", file=file
913+
)
910914
print(file=file)
911915

912916
# Write the initial values for read-only memories. If we ever add support outside of
@@ -915,9 +919,10 @@ def name_list(wires):
915919
for m in sorted(roms, key=lambda m: m.id):
916920
print(" initial begin", file=file)
917921
for i in range(1 << m.addrwidth):
918-
mem_elem_str = f"mem_{m.id}[{i:d}]"
919-
mem_data_str = f"{m.bitwidth:d}'h{m._get_read_data(i):x}"
920-
print(f" {mem_elem_str:s}={mem_data_str:s};", file=file)
922+
print(
923+
f" mem_{m.id}[{i}]={m.bitwidth}'h{m._get_read_data(i):x};",
924+
file=file,
925+
)
921926
print(" end", file=file)
922927
print(file=file)
923928

@@ -932,39 +937,37 @@ def name_sorted(wires):
932937

933938
# assign constants (these could be folded for readability later)
934939
for const in name_sorted(block.wirevector_subset(Const)):
935-
print(f" assign {varname(const):s} = {const.val:d};", file=file)
940+
print(f" assign {varname(const)} = {const.val:d};", file=file)
936941

937942
# walk the block and output combination logic
938943
for net in _net_sorted(block.logic, varname):
944+
assign = None
945+
if net.dests:
946+
assign = f" assign {varname(net.dests[0])}"
939947
if net.op in "w~": # unary ops
940948
opstr = "" if net.op == "w" else net.op
941-
t = (varname(net.dests[0]), opstr, varname(net.args[0]))
942-
print(" assign {} = {}{};".format(*t), file=file)
949+
print(f"{assign} = {opstr}{varname(net.args[0])};", file=file)
943950
elif net.op in "&|^+-*<>": # binary ops
944-
t = (
945-
varname(net.dests[0]),
946-
varname(net.args[0]),
947-
net.op,
948-
varname(net.args[1]),
951+
print(
952+
f"{assign} = {varname(net.args[0])} {net.op} {varname(net.args[1])};",
953+
file=file,
949954
)
950-
print(" assign {} = {} {} {};".format(*t), file=file)
951955
elif net.op == "=":
952-
t = (varname(net.dests[0]), varname(net.args[0]), varname(net.args[1]))
953-
print(" assign {} = {} == {};".format(*t), file=file)
956+
print(
957+
f"{assign} = {varname(net.args[0])} == {varname(net.args[1])};",
958+
file=file,
959+
)
954960
elif net.op == "x":
955961
# note that the argument order for 'x' is backwards from the ternary
956962
# operator
957-
t = (
958-
varname(net.dests[0]),
959-
varname(net.args[0]),
960-
varname(net.args[2]),
961-
varname(net.args[1]),
963+
print(
964+
f"{assign} = {varname(net.args[0])} ? "
965+
f"{varname(net.args[2])} : {varname(net.args[1])};",
966+
file=file,
962967
)
963-
print(" assign {} = {} ? {} : {};".format(*t), file=file)
964968
elif net.op == "c":
965969
catlist = ", ".join([varname(w) for w in net.args])
966-
t = (varname(net.dests[0]), catlist)
967-
print(" assign {} = {{{}}};".format(*t), file=file)
970+
print(f"{assign} = {{{catlist}}};", file=file)
968971
elif net.op == "s":
969972
# someone please check if we need this special handling for scalars
970973
catlist = ", ".join(
@@ -975,8 +978,7 @@ def name_sorted(wires):
975978
for i in reversed(net.op_param)
976979
]
977980
)
978-
t = (varname(net.dests[0]), catlist)
979-
print(" assign {} = {{{}}};".format(*t), file=file)
981+
print(f"{assign} = {{{catlist}}};", file=file)
980982
elif net.op in "rm@":
981983
pass # do nothing for registers and memories
982984
else:
@@ -1000,20 +1002,21 @@ def _to_verilog_sequential(file, block, varname, add_reset):
10001002
print(" if (rst) begin", file=file)
10011003
for net in _net_sorted(block.logic, varname):
10021004
if net.op == "r":
1003-
dest = varname(net.dests[0])
10041005
rval = net.dests[0].reset_value
10051006
if rval is None:
10061007
rval = 0
1007-
print(f" {dest:s} <= {rval:d};", file=file)
1008+
print(f" {varname(net.dests[0])} <= {rval:d};", file=file)
10081009
print(" end", file=file)
10091010
print(" else begin", file=file)
10101011
else:
10111012
print(" begin", file=file)
10121013

10131014
for net in _net_sorted(block.logic, varname):
10141015
if net.op == "r":
1015-
dest, src = (varname(net.dests[0]), varname(net.args[0]))
1016-
print(f" {dest:s} <= {src:s};", file=file)
1016+
print(
1017+
f" {varname(net.dests[0])} <= {varname(net.args[0])};",
1018+
file=file,
1019+
)
10171020
print(" end", file=file)
10181021
print(" end", file=file)
10191022
print(file=file)
@@ -1033,18 +1036,11 @@ def _to_verilog_memories(file, block, varname):
10331036
print(" always @(posedge clk)", file=file)
10341037
print(" begin", file=file)
10351038
for net in writes:
1036-
t = (
1037-
varname(net.args[2]),
1038-
net.op_param[0],
1039-
varname(net.args[0]),
1040-
varname(net.args[1]),
1041-
)
10421039
print(
1043-
(
1044-
" if ({}) begin\n"
1045-
" mem_{}[{}] <= {};\n"
1046-
" end"
1047-
).format(*t),
1040+
f" if ({varname(net.args[2])}) begin\n"
1041+
f" mem_{net.op_param[0]}[{varname(net.args[0])}] <= "
1042+
f"{varname(net.args[1])};\n"
1043+
" end",
10481044
file=file,
10491045
)
10501046
print(" end", file=file)
@@ -1054,10 +1050,11 @@ def _to_verilog_memories(file, block, varname):
10541050
if net.op_param[1] == m
10551051
]
10561052
for net in reads:
1057-
dest = varname(net.dests[0])
1058-
m_id = net.op_param[0]
1059-
index = varname(net.args[0])
1060-
print(f" assign {dest:s} = mem_{m_id}[{index:s}];", file=file)
1053+
print(
1054+
f" assign {varname(net.dests[0])} = "
1055+
f"mem_{net.op_param[0]}[{varname(net.args[0])}];",
1056+
file=file,
1057+
)
10611058
print(file=file)
10621059

10631060

@@ -1186,7 +1183,7 @@ def default_value():
11861183

11871184
# Output an include, if given
11881185
if toplevel_include:
1189-
print(f'`include "{toplevel_include:s}"', file=dest_file)
1186+
print(f'`include "{toplevel_include}"', file=dest_file)
11901187
print(file=dest_file)
11911188

11921189
# Output header
@@ -1198,14 +1195,14 @@ def default_value():
11981195
print(" reg rst;", file=dest_file)
11991196
for w in name_sorted(inputs):
12001197
print(
1201-
f" reg{_verilog_vector_decl(w):s} {ver_name[w.name]:s};",
1198+
f" reg{_verilog_vector_size_decl(w.bitwidth)} {ver_name[w.name]};",
12021199
file=dest_file,
12031200
)
12041201

12051202
# Declare all block outputs as wires
12061203
for w in name_sorted(outputs):
12071204
print(
1208-
f" wire{_verilog_vector_decl(w):s} {ver_name[w.name]:s};",
1205+
f" wire{_verilog_vector_size_decl(w.bitwidth)} {ver_name[w.name]};",
12091206
file=dest_file,
12101207
)
12111208
print(file=dest_file)
@@ -1260,11 +1257,8 @@ def default_value():
12601257
for i in range(tracelen):
12611258
for w in name_sorted(inputs):
12621259
print(
1263-
" {:s} = {:s}{:d};".format(
1264-
ver_name[w.name],
1265-
f"{len(w):d}'d",
1266-
simulation_trace.trace[w.name][i],
1267-
),
1260+
f" {ver_name[w.name]} = "
1261+
f"{w.bitwidth}'d{simulation_trace.trace[w.name][i]};",
12681262
file=dest_file,
12691263
)
12701264
print("\n #10", file=dest_file)

0 commit comments

Comments
 (0)