From ec3ad586835ec13cd5b3c32f6c2b7580247c562b Mon Sep 17 00:00:00 2001 From: David Shah Date: Wed, 29 Nov 2017 12:37:40 +0000 Subject: Figure out missing SPI config bits, and add to chipdb --- icebox/icebox.py | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'icebox/icebox.py') diff --git a/icebox/icebox.py b/icebox/icebox.py index 25e01e4..37f7767 100644 --- a/icebox/icebox.py +++ b/icebox/icebox.py @@ -4862,6 +4862,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 +4916,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"), -- cgit v1.2.3 From 0932c559a781c261c6d7f10f54faeb27aef4b702 Mon Sep 17 00:00:00 2001 From: David Shah Date: Mon, 4 Dec 2017 14:23:58 +0000 Subject: Misc routing tweaks --- icebox/icebox.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'icebox/icebox.py') diff --git a/icebox/icebox.py b/icebox/icebox.py index 37f7767..13f8641 100644 --- a/icebox/icebox.py +++ b/icebox/icebox.py @@ -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") @@ -650,7 +650,7 @@ 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(): + if self.is_ultra(): # Might have sp4 not span4 here vert_net = vert_net.replace("_h_", "_v_") horz_net = horz_net.replace("_v_", "_h_") @@ -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) -- cgit v1.2.3 From 9e81ac7786d7633b7d1c204318f1559bca300643 Mon Sep 17 00:00:00 2001 From: David Shah Date: Mon, 4 Dec 2017 17:37:14 +0000 Subject: New UltraPlus corner tracing algorithm --- icebox/icebox.py | 173 +++++++++++++++++++++++++++---------------------------- 1 file changed, 86 insertions(+), 87 deletions(-) (limited to 'icebox/icebox.py') diff --git a/icebox/icebox.py b/icebox/icebox.py index 13f8641..ed27d1b 100644 --- a/icebox/icebox.py +++ b/icebox/icebox.py @@ -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) @@ -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: @@ -1230,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: @@ -1320,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")) -- cgit v1.2.3 From 77eafa89b4b9d8852071cc68298f92465311470b Mon Sep 17 00:00:00 2001 From: David Shah Date: Wed, 6 Dec 2017 17:48:15 +0000 Subject: HFOSC trimming info --- icebox/icebox.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'icebox/icebox.py') diff --git a/icebox/icebox.py b/icebox/icebox.py index ed27d1b..331aa74 100644 --- a/icebox/icebox.py +++ b/icebox/icebox.py @@ -4695,8 +4695,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"), -- cgit v1.2.3 From 02a986b2f4b9d0cf5166a8a4915abe196116d259 Mon Sep 17 00:00:00 2001 From: David Shah Date: Thu, 11 Jan 2018 19:22:45 +0000 Subject: Add pinout for 5k UWG30 package --- icebox/icebox.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'icebox/icebox.py') diff --git a/icebox/icebox.py b/icebox/icebox.py index 331aa74..9816db7 100644 --- a/icebox/icebox.py +++ b/icebox/icebox.py @@ -4399,6 +4399,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 -- cgit v1.2.3 From a59472812c808416d2a56bccc07a9540357e18d9 Mon Sep 17 00:00:00 2001 From: David Shah Date: Sat, 13 Jan 2018 15:55:32 +0000 Subject: Remove seperate 5k RAM DB and share with 8k instead This should ensure that the 5k RAM routing entries are now complete, fixing #115 --- icebox/icebox.py | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'icebox/icebox.py') diff --git a/icebox/icebox.py b/icebox/icebox.py index 9816db7..e19e489 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 @@ -725,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: @@ -735,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: @@ -4991,8 +4991,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") @@ -5089,19 +5087,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() -- cgit v1.2.3 From 7e587c9b6b62057f7e9258ac93c7fec77e994fa1 Mon Sep 17 00:00:00 2001 From: David Shah Date: Sat, 13 Jan 2018 17:31:09 +0000 Subject: Add 5k UWG30 ieren data to db --- icebox/icebox.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'icebox/icebox.py') diff --git a/icebox/icebox.py b/icebox/icebox.py index e19e489..198b5f2 100644 --- a/icebox/icebox.py +++ b/icebox/icebox.py @@ -2347,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) ] } -- cgit v1.2.3