mirror of https://github.com/openXC7/prjxray.git
145 lines
3.8 KiB
Python
145 lines
3.8 KiB
Python
""" IOB bits are more complicated than can be easily expressed to segmaker.
|
|
|
|
There are couple cases that need to be handled here:
|
|
|
|
- There are some bits that are always set for IN-only ports, but are cleared
|
|
selectively for OUT and INOUT ports.
|
|
- There are bits per each IOSTANDARD, in addition to drive patterns. These
|
|
can be merged to provide unique "(IOSTANDARD, DRIVE)" bit sets.
|
|
"""
|
|
import argparse
|
|
|
|
|
|
def get_name(l):
|
|
parts = l.strip().split(' ')
|
|
return parts[0]
|
|
|
|
|
|
def get_site(l):
|
|
return get_name(l).split('.')[1]
|
|
|
|
|
|
def parse_bits(l):
|
|
parts = l.strip().split(' ')
|
|
if parts[1] == '<0':
|
|
return frozenset()
|
|
else:
|
|
return frozenset(parts[1:])
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(
|
|
description="Convert IOB rdb into good rdb."
|
|
"")
|
|
parser.add_argument('input_rdb')
|
|
|
|
args = parser.parse_args()
|
|
|
|
iostandard_lines = []
|
|
with open(args.input_rdb) as f:
|
|
for l in f:
|
|
if '.LVCMOS' in l or '.LVTTL' in l:
|
|
iostandard_lines.append(l)
|
|
else:
|
|
print(l.strip())
|
|
|
|
common_in_bits = {
|
|
'IOB_Y0': set(),
|
|
'IOB_Y1': set(),
|
|
}
|
|
for l in iostandard_lines:
|
|
if 'IN_OUT_COMMON' in l:
|
|
common_in_bits[get_site(l)] |= parse_bits(l)
|
|
|
|
for site in sorted(common_in_bits):
|
|
print('IOB33.{}.IN_ONLY'.format(site), ' '.join(common_in_bits[site]))
|
|
|
|
iostandard_in = {}
|
|
outs = {}
|
|
drives = {}
|
|
in_use = {}
|
|
|
|
for l in iostandard_lines:
|
|
name = get_name(l)
|
|
site = get_site(l)
|
|
iostandard = name.split('.')[2]
|
|
|
|
if name.endswith('.IN_USE'):
|
|
in_use[(site, iostandard)] = parse_bits(l)
|
|
|
|
for l in iostandard_lines:
|
|
name = get_name(l)
|
|
site = get_site(l)
|
|
iostandard = name.split('.')[2]
|
|
|
|
if name.endswith('.IN'):
|
|
in_bits = parse_bits(l) | in_use[(site, iostandard)]
|
|
|
|
if in_bits not in iostandard_in:
|
|
iostandard_in[in_bits] = []
|
|
|
|
iostandard_in[in_bits].append((site, iostandard))
|
|
|
|
if name.endswith('.OUT'):
|
|
outs[(site,
|
|
iostandard)] = parse_bits(l) | in_use[(site, iostandard)]
|
|
|
|
if '.DRIVE.' in name and '.IN_OUT_COMMON' not in name:
|
|
drive = name.split('.')[-1]
|
|
if (site, iostandard) not in drives:
|
|
drives[(site, iostandard)] = {}
|
|
|
|
if drive not in drives[(site, iostandard)]:
|
|
drives[(site, iostandard)][drive] = {}
|
|
|
|
drives[(site, iostandard)][drive] = parse_bits(l)
|
|
|
|
for bits in sorted(iostandard_in.keys()):
|
|
sites, standards = zip(*iostandard_in[bits])
|
|
|
|
site = set(sites)
|
|
|
|
assert len(site) == 1, site
|
|
site = site.pop()
|
|
|
|
print(
|
|
'IOB33.{}.{}.IN'.format(site, '_'.join(standards)), ' '.join(bits))
|
|
|
|
iodrives = {}
|
|
|
|
common_bits = {}
|
|
|
|
for site, iostandard in drives:
|
|
for drive in drives[(site, iostandard)]:
|
|
combined_bits = drives[(site, iostandard)][drive] | outs[(
|
|
site, iostandard)]
|
|
|
|
if site not in common_bits:
|
|
common_bits[site] = set(common_in_bits[site])
|
|
|
|
common_bits[site] |= combined_bits
|
|
|
|
if combined_bits not in iodrives:
|
|
iodrives[combined_bits] = []
|
|
|
|
iodrives[combined_bits].append((site, iostandard, drive))
|
|
|
|
for bits in iodrives:
|
|
sites, standards, drives = zip(*iodrives[bits])
|
|
|
|
site = set(sites)
|
|
|
|
assert len(site) == 1, site
|
|
site = site.pop()
|
|
|
|
neg_bits = set('!' + bit for bit in (common_bits[site] - bits))
|
|
|
|
print(
|
|
'IOB33.{}.{}.DRIVE.{}'.format(
|
|
site, '_'.join(sorted(set(standards))), '_'.join(
|
|
sorted(set(drives)))), ' '.join(bits | neg_bits))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|