2626from pyrtl .wire import Const , Input , Output , Register , WireVector , next_tempvar_name
2727
2828if 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
837838def _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