| import pytrellis |
| import route |
| import tiles |
| |
| # Simple demo design builder |
| class Design: |
| def __init__(self, family): |
| self.chip = pytrellis.Chip("LFE5U-45F") |
| self.router = route.Autorouter(self.chip) |
| self.config = {_.info.name: pytrellis.TileConfig() for _ in self.chip.get_all_tiles()} |
| # TODO: load skeleton config |
| self.bels = dict() |
| self.bel_to_cell = {} |
| self.bels_by_type = {} |
| |
| self.auto_netid = 0 |
| self.auto_cellid = 0 |
| |
| self.init_bels() |
| |
| def get_netid(self, postfix=""): |
| self.auto_netid += 1 |
| return "n{}{}".format(self.auto_netid, postfix) |
| |
| def get_cellid(self, postfix=""): |
| self.auto_cellid += 1 |
| return "c{}{}".format(self.auto_cellid, postfix) |
| |
| def init_bels(self): |
| self.bels_by_type = {"SLICE": []} |
| all_tiles = self.chip.get_all_tiles() |
| for tile in all_tiles: |
| tinf = tile.info |
| tname = tinf.name |
| 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) |
| self.bels[bel] = ("SLICE", (tname, loc)) |
| self.bels_by_type["SLICE"].append(bel) |
| |
| def connect_input(self, wire, net): |
| if net is not None: |
| self.router.route_net_to_wire(net, wire, self.config) |
| |
| def connect_output(self, wire, net): |
| if net is not None: |
| self.router.bind_net_to_port(net, wire) |
| |
| def bel_for_cell(self, cell, type): |
| for bel in self.bels_by_type["SLICE"]: |
| if bel not in self.bel_to_cell: |
| self.bel_to_cell[bel] = cell |
| return bel |
| assert False, "can't place cell {}, no remaining bels of type {}".format(cell, type) |
| |
| def inst_slice(self, name, a0=None, a1=None, b0=None, b1=None, c0=None, c1=None, d0=None, d1=None, m0=None, m1=None, |
| clk=None, ce=None, lsr=None, f0=None, f1=None, q0=None, q1=None, params=dict()): |
| print("Instantiating slice {}".format(name)) |
| bel = self.bel_for_cell(name, "SLICE") |
| beltype, belloc = self.bels[bel] |
| tile, loc = belloc |
| 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 |
| lc1 = 2 * slice_index + 1 |
| |
| self.connect_output("{}_F{}".format(net_prefix, lc0), f0) |
| self.connect_output("{}_F{}".format(net_prefix, lc1), f1) |
| self.connect_output("{}_Q{}".format(net_prefix, lc0), q0) |
| self.connect_output("{}_Q{}".format(net_prefix, lc1), q1) |
| |
| self.connect_input("{}_A{}".format(net_prefix, lc0), a0) |
| self.connect_input("{}_A{}".format(net_prefix, lc1), a1) |
| self.connect_input("{}_B{}".format(net_prefix, lc0), b0) |
| self.connect_input("{}_B{}".format(net_prefix, lc1), b1) |
| self.connect_input("{}_C{}".format(net_prefix, lc0), c0) |
| self.connect_input("{}_C{}".format(net_prefix, lc1), c1) |
| self.connect_input("{}_D{}".format(net_prefix, lc0), d0) |
| self.connect_input("{}_D{}".format(net_prefix, lc1), d1) |
| |
| self.connect_input("{}_M{}".format(net_prefix, lc0), m0) |
| self.connect_input("{}_M{}".format(net_prefix, lc1), m1) |
| |
| self.connect_input("{}_MUXCLK{}".format(net_prefix, slice_index), clk) |
| self.connect_input("{}_CE{}".format(net_prefix, slice_index), ce) |
| self.connect_input("{}_MUXLSR{}".format(net_prefix, slice_index), lsr) |
| |
| for key, value in sorted(params.items()): |
| if key.endswith(".INIT"): |
| bv = pytrellis.BoolVector() |
| for x in value: |
| bv.append(x) |
| self.config[tile].add_word("SLICE{}.{}".format(loc, key), bv) |
| else: |
| self.config[tile].add_enum("SLICE{}.{}".format(loc, key), value) |
| print() |
| |
| def make_bitstream(self, filename): |
| # Open debug file |
| debugfile = filename + ".dbg" |
| with open(debugfile, 'w') as dbgf: |
| for tname, tcfg in sorted(self.config.items()): |
| tile = self.chip.tiles[tname] |
| tinfo = tile.info |
| tdb = pytrellis.get_tile_bitdata( |
| pytrellis.TileLocator(self.chip.info.family, self.chip.info.name, tinfo.type)) |
| tile.cram.clear() |
| tdb.config_to_tile_cram(tcfg, tile.cram) |
| textcfg = tcfg.to_string() |
| if len(textcfg.strip()) > 0: |
| dbgf.write(".tile {}\n".format(tname)) |
| dbgf.write(textcfg) |
| dbgf.write("\n") |
| |
| bs = pytrellis.Bitstream.serialise_chip(self.chip) |
| bs.write_bit(filename) |