mirror of https://github.com/openXC7/prjxray.git
143 lines
3.6 KiB
Python
143 lines
3.6 KiB
Python
from collections import namedtuple
|
|
from prjxray import bitstream
|
|
import enum
|
|
|
|
|
|
class PsuedoPipType(enum.Enum):
|
|
ALWAYS = 'always'
|
|
DEFAULT = 'default'
|
|
HINT = 'hint'
|
|
|
|
|
|
def read_ppips(f):
|
|
ppips = {}
|
|
|
|
for l in f:
|
|
l = l.strip()
|
|
if not l:
|
|
continue
|
|
|
|
feature, ppip_type = l.split(' ')
|
|
|
|
ppips[feature] = PsuedoPipType(ppip_type)
|
|
|
|
return ppips
|
|
|
|
|
|
Bit = namedtuple('Bit', 'word_column word_bit isset')
|
|
|
|
|
|
def parsebit(val):
|
|
'''Return "!012_23" => (12, 23, False)'''
|
|
isset = True
|
|
# Default is 0. Skip explicit call outs
|
|
if val[0] == '!':
|
|
isset = False
|
|
val = val[1:]
|
|
# 28_05 => 28, 05
|
|
seg_word_column, word_bit_n = val.split('_')
|
|
|
|
return Bit(
|
|
word_column=int(seg_word_column),
|
|
word_bit=int(word_bit_n),
|
|
isset=isset,
|
|
)
|
|
|
|
|
|
def read_segbits(f):
|
|
segbits = {}
|
|
|
|
for l in f:
|
|
# CLBLM_L.SLICEL_X1.ALUT.INIT[10] 29_14
|
|
l = l.strip()
|
|
|
|
if not l:
|
|
continue
|
|
|
|
parts = l.split(' ')
|
|
|
|
assert len(parts) > 1
|
|
|
|
segbits[parts[0]] = [parsebit(val) for val in parts[1:]]
|
|
|
|
return segbits
|
|
|
|
|
|
class TileSegbits(object):
|
|
def __init__(self, tile_db):
|
|
self.segbits = {}
|
|
self.ppips = {}
|
|
self.feature_addresses = {}
|
|
|
|
if tile_db.ppips is not None:
|
|
with open(tile_db.ppips) as f:
|
|
self.ppips = read_ppips(f)
|
|
|
|
if tile_db.segbits is not None:
|
|
with open(tile_db.segbits) as f:
|
|
self.segbits = read_segbits(f)
|
|
|
|
for feature in self.segbits:
|
|
sidx = feature.rfind('[')
|
|
eidx = feature.rfind(']')
|
|
|
|
if sidx != -1:
|
|
assert eidx != -1
|
|
|
|
base_feature = feature[:sidx]
|
|
|
|
if base_feature not in self.feature_addresses:
|
|
self.feature_addresses[base_feature] = {}
|
|
|
|
self.feature_addresses[base_feature][int(
|
|
feature[sidx + 1:eidx])] = feature
|
|
|
|
def match_bitdata(self, bits, bitdata):
|
|
""" Return matching features for tile bits data (grid.Bits) and bitdata.
|
|
|
|
See bitstream.load_bitdata for details on bitdata structure.
|
|
|
|
"""
|
|
|
|
for feature, segbit in self.segbits.items():
|
|
match = True
|
|
for query_bit in segbit:
|
|
frame = bits.base_address + query_bit.word_column
|
|
bitidx = bits.offset * bitstream.WORD_SIZE_BITS + query_bit.word_bit
|
|
|
|
if frame not in bitdata:
|
|
match = not query_bit.isset
|
|
if match:
|
|
continue
|
|
else:
|
|
break
|
|
|
|
found_bit = bitidx in bitdata[frame][1]
|
|
match = found_bit == query_bit.isset
|
|
|
|
if not match:
|
|
break
|
|
|
|
if not match:
|
|
continue
|
|
|
|
def inner():
|
|
for query_bit in segbit:
|
|
if query_bit.isset:
|
|
frame = bits.base_address + query_bit.word_column
|
|
bitidx = bits.offset * bitstream.WORD_SIZE_BITS + query_bit.word_bit
|
|
yield (frame, bitidx)
|
|
|
|
yield (tuple(inner()), feature)
|
|
|
|
def feature_to_bits(self, feature, address=0):
|
|
if feature in self.ppips:
|
|
return
|
|
|
|
if address == 0 and feature in self.segbits:
|
|
for bit in self.segbits[feature]:
|
|
yield bit
|
|
else:
|
|
for bit in self.segbits[self.feature_addresses[feature][address]]:
|
|
yield bit
|