@@ -30,26 +30,26 @@ def _cpp_len(identifier: str) -> int:
3030 return n
3131
3232
33- def build_id_map (text : str ) -> dict :
33+ def build_id_map (text : str , * , limit : int = VERILATOR_LIMIT ) -> dict :
3434 """Return a mapping of long identifier -> shortened identifier (no backslashes)."""
3535 escaped_re = re .compile (r'\\([^ \t\n;,)(]+)' )
3636 all_ids = set (escaped_re .findall (text ))
37- long_ids = sorted (i for i in all_ids if _cpp_len (i ) >= VERILATOR_LIMIT )
37+ long_ids = sorted (i for i in all_ids if _cpp_len (i ) >= limit )
3838
3939 if not long_ids :
4040 return {}
4141
4242 # Pre-populate 'used' with every short identifier already in the file so
4343 # that trimmed names never collide with pre-existing signals.
44- used = {i for i in all_ids if _cpp_len (i ) < VERILATOR_LIMIT }
44+ used = {i for i in all_ids if _cpp_len (i ) < limit }
4545
4646 id_map = {}
4747 for ident in long_ids :
4848 segments = ident .split ('.' )
4949 chosen = None
5050 for start in range (len (segments )):
5151 base = '.' .join (segments [start :])
52- if _cpp_len (base ) >= VERILATOR_LIMIT :
52+ if _cpp_len (base ) >= limit :
5353 continue
5454 if base not in used :
5555 chosen = base
@@ -58,7 +58,7 @@ def build_id_map(text: str) -> dict:
5858 n = 2
5959 while True :
6060 candidate = f'{ base } _{ n } '
61- if _cpp_len (candidate ) >= VERILATOR_LIMIT :
61+ if _cpp_len (candidate ) >= limit :
6262 break # suffix too long at this trim depth — drop more segments
6363 if candidate not in used :
6464 chosen = candidate
@@ -67,14 +67,14 @@ def build_id_map(text: str) -> dict:
6767 if chosen is not None :
6868 break
6969 if chosen is None :
70- base = segments [- 1 ][:VERILATOR_LIMIT - 1 ]
70+ base = segments [- 1 ][:limit - 1 ]
7171 if base not in used :
7272 chosen = base
7373 else :
7474 n = 2
7575 while True :
7676 suffix = f'_{ n } '
77- chosen = base [:VERILATOR_LIMIT - 1 - len (suffix )] + suffix
77+ chosen = base [:limit - 1 - len (suffix )] + suffix
7878 if chosen not in used :
7979 break
8080 n += 1
@@ -84,15 +84,15 @@ def build_id_map(text: str) -> dict:
8484 return id_map
8585
8686
87- def shorten_verilog (path : str ) -> None :
87+ def shorten_verilog (path : str , * , limit : int = VERILATOR_LIMIT ) -> None :
8888 """Shorten escaped identifiers in a Verilog file in-place."""
8989 with open (path ) as f :
9090 original = f .read ()
9191
92- id_map = build_id_map (original )
92+ id_map = build_id_map (original , limit = limit )
9393
9494 if not id_map :
95- print (f'No identifiers reach { VERILATOR_LIMIT } -char limit in { path } ' )
95+ print (f'No identifiers reach { limit } -char limit in { path } ' )
9696 return
9797
9898 escaped_re = re .compile (r'\\([^ \t\n;,)(]+)' )
@@ -126,15 +126,18 @@ def _replace(m: re.Match) -> str:
126126
127127 with open (path , 'w' ) as f :
128128 f .write (shortened )
129- print (f'Shortened { len (id_map )} identifiers in { path } (round-trip OK)' )
129+ print (f'Shortened { len (id_map )} identifiers in { path } (limit= { limit } , round-trip OK)' )
130130
131131
132132def main () -> None :
133133 parser = argparse .ArgumentParser (description = __doc__ )
134134 parser .add_argument ('netlist' , help = 'Verilog netlist to process in-place' )
135+ parser .add_argument ('--reserve' , type = int , default = 0 ,
136+ help = 'Reserve N chars for suffixes appended after shortening '
137+ '(effective limit = VERILATOR_LIMIT - reserve)' )
135138 args = parser .parse_args ()
136139
137- shorten_verilog (args .netlist )
140+ shorten_verilog (args .netlist , limit = VERILATOR_LIMIT - args . reserve )
138141
139142
140143if __name__ == '__main__' :
0 commit comments