aboutsummaryrefslogtreecommitdiffstats
path: root/techlibs/nexus/cells_xtra.py
diff options
context:
space:
mode:
Diffstat (limited to 'techlibs/nexus/cells_xtra.py')
-rw-r--r--techlibs/nexus/cells_xtra.py286
1 files changed, 286 insertions, 0 deletions
diff --git a/techlibs/nexus/cells_xtra.py b/techlibs/nexus/cells_xtra.py
new file mode 100644
index 000000000..dc462c29a
--- /dev/null
+++ b/techlibs/nexus/cells_xtra.py
@@ -0,0 +1,286 @@
+#!/usr/bin/env python3
+
+# Based on Xilinx cells_xtra.py; modified for Radiant's structure
+
+from argparse import ArgumentParser
+from io import StringIO
+from enum import Enum, auto
+import os.path
+import sys
+import re
+
+
+class Cell:
+ def __init__(self, name, keep=False, port_attrs={}):
+ self.name = name
+ self.keep = keep
+ self.port_attrs = port_attrs
+ self.found = False
+
+class State(Enum):
+ OUTSIDE = auto()
+ IN_MODULE = auto()
+ IN_OTHER_MODULE = auto()
+ IN_FUNCTION = auto()
+ IN_TASK = auto()
+
+devices = [
+ ("lifcl", [
+ Cell("ACC54"),
+ Cell("ADC"),
+ Cell("ALUREG"),
+ Cell("BB_ADC", keep=True),
+ Cell("BB_CDR", keep=True),
+ Cell("BB_I3C_A", keep=True),
+ Cell("BFD1P3KX"),
+ Cell("BFD1P3LX"),
+ Cell("BNKREF18", keep=True),
+ Cell("CONFIG_LMMI", keep=True),
+ Cell("DCC"),
+ Cell("DCS"),
+ Cell("DDRDLL"),
+ Cell("DELAYA"),
+ Cell("DELAYB"),
+ Cell("DIFFIO18", keep=True),
+ Cell("DLLDEL"),
+ Cell("DP16K_MODE"),
+ Cell("DP16K"),
+ Cell("DPHY", keep=True),
+ Cell("DPSC512K"),
+ Cell("DQSBUF"),
+ Cell("EBR_CORE"),
+ Cell("EBR"),
+ Cell("ECLKDIV"),
+ Cell("ECLKSYNC"),
+ Cell("FBMUX"),
+ Cell("FIFO16K_MODE"),
+ Cell("FIFO16K"),
+ Cell("GSR"),
+ Cell("HSE"),
+ Cell("I2CFIFO"),
+ Cell("IDDR71"),
+ Cell("IDDRX1"),
+ Cell("IDDRX2DQ"),
+ Cell("IDDRX2"),
+ Cell("IDDRX4DQ"),
+ Cell("IDDRX4"),
+ Cell("IDDRX5"),
+ Cell("IFD1P3BX"),
+ Cell("IFD1P3DX"),
+ Cell("IFD1P3IX"),
+ Cell("IFD1P3JX"),
+ Cell("JTAG", keep=True),
+ Cell("LRAM"),
+ Cell("M18X36"),
+ Cell("MIPI"),
+ Cell("MULT18"),
+ Cell("MULT18X18"),
+ Cell("MULT18X36"),
+ Cell("MULT36"),
+ Cell("MULT36X36"),
+ Cell("MULT9"),
+ Cell("MULT9X9"),
+ Cell("MULTADDSUB18X18"),
+ Cell("MULTADDSUB18X18WIDE"),
+ Cell("MULTADDSUB18X36"),
+ Cell("MULTADDSUB36X36"),
+ Cell("MULTADDSUB9X9WIDE"),
+ Cell("MULTIBOOT", keep=True),
+ Cell("MULTPREADD18X18"),
+ Cell("MULTPREADD9X9"),
+ Cell("ODDR71"),
+ Cell("ODDRX1"),
+ Cell("ODDRX2DQS"),
+ Cell("ODDRX2DQ"),
+ Cell("ODDRX2"),
+ Cell("ODDRX4DQS"),
+ Cell("ODDRX4DQ"),
+ Cell("ODDRX4"),
+ Cell("ODDRX5"),
+ Cell("OFD1P3BX"),
+ Cell("OFD1P3DX"),
+ Cell("OFD1P3IX"),
+ Cell("OFD1P3JX"),
+ Cell("OSC"),
+ Cell("OSCA"),
+ Cell("OSHX2"),
+ Cell("OSHX4"),
+ Cell("PCIE"),
+ Cell("PCLKDIV"),
+ Cell("PCLKDIVSP"),
+ Cell("PDP16K_MODE"),
+ Cell("PDP16K"),
+ Cell("PDPSC16K_MODE"),
+ Cell("PDPSC16K"),
+ Cell("PDPSC512K"),
+ Cell("PLL"),
+ Cell("PREADD9"),
+ Cell("PUR", keep=True),
+ Cell("REFMUX"),
+ Cell("REG18"),
+ Cell("SEDC", keep=True),
+ Cell("SEIO18"),
+ Cell("SEIO33"),
+ Cell("SGMIICDR"),
+ Cell("SP16K_MODE"),
+ Cell("SP16K"),
+ Cell("SP512K"),
+ Cell("TSALLA"),
+ Cell("TSHX2DQS"),
+ Cell("TSHX2DQ"),
+ Cell("TSHX4DQS"),
+ Cell("TSHX4DQ"),
+ Cell("WDT", keep=True),
+
+ Cell("ACC54_CORE"),
+ Cell("ADC_CORE"),
+ Cell("ALUREG_CORE"),
+ Cell("BNKREF18_CORE"),
+ Cell("BNKREF33_CORE"),
+ Cell("DIFFIO18_CORE"),
+ Cell("CONFIG_CLKRST_CORE", keep=True),
+ Cell("CONFIG_HSE_CORE", keep=True),
+ Cell("CONFIG_IP_CORE", keep=True),
+ Cell("CONFIG_JTAG_CORE", keep=True),
+ Cell("CONFIG_LMMI_CORE", keep=True),
+ Cell("CONFIG_MULTIBOOT_CORE", keep=True),
+ Cell("CONFIG_SEDC_CORE", keep=True),
+ Cell("CONFIG_WDT_CORE", keep=True),
+ Cell("DDRDLL_CORE"),
+ Cell("DLLDEL_CORE"),
+ Cell("DPHY_CORE"),
+ Cell("DQSBUF_CORE"),
+ Cell("ECLKDIV_CORE"),
+ Cell("ECLKSYNC_CORE"),
+ Cell("FBMUX_CORE"),
+ Cell("GSR_CORE"),
+ Cell("I2CFIFO_CORE"),
+ Cell("LRAM_CORE"),
+ Cell("MULT18_CORE"),
+ Cell("MULT18X36_CORE"),
+ Cell("MULT36_CORE"),
+ Cell("MULT9_CORE"),
+ Cell("OSC_CORE"),
+ Cell("PCIE_CORE"),
+ Cell("PLL_CORE"),
+ Cell("PREADD9_CORE"),
+ Cell("REFMUX_CORE"),
+ Cell("REG18_CORE"),
+ Cell("SEIO18_CORE"),
+ Cell("SEIO33_CORE"),
+ Cell("SGMIICDR_CORE"),
+ ])
+]
+
+def xtract_cells_decl(device, cells, dirs, outf):
+ fname = os.path.join(dir, device + '.v')
+ with open(fname) as f:
+ state = State.OUTSIDE
+ # Probably the most horrible Verilog "parser" ever written.
+ cell = None
+ for l in f:
+ l, _, comment = l.partition('//')
+ l = l.strip()
+ if l.startswith("module "):
+ cell_name = l[7:l.find('(')].strip()
+ cell = None
+ module_ports = []
+ iopad_pin = set()
+ if state != State.OUTSIDE:
+ print('Nested modules in {}.'.format(fname))
+ sys.exit(1)
+ for c in cells:
+ if c.name != cell_name:
+ continue
+ cell = c
+ state = State.IN_MODULE
+ if cell.keep:
+ outf.write('(* keep *)\n')
+ outf.write('module {} (...);\n'.format(cell.name))
+ cell.found = True
+
+ m = re.search(r'synthesis .*black_box_pad_pin="([^"]*)"', comment)
+ if m:
+ iopad_pin = set(m.group(1).split(","))
+
+ if cell is None:
+ state = State.IN_OTHER_MODULE
+ elif l.startswith('task '):
+ if state == State.IN_MODULE:
+ state = State.IN_TASK
+ elif l.startswith('function '):
+ if state == State.IN_MODULE:
+ state = State.IN_FUNCTION
+ elif l == 'endtask':
+ if state == State.IN_TASK:
+ state = State.IN_MODULE
+ elif l == 'endfunction':
+ if state == State.IN_FUNCTION:
+ state = State.IN_MODULE
+ elif l == 'endmodule':
+ if state == State.IN_MODULE:
+ for kind, rng, port in module_ports:
+ for attr in cell.port_attrs.get(port, []):
+ outf.write(' (* {} *)\n'.format(attr))
+ if port in iopad_pin:
+ outf.write(' (* iopad_external_pin *)\n')
+ if rng is None:
+ outf.write(' {} {};\n'.format(kind, port))
+ else:
+ outf.write(' {} {} {};\n'.format(kind, rng, port))
+ outf.write(l + '\n')
+ outf.write('\n')
+ elif state != State.IN_OTHER_MODULE:
+ print('endmodule in weird place in {}.'.format(cell.name, fname))
+ sys.exit(1)
+ state = State.OUTSIDE
+ elif l.startswith(('input ', 'output ', 'inout ')) and state == State.IN_MODULE:
+ if l.endswith((';', ',')):
+ l = l[:-1]
+ if ';' in l:
+ print('Weird port line in {} [{}].'.format(fname, l))
+ sys.exit(1)
+ kind, _, ports = l.partition(' ')
+ for port in ports.split(','):
+ port = port.strip()
+ if port.startswith('['):
+ rng, port = port.split()
+ else:
+ rng = None
+ module_ports.append((kind, rng, port))
+ elif l.startswith('parameter ') and state == State.IN_MODULE:
+ if l.endswith((';', ',')):
+ l = l[:-1]
+ while ' ' in l:
+ l = l.replace(' ', ' ')
+ if ';' in l:
+ print('Weird parameter line in {} [{}].'.format(fname, l))
+ sys.exit(1)
+ outf.write(' {};\n'.format(l))
+
+ if state != State.OUTSIDE:
+ print('endmodule not found in {}.'.format(fname))
+ sys.exit(1)
+ for cell in cells:
+ if not cell.found:
+ print('cell {} not found in {}.'.format(cell.name, fname))
+if __name__ == '__main__':
+ parser = ArgumentParser(description='Extract Lattice blackbox cell definitions from Radiant.')
+ parser.add_argument('radiant_dir', nargs='?', default='/opt/lscc/radiant/2.0/')
+ args = parser.parse_args()
+
+ dirs = [
+ os.path.join(args.radiant_dir, 'cae_library/synthesis/verilog/'),
+ ]
+ for dir in dirs:
+ if not os.path.isdir(dir):
+ print('{} is not a directory'.format(dir))
+
+ out = StringIO()
+ for device, cells in devices:
+ xtract_cells_decl(device, cells, dirs, out)
+
+ with open('cells_xtra.v', 'w') as f:
+ f.write('// Created by cells_xtra.py from Lattice models\n')
+ f.write('\n')
+ f.write(out.getvalue())