mirror of https://github.com/openXC7/prjxray.git
Merge pull request #690 from litghost/iob_sing
IOB_SING solution via segbit aliases.
This commit is contained in:
commit
7a57020ce9
|
|
@ -245,6 +245,78 @@ def propagate_rebuf(database, tiles_by_grid):
|
||||||
database[rebuf_above]['bits']['CLB_IO_CLK']['words'] = 4
|
database[rebuf_above]['bits']['CLB_IO_CLK']['words'] = 4
|
||||||
|
|
||||||
|
|
||||||
|
def propagate_IOB_SING(database, tiles_by_grid):
|
||||||
|
""" The IOB_SING are half tiles at top and bottom of every IO column.
|
||||||
|
|
||||||
|
Unlike most tiles, they do not behave consistently. The tile at the top
|
||||||
|
of the column is the bottom half of a full IOB, and the tile at the bottom
|
||||||
|
of the column is the top half of a full IOB. For this reason, explicit
|
||||||
|
bit aliasing is used to map the full IOB bits into the two halves, and a
|
||||||
|
mapping is provided for the site naming.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
seen_iobs = set()
|
||||||
|
for tile in database:
|
||||||
|
if tile in seen_iobs:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if database[tile]["type"] not in ["LIOB33", "RIOB33"]:
|
||||||
|
continue
|
||||||
|
|
||||||
|
while True:
|
||||||
|
prev_tile = tile
|
||||||
|
tile = tiles_by_grid[(
|
||||||
|
database[tile]['grid_x'], database[tile]['grid_y'] + 1)]
|
||||||
|
if '_SING' in database[tile]['type']:
|
||||||
|
break
|
||||||
|
|
||||||
|
bottom_tile = tile
|
||||||
|
seen_iobs.add(bottom_tile)
|
||||||
|
|
||||||
|
bits = database[prev_tile]['bits']['CLB_IO_CLK']
|
||||||
|
|
||||||
|
while True:
|
||||||
|
tile = tiles_by_grid[(
|
||||||
|
database[tile]['grid_x'], database[tile]['grid_y'] - 1)]
|
||||||
|
seen_iobs.add(tile)
|
||||||
|
|
||||||
|
if '_SING' in database[tile]['type']:
|
||||||
|
break
|
||||||
|
|
||||||
|
if 'CLB_IO_CLK' in database[tile]['bits']:
|
||||||
|
assert bits['baseaddr'] == database[tile]['bits'][
|
||||||
|
'CLB_IO_CLK']['baseaddr']
|
||||||
|
assert bits['frames'] == database[tile]['bits']['CLB_IO_CLK'][
|
||||||
|
'frames']
|
||||||
|
assert bits['words'] == database[tile]['bits']['CLB_IO_CLK'][
|
||||||
|
'words']
|
||||||
|
|
||||||
|
top_tile = tile
|
||||||
|
|
||||||
|
database[top_tile]['bits']['CLB_IO_CLK'] = copy.deepcopy(bits)
|
||||||
|
database[top_tile]['bits']['CLB_IO_CLK']['words'] = 2
|
||||||
|
database[top_tile]['bits']['CLB_IO_CLK']['offset'] = 99
|
||||||
|
database[top_tile]['bits']['CLB_IO_CLK']['alias'] = {
|
||||||
|
'type': database[prev_tile]['type'],
|
||||||
|
'start_offset': 0,
|
||||||
|
'sites': {
|
||||||
|
'IOB33_Y0': 'IOB33_Y1',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
database[bottom_tile]['bits']['CLB_IO_CLK'] = copy.deepcopy(bits)
|
||||||
|
database[bottom_tile]['bits']['CLB_IO_CLK']['words'] = 2
|
||||||
|
database[bottom_tile]['bits']['CLB_IO_CLK']['offset'] = 0
|
||||||
|
database[bottom_tile]['bits']['CLB_IO_CLK']['alias'] = {
|
||||||
|
'type': database[prev_tile]['type'],
|
||||||
|
'start_offset': 2,
|
||||||
|
'sites': {
|
||||||
|
'IOB33_Y0': 'IOB33_Y0',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def run(json_in_fn, json_out_fn, verbose=False):
|
def run(json_in_fn, json_out_fn, verbose=False):
|
||||||
# Load input files
|
# Load input files
|
||||||
database = json.load(open(json_in_fn, "r"))
|
database = json.load(open(json_in_fn, "r"))
|
||||||
|
|
@ -253,6 +325,7 @@ def run(json_in_fn, json_out_fn, verbose=False):
|
||||||
propagate_INT_lr_bits(database, tiles_by_grid, verbose=verbose)
|
propagate_INT_lr_bits(database, tiles_by_grid, verbose=verbose)
|
||||||
propagate_INT_bits_in_column(database, tiles_by_grid)
|
propagate_INT_bits_in_column(database, tiles_by_grid)
|
||||||
propagate_rebuf(database, tiles_by_grid)
|
propagate_rebuf(database, tiles_by_grid)
|
||||||
|
propagate_IOB_SING(database, tiles_by_grid)
|
||||||
|
|
||||||
# Save
|
# Save
|
||||||
xjson.pprint(open(json_out_fn, "w"), database)
|
xjson.pprint(open(json_out_fn, "w"), database)
|
||||||
|
|
|
||||||
|
|
@ -114,7 +114,7 @@ class Database(object):
|
||||||
def grid(self):
|
def grid(self):
|
||||||
""" Return Grid object for database. """
|
""" Return Grid object for database. """
|
||||||
self._read_tilegrid()
|
self._read_tilegrid()
|
||||||
return grid.Grid(self.tilegrid)
|
return grid.Grid(self, self.tilegrid)
|
||||||
|
|
||||||
def _read_tile_types(self):
|
def _read_tile_types(self):
|
||||||
for tile_type, db in self.tile_types.items():
|
for tile_type, db in self.tile_types.items():
|
||||||
|
|
|
||||||
|
|
@ -98,26 +98,18 @@ class FasmAssembler(object):
|
||||||
def enable_feature(self, tile, feature, address, line):
|
def enable_feature(self, tile, feature, address, line):
|
||||||
gridinfo = self.grid.gridinfo_at_tilename(tile)
|
gridinfo = self.grid.gridinfo_at_tilename(tile)
|
||||||
|
|
||||||
def update_segbit(block_type, bit):
|
def update_segbit(bit):
|
||||||
'''Set or clear a single bit in a segment at the given word column and word bit position'''
|
'''Set or clear a single bit in a segment at the given word column and word bit position'''
|
||||||
|
|
||||||
bits = gridinfo.bits[block_type]
|
frame_addr = bit.word_column
|
||||||
|
word_addr = bit.word_bit // bitstream.WORD_SIZE_BITS
|
||||||
seg_baseaddr = bits.base_address
|
|
||||||
seg_word_base = bits.offset
|
|
||||||
|
|
||||||
# Now we have the word column and word bit index
|
|
||||||
# Combine with the segments relative frame position to fully get the position
|
|
||||||
frame_addr = seg_baseaddr + bit.word_column
|
|
||||||
# 2 words per segment
|
|
||||||
word_addr = seg_word_base + bit.word_bit // bitstream.WORD_SIZE_BITS
|
|
||||||
bit_index = bit.word_bit % bitstream.WORD_SIZE_BITS
|
bit_index = bit.word_bit % bitstream.WORD_SIZE_BITS
|
||||||
if bit.isset:
|
if bit.isset:
|
||||||
self.frame_set(frame_addr, word_addr, bit_index, line)
|
self.frame_set(frame_addr, word_addr, bit_index, line)
|
||||||
else:
|
else:
|
||||||
self.frame_clear(frame_addr, word_addr, bit_index, line)
|
self.frame_clear(frame_addr, word_addr, bit_index, line)
|
||||||
|
|
||||||
segbits = self.db.get_tile_segbits(gridinfo.tile_type)
|
segbits = self.grid.get_tile_segbits_at_tilename(tile)
|
||||||
|
|
||||||
self.seen_tile.add(tile)
|
self.seen_tile.add(tile)
|
||||||
|
|
||||||
|
|
@ -126,9 +118,10 @@ class FasmAssembler(object):
|
||||||
any_bits = set()
|
any_bits = set()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
for block_type, bit in segbits.feature_to_bits(db_k, address):
|
for block_type, bit in segbits.feature_to_bits(gridinfo.bits, db_k,
|
||||||
|
address):
|
||||||
any_bits.add(block_type)
|
any_bits.add(block_type)
|
||||||
update_segbit(block_type, bit)
|
update_segbit(bit)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise FasmLookupError(
|
raise FasmLookupError(
|
||||||
"Segment DB %s, key %s not found from line '%s'" %
|
"Segment DB %s, key %s not found from line '%s'" %
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ class FasmDisassembler(object):
|
||||||
gridinfo = self.grid.gridinfo_at_tilename(tile_name)
|
gridinfo = self.grid.gridinfo_at_tilename(tile_name)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
tile_segbits = self.db.get_tile_segbits(gridinfo.tile_type)
|
tile_segbits = self.grid.get_tile_segbits_at_tilename(tile_name)
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
if not verbose:
|
if not verbose:
|
||||||
return
|
return
|
||||||
|
|
@ -163,3 +163,19 @@ class FasmDisassembler(object):
|
||||||
annotations=tuple(annotations),
|
annotations=tuple(annotations),
|
||||||
comment=None,
|
comment=None,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def is_zero_feature(self, feature):
|
||||||
|
parts = feature.split('.')
|
||||||
|
tile = parts[0]
|
||||||
|
gridinfo = self.grid.gridinfo_at_tilename(tile)
|
||||||
|
feature = '.'.join(parts[1:])
|
||||||
|
|
||||||
|
db_k = '%s.%s' % (gridinfo.tile_type, feature)
|
||||||
|
segbits = self.grid.get_tile_segbits_at_tilename(tile)
|
||||||
|
any_bits = False
|
||||||
|
for block_type, bit in segbits.feature_to_bits(gridinfo.bits, db_k):
|
||||||
|
if bit.isset:
|
||||||
|
any_bits = True
|
||||||
|
break
|
||||||
|
|
||||||
|
return not any_bits
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,6 @@
|
||||||
from collections import namedtuple
|
|
||||||
import enum
|
|
||||||
from prjxray import segment_map
|
from prjxray import segment_map
|
||||||
|
from prjxray.grid_types import BlockType, GridLoc, GridInfo, BitAlias, Bits, BitsInfo
|
||||||
|
from prjxray.tile_segbits_alias import TileSegbitsAlias
|
||||||
class BlockType(enum.Enum):
|
|
||||||
# Frames describing CLB features, interconnect, clocks and IOs.
|
|
||||||
CLB_IO_CLK = 'CLB_IO_CLK'
|
|
||||||
|
|
||||||
# Frames describing block RAM initialization.
|
|
||||||
BLOCK_RAM = 'BLOCK_RAM'
|
|
||||||
|
|
||||||
|
|
||||||
GridLoc = namedtuple('GridLoc', 'grid_x grid_y')
|
|
||||||
GridInfo = namedtuple('GridInfo', 'bits sites tile_type')
|
|
||||||
Bits = namedtuple('Bits', 'base_address frames offset words')
|
|
||||||
BitsInfo = namedtuple('BitsInfo', 'block_type tile bits')
|
|
||||||
|
|
||||||
|
|
||||||
class Grid(object):
|
class Grid(object):
|
||||||
|
|
@ -24,7 +10,8 @@ class Grid(object):
|
||||||
of segment offsets for particular grid locations and their tile types.
|
of segment offsets for particular grid locations and their tile types.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, tilegrid):
|
def __init__(self, db, tilegrid):
|
||||||
|
self.db = db
|
||||||
self.tilegrid = tilegrid
|
self.tilegrid = tilegrid
|
||||||
self.loc = {}
|
self.loc = {}
|
||||||
self.tileinfo = {}
|
self.tileinfo = {}
|
||||||
|
|
@ -41,11 +28,22 @@ class Grid(object):
|
||||||
for k in tileinfo['bits']:
|
for k in tileinfo['bits']:
|
||||||
segment_type = BlockType(k)
|
segment_type = BlockType(k)
|
||||||
base_address = int(tileinfo['bits'][k]['baseaddr'], 0)
|
base_address = int(tileinfo['bits'][k]['baseaddr'], 0)
|
||||||
|
|
||||||
|
alias = None
|
||||||
|
if 'alias' in tileinfo['bits'][k]:
|
||||||
|
alias = BitAlias(
|
||||||
|
tile_type=tileinfo['bits'][k]['alias']['type'],
|
||||||
|
start_offset=tileinfo['bits'][k]['alias']
|
||||||
|
['start_offset'],
|
||||||
|
sites=tileinfo['bits'][k]['alias']['sites'],
|
||||||
|
)
|
||||||
|
|
||||||
bits[segment_type] = Bits(
|
bits[segment_type] = Bits(
|
||||||
base_address=base_address,
|
base_address=base_address,
|
||||||
frames=tileinfo['bits'][k]['frames'],
|
frames=tileinfo['bits'][k]['frames'],
|
||||||
offset=tileinfo['bits'][k]['offset'],
|
offset=tileinfo['bits'][k]['offset'],
|
||||||
words=tileinfo['bits'][k]['words'],
|
words=tileinfo['bits'][k]['words'],
|
||||||
|
alias=alias,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.tileinfo[tile] = GridInfo(
|
self.tileinfo[tile] = GridInfo(
|
||||||
|
|
@ -103,3 +101,17 @@ class Grid(object):
|
||||||
tile_type = gridinfo.tile_type
|
tile_type = gridinfo.tile_type
|
||||||
|
|
||||||
return (tile_type, loc.grid_x, -loc.grid_y)
|
return (tile_type, loc.grid_x, -loc.grid_y)
|
||||||
|
|
||||||
|
def get_tile_segbits_at_tilename(self, tilename):
|
||||||
|
gridinfo = self.gridinfo_at_tilename(tilename)
|
||||||
|
|
||||||
|
# Check to see if alias is present
|
||||||
|
any_alias = False
|
||||||
|
for block_type, bits in gridinfo.bits.items():
|
||||||
|
if bits.alias is not None:
|
||||||
|
any_alias = True
|
||||||
|
|
||||||
|
if any_alias:
|
||||||
|
return TileSegbitsAlias(self.db, gridinfo.tile_type, gridinfo.bits)
|
||||||
|
else:
|
||||||
|
return self.db.get_tile_segbits(gridinfo.tile_type)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
from collections import namedtuple
|
||||||
|
import enum
|
||||||
|
|
||||||
|
|
||||||
|
class BlockType(enum.Enum):
|
||||||
|
# Frames describing CLB features, interconnect, clocks and IOs.
|
||||||
|
CLB_IO_CLK = 'CLB_IO_CLK'
|
||||||
|
|
||||||
|
# Frames describing block RAM initialization.
|
||||||
|
BLOCK_RAM = 'BLOCK_RAM'
|
||||||
|
|
||||||
|
|
||||||
|
GridLoc = namedtuple('GridLoc', 'grid_x grid_y')
|
||||||
|
GridInfo = namedtuple('GridInfo', 'bits sites tile_type')
|
||||||
|
BitAlias = namedtuple('BitAlias', 'tile_type start_offset sites')
|
||||||
|
Bits = namedtuple('Bits', 'base_address frames offset words alias')
|
||||||
|
BitsInfo = namedtuple('BitsInfo', 'block_type tile bits')
|
||||||
|
|
@ -99,7 +99,7 @@ class TileSegbits(object):
|
||||||
self.feature_addresses[base_feature][int(
|
self.feature_addresses[base_feature][int(
|
||||||
feature[sidx + 1:eidx])] = (block_type, feature)
|
feature[sidx + 1:eidx])] = (block_type, feature)
|
||||||
|
|
||||||
def match_bitdata(self, block_type, bits, bitdata):
|
def match_bitdata(self, block_type, bits, bitdata, match_filter=None):
|
||||||
""" Return matching features for tile bits data (grid.Bits) and bitdata.
|
""" Return matching features for tile bits data (grid.Bits) and bitdata.
|
||||||
|
|
||||||
See bitstream.load_bitdata for details on bitdata structure.
|
See bitstream.load_bitdata for details on bitdata structure.
|
||||||
|
|
@ -111,7 +111,13 @@ class TileSegbits(object):
|
||||||
|
|
||||||
for feature, segbit in self.segbits[block_type].items():
|
for feature, segbit in self.segbits[block_type].items():
|
||||||
match = True
|
match = True
|
||||||
|
skip = False
|
||||||
for query_bit in segbit:
|
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
|
frame = bits.base_address + query_bit.word_column
|
||||||
bitidx = bits.offset * bitstream.WORD_SIZE_BITS + query_bit.word_bit
|
bitidx = bits.offset * bitstream.WORD_SIZE_BITS + query_bit.word_bit
|
||||||
|
|
||||||
|
|
@ -128,7 +134,7 @@ class TileSegbits(object):
|
||||||
if not match:
|
if not match:
|
||||||
break
|
break
|
||||||
|
|
||||||
if not match:
|
if not match or skip:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
def inner():
|
def inner():
|
||||||
|
|
@ -140,16 +146,26 @@ class TileSegbits(object):
|
||||||
|
|
||||||
yield (tuple(inner()), feature)
|
yield (tuple(inner()), feature)
|
||||||
|
|
||||||
def feature_to_bits(self, feature, address=0):
|
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:
|
if feature in self.ppips:
|
||||||
return
|
return
|
||||||
|
|
||||||
for block_type in self.segbits:
|
for block_type in self.segbits:
|
||||||
if address == 0 and feature in self.segbits[block_type]:
|
if address == 0 and feature in self.segbits[block_type]:
|
||||||
for bit in self.segbits[block_type][feature]:
|
for bit in self.segbits[block_type][feature]:
|
||||||
yield block_type, bit
|
yield block_type, self.map_bit_to_frame(
|
||||||
|
block_type, bits_map[block_type], bit)
|
||||||
return
|
return
|
||||||
|
|
||||||
block_type, feature = self.feature_addresses[feature][address]
|
block_type, feature = self.feature_addresses[feature][address]
|
||||||
for bit in self.segbits[block_type][feature]:
|
for bit in self.segbits[block_type][feature]:
|
||||||
yield block_type, bit
|
yield block_type, self.map_bit_to_frame(
|
||||||
|
block_type, bits_map[block_type], bit)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,106 @@
|
||||||
|
""" TileSegbitsAlias provides an alias from one tile type to another.
|
||||||
|
|
||||||
|
TileSegbitsAlias performs severals functions to achieve the alias:
|
||||||
|
- Remaps tile type from the original tile type to the alias tile type
|
||||||
|
- Offsets the bits from the original to the alias type
|
||||||
|
- Renames sites from the original to the alias type
|
||||||
|
- Filters bits outside of the alias.
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
from prjxray import bitstream
|
||||||
|
from prjxray.grid_types import Bits
|
||||||
|
|
||||||
|
|
||||||
|
class TileSegbitsAlias(object):
|
||||||
|
def __init__(self, db, tile_type, bits_map):
|
||||||
|
# Name of tile_type that is using the alias
|
||||||
|
self.tile_type = tile_type
|
||||||
|
|
||||||
|
# Name of aliased tile_type
|
||||||
|
self.alias_tile_type = None
|
||||||
|
|
||||||
|
# BlockType -> BitAlias map
|
||||||
|
self.alias = {}
|
||||||
|
|
||||||
|
self.bits_map = bits_map
|
||||||
|
|
||||||
|
# BlockType -> aliased Bits map
|
||||||
|
self.alias_bits_map = {}
|
||||||
|
|
||||||
|
# aliased site name to site name map
|
||||||
|
self.sites_rev_map = {}
|
||||||
|
|
||||||
|
for block_type in bits_map:
|
||||||
|
self.alias[block_type] = bits_map[block_type].alias
|
||||||
|
self.alias_bits_map[block_type] = Bits(
|
||||||
|
base_address=bits_map[block_type].base_address,
|
||||||
|
frames=bits_map[block_type].frames,
|
||||||
|
offset=bits_map[block_type].offset -
|
||||||
|
self.alias[block_type].start_offset,
|
||||||
|
words=bits_map[block_type].words,
|
||||||
|
alias=None,
|
||||||
|
)
|
||||||
|
|
||||||
|
if self.alias_tile_type is None:
|
||||||
|
self.alias_tile_type = self.alias[block_type].tile_type
|
||||||
|
else:
|
||||||
|
assert self.alias_tile_type == self.alias[block_type].tile_type
|
||||||
|
|
||||||
|
self.sites_rev_map[block_type] = {}
|
||||||
|
for site, alias_site in self.alias[block_type].sites.items():
|
||||||
|
assert alias_site not in self.sites_rev_map[block_type]
|
||||||
|
self.sites_rev_map[block_type][alias_site] = site
|
||||||
|
|
||||||
|
self.tile_segbits = db.get_tile_segbits(self.alias_tile_type)
|
||||||
|
|
||||||
|
def map_feature_to_segbits(self, feature):
|
||||||
|
""" Map from the output feature name to the aliased feature name. """
|
||||||
|
parts = feature.split('.')
|
||||||
|
|
||||||
|
assert parts[0] == self.tile_type
|
||||||
|
parts[0] = self.alias_tile_type
|
||||||
|
|
||||||
|
for block_type in self.alias:
|
||||||
|
if len(parts) > 1 and parts[1] in self.alias[block_type].sites:
|
||||||
|
parts[1] = self.alias[block_type].sites[parts[1]]
|
||||||
|
|
||||||
|
return '.'.join(parts)
|
||||||
|
|
||||||
|
def map_feature_from_segbits(self, feature):
|
||||||
|
""" Map from the aliases feature name to the output feature name. """
|
||||||
|
parts = feature.split('.')
|
||||||
|
|
||||||
|
assert parts[0] == self.alias_tile_type
|
||||||
|
parts[0] = self.tile_type
|
||||||
|
|
||||||
|
for block_type in self.alias:
|
||||||
|
if len(parts) > 1 and parts[1] in self.sites_rev_map[block_type]:
|
||||||
|
parts[1] = self.sites_rev_map[block_type][parts[1]]
|
||||||
|
|
||||||
|
return '.'.join(parts)
|
||||||
|
|
||||||
|
def match_filter(self, block_type, query_bit):
|
||||||
|
word = query_bit.word_bit // bitstream.WORD_SIZE_BITS
|
||||||
|
real_word = word - self.alias[block_type].start_offset
|
||||||
|
if real_word < 0 or real_word >= self.bits_map[block_type].words:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def match_bitdata(self, block_type, bits, bitdata):
|
||||||
|
alias_bits = self.alias_bits_map[block_type]
|
||||||
|
|
||||||
|
for bits_found, alias_feature in self.tile_segbits.match_bitdata(
|
||||||
|
block_type, alias_bits, bitdata,
|
||||||
|
match_filter=self.match_filter):
|
||||||
|
feature = self.map_feature_from_segbits(alias_feature)
|
||||||
|
|
||||||
|
yield (bits_found, feature)
|
||||||
|
|
||||||
|
def feature_to_bits(self, bits_map, feature, address=0):
|
||||||
|
alias_feature = self.map_feature_to_segbits(feature)
|
||||||
|
for block_type, bit in self.tile_segbits.feature_to_bits(
|
||||||
|
self.alias_bits_map, alias_feature, address):
|
||||||
|
yield block_type, bit
|
||||||
|
|
@ -35,24 +35,9 @@ def bits_to_fasm(db_root, bits_file, verbose, canonical):
|
||||||
with open(bits_file) as f:
|
with open(bits_file) as f:
|
||||||
bitdata = bitstream.load_bitdata(f)
|
bitdata = bitstream.load_bitdata(f)
|
||||||
|
|
||||||
def is_zero_feature(feature):
|
|
||||||
parts = feature.split('.')
|
|
||||||
tile = parts[0]
|
|
||||||
gridinfo = grid.gridinfo_at_tilename(tile)
|
|
||||||
feature = '.'.join(parts[1:])
|
|
||||||
|
|
||||||
db_k = '%s.%s' % (gridinfo.tile_type, feature)
|
|
||||||
segbits = db.get_tile_segbits(gridinfo.tile_type)
|
|
||||||
any_bits = False
|
|
||||||
for block_type, bit in segbits.feature_to_bits(db_k):
|
|
||||||
if bit.isset:
|
|
||||||
any_bits = True
|
|
||||||
|
|
||||||
return not any_bits
|
|
||||||
|
|
||||||
model = fasm.output.merge_and_sort(
|
model = fasm.output.merge_and_sort(
|
||||||
disassembler.find_features_in_bitstream(bitdata, verbose=verbose),
|
disassembler.find_features_in_bitstream(bitdata, verbose=verbose),
|
||||||
zero_function=is_zero_feature,
|
zero_function=disassembler.is_zero_feature,
|
||||||
sort_key=grid.tile_key,
|
sort_key=grid.tile_key,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue