| #!/usr/bin/env python3 |
| |
| import sys |
| import os |
| import lxml.etree as ET |
| |
| import icebox |
| |
| from ice40_list_layout_in_icebox import versions |
| |
| |
| def vpr_pos(x, y): |
| return x + 2, y + 2 |
| |
| |
| def get_corner_tiles(ic): |
| corner_tiles = set() |
| for x in (0, ic.max_x): |
| for y in (0, ic.max_y): |
| corner_tiles.add((x, y)) |
| return corner_tiles |
| |
| |
| def add_metadata(parent_xml, key, value): |
| metadata_xml = parent_xml.find("./metadata") |
| if metadata_xml is None: |
| metadata_xml = ET.SubElement(parent_xml, "metadata") |
| |
| m = ET.SubElement(metadata_xml, "meta", {"name": str(key)}) |
| m.text = str(value) |
| |
| |
| def add_tile(layout_xml, type_name, pos): |
| return ET.SubElement( |
| layout_xml, "single", { |
| 'type': type_name, |
| 'x': str(pos[0]), |
| 'y': str(pos[1]), |
| 'priority': '1' |
| } |
| ) |
| |
| |
| SKIP = [] |
| |
| for name, pins in icebox.pinloc_db.items(): |
| part, package = name.split('-') |
| if ':' in package: |
| continue |
| #if part != "1k": |
| # continue |
| pin_locs = {} |
| for name, x, y, z in pins: |
| if (x, y) not in pin_locs: |
| pin_locs[(x, y)] = {} |
| pin_locs[(x, y)][z] = name |
| |
| ic = icebox.iceconfig() |
| getattr(ic, "setup_empty_{}".format(part))() |
| |
| def edge_blocks(x, y): |
| p = [[0, 0], [0, 0], [0, 0]] |
| if x == 0: |
| p[0][0] -= 1 |
| p[1][0] -= 1 |
| if x == ic.max_x: |
| p[0][0] += 1 |
| p[1][0] += 1 |
| if y == 0: |
| p[1][1] -= 1 |
| p[2][1] -= 1 |
| if y == ic.max_y: |
| p[1][1] += 1 |
| p[2][1] += 1 |
| p = set(tuple(x) for x in p) |
| try: |
| p.remove((0, 0)) |
| except KeyError: |
| pass |
| return tuple(p) |
| |
| def find_fabric_glb_netwk(x, y): |
| fabric_glb_network = "" |
| for gx, gy, gn in ic.gbufin_db(): |
| if (gx, gy) == (x, y): |
| fabric_glb_network = "glb_netwk_{}".format(gn) |
| return fabric_glb_network |
| |
| def tile_type(x, y): |
| tt = ic.tile_type(x, y) |
| |
| if tt == "IO": |
| fasm_prefix = "" |
| for z in range(2): |
| fasm_prefix += "{}_X{:d}_Y{:d}.IOB_{:d} ".format(tt, x, y, z) |
| else: |
| fasm_prefix = "{}_X{:d}_Y{:d}".format(tt, x, y) |
| |
| metadata = { |
| 'hlc_coord': "{:d} {:d}".format(x, y), |
| "fasm_prefix": fasm_prefix |
| } |
| if (x, y) in get_corner_tiles(ic): |
| return None, {} |
| if tt == "RAMB": |
| return "RAM", metadata |
| if tt == "RAMT": |
| return SKIP, {} |
| if tt.startswith("DSP"): |
| if tt.endswith("0"): |
| return "DSP", metadata |
| return SKIP, {} |
| if tt == "IO": |
| padin = ic.padin_pio_db() |
| |
| details = [] |
| for z in (0, 1): |
| try: |
| metadata["hlc_global_io:{}".format(z) |
| ] = "glb_netwk_{}".format(padin.index((x, y, z))) |
| metadata["hlc_global_fabric:{}".format(z) |
| ] = find_fabric_glb_netwk(x, y) |
| tt = "GPIO{}".format(z) |
| except ValueError: |
| pass |
| |
| name = "" |
| if (x, y) in pin_locs: |
| tile = pin_locs[(x, y)] |
| if z in tile: |
| name = tile[z] |
| |
| if (x, y) in ic.iolatch_db(): |
| metadata["hlc_latch_io"] = z |
| |
| print( |
| "(%2d,%2d)-%d i:%12s f:%12s l:%2s n:%s" % ( |
| x, y, z, |
| metadata.get("hlc_global_io:{}".format(z), ""), |
| metadata.get("hlc_global_fabric:{}".format(z), ""), |
| metadata.get("hlc_latch_io", ""), name |
| ) |
| ) |
| return "PIO", metadata |
| if tt == "LOGIC": |
| return "PLB", metadata |
| return None, {} |
| assert False, tt |
| |
| for version in versions(part): |
| layout_xml = ET.Element( |
| "fixed_layout", { |
| 'name': '{}-{}'.format(version, package), |
| 'width': str(ic.max_x + 4 + 1), |
| 'height': str(ic.max_y + 4 + 1), |
| } |
| ) |
| |
| pin_map = {} |
| for x in range(0, ic.max_x + 1): |
| for y in range(0, ic.max_y + 1): |
| ipos = (x, y) |
| vpos = vpr_pos(*ipos) |
| |
| tt, metadata = tile_type(*ipos) |
| if tt is not None: |
| if tt is not SKIP: |
| tile_xml = add_tile(layout_xml, tt, vpos) |
| else: |
| tile_xml = add_tile(layout_xml, "EMPTY", vpos) |
| |
| for k, v in metadata.items(): |
| add_metadata(tile_xml, k, str(v)) |
| |
| eposes = edge_blocks(x, y) |
| #print(vpos, eposes) |
| for e in eposes: |
| pad_xml = add_tile( |
| layout_xml, "EMPTY", |
| (vpos[0] + e[0] * 2, vpos[1] + e[1] * 2) |
| ) |
| |
| pin_pos = vpos[0] + e[0] * 1, vpos[1] + e[1] * 1 |
| if ipos in pin_locs: |
| pin_xml = add_tile(layout_xml, "EMPTY", pin_pos) |
| for z, name in pin_locs[ipos].items(): |
| add_metadata(pin_xml, "hlc_pin:{}".format(z), name) |
| pin_map[(*vpos, z)] = name |
| else: |
| pin_xml = add_tile(layout_xml, "EMPTY", pin_pos) |
| |
| add_metadata( |
| pin_xml, "hlc_coord", |
| "{} {}".format(x + e[0], y + e[1]) |
| ) |
| |
| with open("{}.{}.fixed_layout.xml".format(version, package), |
| "wb+") as f: |
| f.write(ET.tostring(layout_xml, pretty_print=True)) |
| |
| def i(x): |
| try: |
| return int(x) |
| except ValueError: |
| return x |
| |
| lines = [(i(v), *k) for k, v in pin_map.items()] |
| with open("{}.{}.pinmap.csv".format(version, package), "wb+") as f: |
| f.write("name,x,y,z\n".format(*k, v).encode("utf-8")) |
| for i in sorted(lines): |
| f.write("{},{},{},{}\n".format(*i).encode("utf-8")) |