Skip to content

Commit

Permalink
util/tools: Use the C++ implementation to map tile names to locations.
Browse files Browse the repository at this point in the history
Signed-off-by: William D. Jones <thor0505@comcast.net>
  • Loading branch information
cr1901 committed Nov 12, 2018
1 parent aec0b25 commit cfe647f
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 63 deletions.
22 changes: 11 additions & 11 deletions tools/connectivity.py
Expand Up @@ -24,52 +24,52 @@ def main():
# Returns (source, configurable, loc)
def get_fanin(net):
drivers = []
npos = tiles.pos_from_name(net)
npos = tiles.pos_from_name(net, chip_size, 0)
for tile in c.get_all_tiles():
tinf = tile.info
tname = tinf.name
pos = tiles.pos_from_name(tname)
pos = tiles.pos_from_name(tname, chip_size, 0)
if abs(pos[0] - npos[0]) >= 10 or abs(pos[1] - npos[1]) >= 10:
continue
if net.startswith("G_"):
tnet = net
else:
tnet = nets.normalise_name(chip_size, tname, net)
tnet = nets.normalise_name(chip_size, tname, net, 0)
tdb = pytrellis.get_tile_bitdata(pytrellis.TileLocator(c.info.family, c.info.name, tinf.type))
try:
mux = tdb.get_mux_data_for_sink(tnet)
for src in mux.get_sources():
drivers.append((nets.canonicalise_name(chip_size, tname, src), True, tname))
drivers.append((nets.canonicalise_name(chip_size, tname, src, 0), True, tname))
except IndexError:
pass
for fc in tdb.get_fixed_conns():
if fc.sink == tnet:
drivers.append((nets.canonicalise_name(chip_size, tname, fc.source), False, tname))
drivers.append((nets.canonicalise_name(chip_size, tname, fc.source, 0), False, tname))
return drivers

# Get fan-out of a net
# Returns (dest, configurable, loc)
def get_fanout(net):
drivers = []
npos = tiles.pos_from_name(net)
npos = tiles.pos_from_name(net, chip_size, 0)
for tile in c.get_all_tiles():
tinf = tile.info
tname = tinf.name
pos = tiles.pos_from_name(tname)
pos = tiles.pos_from_name(tname, chip_size, 0)
if abs(pos[0] - npos[0]) >= 12 or abs(pos[1] - npos[1]) >= 12:
continue
if net.startswith("G_"):
tnet = net
else:
tnet = nets.normalise_name(chip_size, tname, net)
tnet = nets.normalise_name(chip_size, tname, net, 0)
tdb = pytrellis.get_tile_bitdata(pytrellis.TileLocator(c.info.family, c.info.name, tinf.type))
for sink in tdb.get_sinks():
mux = tdb.get_mux_data_for_sink(sink)
if tnet in mux.arcs:
drivers.append((nets.canonicalise_name(chip_size, tname, sink), True, tname))
drivers.append((nets.canonicalise_name(chip_size, tname, sink, 0), True, tname))
for fc in tdb.get_fixed_conns():
if fc.source == tnet:
drivers.append((nets.canonicalise_name(chip_size, tname, fc.sink), False, tname))
drivers.append((nets.canonicalise_name(chip_size, tname, fc.sink, 0), False, tname))
return drivers


