blob: 39e6c0fbb4d39f1b9f1e003ef83885c70c7701bd [file] [log] [blame]
from collections import namedtuple
from utils import bitstream
from utils.grid import BlockType
import enum
import functools
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[BlockType.CLB_IO_CLK] = read_segbits(f)
if tile_db.block_ram_segbits is not None:
with open(tile_db.block_ram_segbits) as f:
self.segbits[BlockType.BLOCK_RAM] = read_segbits(f)
for block_type in self.segbits:
for feature in self.segbits[block_type]:
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])] = (block_type, feature)
def match_bitdata(self, block_type, bits, bitdata, match_filter=None):
""" Return matching features for tile bits data (grid.Bits) and bitdata.
See bitstream.load_bitdata for details on bitdata structure.
"""
if block_type not in self.segbits:
return
for feature, segbit in self.segbits[block_type].items():
match = True
skip = False
for query_bit in segbit:
if match_filter is not None and not match_filter(block_type,
query_bit):
skip = True
break
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 or skip:
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 map_bit_to_frame(self, block_type, bits, bit):
""" Convert bit from segbit to frame data. """
return Bit(
word_column=bits.base_address + bit.word_column,
word_bit=bits.offset * bitstream.WORD_SIZE_BITS + bit.word_bit,
isset=bit.isset,
)
def feature_to_bits(self, bits_map, feature, address=0):
if feature in self.ppips:
return
for block_type in self.segbits:
if address == 0 and feature in self.segbits[block_type]:
for bit in self.segbits[block_type][feature]:
yield block_type, self.map_bit_to_frame(
block_type, bits_map[block_type], bit)
return
block_type, feature = self.feature_addresses[feature][address]
for bit in self.segbits[block_type][feature]:
yield block_type, self.map_bit_to_frame(
block_type, bits_map[block_type], bit)