| 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) |