Skip to content

Commit d7730c7

Browse files
committed
[otbn, sca] Don't flatten the netlist when shortening signal names
When shortening signal names the shorten_alma_identifiers.py script used to flatten the design before shortening the identifiers. This commit changes this. Now the signal names are shortened without an initial flattening step. This is done by adding a --reserve flag that decides how long the unflattened signal names can get (how much should be left in reserve). Signed-off-by: Hakim Filali <hfilali@lowrisc.org>
1 parent d4f27fa commit d7730c7

2 files changed

Lines changed: 22 additions & 19 deletions

File tree

hw/ip/otbn/pre_sca/alma/shorten_alma_identifiers.py

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -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

132132
def 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

140143
if __name__ == '__main__':

hw/ip/otbn/pre_sca/alma/verify_mai.sh

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,16 @@ case "$TARGET_TYPE" in
3333
esac
3434
export TOP_MODULE
3535

36-
echo "Verifying ${TOP_MODULE} using Alma"
36+
echo "Verifying ${TOP_MODULE} using CocoAlma"
3737

38-
# Pre-process alma.v: flatten all sub-module instances first so that parse.py's
39-
# own 'flatten' step has nothing left to inline (preventing it from creating new
40-
# long hierarchical signal names at that stage). Then shorten every escaped
41-
# identifier whose C++ length exceeds Verilator's ~128-char limit in one pass.
38+
# Pre-process alma.v: shorten escaped identifiers whose C++ length exceeds
39+
# VERILATOR_LIMIT - 11. The 11-char reserve accounts for the longest port
40+
# suffix that parse.py's internal flatten appends to kept prim_* instance names
41+
# ('.out_o_n' from prim_xnor2: 4 cpp-chars for the dot + 7 chars = 11).
4242
ALMA_V="${REPO_TOP}/hw/ip/otbn/pre_syn/syn_out/latest/generated/${TOP_MODULE}.alma.v"
4343
ALMA_FLAT="${REPO_TOP}/hw/ip/otbn/pre_syn/syn_out/latest/generated/${TOP_MODULE}.alma.flat.v"
44-
yosys -q -p "read_verilog ${ALMA_V}; proc; flatten; clean; write_verilog -noattr ${ALMA_FLAT}"
45-
python3 ${REPO_TOP}/hw/ip/otbn/pre_sca/alma/shorten_alma_identifiers.py "${ALMA_FLAT}"
44+
cp "${ALMA_V}" "${ALMA_FLAT}"
45+
python3 ${REPO_TOP}/hw/ip/otbn/pre_sca/alma/shorten_alma_identifiers.py --reserve 11 "${ALMA_FLAT}"
4646

4747
# Parse
4848
./parse.py --top-module ${TOP_MODULE} \

0 commit comments

Comments
 (0)