Expand Down Expand Up @@ -105,7 +105,7 @@ def get_nets_at(loc):
def completer(str, idx):
if not tile_net_re.match(str):
return None
loc = tiles.pos_from_name(str)
loc = tiles.pos_from_name(str, chip_size, 0)
nets = get_nets_at(loc)
for n in nets:
if n.startswith(str):
Expand Down
6 changes: 4 additions & 2 deletions tools/demobuilder/design.py
Expand Up @@ -32,7 +32,8 @@ def init_bels(self):
for tile in all_tiles:
tinf = tile.info
tname = tinf.name
pos = tiles.pos_from_name(tname)
chip_size = (self.chip.get_max_row(), self.chip.get_max_col())
pos = tiles.pos_from_name(tname, chip_size, 0)
if tinf.type == "PLC2":
for loc in ("A", "B", "C", "D"):
bel = "R{}C{}{}".format(pos[0], pos[1], loc)
Expand Down Expand Up @@ -60,7 +61,8 @@ def inst_slice(self, name, a0=None, a1=None, b0=None, b1=None, c0=None, c1=None,
bel = self.bel_for_cell(name, "SLICE")
beltype, belloc = self.bels[bel]
tile, loc = belloc
pos = tiles.pos_from_name(tile)
chip_size = (self.chip.get_max_row(), self.chip.get_max_col())
pos = tiles.pos_from_name(tile, chip_size, 0)
net_prefix = "R{}C{}".format(pos[0], pos[1])
slice_index = "ABCD".index(loc)
lc0 = 2 * slice_index
Expand Down
18 changes: 10 additions & 8 deletions tools/demobuilder/route.py
Expand Up @@ -22,8 +22,9 @@ def get_arcs_downhill(self, wire):
return self.dh_arc_cache[wire]
else:
drivers = []
chip_size = (self.chip.get_max_row(), self.chip.get_max_col())
try:
npos = tiles.pos_from_name(wire)
npos = tiles.pos_from_name(wire, chip_size, 0)
except AssertionError:
return []
wname = wire.split("_", 1)[1]
Expand All @@ -41,20 +42,20 @@ def get_arcs_downhill(self, wire):
tname = tinf.name
if tname.startswith("TAP"):
continue
pos = tiles.pos_from_name(tname)
pos = tiles.pos_from_name(tname, chip_size, 0)

if abs(pos[0] - npos[0]) not in (vspan, 0) or abs(pos[1] - npos[1]) not in (hspan, 0):
continue
if wire.startswith("G_"):
twire = wire
else:
twire = nets.normalise_name(self.chip_size, tname, wire)
twire = nets.normalise_name(self.chip_size, tname, wire, 0)

tdb = pytrellis.get_tile_bitdata(
pytrellis.TileLocator(self.chip.info.family, self.chip.info.name, tinf.type))
downhill = tdb.get_downhill_wires(twire)
for sink in downhill:
nn = nets.canonicalise_name(self.chip_size, tname, sink.first)
nn = nets.canonicalise_name(self.chip_size, tname, sink.first, 0)
if nn is not None:
drivers.append((nn, sink.second, tname))
self.dh_arc_cache[wire] = drivers
Expand All @@ -72,8 +73,8 @@ def bind_arc(self, net, uphill_wire, arc, config):
else:
self.net_to_wire[net] = {dest_wire}
if configurable and not exists:
src_wirename = nets.normalise_name(self.chip_size, tile, uphill_wire)
sink_wirename = nets.normalise_name(self.chip_size, tile, dest_wire)
src_wirename = nets.normalise_name(self.chip_size, tile, uphill_wire, 0)
sink_wirename = nets.normalise_name(self.chip_size, tile, dest_wire, 0)
config[tile].add_arc(sink_wirename, src_wirename)

# Bind a net to a wire (used for port connections)
Expand All @@ -88,9 +89,10 @@ def bind_net_to_port(self, net, port_wire):
# Route a net to a wire
def route_net_to_wire(self, net, wire, config):
print(" Routing net '{}' to wire/pin '{}'...".format(net, wire))
dest_pos = tiles.pos_from_name(wire)
chip_size = (self.chip.get_max_row(), self.chip.get_max_col())
dest_pos = tiles.pos_from_name(wire, chip_size, 0)
def get_score(x_wire):
pos = tiles.pos_from_name(x_wire)
pos = tiles.pos_from_name(x_wire, chip_size, 0)
score = abs(pos[0] - dest_pos[0]) + abs(pos[1] - dest_pos[1])
x_wname = x_wire.split("_", 1)[1]
if x_wname[1:3].isdigit() and score > 3:
Expand Down
21 changes: 5 additions & 16 deletions tools/html_tilegrid.py
Expand Up @@ -5,6 +5,7 @@
import sys, re
import argparse
import database
import tiles as tilelib

parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('family', type=str,
Expand All @@ -14,15 +15,6 @@
parser.add_argument('outfile', type=argparse.FileType('w'),
help="output HTML file")

rc_regex = re.compile(r"[A-Za-z0-9_]*R(\d+)C(\d+)")


def get_rc(name):
rc = rc_regex.match(name)
row = int(rc.group(1))
col = int(rc.group(2))
return (row, col)


def get_colour(ttype):
colour = "#FFFFFF"
Expand Down Expand Up @@ -50,13 +42,10 @@ def get_colour(ttype):
def main(argv):
args = parser.parse_args(argv[1:])
tilegrid = database.get_tilegrid(args.family, args.device)
device_info = database.get_devices()["families"][args.family]["devices"][args.device]

max_row = 0
max_col = 0
for name in sorted(tilegrid.keys()):
row, col = get_rc(name)
if row > max_row: max_row = row
if col > max_col: max_col = col
max_row = device_info["max_row"]
max_col = device_info["max_col"]

tiles = []
for i in range(max_row + 1):
Expand All @@ -67,7 +56,7 @@ def main(argv):

for identifier, data in sorted(tilegrid.items()):
name = identifier.split(":")[0]
row, col = get_rc(name)
row, col = tilelib.pos_from_name(name, (max_row, max_col), 0)
colour = get_colour(data["type"])
tiles[row][col].append((name, data["type"], colour))

Expand Down
33 changes: 17 additions & 16 deletions util/common/nets.py
Expand Up @@ -196,7 +196,7 @@ def handle_edge_name(chip_size, tile_pos, wire_pos, netname):
return netname, wire_pos


def normalise_name(chip_size, tile, wire):
def normalise_name(chip_size, tile, wire, bias):
"""
Wire name normalisation for tile wires and fuzzing
All net names that we have access too are canonical, global names
Expand Down Expand Up @@ -224,13 +224,14 @@ def normalise_name(chip_size, tile, wire):
chip_size: chip size as tuple (max_row, max_col)
tile: name of the relevant tile
wire: full Lattice name of the wire
bias: Use 1-based column indexing
Returns the normalised netname
"""
upos = wire.index("_")
prefix = wire[:upos]
prefix_pos = tiles.pos_from_name(prefix)
tile_pos = tiles.pos_from_name(tile)
prefix_pos = tiles.pos_from_name(prefix, chip_size, bias)
tile_pos = tiles.pos_from_name(tile, chip_size, bias)
netname = wire[upos+1:]
if tile.startswith("TAP") and netname.startswith("H"):
if prefix_pos[1] < tile_pos[1]:
Expand Down Expand Up @@ -269,7 +270,7 @@ def normalise_name(chip_size, tile, wire):
rel_netname_re = re.compile(r'^([NS]\d+)?([EW]\d+)?_.*')


def canonicalise_name(chip_size, tile, wire):
def canonicalise_name(chip_size, tile, wire, bias):
"""
Convert a normalised name in a given tile back to a canonical global name
:param chip_size: chip size as tuple (max_row, max_col)
Expand All @@ -280,7 +281,7 @@ def canonicalise_name(chip_size, tile, wire):
if wire.startswith("G_"):
return wire
m = rel_netname_re.match(wire)
tile_pos = tiles.pos_from_name(tile)
tile_pos = tiles.pos_from_name(tile, chip_size, bias)
wire_pos = tile_pos
if m:
assert len(m.groups()) >= 1
Expand Down Expand Up @@ -314,17 +315,17 @@ def main():
assert is_cib("R47C58_H06W0003")
assert is_cib("R47C61_CLK0")

assert normalise_name((95, 126), "R48C26", "R48C26_B1") == "B1"
assert normalise_name((95, 126), "R48C26", "R48C26_HPBX0600") == "G_HPBX0600"
assert normalise_name((95, 126), "R48C26", "R48C25_H02E0001") == "W1_H02E0001"
assert normalise_name((95, 126), "R48C1", "R48C1_H02E0002") == "W1_H02E0001"
assert normalise_name((95, 126), "R82C90", "R79C90_V06S0003") == "N3_V06S0003"
assert normalise_name((95, 126), "R5C95", "R3C95_V06S0004") == "N3_V06S0003"
assert normalise_name((95, 126), "R1C95", "R1C95_V06S0006") == "N3_V06S0003"
assert normalise_name((95, 126), "R3C95", "R2C95_V06S0005") == "N3_V06S0003"
assert normalise_name((95, 126), "R82C95", "R85C95_V06N0303") == "S3_V06N0303"
assert normalise_name((95, 126), "R90C95", "R92C95_V06N0304") == "S3_V06N0303"
assert normalise_name((95, 126), "R93C95", "R94C95_V06N0305") == "S3_V06N0303"
assert normalise_name((95, 126), "R48C26", "R48C26_B1", 0) == "B1"
assert normalise_name((95, 126), "R48C26", "R48C26_HPBX0600", 0) == "G_HPBX0600"
assert normalise_name((95, 126), "R48C26", "R48C25_H02E0001", 0) == "W1_H02E0001"
assert normalise_name((95, 126), "R48C1", "R48C1_H02E0002", 0) == "W1_H02E0001"
assert normalise_name((95, 126), "R82C90", "R79C90_V06S0003", 0) == "N3_V06S0003"
assert normalise_name((95, 126), "R5C95", "R3C95_V06S0004", 0) == "N3_V06S0003"
assert normalise_name((95, 126), "R1C95", "R1C95_V06S0006", 0) == "N3_V06S0003"
assert normalise_name((95, 126), "R3C95", "R2C95_V06S0005", 0) == "N3_V06S0003"
assert normalise_name((95, 126), "R82C95", "R85C95_V06N0303", 0) == "S3_V06N0303"
assert normalise_name((95, 126), "R90C95", "R92C95_V06N0304", 0) == "S3_V06N0303"
assert normalise_name((95, 126), "R93C95", "R94C95_V06N0305", 0) == "S3_V06N0303"


if __name__ == "__main__":
Expand Down
14 changes: 8 additions & 6 deletions util/common/tiles.py
@@ -1,15 +1,17 @@
import re
import pytrellis

pos_re = re.compile(r'R(\d+)C(\d+)')


def pos_from_name(tile):
def pos_from_name(tile, chip_size, bias):
"""
Extract the tile position as a (row, column) tuple from its name
"""
s = pos_re.search(tile)
assert s
return int(s.group(1)), int(s.group(2))
size = pytrellis.IntPair()
size.first = chip_size[0]
size.second = chip_size[1]

pos = pytrellis.get_row_col_pair_from_chipsize(tile, size, bias)
return int(pos.first), int(pos.second)


def type_from_fullname(tile):
Expand Down
14 changes: 10 additions & 4 deletions util/fuzz/interconnect.py
Expand Up @@ -27,7 +27,8 @@ def fuzz_interconnect(config,
enable_span1_fix=False,
func_cib=False,
fc_prefix="",
nonlocal_prefix=""):
nonlocal_prefix="",
bias=0):
"""
The fully-automatic interconnect fuzzer function. This performs the fuzzing and updates the database with the
results. It is expected that PyTrellis has already been initialised with the database prior to this function being
Expand All @@ -48,6 +49,8 @@ def fuzz_interconnect(config,
:param func_cib: if True, we are fuzzing a special function to CIB interconnect, enable optimisations for this
:param fc_prefix: add a prefix to non-global fixed connections for device-specific fuzzers
:param nonlocal_prefix: add a prefix to non-global and non-neighbour wires for device-specific fuzzers
:param bias: Apply offset correction for n-based column numbering, n > 0. Used used by Lattice
on certain families.
"""
netdata = isptcl.get_wires_at_position(config.ncd_prf, location)
netnames = [x[0] for x in netdata]
Expand All @@ -67,7 +70,7 @@ def fuzz_interconnect(config,
if func_cib and not netname_filter_union:
netnames = list(filter(lambda x: netname_predicate(x, netnames), netnames))
fuzz_interconnect_with_netnames(config, netnames, netname_predicate, arc_predicate, fc_predicate, func_cib,
netname_filter_union, False, fc_prefix, nonlocal_prefix)
netname_filter_union, False, fc_prefix, nonlocal_prefix, bias)


def fuzz_interconnect_with_netnames(
Expand All @@ -80,7 +83,8 @@ def fuzz_interconnect_with_netnames(
netname_filter_union=False,
full_mux_style=False,
fc_prefix="",
nonlocal_prefix=""):
nonlocal_prefix="",
bias=0):
"""
Fuzz interconnect given a list of netnames to analyse. Arcs associated these netnames will be found using the Tcl
API and bits identified as described above.
Expand All @@ -96,6 +100,8 @@ def fuzz_interconnect_with_netnames(
nets much pass the predicate.
:param full_mux_style: if True, is a full mux, and all 0s is considered a valid config bit possibility
:param fc_prefix: add a prefix to non-global fixed connections for device-specific fuzzers
:param bias: Apply offset correction for n-based column numbering, n > 0. Used used by Lattice
on certain families.
"""
net_arcs = isptcl.get_arcs_on_wires(config.ncd_prf, netnames, not bidir)
baseline_bitf = config.build_design(config.ncl, {}, "base_")
Expand All @@ -105,7 +111,7 @@ def fuzz_interconnect_with_netnames(
max_col = baseline_chip.get_max_col()

def normalise_arc_in_tile(tile, arc):
return tuple(nets.normalise_name((max_row, max_col), tile, x) for x in arc)
return tuple(nets.normalise_name((max_row, max_col), tile, x, bias) for x in arc)

def add_nonlocal_prefix(wire):
if wire.startswith("G_"):
Expand Down

0 comments on commit cfe647f

Please sign in to comment.