yosys/techlibs/gowin/cells_xtra.py

87 lines
3.7 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
# Base on Nexus cells_xtra.py
from argparse import ArgumentParser
import os.path
from enum import Enum, auto
import sys
import re
class State(Enum):
OUTSIDE = auto()
IN_MODULE = auto()
IN_PARAMETER = auto()
_skip = { # These are already described, no need to extract them from the vendor files
'ALU', 'BANDGAP', 'DFF', 'DFFC', 'DFFCE', 'DFFE', 'DFFN', 'DFFNC', 'DFFNCE',
'DFFNE', 'DFFNP', 'DFFNPE', 'DFFNR', 'DFFNRE', 'DFFNS', 'DFFNSE',
'DFFP', 'DFFPE', 'DFFR', 'DFFRE', 'DFFS', 'DFFSE', 'DP', 'DPX9',
'ELVDS_OBUF', 'GND', 'GSR', 'IBUF', 'IDDR', 'IDDRC', 'IDES10',
'IDES16', 'IDES4', 'IDES8', 'IOBUF', 'IVIDEO', 'LUT1', 'LUT2',
'LUT3', 'LUT4', 'MUX2', 'MUX2_LUT5', 'MUX2_LUT6', 'MUX2_LUT7',
'MUX2_LUT8', 'OBUF', 'ODDR', 'ODDRC', 'OSC', 'OSCF', 'OSCH',
'OSCO', 'OSCW', 'OSCZ', 'OSER10', 'OSER16', 'OSER10', 'OSER4',
'OSER8', 'OVIDEO', 'PLLVR', 'RAM16S1', 'RAM16S2', 'RAM16S4',
'RAM16SDP1', 'RAM16SDP2', 'RAM16SDP4', 'rPLL', 'SDP',
'SDPX9', 'SP', 'SPX9', 'TBUF', 'TLVDS_OBUF', 'VCC', 'DCS', 'EMCU',
# These are not planned for implementation
'MUX2_MUX8', 'MUX2_MUX16', 'MUX2_MUX32', 'MUX4', 'MUX8', 'MUX16',
'MUX32', 'DL', 'DLE', 'DLC', 'DLCE', 'DLP', 'DLPE', 'DLN', 'DLNE',
'DLNC', 'DLNCE', 'DLNP', 'DLNPE', 'rSDP', 'rSDPX9', 'rROM', 'rROMX9',
'TLVDS_OEN_BK', 'DLL', 'DCC', 'I3C', 'IODELAYA', 'IODELAYC', 'IODELAYB',
'SPMI', 'PLLO', 'DCCG', 'MIPI_DPHY_RX', 'CLKDIVG', 'PWRGRD', 'FLASH96KA',
}
def xtract_cells_decl(dir, fout):
fname = os.path.join(dir, 'prim_sim.v')
with open(fname) as f:
state = State.OUTSIDE
for l in f:
l, _, comment = l.partition('//')
if l.startswith("module "):
cell_name = l[7:l.find('(')].strip()
if cell_name not in _skip:
state = State.IN_MODULE
fout.write(f'\nmodule {cell_name} (...);\n')
elif l.startswith(('input', 'output', 'inout')) and state == State.IN_MODULE:
fout.write(l)
if l[-1] != '\n':
fout.write('\n')
elif l.startswith('parameter') and state == State.IN_MODULE:
fout.write(l)
if l.rstrip()[-1] == ',':
state = State.IN_PARAMETER
if l[-1] != '\n':
fout.write('\n')
elif state == State.IN_PARAMETER:
fout.write(l)
if l.rstrip()[-1] == ';':
state = State.IN_MODULE
if l[-1] != '\n':
fout.write('\n')
elif l.startswith('endmodule') and state == State.IN_MODULE:
state = State.OUTSIDE
fout.write('endmodule\n')
if l[-1] != '\n':
fout.write('\n')
if __name__ == '__main__':
parser = ArgumentParser(description='Extract Gowin blackbox cell definitions.')
parser.add_argument('gowin_dir', nargs='?', default='/opt/gowin/')
args = parser.parse_args()
2024-11-26 15:42:22 +01:00
families = {
'gw1n': os.path.join(args.gowin_dir, 'IDE/simlib/gw1n/'),
'gw2a': os.path.join(args.gowin_dir, 'IDE/simlib/gw2a/'),
'gw5a': os.path.join(args.gowin_dir, 'IDE/simlib/gw5a/'),
}
2024-11-26 15:42:22 +01:00
for family, dir in families.items():
if not os.path.isdir(dir):
print(f'{dir} is not a directory')
else:
with open(f'cells_xtra_{family}.v', 'w') as fout:
fout.write('// Created by cells_xtra.py\n')
fout.write('\n')
xtract_cells_decl(dir, fout)