Fixes.
diff --git a/scripts/python-skywater-pdk/generate_symbols.sh b/scripts/python-skywater-pdk/generate_symbols.sh
index 0f31470..7a7c86b 100755
--- a/scripts/python-skywater-pdk/generate_symbols.sh
+++ b/scripts/python-skywater-pdk/generate_symbols.sh
@@ -11,12 +11,10 @@
find $1/skywater-pdk/ -name *.tb.v -delete
find $1/skywater-pdk/ -name *.blackbox.v -delete
find $1/skywater-pdk/ -name *.symbol.v -delete
-find $1/skywater-pdk/ -name *.svg -delete
./generate_verilog_blackbox.py $1/skywater-pdk/libraries/*/*/models/*
./generate_verilog_blackbox.py $1/skywater-pdk/libraries/*/*/cells/*
-#exit
-
+exit 1
#(cd $1/ ; git diff --no-renames --name-only --diff-filter=D -z | xargs -0 git checkout --)
for LIB in $1/skywater-pdk/libraries/*; do
diff --git a/scripts/python-skywater-pdk/generate_verilog_blackbox.py b/scripts/python-skywater-pdk/generate_verilog_blackbox.py
index e764506..37b7ca4 100755
--- a/scripts/python-skywater-pdk/generate_verilog_blackbox.py
+++ b/scripts/python-skywater-pdk/generate_verilog_blackbox.py
@@ -489,7 +489,7 @@
f.seek(current_pos+1)
-def transistor_sizes(basename, cellpath):
+def cell_sizes(basename, cellpath):
sizes = []
for f in os.listdir(cellpath):
if not f.endswith('.gds'):
@@ -504,8 +504,72 @@
sizes.append(size)
return [parse_size(s) for s in sizes]
+
+
+LOGICS = [
+ ' | ',
+ ' & ',
+ ' OR ',
+ ' AND ',
+ ' NOR ',
+ ' NAND ',
+ '( ',
+ ' )',
+ ' of ',
+ ' input ',
+ ' output ',
+ 'input ',
+ 'output ',
+ 'of ',
+ ' input',
+ ' output',
+ ' of',
+ '1 ',
+ '2 ',
+ '3 ',
+ '4 ',
+ '5 ',
+ '6 ',
+ '7 ',
+ '8 ',
+ '9 ',
+ '0 ',
+]
+DONT_BREAK = {}
+for l in LOGICS:
+ DONT_BREAK[l] = l.replace(' ', '\u00a0')
+
+# Convert whitespace inside equations to non-breaking.
+# \u00a0
+#
+# '2-input AND into first input of 4-input OR ((A1 & A2) | B1 | C1 | D1)'
+
+def whitespace_convert(s):
+ for fs, ts in DONT_BREAK.items():
+ s = s.replace(fs, ts)
+ return s
+
+def whitespace_revert(s):
+ for fs, ts in DONT_BREAK.items():
+ s = s.replace(ts, fs)
+ return s
+
+
def wrap(s, i=''):
- return "\n".join(textwrap.wrap(s, initial_indent=' * '+i, subsequent_indent=' * '+i))
+ s = whitespace_convert(s)
+
+ p = ' * '+i
+ m = ' * '+(' '*len(i))
+
+ s = "\n".join(textwrap.wrap(
+ s,
+ initial_indent=p,
+ subsequent_indent=m,
+ break_on_hyphens=False,
+ expand_tabs=True,
+ ))
+
+ return whitespace_revert(s)
warning = """\
@@ -518,7 +582,7 @@
return fname.upper()
-def write_verilog_header(f, desc, define_data):
+def write_verilog_header(f, vdesc, define_data):
assert f.name, f
guard = file_guard(os.path.basename(f.name))
f.write(copyright_header)
@@ -527,16 +591,28 @@
f.write(f'`define {guard}\n')
f.write('\n')
f.write(f"/**\n")
- if '\n' in define_data['description']:
- f.write(f" * {define_data['name']}:\n")
- for l in define_data['description'].splitlines():
+
+ assert 'description' in define_data, define_data
+ desc = define_data['description']
+ eq = define_data.get('equation', '')
+
+ if '\n' in desc:
+ if eq:
+ eq = ' '+eq
+ f.write(wrap(eq, i=define_data['name']+":"))
+ f.write("\n")
+ for l in desc.splitlines():
f.write(wrap(l.rstrip(), i=' '))
f.write('\n')
else:
- f.write(wrap(f"{define_data['name']}: {define_data['description']}"))
+ f.write(wrap(desc, i=define_data['name']+": "))
f.write('\n')
+ if eq:
+ f.write(f" *\n")
+ f.write(wrap(eq, i=((len(define_data['name'])+2)*" ")))
+ f.write('\n')
f.write(f" *\n")
- f.write(wrap(desc))
+ f.write(wrap(vdesc))
f.write('\n')
f.write(f" *\n")
f.write(wrap(warning))
@@ -544,6 +620,7 @@
f.write(f" */\n")
f.write('\n')
f.write('`timescale 1ns / 1ps\n')
+ f.write('`default_nettype none\n')
f.write('\n')
@@ -551,6 +628,7 @@
assert f.name, f
guard = file_guard(os.path.basename(f.name))
f.write('\n')
+ f.write('`default_nettype wire\n')
f.write(f'`endif // {guard}\n')
f.close()
@@ -830,6 +908,12 @@
pprint.pprint(ports_by_class)
pprint.pprint(ports_by_dir)
+ if PortGroup.CLOCK in ports_by_class and len(ports_by_class[PortGroup.CLOCK]) > 1:
+ print("WARNING: Can't generate testbench for define with multiple clocks (", end="")
+ print(ports_by_class[PortGroup.CLOCK], end="")
+ print(")")
+ return
+
vfile = outfile(cellpath, define_data, exists=True)
outpath = outfile(cellpath, define_data, 'tb')
@@ -855,7 +939,7 @@
if PortGroup.classify(pname, define_data['name']) == PortGroup.CLOCK:
continue
input_port_names.append(pname)
- maxlen = max(len(i) for i in input_port_names)
+ maxlen = max((len(i) for i in input_port_names), default=0)
input_port_names = [n.ljust(maxlen) for n in input_port_names]
f.write(' // Inputs are registered\n')
@@ -923,9 +1007,8 @@
""")
-
if PortGroup.CLOCK in ports_by_class:
- assert len(ports_by_class[PortGroup.CLOCK]) == 1, ports
+ assert len(ports_by_class[PortGroup.CLOCK]) == 1, ports_by_class
clk_port = ports_by_class[PortGroup.CLOCK][0]
clk_class, clk_name, clk_dir, clk_type = clk_port
@@ -1058,6 +1141,33 @@
write_verilog_footer(f)
+def write_verilog_cell_top(cellpath, define_data):
+ outpath = outfile(cellpath, define_data, '')
+
+ with open(outpath, "w+") as f:
+ write_verilog_header(
+ f,
+ "Verilog top module.",
+ define_data)
+ f.write('`ifdef USE_POWER_PINS\n')
+ f.write('\n')
+ f.write('`ifdef FUNCTIONAL\n')
+ f.write(f'`include "{define_data["file_prefix"]}.pp.functional.v"\n')
+ f.write('`else // FUNCTIONAL\n')
+ f.write(f'`include "{define_data["file_prefix"]}.pp.behavioural.v"\n')
+ f.write('`endif // FUNCTIONAL\n')
+ f.write('\n')
+ f.write('`else // USE_POWER_PINS\n')
+ f.write('\n')
+ f.write('`ifdef FUNCTIONAL\n')
+ f.write(f'`include "{define_data["file_prefix"]}.functional.v"\n')
+ f.write('`else // FUNCTIONAL\n')
+ f.write(f'`include "{define_data["file_prefix"]}.behavioural.v"\n')
+ f.write('`endif // FUNCTIONAL\n')
+ f.write('\n')
+ f.write('`endif // USE_POWER_PINS\n')
+ write_verilog_footer(f)
+
def process(cellpath):
print()
@@ -1078,12 +1188,17 @@
write_symbol_pp(cellpath, define_data)
if define_data['type'] == 'cell':
- for d in transistor_sizes(define_data['name'], cellpath):
+ for d in cell_sizes(define_data['name'], cellpath):
write_size_wrapper(d, cellpath, define_data)
if define_data['type'] == 'primitive':
write_primitive(cellpath, define_data)
write_testbench(cellpath, define_data)
+
+ if define_data['type'] == 'cell':
+ write_verilog_cell_top(cellpath, define_data)
+ write_testbench(cellpath, define_data)
+
return
@@ -1092,7 +1207,6 @@
process(a)
-
if __name__ == "__main__":
import doctest
fails, _ = doctest.testmod()