Skip to content

Commit

Permalink
Add exact_table_cover and parse_tile_exact functions for more specifi…
Browse files Browse the repository at this point in the history
…c tile parsing (#237)
  • Loading branch information
Seyviour authored Mar 27, 2024
1 parent 19a2aab commit 6d8b806
Showing 1 changed file with 61 additions and 0 deletions.
61 changes: 61 additions & 0 deletions apycula/fuse_h4x.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,67 @@ def parse_tile(d, ttyp, tile):

return res

def parse_tile_exact(d, ttyp, tile, fuse_loc=True):
w = d[ttyp]['width']
h = d[ttyp]['height']
res = {}
for start, table in [(2, 'shortval'), (2, 'wire'), (16, 'longval'),
(1, 'longfuse'), (0, 'const')]:
if table in d[ttyp]: # skip missing entries
for subtyp, tablerows in d[ttyp][table].items():
pos_items, neg_items = {}, {}
active_rows = []
for row in tablerows:
if row[0] > 0:
row_fuses = [fuse for fuse in row[start:] if fuse >= 0]
locs = [fuse_lookup(d,ttyp, fuse) for fuse in row_fuses]
test = [tile[loc[0]][loc[1]] == 1 for loc in locs]
if all(test):
full_row = row[:start]
full_row.extend(row_fuses)
active_rows.append(full_row)

# report fuse locations
if (active_rows):
exact_cover = exact_table_cover(active_rows, start, table)
if fuse_loc:
for cover_row in exact_cover:
cover_row[start:] = [fuse_lookup(d, ttyp, fuse) for fuse in cover_row[start:]]

res.setdefault(table, {})[subtyp] = exact_cover
return res


def exact_table_cover(t_rows, start, table=None):
try:
import xcover
except:
raise ModuleNotFoundError ("The xcover package needs to be installed to use the exact_cover function.\
\nYou may install it via pip: `pip install xcover`")

row_fuses = [set ([fuse for fuse in row[start:] if fuse!=-1]) for row in t_rows]
primary = set()
for row in row_fuses:
primary.update(row)
secondary = set()

# Enforce that every destination node has a single source
if table == 'wire':
for id, row in enumerate(t_rows):
# Casting the wire_id to a string ensures that it doesn't conflict with fuse_ids
row_fuses[id].add(str(row[1]))
secondary.add(str(row[1]))

g = xcover.covers(row_fuses, primary=primary, secondary=secondary, colored=False)
if g:
for r in g:
#g is an iterator, so this is just a hack to return the first solution.
#A future commit might introduce a heuristic for determining what solution is most plausible
#where there are multiple solutions
return [t_rows[idx] for idx in r]
else:
return []

def scan_fuses(d, ttyp, tile):
w = d[ttyp]['width']
h = d[ttyp]['height']
Expand Down

0 comments on commit 6d8b806

Please sign in to comment.