3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-09-30 13:19:05 +00:00
yosys/techlibs/gowin/cells_xtra.py
YRabbit d60dc93e92 Gowin. Renaming inputs of the DCS primitive.
The dynamic clock selection (DCS) primitive has undergone changes with
the release of the GW5A series—the CLK0,1,2,3 inputs are now
CLKIN0,1,2,3, but only for GW5A series chips.

There are no functional changes, only renaming.

Here we are transferring the description of the DCS primitive from
general to specialized files for each chip series.

We have also fixed a bug in the generation script that caused the loss
of primitive parameters. Fortunately, this only affected the
analog-to-digital converter, which has not yet been implemented.

Signed-off-by: YRabbit <rabbit@yrabbit.cyou>
2025-09-20 16:22:23 +01:00

96 lines
4 KiB
Python

#!/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_MODULE_MULTILINE = 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', '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')
if l.rstrip()[-1] != ';':
state = State.IN_MODULE_MULTILINE
elif l.lstrip().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 l and state == State.IN_MODULE_MULTILINE:
fout.write(l)
if l[-1] != '\n':
fout.write('\n')
if l.rstrip()[-1] == ';':
state = State.IN_MODULE
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()
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/'),
}
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)