diff options
Diffstat (limited to 'icebox/icebox.py')
| -rw-r--r-- | icebox/icebox.py | 251 | 
1 files changed, 149 insertions, 102 deletions
diff --git a/icebox/icebox.py b/icebox/icebox.py index 25e01e4..198b5f2 100644 --- a/icebox/icebox.py +++ b/icebox/icebox.py @@ -318,8 +318,8 @@ class iceconfig:              if (x, y) in self.ramt_tiles: return ramttile_db          elif self.device == "5k":              if (x, y) in self.logic_tiles: return logictile_5k_db -            if (x, y) in self.ramb_tiles: return rambtile_5k_db -            if (x, y) in self.ramt_tiles: return ramttile_5k_db +            if (x, y) in self.ramb_tiles: return rambtile_8k_db +            if (x, y) in self.ramt_tiles: return ramttile_8k_db              if (x, y) in self.ipcon_tiles: return ipcon_5k_db              if (x, y) in self.dsp_tiles[0]: return dsp0_5k_db              if (x, y) in self.dsp_tiles[1]: return dsp1_5k_db @@ -419,7 +419,7 @@ class iceconfig:          def do_direction(name, nx, ny):              if (0 < nx < self.max_x or self.is_ultra()) and 0 < ny < self.max_y:                  neighbours.add((nx, ny, "neigh_op_%s_%d" % (name, func))) -            if nx in (0, self.max_x) and 0 < ny < self.max_y and nx != x: +            if nx in (0, self.max_x) and 0 < ny < self.max_y and nx != x and (not self.is_ultra()):                  neighbours.add((nx, ny, "logic_op_%s_%d" % (name, func)))              if ny in (0, self.max_y) and 0 < nx < self.max_x and ny != y:                  neighbours.add((nx, ny, "logic_op_%s_%d" % (name, func))) @@ -463,7 +463,7 @@ class iceconfig:                      else:                          assert False -            elif pos == "x" and npos in ("l", "r", "t", "b"): +            elif pos == "x" and ((npos in ("t", "b")) or ((not self.is_ultra()) and (npos in ("l", "r")))):                  if func in (0, 4): return (nx, ny, "io_0/D_IN_0")                  if func in (1, 5): return (nx, ny, "io_0/D_IN_1")                  if func in (2, 6): return (nx, ny, "io_1/D_IN_0") @@ -507,34 +507,52 @@ class iceconfig:          return funcnets +    def ultraplus_follow_corner(self, corner, direction, netname): +        m = re.match("span4_(horz|vert)_([lrtb])_(\d+)$", netname) +        if not m: +            return None +        cur_edge = m.group(2) +        cur_index = int(m.group(3)) +        if direction not in corner: +            return None +        if direction != cur_edge: +            return None +        h_idx, v_idx = self.ultraplus_trace_corner_idx(corner, cur_index) +        if h_idx is None and (direction == "b" or direction == "t"): +            return None +        if v_idx is None and (direction == "l" or direction == "r"): +            return None +        if corner == "bl" and direction == "l": +            return (0, 1, sp4v_normalize("sp4_v_b_%d" % v_idx)) +        if corner == "bl" and direction == "b": +            return (1, 0, ultra_span4_horz_normalize("span4_horz_l_%d" % h_idx)) +        if corner == "br" and direction == "r": +            return (self.max_x, 1, sp4v_normalize("sp4_v_b_%d" % v_idx)) +        if corner == "br" and direction == "b": +            return (self.max_x-1, 0, ultra_span4_horz_normalize("span4_horz_r_%d" % h_idx)) +        if corner == "tl" and direction == "l": +            return (0, self.max_y-1, sp4v_normalize("sp4_v_t_%d" % v_idx)) +        if corner == "tl" and direction == "t": +            return (1, self.max_y, ultra_span4_horz_normalize("span4_horz_l_%d" % h_idx)) +        if corner == "tr" and direction == "r": +            return (self.max_x, self.max_y-1, sp4v_normalize("sp4_v_t_%d" % v_idx)) +        if corner == "tr" and direction == "t": +            return (self.max_x-1, self.max_y, ultra_span4_horz_normalize("span4_horz_r_%d" % h_idx)) +        assert False      #UltraPlus corner routing: given the corner name and net index,      #return a tuple containing H and V indexes, or none if NA -    def ultraplus_trace_corner(self, corner, idx): +    def ultraplus_trace_corner_idx(self, corner, idx):          h_idx = None          v_idx = None -        if corner == "bl": -            if idx >= 4: -                v_idx = idx + 28 -            if idx >= 32 and idx < 48: -                h_idx = idx - 28 -        elif corner == "tl": -            #TODO: bounds check for v_idx case? -            if idx >= 4: -                v_idx = (idx + 8) ^ 1 -            if idx >= 12 and idx < 28: -                h_idx = (idx ^ 1) - 8 -        elif corner == "tr": -            #TODO: bounds check for v_idx case? -            if idx <= 16: -                v_idx = (idx + 12) ^ 1 -            if idx >= 12 and idx < 28: -                h_idx = (idx ^ 1) - 12             -        elif corner == "br": -            #TODO: bounds check for v_idx case? -            if idx <= 16: +        if corner == "bl" or corner == "br": +            if idx < 16:                  v_idx = idx + 32 -            if idx >= 32 and idx < 48: #check +            if idx >= 32 and idx < 48:                  h_idx = idx - 32 +        elif corner == "tl" or corner == "tr": +            if idx >= 0 and idx < 16: +                v_idx = idx +                h_idx = idx          return (h_idx, v_idx)      def get_corner(self, x, y): @@ -551,7 +569,7 @@ class iceconfig:              corner += "r"          else:              corner += "x" -        return corner     +        return corner      def follow_net(self, netspec):          x, y, netname = netspec @@ -608,37 +626,16 @@ class iceconfig:                  if direction == "b": s = (x, y-1, n)                  if s[0] in (0, self.max_x) and s[1] in (0, self.max_y): -                    if re.match("span4_(vert|horz)_[lrtb]_\d+$", n): -                        m = re.match("span4_(vert|horz)_([lrtb])_\d+$", n) -                        #We ignore L and T edges when performing the Ultra/UltraPlus corner algorithm -                        if self.is_ultra() and (m.group(2) == "l" or m.group(2) == "t"):  +                    if self.is_ultra(): +                        s = self.ultraplus_follow_corner(self.get_corner(s[0], s[1]), direction, n) +                        if s is None:                              continue +                    elif re.match("span4_(vert|horz)_[lrtb]_\d+$", n) and not self.is_ultra(): +                        m = re.match("span4_(vert|horz)_([lrtb])_\d+$", n) +                          vert_net = n.replace("_l_", "_t_").replace("_r_", "_b_").replace("_horz_", "_vert_")                          horz_net = n.replace("_t_", "_l_").replace("_b_", "_r_").replace("_vert_", "_horz_") -                         -                        if self.is_ultra(): #Convert between span4 and sp4, and perform U/UP corner tracing -                            m = re.match("span4_vert_([lrtb])_(\d+)$", vert_net) -                            assert m -                            idx = int(m.group(2)) -                            h_idx, v_idx = self.ultraplus_trace_corner(self.get_corner(s[0], s[1]), idx) -                            if v_idx is None: -                                if (s[0] == 0 and s[1] == 0 and direction == "l") or (s[0] == self.max_x and s[1] == self.max_y and direction == "r"): -                                    continue #Not routed, skip -                            else:     -                                vert_net = "sp4_v_%s_%d" % (m.group(1), v_idx) - -                            m = re.match("span4_horz_([lrtb])_(\d+)$", horz_net) -                            assert m -                            idx = int(m.group(2)) -                            h_idx, v_idx = self.ultraplus_trace_corner(self.get_corner(s[0], s[1]), idx) -                            if h_idx is None: -                                if (s[0] == 0 and s[1] == 0 and direction == "b") or (s[0] == self.max_x and s[1] == self.max_y and direction == "t"): -                                    continue #Not routed, skip -                            else: -                                horz_net = "span4_horz_%s_%d" % (m.group(1), h_idx) -                             -                             -                             +                                                              if s[0] == 0 and s[1] == 0:                              if direction == "l": s = (0, 1, vert_net)                              if direction == "b": s = (1, 0, horz_net) @@ -649,30 +646,6 @@ class iceconfig:                          vert_net = netname.replace("_l_", "_t_").replace("_r_", "_b_").replace("_horz_", "_vert_")                          horz_net = netname.replace("_t_", "_l_").replace("_b_", "_r_").replace("_vert_", "_horz_") - -                        if self.is_ultra():    -                            # Might have sp4 not span4 here -                            vert_net = vert_net.replace("_h_", "_v_") -                            horz_net = horz_net.replace("_v_", "_h_") -                            m = re.match("(span4_vert|sp4_v)_([lrtb])_(\d+)$", vert_net)  -                            assert m -                            idx = int(m.group(3)) -                            h_idx, v_idx = self.ultraplus_trace_corner(self.get_corner(s[0], s[1]), idx) -                            if v_idx is None: -                                if (s[0] == 0 and s[1] == self.max_y and direction == "l") or (s[0] == self.max_x and s[1] == 0 and direction == "r"): -                                    continue -                            else: -                                vert_net = "sp4_v_%s_%d" % (m.group(2), v_idx) -                             -                            m = re.match("(span4_horz|sp4_h)_([lrtb])_(\d+)$", horz_net) -                            assert m -                            idx = int(m.group(3)) -                            h_idx, v_idx = self.ultraplus_trace_corner(self.get_corner(s[0], s[1]), idx) -                            if h_idx is None: -                                if (s[0] == 0 and s[1] == self.max_y and direction == "t") or (s[0] == self.max_x and s[1] == 0 and direction == "b"): -                                    continue -                            else: -                                horz_net = "span4_horz_%s_%d" % (m.group(2), h_idx)                          if s[0] == 0 and s[1] == self.max_y:                              if direction == "l": s = (0, self.max_y-1, vert_net) @@ -752,7 +725,7 @@ class iceconfig:              if self.device == "1k":                  add_seed_segments(idx, tile, rambtile_db)              elif self.device == "5k": -                add_seed_segments(idx, tile, rambtile_5k_db) +                add_seed_segments(idx, tile, rambtile_8k_db)              elif self.device == "8k":                  add_seed_segments(idx, tile, rambtile_8k_db)              else: @@ -762,7 +735,7 @@ class iceconfig:              if self.device == "1k":                  add_seed_segments(idx, tile, ramttile_db)              elif self.device == "5k": -                add_seed_segments(idx, tile, ramttile_5k_db) +                add_seed_segments(idx, tile, ramttile_8k_db)              elif self.device == "8k":                  add_seed_segments(idx, tile, ramttile_8k_db)              else: @@ -1008,7 +981,34 @@ def sp4h_normalize(netname, edge=""):          return "sp4_h_r_%d" % ((cur_index+12)^1)      return netname - +# "Normalization" of span4 (not just sp4) is needed during Ultra/UltraPlus +# corner tracing +def ultra_span4_horz_normalize(netname, edge=""): +    m = re.match("span4_horz_([rl])_(\d+)$", netname) +    assert m +    if not m: return None +    cur_edge = m.group(1) +    cur_index = int(m.group(2)) +    if cur_edge == edge: +        return netname +    if edge == "": +        if cur_edge == "l" and cur_index < 12: +            return "span4_horz_r_%d" % (cur_index + 4) +        else: +            return netname +    elif edge == "l" and cur_edge == "r": +        if cur_index < 4: +            return None +        else: +            cur_index -= 4 +        return "span4_horz_l_%d" % cur_index +    elif edge == "r" and cur_edge == "l": +        if cur_index < 12: +            return "span4_horz_r_%d" % (cur_index + 4) +        else: +            return None +    assert False +      def sp4v_normalize(netname, edge=""):      m = re.match("sp4_v_([bt])_(\d+)$", netname)      assert m @@ -1141,11 +1141,11 @@ def pos_follow_net(pos, direction, netname, is_ultra):              m = re.match("sp4_v_[tb]_(\d+)$", netname)              if m and direction in ("t", "T"): -                if is_ultra and direction == "T" and pos in ("l", "r"): -                    return re.sub("sp4_v_", "span4_vert_", netname)                  n = sp4v_normalize(netname, "t")                  if n is not None: -                    if direction == "t": +                    if is_ultra and direction == "T" and pos in ("l", "r"): +                        return re.sub("sp4_v_", "span4_vert_", n) +                    elif direction == "t":                          n = re.sub("_t_", "_b_", n)                          n = sp4v_normalize(n)                      else: @@ -1153,11 +1153,11 @@ def pos_follow_net(pos, direction, netname, is_ultra):                          n = re.sub("sp4_v_", "span4_vert_", n)                      return n              if m and direction in ("b", "B"): -                if is_ultra and direction == "B" and pos in ("l", "r"): -                    return re.sub("sp4_v_", "span4_vert_", netname)                  n = sp4v_normalize(netname, "b")                  if n is not None: -                    if direction == "b": +                    if is_ultra and direction == "B" and pos in ("l", "r"): +                        return re.sub("sp4_v_", "span4_vert_", n) +                    elif direction == "b":                          n = re.sub("_b_", "_t_", n)                          n = sp4v_normalize(n)                      else: @@ -1194,6 +1194,8 @@ def pos_follow_net(pos, direction, netname, is_ultra):                      if direction == "t":                          n = re.sub("_t_", "_b_", n)                          n = sp12v_normalize(n) +                    elif direction == "T" and pos in ("l", "r"): +                        pass                      else:                          n = re.sub("_t_", "_", n)                          n = re.sub("sp12_v_", "span12_vert_", n) @@ -1204,6 +1206,8 @@ def pos_follow_net(pos, direction, netname, is_ultra):                      if direction == "b":                          n = re.sub("_b_", "_t_", n)                          n = sp12v_normalize(n) +                    elif direction == "B" and pos in ("l", "r"): +                        pass                      else:                          n = re.sub("_b_", "_", n)                          n = re.sub("sp12_v_", "span12_vert_", n) @@ -1226,8 +1230,10 @@ def pos_follow_net(pos, direction, netname, is_ultra):          m = re.match("span4_horz_([rl])_(\d+)$", netname)          if m:              case, idx = direction + m.group(1), int(m.group(2)) -            if direction == "L" or direction == "R": -                return netname +            if direction == "L": +                return ultra_span4_horz_normalize(netname, "l") +            elif direction == "R": +                return ultra_span4_horz_normalize(netname, "r")                          if case == "ll":                  return "span4_horz_r_%d" % idx              if case == "lr" and idx >= 4: @@ -1316,9 +1322,6 @@ def run_checks_neigh():              # Skip the corners.              if x in (0, ic.max_x) and y in (0, ic.max_y):                  continue -            # Skip the sides of a 5k device. -            if self.is_ultra() and x in (0, ic.max_x): -                continue              add_segments((x, y), ic.tile_db(x, y))              if (x, y) in ic.logic_tiles:                  all_segments.add((x, y, "lutff_7/cout")) @@ -2344,7 +2347,11 @@ ieren_db = {          ( 7,  0,  1,  7,  0,  0),          ( 5,  0,  0,  5,  0,  1),          ( 6,  0,  0,  6,  0,  1), -        ( 7,  0,  0,  7,  0,  1) +        ( 7,  0,  0,  7,  0,  1), +        (12, 31,  0, 12, 31,  1), +        (12,  0,  0, 12,  0,  1), +        (13,  0,  0, 13,  0,  1), +        (12,  0,  1, 12,  0,  0)      ]  } @@ -4396,6 +4403,29 @@ pinloc_db = {          ( "47",  6,  0, 0),          ( "48",  7,  0, 0),      ], +    "5k-uwg30": [ +        ( "A1", 19, 31, 1), +        ( "A2", 19, 31, 0), +        ( "A4", 12, 31, 0), +        ( "A5",  4, 31, 0), +        ( "B1", 19,  0, 0), +        ( "B3", 12, 31, 1), +        ( "B5",  5, 31, 0), +        ( "C1", 24,  0, 1), +        ( "C3", 12,  0, 0), +        ( "C5",  6, 31, 0), +        ( "D1", 24,  0, 0), +        ( "D3", 13,  0, 0), +        ( "D5",  6,  0, 0), +        ( "E1", 23,  0, 1), +        ( "E3", 13,  0, 1), +        ( "E4",  9,  0, 1), +        ( "E5",  5,  0, 0), +        ( "F1", 23,  0, 0), +        ( "F2", 19,  0, 1), +        ( "F4", 12,  0, 1), +        ( "F5",  6,  0, 1), +    ]  }  # This database contains the locations of configuration bits of the DSP tiles @@ -4692,8 +4722,19 @@ extra_cells_db = {              "CLKHFEN":                      (0, 29, "lutff_7/in_3"),              "CLKHF":                        (0, 29, "glb_netwk_4"),              "CLKHF_FABRIC":                 (0, 28, "slf_op_7"), +            "TRIM0":                        (25, 28, "lutff_4/in_0"), +            "TRIM1":                        (25, 28, "lutff_5/in_0"), +            "TRIM2":                        (25, 28, "lutff_6/in_0"), +            "TRIM3":                        (25, 28, "lutff_7/in_0"), +            "TRIM4":                        (25, 29, "lutff_0/in_3"), +            "TRIM5":                        (25, 29, "lutff_1/in_3"), +            "TRIM6":                        (25, 29, "lutff_2/in_3"), +            "TRIM7":                        (25, 29, "lutff_3/in_3"), +            "TRIM8":                        (25, 29, "lutff_4/in_3"), +            "TRIM9":                        (25, 29, "lutff_5/in_3"),              "CLKHF_DIV_1":                  (0, 16, "CBIT_4"), -            "CLKHF_DIV_0":                  (0, 16, "CBIT_3")  +            "CLKHF_DIV_0":                  (0, 16, "CBIT_3"), +            "TRIM_EN":                      (0, 16, "CBIT_5")          },          ("LFOSC", (25, 31, 1)) : {              "CLKLFPU":                      (25, 29, "lutff_0/in_1"), @@ -4862,6 +4903,10 @@ extra_cells_db = {      		"SOE":                   (0, 20, "slf_op_5"),       		"SPIIRQ":                (0, 20, "slf_op_2"),       		"SPIWKUP":               (0, 20, "slf_op_3"),  +    		"SPI_ENABLE_0":          (7, 0, "cbit2usealt_in_0"),  +    		"SPI_ENABLE_1":          (7, 0, "cbit2usealt_in_1"),  +    		"SPI_ENABLE_2":          (6, 0, "cbit2usealt_in_0"),  +    		"SPI_ENABLE_3":          (6, 0, "cbit2usealt_in_1"),       	},      	("SPI", (25, 0, 1)): {      		"MCSNO0":                (25, 21, "slf_op_2"),  @@ -4912,6 +4957,10 @@ extra_cells_db = {      		"SOE":                   (25, 20, "slf_op_5"),       		"SPIIRQ":                (25, 20, "slf_op_2"),       		"SPIWKUP":               (25, 20, "slf_op_3"),  +    		"SPI_ENABLE_0":          (23, 0, "cbit2usealt_in_0"),  +    		"SPI_ENABLE_1":          (24, 0, "cbit2usealt_in_0"),  +    		"SPI_ENABLE_2":          (23, 0, "cbit2usealt_in_1"),  +    		"SPI_ENABLE_3":          (24, 0, "cbit2usealt_in_1"),       	},      	("LEDDA_IP", (0, 31, 2)): {      		"LEDDADDR0":             (0, 28, "lutff_4/in_0"),  @@ -4946,8 +4995,6 @@ logictile_8k_db = parse_db(iceboxdb.database_logic_txt, "8k")  logictile_384_db = parse_db(iceboxdb.database_logic_txt, "384")  rambtile_db = parse_db(iceboxdb.database_ramb_txt, "1k")  ramttile_db = parse_db(iceboxdb.database_ramt_txt, "1k") -rambtile_5k_db = parse_db(iceboxdb.database_ramb_5k_txt, "5k") -ramttile_5k_db = parse_db(iceboxdb.database_ramt_5k_txt, "5k")  rambtile_8k_db = parse_db(iceboxdb.database_ramb_8k_txt, "8k")  ramttile_8k_db = parse_db(iceboxdb.database_ramt_8k_txt, "8k") @@ -5044,19 +5091,19 @@ iotile_b_5k_db.append([["B12[2]"], "IpConfig", "cbit2usealt_in_1"])  iotile_b_5k_db.append([["B12[3]"], "IpConfig", "SDA_input_delay"])  iotile_b_5k_db.append([["B15[3]"], "IpConfig", "SDA_output_delay"]) -for db in [iotile_l_db, iotile_r_db, iotile_t_db, iotile_b_db, iotile_t_5k_db, iotile_b_5k_db, logictile_db, logictile_5k_db, logictile_8k_db, logictile_384_db, rambtile_db, ramttile_db, rambtile_5k_db, ramttile_5k_db, rambtile_8k_db, ramttile_8k_db, dsp0_5k_db, dsp1_5k_db, dsp2_5k_db, dsp3_5k_db, ipcon_5k_db]: +for db in [iotile_l_db, iotile_r_db, iotile_t_db, iotile_b_db, iotile_t_5k_db, iotile_b_5k_db, logictile_db, logictile_5k_db, logictile_8k_db, logictile_384_db, rambtile_db, ramttile_db, rambtile_8k_db, ramttile_8k_db, dsp0_5k_db, dsp1_5k_db, dsp2_5k_db, dsp3_5k_db, ipcon_5k_db]:      for entry in db:          if entry[1] in ("buffer", "routing"):              entry[2] = netname_normalize(entry[2],                                           ramb=(db == rambtile_db),                                           ramt=(db == ramttile_db), -                                         ramb_8k=(db in (rambtile_8k_db, rambtile_5k_db)), -                                         ramt_8k=(db in (ramttile_8k_db, ramttile_5k_db))) +                                         ramb_8k=(db == rambtile_8k_db), +                                         ramt_8k=(db == ramttile_8k_db))              entry[3] = netname_normalize(entry[3],                                           ramb=(db == rambtile_db),                                           ramt=(db == ramttile_db), -                                         ramb_8k=(db in (rambtile_8k_db, rambtile_5k_db)), -                                         ramt_8k=(db in (ramttile_8k_db, ramttile_5k_db))) +                                         ramb_8k=(db == rambtile_8k_db), +                                         ramt_8k=(db == ramttile_8k_db))      unique_entries = dict()      while db:          entry = db.pop()  | 
