3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-05-10 09:15:49 +00:00
yosys/techlibs/lattice/cells_xtra.py
David Anderson af8e85b7d2 techlibs/lattice: add missing clock muxes to ECP5 block ram blackboxes
prjtrellis documentation shows that EBR clock inputs have optional inverters.
The bram techmap outputs those parameters, and nextpnr consumes them. But for
whatever reason, Diamond doesn't include those parameters in its blackbox
models. This makes synth_lattice fail when targeting ECP5 with a design that
maps block RAMs if you include any pass that needs cells_bb_ecp5.v's definitions.

This change fixes up the ECP5 bram blackbox models at generation time, by
adding the missing parameters back in.

Signed-off-by: David Anderson <dave@natulte.net>
2025-04-21 11:57:49 -07:00

871 lines
24 KiB
Python

#!/usr/bin/env python3
# Based on Xilinx cells_xtra.py; modified for Lattice'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={}, extra_params={}):
self.name = name
self.keep = keep
self.port_attrs = port_attrs
self.extra_params = extra_params
self.found = False
class State(Enum):
OUTSIDE = auto()
IN_MODULE = auto()
IN_OTHER_MODULE = auto()
IN_FUNCTION = auto()
IN_TASK = auto()
devices = [
("cells_bb_ecp5.v", "ecp5u", [
#Cell("AND2"),
#Cell("AND3"),
#Cell("AND4"),
#Cell("AND5"),
#Cell("BB"),
#Cell("BBPD"),
#Cell("BBPU"),
#Cell("CCU2C"),
#Cell("FD1P3AX"),
#Cell("FD1P3AY"),
#Cell("FD1P3BX"),
#Cell("FD1P3DX"),
#Cell("FD1P3IX"),
#Cell("FD1P3JX"),
#Cell("FD1S3AX"),
#Cell("FD1S3AY"),
#Cell("FD1S3BX"),
#Cell("FD1S3DX"),
#Cell("FD1S3IX"),
#Cell("FD1S3JX"),
#Cell("FL1P3AY"),
#Cell("FL1P3AZ"),
#Cell("FL1P3BX"),
#Cell("FL1P3DX"),
#Cell("FL1P3IY"),
#Cell("FL1P3JY"),
#Cell("FL1S3AX"),
#Cell("FL1S3AY"),
Cell("GSR", True),
#Cell("IB"),
#Cell("IBPD"),
#Cell("IBPU"),
#Cell("IFS1P3BX"),
#Cell("IFS1P3DX"),
#Cell("IFS1P3IX"),
#Cell("IFS1P3JX"),
#Cell("IFS1S1B"),
#Cell("IFS1S1D"),
#Cell("IFS1S1I"),
#Cell("IFS1S1J"),
#Cell("ILVDS"),
#Cell("INV"),
#Cell("L6MUX21"),
#Cell("LUT4"),
#Cell("LUT5"),
#Cell("LUT6"),
#Cell("LUT7"),
#Cell("LUT8"),
#Cell("MUX161"),
#Cell("MUX21"),
#Cell("MUX321"),
#Cell("MUX41"),
#Cell("MUX81"),
#Cell("ND2"),
#Cell("ND3"),
#Cell("ND4"),
#Cell("ND5"),
#Cell("NR2"),
#Cell("NR3"),
#Cell("NR4"),
#Cell("NR5"),
#Cell("OB"),
#Cell("OBCO"),
#Cell("OBZ"),
#Cell("OBZPU"),
#Cell("OFS1P3BX"),
#Cell("OFS1P3DX"),
#Cell("OFS1P3IX"),
#Cell("OFS1P3JX"),
#Cell("OLVDS"),
#Cell("OR2"),
#Cell("OR3"),
#Cell("OR4"),
#Cell("OR5"),
#Cell("PFUMX"),
Cell("PUR"),
#Cell("ROM128X1A"),
#Cell("ROM16X1A"),
#Cell("ROM256X1A"),
#Cell("ROM32X1A"),
#Cell("ROM64X1A"),
Cell("SGSR", True),
#Cell("VHI"),
#Cell("VLO"),
#Cell("XNOR2"),
#Cell("XNOR3"),
#Cell("XNOR4"),
#Cell("XNOR5"),
#Cell("XOR11"),
#Cell("XOR2"),
#Cell("XOR21"),
#Cell("XOR3"),
#Cell("XOR4"),
#Cell("XOR5"),
Cell("DP16KD", extra_params={
# Optional clock inverters, present in prjtrellis data but
# not in Diamond bb models.
"CLKAMUX": "CLKA",
"CLKBMUX": "CLKB",
}),
Cell("PDPW16KD", extra_params={
# Optional clock inverters, present in prjtrellis data but
# not in Diamond bb models.
"CLKWMUX": "CLKW",
"CLKRMUX": "CLKR",
}),
#Cell("DPR16X4C"),
#Cell("SPR16X4C"),
#Cell("LVDSOB"),
#Cell("IMIPI"),
#Cell("MULT9X9C"),
#Cell("MULT9X9D"),
#Cell("MULT18X18C"),
Cell("MULT18X18D"),
#Cell("ALU24A"),
#Cell("ALU54A"),
#Cell("ALU24B"),
Cell("ALU54B"),
#Cell("PRADD9A"),
#Cell("PRADD18A"),
#Cell("BCINRD"),
#Cell("BCLVDSOB"),
#Cell("INRDB"),
Cell("CLKDIVF"),
Cell("PCSCLKDIV"),
Cell("DCSC"),
Cell("DCCA"),
Cell("ECLKSYNCB"),
Cell("ECLKBRIDGECS"),
#Cell("PLLREFCS"),
Cell("DELAYF"),
Cell("DELAYG"),
#Cell("START"),
Cell("USRMCLK", True),
Cell("DQSBUFM"),
Cell("DDRDLLA"),
Cell("DLLDELD"),
Cell("IDDRX1F"),
Cell("IDDRX2F"),
Cell("IDDR71B"),
Cell("IDDRX2DQA"),
Cell("ODDRX1F"),
Cell("ODDRX2F"),
Cell("ODDR71B"),
Cell("OSHX2A"),
Cell("TSHX2DQA"),
Cell("TSHX2DQSA"),
Cell("ODDRX2DQA"),
Cell("ODDRX2DQSB"),
Cell("EHXPLLL"),
Cell("DTR"),
Cell("OSCG"),
Cell("EXTREFB"),
Cell("JTAGG", True, port_attrs={'TCK': ['iopad_external_pin'], 'TMS': ['iopad_external_pin'], 'TDO': ['iopad_external_pin'], 'TDI': ['iopad_external_pin']}),
#Cell("SEDGA"),
Cell("DCUA", True, port_attrs={'CH0_HDINP': ['iopad_external_pin'], 'CH1_HDINP': ['iopad_external_pin'], 'CH0_HDINN': ['iopad_external_pin'], 'CH1_HDINN': ['iopad_external_pin']}),
]),
("cells_bb_xo2.v", "machxo2", [
#Cell("AGEB2"),
#Cell("ALEB2"),
#Cell("AND2"),
#Cell("AND3"),
#Cell("AND4"),
#Cell("AND5"),
#Cell("ANEB2"),
#Cell("BB"),
#Cell("BBPD"),
#Cell("BBPU"),
#Cell("BBW"),
#Cell("CB2"),
#Cell("CD2"),
#Cell("CU2"),
#Cell("FADD2B"),
#Cell("FADSU2"),
#Cell("FD1P3AX"),
#Cell("FD1P3AY"),
#Cell("FD1P3BX"),
#Cell("FD1P3DX"),
#Cell("FD1P3IX"),
#Cell("FD1P3JX"),
#Cell("FD1S1A"),
#Cell("FD1S1AY"),
#Cell("FD1S1B"),
#Cell("FD1S1D"),
#Cell("FD1S1I"),
#Cell("FD1S1J"),
#Cell("FD1S3AX"),
#Cell("FD1S3AY"),
#Cell("FD1S3BX"),
#Cell("FD1S3DX"),
#Cell("FD1S3IX"),
#Cell("FD1S3JX"),
#Cell("FL1P3AY"),
#Cell("FL1P3AZ"),
#Cell("FL1P3BX"),
#Cell("FL1P3DX"),
#Cell("FL1P3IY"),
#Cell("FL1P3JY"),
#Cell("FL1S1A"),
#Cell("FL1S1AY"),
#Cell("FL1S1B"),
#Cell("FL1S1D"),
#Cell("FL1S1I"),
#Cell("FL1S1J"),
#Cell("FL1S3AX"),
#Cell("FL1S3AY"),
#Cell("FSUB2B"),
Cell("GSR", True),
#Cell("IB"),
#Cell("IBPD"),
#Cell("IBPU"),
#Cell("IFS1P3BX"),
#Cell("IFS1P3DX"),
#Cell("IFS1P3IX"),
#Cell("IFS1P3JX"),
#Cell("ILVDS"),
#Cell("INV"),
#Cell("L6MUX21"),
#Cell("LB2P3AX"),
#Cell("LB2P3AY"),
#Cell("LB2P3BX"),
#Cell("LB2P3DX"),
#Cell("LB2P3IX"),
#Cell("LB2P3JX"),
#Cell("LD2P3AX"),
#Cell("LD2P3AY"),
#Cell("LD2P3BX"),
#Cell("LD2P3DX"),
#Cell("LD2P3IX"),
#Cell("LD2P3JX"),
#Cell("LU2P3AX"),
#Cell("LU2P3AY"),
#Cell("LU2P3BX"),
#Cell("LU2P3DX"),
#Cell("LU2P3IX"),
#Cell("LU2P3JX"),
#Cell("MULT2"),
#Cell("MUX161"),
#Cell("MUX21"),
#Cell("MUX321"),
#Cell("MUX41"),
#Cell("MUX81"),
#Cell("ND2"),
#Cell("ND3"),
#Cell("ND4"),
#Cell("ND5"),
#Cell("NR2"),
#Cell("NR3"),
#Cell("NR4"),
#Cell("NR5"),
#Cell("OB"),
#Cell("OBCO"),
#Cell("OBZ"),
#Cell("OBZPU"),
#Cell("OFS1P3BX"),
#Cell("OFS1P3DX"),
#Cell("OFS1P3IX"),
#Cell("OFS1P3JX"),
#Cell("OLVDS"),
#Cell("OR2"),
#Cell("OR3"),
#Cell("OR4"),
#Cell("OR5"),
#Cell("LUT4"),
#Cell("LUT5"),
#Cell("LUT6"),
#Cell("LUT7"),
#Cell("LUT8"),
#Cell("PFUMX"),
#Cell("PUR"),
#Cell("ROM128X1A"),
#Cell("ROM16X1A"),
#Cell("ROM256X1A"),
#Cell("ROM32X1A"),
#Cell("ROM64X1A"),
#Cell("CCU2D"),
#Cell("VHI"),
#Cell("VLO"),
#Cell("XNOR2"),
#Cell("XNOR3"),
#Cell("XNOR4"),
#Cell("XNOR5"),
#Cell("XOR11"),
#Cell("XOR2"),
#Cell("XOR21"),
#Cell("XOR3"),
#Cell("XOR4"),
#Cell("XOR5"),
#Cell("IFS1S1B"),
#Cell("IFS1S1D"),
#Cell("IFS1S1I"),
#Cell("IFS1S1J"),
#Cell("DPR16X4C"),
#Cell("SPR16X4C"),
Cell("SGSR", True),
Cell("DP8KC"),
Cell("PDPW8KC"),
Cell("SP8KC"),
Cell("FIFO8KB"),
Cell("CLKDIVC"),
Cell("DCMA"),
Cell("ECLKSYNCA"),
Cell("ECLKBRIDGECS"),
Cell("DCCA"),
#Cell("JTAGF", True, port_attrs={'TCK': ['iopad_external_pin'], 'TMS': ['iopad_external_pin'], 'TDO': ['iopad_external_pin'], 'TDI': ['iopad_external_pin']}),
Cell("START", True),
#Cell("SEDFA"),
#Cell("SEDFB"),
#Cell("IDDRXE"),
#Cell("IDDRX2E"),
#Cell("IDDRX4B"),
#Cell("IDDRDQSX1A"),
#Cell("IDDRX71A"),
#Cell("ODDRXE"),
#Cell("ODDRX2E"),
#Cell("ODDRX4B"),
#Cell("ODDRDQSX1A"),
#Cell("ODDRX71A"),
#Cell("TDDRA"),
#Cell("DQSBUFH"),
#Cell("DQSDLLC"),
#Cell("DELAYE"),
#Cell("DELAYD"),
#Cell("DLLDELC"),
#Cell("CLKFBBUFA"),
#Cell("PCNTR"),
#Cell("BCINRD"),
#Cell("BCLVDSO"),
#Cell("INRDB"),
#Cell("LVDSOB"),
#Cell("PG"),
Cell("EHXPLLJ"),
#Cell("PLLREFCS"),
Cell("OSCH"),
#Cell("EFB"),
Cell("TSALL", True),
]),
("cells_bb_xo3.v", "machxo3lf", [
#Cell("AGEB2"),
#Cell("ALEB2"),
#Cell("AND2"),
#Cell("AND3"),
#Cell("AND4"),
#Cell("AND5"),
#Cell("ANEB2"),
#Cell("BB"),
#Cell("BBPD"),
#Cell("BBPU"),
#Cell("BBW"),
#Cell("CB2"),
#Cell("CD2"),
#Cell("CU2"),
#Cell("FADD2B"),
#Cell("FADSU2"),
#Cell("FD1P3AX"),
#Cell("FD1P3AY"),
#Cell("FD1P3BX"),
#Cell("FD1P3DX"),
#Cell("FD1P3IX"),
#Cell("FD1P3JX"),
#Cell("FD1S1A"),
#Cell("FD1S1AY"),
#Cell("FD1S1B"),
#Cell("FD1S1D"),
#Cell("FD1S1I"),
#Cell("FD1S1J"),
#Cell("FD1S3AX"),
#Cell("FD1S3AY"),
#Cell("FD1S3BX"),
#Cell("FD1S3DX"),
#Cell("FD1S3IX"),
#Cell("FD1S3JX"),
#Cell("FL1P3AY"),
#Cell("FL1P3AZ"),
#Cell("FL1P3BX"),
#Cell("FL1P3DX"),
#Cell("FL1P3IY"),
#Cell("FL1P3JY"),
#Cell("FL1S1A"),
#Cell("FL1S1AY"),
#Cell("FL1S1B"),
#Cell("FL1S1D"),
#Cell("FL1S1I"),
#Cell("FL1S1J"),
#Cell("FL1S3AX"),
#Cell("FL1S3AY"),
#Cell("FSUB2B"),
Cell("GSR", True),
#Cell("IB"),
#Cell("IBPD"),
#Cell("IBPU"),
#Cell("IFS1P3BX"),
#Cell("IFS1P3DX"),
#Cell("IFS1P3IX"),
#Cell("IFS1P3JX"),
#Cell("ILVDS"),
#Cell("INV"),
#Cell("L6MUX21"),
#Cell("LB2P3AX"),
#Cell("LB2P3AY"),
#Cell("LB2P3BX"),
#Cell("LB2P3DX"),
#Cell("LB2P3IX"),
#Cell("LB2P3JX"),
#Cell("LD2P3AX"),
#Cell("LD2P3AY"),
#Cell("LD2P3BX"),
#Cell("LD2P3DX"),
#Cell("LD2P3IX"),
#Cell("LD2P3JX"),
#Cell("LU2P3AX"),
#Cell("LU2P3AY"),
#Cell("LU2P3BX"),
#Cell("LU2P3DX"),
#Cell("LU2P3IX"),
#Cell("LU2P3JX"),
#Cell("MULT2"),
#Cell("MUX161"),
#Cell("MUX21"),
#Cell("MUX321"),
#Cell("MUX41"),
#Cell("MUX81"),
#Cell("ND2"),
#Cell("ND3"),
#Cell("ND4"),
#Cell("ND5"),
#Cell("NR2"),
#Cell("NR3"),
#Cell("NR4"),
#Cell("NR5"),
#Cell("OB"),
#Cell("OBCO"),
#Cell("OBZ"),
#Cell("OBZPU"),
#Cell("OFS1P3BX"),
#Cell("OFS1P3DX"),
#Cell("OFS1P3IX"),
#Cell("OFS1P3JX"),
#Cell("OLVDS"),
#Cell("OR2"),
#Cell("OR3"),
#Cell("OR4"),
#Cell("OR5"),
#Cell("LUT4"),
#Cell("LUT5"),
#Cell("LUT6"),
#Cell("LUT7"),
#Cell("LUT8"),
#Cell("PFUMX"),
#Cell("PUR"),
#Cell("ROM128X1A"),
#Cell("ROM16X1A"),
#Cell("ROM256X1A"),
#Cell("ROM32X1A"),
#Cell("ROM64X1A"),
#Cell("CCU2D"),
#Cell("VHI"),
#Cell("VLO"),
#Cell("XNOR2"),
#Cell("XNOR3"),
#Cell("XNOR4"),
#Cell("XNOR5"),
#Cell("XOR11"),
#Cell("XOR2"),
#Cell("XOR21"),
#Cell("XOR3"),
#Cell("XOR4"),
#Cell("XOR5"),
#Cell("IFS1S1B"),
#Cell("IFS1S1D"),
#Cell("IFS1S1I"),
#Cell("IFS1S1J"),
#Cell("DPR16X4C"),
#Cell("SPR16X4C"),
Cell("SGSR", True),
Cell("DP8KC"),
Cell("PDPW8KC"),
Cell("SP8KC"),
Cell("FIFO8KB"),
Cell("CLKDIVC"),
Cell("DCMA"),
Cell("ECLKSYNCA"),
Cell("ECLKBRIDGECS"),
Cell("DCCA"),
#Cell("JTAGF", True, port_attrs={'TCK': ['iopad_external_pin'], 'TMS': ['iopad_external_pin'], 'TDO': ['iopad_external_pin'], 'TDI': ['iopad_external_pin']}),
Cell("START", True),
#Cell("SEDFA"),
#Cell("SEDFB"),
#Cell("IDDRXE"),
#Cell("IDDRX2E"),
#Cell("IDDRX4B"),
#Cell("IDDRX71A"),
#Cell("ODDRXE"),
#Cell("ODDRX2E"),
#Cell("ODDRX4B"),
#Cell("ODDRX71A"),
#Cell("DQSDLLC"),
#Cell("DELAYE"),
#Cell("DELAYD"),
#Cell("DLLDELC"),
#Cell("CLKFBBUFA"),
#Cell("PCNTR"),
#Cell("BCINRD"),
#Cell("BCLVDSO"),
#Cell("INRDB"),
#Cell("LVDSOB"),
#Cell("PG"),
Cell("EHXPLLJ"),
#Cell("PLLREFCS"),
Cell("OSCH"),
#Cell("EFB"),
Cell("TSALL", True),
]),
("cells_bb_xo3d.v", "machxo3d", [
#Cell("AGEB2"),
#Cell("ALEB2"),
#Cell("AND2"),
#Cell("AND3"),
#Cell("AND4"),
#Cell("AND5"),
#Cell("ANEB2"),
#Cell("BB"),
#Cell("BBPD"),
#Cell("BBPU"),
#Cell("BBI3C"),
#Cell("BBW"),
#Cell("CB2"),
#Cell("CD2"),
#Cell("CU2"),
#Cell("FADD2B"),
#Cell("FADSU2"),
#Cell("FD1P3AX"),
#Cell("FD1P3AY"),
#Cell("FD1P3BX"),
#Cell("FD1P3DX"),
#Cell("FD1P3IX"),
#Cell("FD1P3JX"),
#Cell("FD1S1A"),
#Cell("FD1S1AY"),
#Cell("FD1S1B"),
#Cell("FD1S1D"),
#Cell("FD1S1I"),
#Cell("FD1S1J"),
#Cell("FD1S3AX"),
#Cell("FD1S3AY"),
#Cell("FD1S3BX"),
#Cell("FD1S3DX"),
#Cell("FD1S3IX"),
#Cell("FD1S3JX"),
#Cell("FL1P3AY"),
#Cell("FL1P3AZ"),
#Cell("FL1P3BX"),
#Cell("FL1P3DX"),
#Cell("FL1P3IY"),
#Cell("FL1P3JY"),
#Cell("FL1S1A"),
#Cell("FL1S1AY"),
#Cell("FL1S1B"),
#Cell("FL1S1D"),
#Cell("FL1S1I"),
#Cell("FL1S1J"),
#Cell("FL1S3AX"),
#Cell("FL1S3AY"),
#Cell("FSUB2B"),
Cell("GSR", True),
#Cell("IB"),
#Cell("IBPD"),
#Cell("IBPU"),
#Cell("IFS1P3BX"),
#Cell("IFS1P3DX"),
#Cell("IFS1P3IX"),
#Cell("IFS1P3JX"),
#Cell("ILVDS"),
#Cell("INV"),
#Cell("L6MUX21"),
#Cell("LB2P3AX"),
#Cell("LB2P3AY"),
#Cell("LB2P3BX"),
#Cell("LB2P3DX"),
#Cell("LB2P3IX"),
#Cell("LB2P3JX"),
#Cell("LD2P3AX"),
#Cell("LD2P3AY"),
#Cell("LD2P3BX"),
#Cell("LD2P3DX"),
#Cell("LD2P3IX"),
#Cell("LD2P3JX"),
#Cell("LU2P3AX"),
#Cell("LU2P3AY"),
#Cell("LU2P3BX"),
#Cell("LU2P3DX"),
#Cell("LU2P3IX"),
#Cell("LU2P3JX"),
#Cell("MULT2"),
#Cell("MUX161"),
#Cell("MUX21"),
#Cell("MUX321"),
#Cell("MUX41"),
#Cell("MUX81"),
#Cell("ND2"),
#Cell("ND3"),
#Cell("ND4"),
#Cell("ND5"),
#Cell("NR2"),
#Cell("NR3"),
#Cell("NR4"),
#Cell("NR5"),
#Cell("OB"),
#Cell("OBCO"),
#Cell("OBZ"),
#Cell("OBZPU"),
#Cell("OFS1P3BX"),
#Cell("OFS1P3DX"),
#Cell("OFS1P3IX"),
#Cell("OFS1P3JX"),
#Cell("OLVDS"),
#Cell("OR2"),
#Cell("OR3"),
#Cell("OR4"),
#Cell("OR5"),
#Cell("LUT4"),
#Cell("LUT5"),
#Cell("LUT6"),
#Cell("LUT7"),
#Cell("LUT8"),
#Cell("PFUMX"),
#Cell("PUR"),
#Cell("ROM128X1A"),
#Cell("ROM16X1A"),
#Cell("ROM256X1A"),
#Cell("ROM32X1A"),
#Cell("ROM64X1A"),
#Cell("CCU2D"),
#Cell("VHI"),
#Cell("VLO"),
#Cell("XNOR2"),
#Cell("XNOR3"),
#Cell("XNOR4"),
#Cell("XNOR5"),
#Cell("XOR11"),
#Cell("XOR2"),
#Cell("XOR21"),
#Cell("XOR3"),
#Cell("XOR4"),
#Cell("XOR5"),
#Cell("IFS1S1B"),
#Cell("IFS1S1D"),
#Cell("IFS1S1I"),
#Cell("IFS1S1J"),
#Cell("DPR16X4C"),
#Cell("SPR16X4C"),
Cell("SGSR", True),
Cell("DP8KC"),
Cell("PDPW8KC"),
Cell("SP8KC"),
Cell("FIFO8KB"),
Cell("CLKDIVC"),
Cell("DCMA"),
Cell("ECLKSYNCA"),
Cell("ECLKBRIDGECS"),
Cell("DCCA"),
#Cell("JTAGF", True, port_attrs={'TCK': ['iopad_external_pin'], 'TMS': ['iopad_external_pin'], 'TDO': ['iopad_external_pin'], 'TDI': ['iopad_external_pin']}),
Cell("START", True),
#Cell("SEDFA"),
#Cell("SEDFB"),
#Cell("IDDRXE"),
#Cell("IDDRX2E"),
#Cell("IDDRX4B"),
#Cell("IDDRX71A"),
#Cell("ODDRXE"),
#Cell("ODDRX2E"),
#Cell("ODDRX4B"),
#Cell("ODDRX71A"),
#Cell("DQSDLLC"),
#Cell("DELAYE"),
#Cell("DELAYD"),
#Cell("DLLDELC"),
#Cell("CLKFBBUFA"),
#Cell("PCNTR"),
#Cell("BCINRD"),
#Cell("BCLVDSO"),
#Cell("INRDB"),
#Cell("LVDSOB"),
#Cell("PG"),
Cell("EHXPLLJ"),
#Cell("PLLREFCS"),
Cell("OSCJ"),
#Cell("EFBB"),
Cell("TSALL", True),
#Cell("ESBA"),
#Cell("BCSLEWRATEA"),
])
]
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
kind = None
for l in f:
l, _, comment = l.partition('//')
l = l.strip()
m = re.search(r'synthesis .*black_box_pad_pin="([^"]*)"', comment)
if m:
iopad_pin = set(m.group(1).split(","))
if l.startswith("module "):
cell_name = l[7:l.find('(')].strip()
cell = None
kind = 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
outf.write('(* blackbox *)')
if cell.keep:
outf.write(' (* keep *)\n')
else:
outf.write('\n')
outf.write('module {} (...);\n'.format(cell.name))
cell.found = True
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:
l = l.strip()
if l == "":
continue
if l.endswith((';', ',', ")")):
l = l[:-1]
l = l.replace(")","")
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 cell.extra_params:
for name, default in sorted(cell.extra_params.items()):
outf.write(' parameter {} = "{}";\n'.format(name, default))
cell.extra_params = None
l = l.strip()
if l.endswith((';', ',')):
l = l[:-1]
while ' ' in l:
l = l.replace(' ', ' ')
if "INITVAL" in l:
l = l.replace('"0x', "320'h")
l = l.replace('"', '')
if ';' in l:
print('Weird parameter line in {} [{}].'.format(fname, l))
sys.exit(1)
outf.write(' {};\n'.format(l))
elif kind is not None and state == State.IN_MODULE:
l = l.strip()
if l == "":
continue
if l.endswith((';', ',', ")")):
l = l[:-1]
l = l.replace(")","")
if l == "":
continue
if ';' in l:
print('Weird port line in {} [{}].'.format(fname, l))
sys.exit(1)
ports = l
for port in ports.split(','):
port = port.strip()
if port.startswith('['):
rng, port = port.split()
else:
rng = None
module_ports.append((kind, rng, port))
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 Lattice Diamond.')
parser.add_argument('diamond_dir', nargs='?', default='/usr/local/diamond/3.12/')
args = parser.parse_args()
dirs = [
os.path.join(args.diamond_dir, 'cae_library/synthesis/verilog/'),
]
for dir in dirs:
if not os.path.isdir(dir):
print('{} is not a directory'.format(dir))
for fn, device, cells in devices:
out = StringIO()
xtract_cells_decl(device, cells, dirs, out)
with open(fn, 'w') as f:
f.write('// Created by cells_xtra.py from Lattice models\n')
f.write('\n')
f.write(out.getvalue())