From 8354bc6086f11002cc58497f91f43200a09c13a9 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 31 Aug 2017 14:55:36 +0200 Subject: Removed files that are under GNU licenses --- icebox/Makefile | 9 - icebox/icebox_asc2hlc.py | 1132 ------------------------------------------- icebox/icebox_hlc2asc.py | 1052 ---------------------------------------- icebox/tc_logic_xpr.py | 42 -- icebox/tc_rxlat_netnames.py | 69 --- icebox/tc_xlat_netnames.py | 79 --- iceprog/Makefile | 3 - iceprog/iceprog.1 | 155 ------ 8 files changed, 2541 deletions(-) delete mode 100755 icebox/icebox_asc2hlc.py delete mode 100755 icebox/icebox_hlc2asc.py delete mode 100644 icebox/tc_logic_xpr.py delete mode 100644 icebox/tc_rxlat_netnames.py delete mode 100644 icebox/tc_xlat_netnames.py delete mode 100644 iceprog/iceprog.1 diff --git a/icebox/Makefile b/icebox/Makefile index 778e2ce..430fb17 100644 --- a/icebox/Makefile +++ b/icebox/Makefile @@ -18,11 +18,6 @@ chipdb-8k.txt: icebox.py iceboxdb.py icebox_chipdb.py python3 icebox_chipdb.py -8 > chipdb-8k.new mv chipdb-8k.new chipdb-8k.txt -check: all - python3 tc_xlat_netnames.py - python3 tc_rxlat_netnames.py - python3 tc_logic_xpr.py - clean: rm -f chipdb-1k.txt chipdb-8k.txt chipdb-384.txt chipdb-5k.txt rm -f icebox.pyc iceboxdb.pyc @@ -38,8 +33,6 @@ install: all cp icebox_chipdb.py $(DESTDIR)$(PREFIX)/bin/icebox_chipdb$(PY_EXE) cp icebox_diff.py $(DESTDIR)$(PREFIX)/bin/icebox_diff$(PY_EXE) cp icebox_explain.py $(DESTDIR)$(PREFIX)/bin/icebox_explain$(PY_EXE) - cp icebox_asc2hlc.py $(DESTDIR)$(PREFIX)/bin/icebox_asc2hlc$(PY_EXE) - cp icebox_hlc2asc.py $(DESTDIR)$(PREFIX)/bin/icebox_hlc2asc$(PY_EXE) cp icebox_colbuf.py $(DESTDIR)$(PREFIX)/bin/icebox_colbuf$(PY_EXE) cp icebox_html.py $(DESTDIR)$(PREFIX)/bin/icebox_html$(PY_EXE) cp icebox_maps.py $(DESTDIR)$(PREFIX)/bin/icebox_maps$(PY_EXE) @@ -52,8 +45,6 @@ uninstall: rm -f $(DESTDIR)$(PREFIX)/bin/icebox_chipdb$(PY_EXE) rm -f $(DESTDIR)$(PREFIX)/bin/icebox_diff$(PY_EXE) rm -f $(DESTDIR)$(PREFIX)/bin/icebox_explain$(PY_EXE) - rm -f $(DESTDIR)$(PREFIX)/bin/icebox_asc2hlc$(PY_EXE) - rm -f $(DESTDIR)$(PREFIX)/bin/icebox_hlc2asc$(PY_EXE) rm -f $(DESTDIR)$(PREFIX)/bin/icebox_colbuf$(PY_EXE) rm -f $(DESTDIR)$(PREFIX)/bin/icebox_html$(PY_EXE) rm -f $(DESTDIR)$(PREFIX)/bin/icebox_maps$(PY_EXE) diff --git a/icebox/icebox_asc2hlc.py b/icebox/icebox_asc2hlc.py deleted file mode 100755 index 0b96441..0000000 --- a/icebox/icebox_asc2hlc.py +++ /dev/null @@ -1,1132 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (C) 2017 Roland Lutz -# -# This program is free software: you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation, either version 3 of -# the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -import getopt, os, re, sys -import icebox - -GLB_NETWK_EXTERNAL_BLOCKS = [(13, 8, 1), (0, 8, 1), (7, 17, 0), (7, 0, 0), - (0, 9, 0), (13, 9, 0), (6, 0, 1), (6, 17, 1)] -GLB_NETWK_INTERNAL_TILES = [(7, 0), (7, 17), (13, 9), (0, 9), - (6, 17), (6, 0), (0, 8), (13, 8)] - - -## Get the global name of a net. -# -# \param x, y coordinates of the tile to which the net belongs -# \param fw, fh width and height of the tile fabric (excluding I/O tiles) -# \param net net name -# -# \return the global name of the net if it is a span wire, otherwise -# the unmodified net name -# -# There are 46624 span wires on the 1k (not counting dummies): -# -# span4_x[1..12]_g[1..20]_[0..11] -# span4_y[1..16]_g[1..16]_[0..11] -# span12_x[1..12]_g[1..28]_[0..1] -# span12_y[1..16]_g[1..24]_[0..1] -# -# span4_left_g[3..16]_[0..3] -# span4_right_g[5..18]_[0..3] -# span4_bottom_g[3..12]_[0..3] -# span4_top_g[5..14]_[0..3] -# -# span4_topleft[2,4,6,8]_[0..3] -# span4_bottomright[2,4,6,8]_[0..3] -# -# dummy_y[1..16]_g[0..3]_[0..11] -# -# "Dummy" nets are horizontal accesses to non-existing vertical span -# wires on the right edge which are listed by icebox but don't -# actually connect to anything outside the tile itself. - -def translate_netname(x, y, fw, fh, net): - def group_and_index(s, group_size): - n = int(s) - g = n // group_size - i = n % group_size - if g % 2 == 1: - i = i + 1 - (i % 2) * 2 - return g, i - - # logic and RAM tiles - - match = re.match(r'sp4_h_r_(\d+)$', net) - if match is not None: - g, i = group_and_index(match.group(1), 12) - return 'span4_y%d_g%d_%d' % (y, x - g + 4, i) - match = re.match(r'sp4_h_l_(\d+)$', net) - if match is not None: - g, i = group_and_index(match.group(1), 12) - return 'span4_y%d_g%d_%d' % (y, x - g + 3, i) - - match = re.match(r'sp4_v_b_(\d+)$', net) - if match is not None: - g, i = group_and_index(match.group(1), 12) - return 'span4_x%d_g%d_%d' % (x, y + g, i) - match = re.match(r'sp4_v_t_(\d+)$', net) - if match is not None: - g, i = group_and_index(match.group(1), 12) - return 'span4_x%d_g%d_%d' % (x, y + g + 1, i) - match = re.match(r'sp4_r_v_b_(\d+)$', net) - if match is not None: - g, i = group_and_index(match.group(1), 12) - if x == fw: - # this net doesn't connect anywhere - return 'dummy_y%d_g%d_%d' % (y, g, i) - else: - return 'span4_x%d_g%d_%d' % (x + 1, y + g, i) - - match = re.match(r'sp12_h_r_(\d+)$', net) - if match is not None: - g, i = group_and_index(match.group(1), 2) - return 'span12_y%d_g%d_%d' % (y, x - g + 12, i) - match = re.match(r'sp12_h_l_(\d+)$', net) - if match is not None: - g, i = group_and_index(match.group(1), 2) - return 'span12_y%d_g%d_%d' % (y, x - g + 11, i) - - match = re.match(r'sp12_v_b_(\d+)$', net) - if match is not None: - g, i = group_and_index(match.group(1), 2) - return 'span12_x%d_g%d_%d' % (x, y + g, i) - match = re.match(r'sp12_v_t_(\d+)$', net) - if match is not None: - g, i = group_and_index(match.group(1), 2) - return 'span12_x%d_g%d_%d' % (x, y + g + 1, i) - - # I/O tiles - - match = re.match(r'span4_horz_(\d+)$', net) - if match is not None: - g, i = group_and_index(match.group(1), 12) - if x == 0: - return 'span4_y%d_g%d_%d' % (y, x - g + 4, i) - else: - return 'span4_y%d_g%d_%d' % (y, x - g + 3, i) - - match = re.match(r'span4_vert_(\d+)$', net) - if match is not None: - g, i = group_and_index(match.group(1), 12) - if y == 0: - return 'span4_x%d_g%d_%d' % (x, y + g + 1, i) - else: - return 'span4_x%d_g%d_%d' % (x, y + g, i) - - match = re.match(r'span12_horz_(\d+)$', net) - if match is not None: - g, i = group_and_index(match.group(1), 2) - if x == 0: - return 'span12_y%d_g%d_%d' % (y, x - g + 12, i) - else: - return 'span12_y%d_g%d_%d' % (y, x - g + 11, i) - - match = re.match(r'span12_vert_(\d+)$', net) - if match is not None: - g, i = group_and_index(match.group(1), 2) - if y == 0: - return 'span12_x%d_g%d_%d' % (x, y + g + 1, i) - else: - return 'span12_x%d_g%d_%d' % (x, y + g, i) - - # I/O tiles - peripheral wires - - match = re.match(r'span4_horz_r_(\d+)$', net) - if match is not None: - n = int(match.group(1)); g = n // 4; i = n % 4 - if y == 0: - if fw - x + g - 4 < 0: - return 'span4_bottomright%d_%d' % ((fw - x + 1 + g) * 2, i) - elif x - g + 1 < 0: - return 'span4_left_g%d_%d' % (-x + 1 + g, i) - else: - return 'span4_bottom_g%d_%d' % (x + 4 - g, i) - else: - if x - g - 1 < 0: - return 'span4_topleft%d_%d' % ((x + 4 - g) * 2, i) - elif x - g + 1 >= fw: - return 'span4_right_g%d_%d' % (fh + fw - x + 1 + g, i) - else: - return 'span4_top_g%d_%d' % (x + 4 - g, i) - - match = re.match(r'span4_horz_l_(\d+)$', net) - if match is not None: - n = int(match.group(1)); g = n // 4; i = n % 4 - if y == 0: - if x - g < 0: - return 'span4_left_g%d_%d' % (-x + 2 + g, i) - else: - return 'span4_bottom_g%d_%d' % (x + 3 - g, i) - else: - if x - g - 2 < 0: - return 'span4_topleft%d_%d' % ((x + 3 - g) * 2, i) - else: - return 'span4_top_g%d_%d' % (x + 3 - g, i) - - match = re.match(r'span4_vert_b_(\d+)$', net) - if match is not None: - n = int(match.group(1)); g = n // 4; i = n % 4 - if x == 0: - if y + g - 3 < 0: - return 'span4_bottom_g%d_%d' % (-y + 5 - g, i) - if fh - y - g < 0: - return 'span4_topleft%d_%d' % ((fh + 5 - y - g) * 2, i) - else: - return 'span4_left_g%d_%d' % (y + g, i) - else: - if y + g - 5 < 0: - return 'span4_bottomright%d_%d' % ((y + g) * 2, i) - elif y + g >= fh + 3: - return 'span4_top_g%d_%d' % (fw + fh + 5 - y - g, i) - else: - return 'span4_right_g%d_%d' % (y + g, i) - - match = re.match(r'span4_vert_t_(\d+)$', net) - if match is not None: - n = int(match.group(1)); g = n // 4; i = n % 4 - if x == 0: - if fh - y - g - 1 < 0: - return 'span4_topleft%d_%d' % ((fh + 4 - y - g) * 2, i) - else: - return 'span4_left_g%d_%d' % (y + g + 1, i) - else: - if y + g >= fh + 2: - return 'span4_top_g%d_%d' % (fw + fh + 4 - y - g, i) - else: - return 'span4_right_g%d_%d' % (y + g + 1, i) - - return net - -## Return the human-readable name of the \c fabout net of IO tile -## (x, y). - -def lookup_fabout(x, y): - if (x, y) in GLB_NETWK_INTERNAL_TILES: - return 'glb_netwk_%d' % GLB_NETWK_INTERNAL_TILES.index((x, y)) - - return 'fabout' - - -## Remove an argument from a LUT string and an associated list of -## argument names. -# -# This is a helper function for \ref lut_to_logic_expression. -# -# \param lut string of 2^N `0' or `1' characters representing the -# logic of an Nx1 look-up table -# \param args list of N strings containing the human-readable names -# of the arguments -# \param i index of the argument to remove -# \param keep boolean value indicating which value of the removed -# argument is to be assumed in the resulting LUT -# -# \return a new pair (lut, args) with the argument removed - -def discard_argument(lut, args, i, keep): - assert len(lut) == 1 << len(args) - assert i >= 0 and i < len(args) - return ''.join(bit for j, bit in enumerate(lut) - if (j & (1 << i) != 0) == keep), \ - args[:i] + args[i + 1:] - -## Negate a tuple representation of a logic expression. -# -# This is a helper function for \ref lut_to_logic_expression. - -def negate_expr(expr): - if len(expr) == 2: - op, a = expr - assert op == 'not' - return a - if len(expr) != 3: - return 'not', expr - a, op, b = expr - if op == 'and': - return negate_expr(a), 'or', negate_expr(b) - if op == 'or': - return negate_expr(a), 'and', negate_expr(b) - assert op == 'xor' - if len(a) == 2 and a[0] == 'not': - return a[1], op, b - if len(b) == 2 and b[0] == 'not': - return a, op, b[1] - return negate_expr(a), op, b - -## Convert a tuple representation of a logic expression into a string. -# -# This is a helper function for \ref lut_to_logic_expression. -# -# \param expr the expression to convert -# \param parenthize whether a compound expression should be -# surrounded by parentheses - -def stringify(expr, parenthize): - if type(expr) == str: - return expr - assert type(expr) == tuple - - if len(expr) == 2: - op, a = expr - assert op == 'not' - assert type(a) == str - return "!" + a - - if len(expr) == 5: - a, op0, b, op1, c = expr - assert op0 == '?' and op1 == ':' - s = '%s ? %s : %s' % (stringify(a, False), stringify(b, False), - stringify(c, False)) - if parenthize: - return '(%s)' % s - return s - - assert len(expr) == 3 - - a, op, b = expr - l = [a, b] - i = 0 - while i < len(l): - if type(l[i]) == tuple and len(l[i]) == 3 and l[i][1] == op: - l = l[:i] + [l[i][0], l[i][2]] + l[i + 1:] - else: - i += 1 - - if op == 'and': - op = '&' - elif op == 'xor': - op = '^' - elif op == 'or': - op = '|' - - s = (' %s ' % op).join(stringify(x, True) for x in l) - if parenthize: - return '(%s)' % s - return s - -## Remove arguments which don't affect the result from a LUT string -## and an associated list of argument names. -# -# This is a helper function for \ref lut_to_logic_expression. -# -# \param lut string of 2^N `0' or `1' characters representing the -# logic of an Nx1 look-up table -# \param args list of N strings containing the human-readable names -# of the arguments -# -# \return a new pair (lut, args) with all unused arguments -# removed - -def discard_unused_arguments(lut, args): - assert len(lut) == 1 << len(args) - i = 0 - while i < len(args): - diff = False - for j in range(len(lut)): - if j & (1 << i) == 0 and lut[j] != lut[j | (1 << i)]: - diff = True - if not diff: - lut, args = discard_argument(lut, args, i, False) - else: - i += 1 - return lut, args - -## Convert a LUT string to a logic expression. -# -# \param lut string of 2^N `0' or `1' characters representing the -# logic of an Nx1 look-up table -# \param args list of N strings containing the human-readable names -# of the arguments -# -# \return a string containing a human-readable logic expression -# equivalent to the look-up table -# -# Example: lut_to_logic_expression('00010000', ['a', 'b', 'c']) -> 'a & b & !c' - -def lut_to_logic_expression(lut, args): - lut, args = discard_unused_arguments(lut, args) - - # filter out independent top-level arguments - toplevel_args = [] - i = 0 - while i < len(args) and len(args) >= 2: - ai_0 = set(bit for j, bit in enumerate(lut) if j & (1 << i) == 0) - ai_1 = set(bit for j, bit in enumerate(lut) if j & (1 << i) != 0) - assert len(ai_0) == 2 or len(ai_1) == 2 - - if len(ai_0) == 1: - # expression is constant if this argument is 0 - # e = (...) & arg or e = (...) | !arg - if tuple(ai_0)[0] == '0': - toplevel_args.append(('and', args[i])) - else: - toplevel_args.append(('or', ('not', args[i]))) - lut, args = discard_argument(lut, args, i, True) - i = 0 - continue - - if len(ai_1) == 1: - # expression is constant if this argument is 1 - # e = (...) & !arg or e = (...) | arg - if tuple(ai_1)[0] == '0': - toplevel_args.append(('and', ('not', args[i]))) - else: - toplevel_args.append(('or', args[i])) - lut, args = discard_argument(lut, args, i, False) - i = 0 - continue - - i += 1 - - i = 0 - while i < len(args) and len(args) >= 2: - is_xor = True - for j in range(len(lut)): - if j & (1 << i) == 0 and lut[j] == lut[j | (1 << i)]: - is_xor = False - break - - if is_xor: - toplevel_args.append(('xor', args[i])) - lut, args = discard_argument(lut, args, i, False) - continue - - i += 1 - - # detect simple top-level ternary conditions - i = 0 - while i < len(args) and len(args) >= 3: - j = i + 1 - while j < len(args): - ai_0_aj_0 = set(bit for k, bit in enumerate(lut) - if k & (1 << i) == 0 and k & (1 << j) == 0) - ai_0_aj_1 = set(bit for k, bit in enumerate(lut) - if k & (1 << i) == 0 and k & (1 << j) != 0) - ai_1_aj_0 = set(bit for k, bit in enumerate(lut) - if k & (1 << i) != 0 and k & (1 << j) == 0) - ai_1_aj_1 = set(bit for k, bit in enumerate(lut) - if k & (1 << i) != 0 and k & (1 << j) != 0) - assert len(ai_0_aj_0) == 2 or len(ai_0_aj_1) == 2 or \ - len(ai_1_aj_0) == 2 or len(ai_1_aj_1) == 2 - - if (len(ai_0_aj_0) == 2 or len(ai_0_aj_1) == 2) and \ - (len(ai_1_aj_0) == 2 or len(ai_1_aj_1) == 2) and \ - (len(ai_0_aj_0) == 2 or len(ai_1_aj_0) == 2) and \ - (len(ai_0_aj_1) == 2 or len(ai_1_aj_1) == 2): - j += 1 - continue - - ai_doesnt_matter_for_aj_0 = True - ai_doesnt_matter_for_aj_1 = True - aj_doesnt_matter_for_ai_0 = True - aj_doesnt_matter_for_ai_1 = True - - for k in range(len(lut)): - if k & (1 << i) != 0 or k & (1 << j) != 0: - continue - if lut[k] != lut[k | (1 << i)]: - ai_doesnt_matter_for_aj_0 = False - if lut[k | (1 << j)] != lut[k | (1 << i) | (1 << j)]: - ai_doesnt_matter_for_aj_1 = False - if lut[k] != lut[k | (1 << j)]: - aj_doesnt_matter_for_ai_0 = False - if lut[k | (1 << i)] != lut[k | (1 << i) | (1 << j)]: - aj_doesnt_matter_for_ai_1 = False - - if len(ai_0_aj_0) == 1 and len(ai_0_aj_1) == 1 and \ - aj_doesnt_matter_for_ai_1: - assert tuple(ai_0_aj_0)[0] != tuple(ai_0_aj_1)[0] - if tuple(ai_0_aj_0)[0] == '0': - toplevel_args.append((args[i], '?', ':', args[j])) - else: - toplevel_args.append((args[i], '?', ':', ('not', args[j]))) - lut, args = discard_argument(lut, args, i, True) - - # break loops - i = len(args) - j = len(args) - break - - if len(ai_1_aj_0) == 1 and len(ai_1_aj_1) == 1 and \ - aj_doesnt_matter_for_ai_0: - assert tuple(ai_1_aj_0)[0] != tuple(ai_1_aj_1)[0] - if tuple(ai_1_aj_0)[0] == '0': - toplevel_args.append((args[i], '?', args[j], ':')) - else: - toplevel_args.append((args[i], '?', ('not', args[j]), ':')) - lut, args = discard_argument(lut, args, i, False) - - # break loops - i = len(args) - j = len(args) - break - - if len(ai_0_aj_0) == 1 and len(ai_1_aj_0) == 1 and \ - ai_doesnt_matter_for_aj_1: - assert tuple(ai_0_aj_0)[0] != tuple(ai_1_aj_0)[0] - if tuple(ai_0_aj_0)[0] == '0': - toplevel_args.append((args[j], '?', ':', args[i])) - else: - toplevel_args.append((args[j], '?', ':', ('not', args[i]))) - lut, args = discard_argument(lut, args, j, True) - - # break loops - i = len(args) - j = len(args) - break - - if len(ai_0_aj_1) == 1 and len(ai_1_aj_1) == 1 and \ - ai_doesnt_matter_for_aj_0: - assert tuple(ai_0_aj_1)[0] != tuple(ai_1_aj_1)[0] - if tuple(ai_0_aj_1)[0] == '0': - toplevel_args.append((args[j], '?', args[i], ':')) - else: - toplevel_args.append((args[j], '?', ('not', args[i]), ':')) - lut, args = discard_argument(lut, args, j, False) - - # break loops - i = len(args) - j = len(args) - break - - j += 1 - i += 1 - - lut, args = discard_unused_arguments(lut, args) - - # group pairwise isolated arguments - i = 0 - while i < len(args): - j = i + 1 - while j < len(args): - ai_doesnt_matter_for_aj_0 = True - ai_doesnt_matter_for_aj_1 = True - aj_doesnt_matter_for_ai_0 = True - aj_doesnt_matter_for_ai_1 = True - both_dont_matter_if_equal = True - both_dont_matter_if_unequal = True - - for k in range(len(lut)): - if k & (1 << i) != 0 or k & (1 << j) != 0: - continue - if lut[k] != lut[k | (1 << i)]: - ai_doesnt_matter_for_aj_0 = False - if lut[k | (1 << j)] != lut[k | (1 << i) | (1 << j)]: - ai_doesnt_matter_for_aj_1 = False - if lut[k] != lut[k | (1 << j)]: - aj_doesnt_matter_for_ai_0 = False - if lut[k | (1 << i)] != lut[k | (1 << i) | (1 << j)]: - aj_doesnt_matter_for_ai_1 = False - if lut[k] != lut[k | (1 << i) | (1 << j)]: - both_dont_matter_if_equal = False - if lut[k | (1 << i)] != lut[k | (1 << j)]: - both_dont_matter_if_unequal = False - - # There are five possibilities of coupled arguments: one - # of the four combinations differs from the other three, - # or they are xor'ed - - if ai_doesnt_matter_for_aj_1 and \ - aj_doesnt_matter_for_ai_1 and \ - both_dont_matter_if_unequal: - # special case is ai=0 aj=0 - args = args[:i] + ((args[i], 'or', args[j]), ) + args[i + 1:] - lut, args = discard_argument(lut, args, j, False) - j = i + 1 - elif ai_doesnt_matter_for_aj_1 and \ - aj_doesnt_matter_for_ai_0 and \ - both_dont_matter_if_equal: - # special case is ai=1 aj=0 - args = args[:i] + ((args[i], 'and', negate_expr(args[j])), ) + \ - args[i + 1:] - lut, args = discard_argument(lut, args, j, False) - j = i + 1 - elif ai_doesnt_matter_for_aj_0 and \ - aj_doesnt_matter_for_ai_1 and \ - both_dont_matter_if_equal: - # special case is ai=0 aj=1 - args = args[:i] + ((args[i], 'or', negate_expr(args[j])), ) + \ - args[i + 1:] - lut, args = discard_argument(lut, args, j, True) - j = i + 1 - elif ai_doesnt_matter_for_aj_0 and \ - aj_doesnt_matter_for_ai_0 and \ - both_dont_matter_if_unequal: - # special case is ai=1 aj=1 - args = args[:i] + ((args[i], 'and', args[j]), ) + args[i + 1:] - lut, args = discard_argument(lut, args, j, True) - j = i + 1 - - elif both_dont_matter_if_equal and \ - both_dont_matter_if_unequal: - args = args[:i] + ((args[i], 'xor', args[j]), ) + args[i + 1:] - lut, args = discard_argument(lut, args, j, False) - j = i + 1 - else: - j += 1 - i += 1 - - # collect the result - - if not args: - # constant expression - assert len(lut) == 1 - return lut - - negate_result = lut.count('1') > lut.count('0') - if negate_result: - lut = ''.join('1' if bit == '0' else '0' for bit in lut) - - result = None - for i, bit in enumerate(lut): - if bit == '0': - continue - expr = None - for j, arg in enumerate(args): - if i & (1 << j) == 0: - arg = negate_expr(arg) - if expr is None: - expr = arg - else: - expr = (expr, 'and', arg) - if result is None: - result = expr - else: - result = (result, 'or', expr) - - if negate_result: - result = negate_expr(result) - - for toplevel_arg in reversed(toplevel_args): - if len(toplevel_arg) != 4: - result = tuple(reversed(toplevel_arg)) + (result, ) - elif toplevel_arg[2] == ':': - result = toplevel_arg[0:2] + (result, ) + toplevel_arg[2:4] - else: - assert toplevel_arg[3] == ':' - result = toplevel_arg + (result, ) - - return stringify(result, False) - - -class Fabric: - def __init__(self, ic): - self.ic = ic - self.tiles = {} - #self.colbuf = set() - - io_blocks = {} - ieren_blocks = {} - - for x0, y0, b0, x1, y1, b1 in self.ic.ieren_db(): - i = IOBlock() - assert (x0, y0, b0) not in io_blocks - io_blocks[x0, y0, b0] = i - assert (x1, y1, b1) not in ieren_blocks - ieren_blocks[x1, y1, b1] = i - - for xy in ic.io_tiles: - assert xy not in self.tiles - self.tiles[xy] = IOTile(self, xy, - (io_blocks.pop((xy[0], xy[1], 0), None), - io_blocks.pop((xy[0], xy[1], 1), None)), - (ieren_blocks.pop((xy[0], xy[1], 0), None), - ieren_blocks.pop((xy[0], xy[1], 1), None))) - assert not io_blocks - assert not ieren_blocks - - for xy in ic.logic_tiles: - assert xy not in self.tiles - self.tiles[xy] = LogicTile(self, xy) - - for xy in ic.ramb_tiles: - assert xy not in self.tiles - self.tiles[xy] = RAMBTile(self, xy) - - for xy in ic.ramt_tiles: - assert xy not in self.tiles - self.tiles[xy] = RAMTTile(self, xy) - - for x, y in self.tiles: - assert x >= 0 and x <= self.ic.max_x - assert y >= 0 and y <= self.ic.max_y - for x in range(self.ic.max_x + 1): - for y in range(self.ic.max_y + 1): - should_exist = (x > 0 and x < self.ic.max_x) or \ - (y > 0 and y < self.ic.max_y) - assert ((x, y) in self.tiles) == should_exist - - for xy in ic.ram_data: - assert type(self.tiles.get(xy, None)) == RAMBTile - - #colbuf_db = ic.colbuf_db() - #for x, y, i in self.colbuf: - # exists = False - # for src_x, src_y, dst_x, dst_y in colbuf_db: - # if src_x != x or src_y != y: - # continue - # assert (dst_x, dst_y) in self.tiles - # assert not self.tiles[dst_x, dst_y].colbuf[i] - # self.tiles[dst_x, dst_y].colbuf[i] = True - # exists = True - # assert exists - # - #for xy in self.tiles: - # for br in self.tiles[xy].buffer_and_routing: - # if br[0].startswith('glb_netwk_'): - # assert self.tiles[xy].colbuf[int(br[0][10:])] - - for bit in self.ic.extra_bits: - directive, arg = self.ic.lookup_extra_bit(bit) - assert directive == 'padin_glb_netwk' - x, y, n = GLB_NETWK_EXTERNAL_BLOCKS[int(arg)] - assert type(self.tiles.get((x, y), None)) == IOTile - block = self.tiles[x, y].io_blocks[n] - assert block is not None - block.padin_glb_netwk = True - - def printout(self, options): - print('device "%s" %d %d' % (self.ic.device, self.ic.max_x - 1, - self.ic.max_y - 1)) - - print('') - # internal_configuration_oscillator_frequency = low | medium | high - #print('coldboot = off') - print('warmboot = on') # IceStorm assumes this to be always on - - for xy in sorted(self.tiles.keys(), key = lambda xy: (xy[1], xy[0])): - self.tiles[xy].printout(options) - -class Tile: - def __init__(self, fabric, xy, data, is_logic_block): - self.fabric = fabric - self.ic = fabric.ic - self.xy = xy - self.data = data - - self.buffer_and_routing = set() - self.used_buffer_and_routing = set() - self.text = set() - self.bitinfo = list() - self.unknown_bits = False - - x, y = xy - db = self.ic.tile_db(x, y) - mapped_bits = set() - - # 'data' is a list of strings containing a series of zeroes and - # ones. 'bits' is a set of strings containing an entry - # "B[]" or "!B[]" for each bit. - - bits = set() - for k, line in enumerate(data): - for i in range(len(line)): - if line[i] == '1': - bits.add('B%d[%d]' % (k, i)) - else: - bits.add('!B%d[%d]' % (k, i)) - - for entry in db: - # LC bits don't have a useful entry in the database; skip them - # for now - if re.match(r'LC_', entry[1]): - continue - - # some nets have different names depending on the tile; filter - # out non-applicable net names - if entry[1] in ('routing', 'buffer') and ( - not self.ic.tile_has_net(x, y, entry[2]) or - not self.ic.tile_has_net(x, y, entry[3])): - continue - - # are all required bits set/unset? - match = True - for bit in entry[0]: - if not bit in bits: - match = False - if match: - for bit in entry[0]: - mapped_bits.add(bit) - - if entry[1:] == ['IoCtrl', 'IE_0']: - if match != (self.ic.device == '1k'): - self.ieren_blocks[0].enable_input = True - continue - if entry[1:] == ['IoCtrl', 'REN_0']: - if match: - self.ieren_blocks[0].disable_pull_up = True - continue - if entry[1:] == ['IoCtrl', 'IE_1']: - if match != (self.ic.device == '1k'): - self.ieren_blocks[1].enable_input = True - continue - if entry[1:] == ['IoCtrl', 'REN_1']: - if match: - self.ieren_blocks[1].disable_pull_up = True - continue - - if entry[1].startswith('IOB_') and entry[2].startswith('PINTYPE_'): - if match: - self.io_blocks[int(entry[1][4:])].pintype \ - |= 1 << int(entry[2][8:]) - continue - - if entry[1:] == ['RamConfig', 'PowerUp']: - if match != (self.ic.device == '1k'): - self.text.add('power_up') - continue - - if entry[1] == 'routing': - if match: - src = translate_netname(self.xy[0], self.xy[1], - self.ic.max_x - 1, - self.ic.max_y - 1, entry[2]) - dst = translate_netname(self.xy[0], self.xy[1], - self.ic.max_x - 1, - self.ic.max_y - 1, entry[3]) - if dst == 'fabout': - dst = lookup_fabout(*self.xy) - self.buffer_and_routing.add((src, '<->', dst)) - continue - if entry[1] == 'buffer': - if match: - src = translate_netname(self.xy[0], self.xy[1], - self.ic.max_x - 1, - self.ic.max_y - 1, entry[2]) - dst = translate_netname(self.xy[0], self.xy[1], - self.ic.max_x - 1, - self.ic.max_y - 1, entry[3]) - if dst == 'fabout': - dst = lookup_fabout(*self.xy) - self.buffer_and_routing.add((src, '->', dst)) - continue - - if entry[1] == 'ColBufCtrl': - assert entry[2].startswith('glb_netwk_') - #if match: - # fabric.colbuf.add(self.xy + (int(entry[2][10:]), )) - continue - - if match: - self.text.add(' '.join(entry[1:])) - - for prefix in ('local_', 'glb2local_'): - for fst in [fst for fst in self.buffer_and_routing - if fst[-1].startswith(prefix)]: - used = False - for snd in [snd for snd in self.buffer_and_routing - if snd[0] == fst[-1]]: - self.buffer_and_routing.remove(snd) - self.buffer_and_routing.add(fst[:-1] + snd) - used = True - if used: - self.buffer_and_routing.remove(fst) - - for k, line in enumerate(data): - self.bitinfo.append('') - extra_text = '' - for i in range(len(line)): - if 36 <= i <= 45 and is_logic_block: - self.bitinfo[-1] += '*' if line[i] == '1' else '-' - elif line[i] == '1' and 'B%d[%d]' % (k, i) not in mapped_bits: - self.unknown_bits = True - extra_text += ' B%d[%d]' % (k, i) - self.bitinfo[-1] += '?' - else: - self.bitinfo[-1] += '+' if line[i] == '1' else '-' - self.bitinfo[-1] += extra_text - - def get_hlc(self): - return sorted(set.union(self.text, - set(' '.join(t) - for t in set.difference( - self.buffer_and_routing, - self.used_buffer_and_routing)))) - - def printout(self, stmt, options): - text = self.get_hlc() - if text or self.unknown_bits or options.print_all: - if self.unknown_bits or options.print_map: - print() - if self.unknown_bits: - print("; Warning: No DB entries for some bits:") - for k, line in enumerate(self.bitinfo): - print("; %4s %s" % ('B%d' % k, line)) - print() - print("%s %d %d {" % (stmt, self.xy[0], self.xy[1])) - for line in text: - print(" " + line) - print("}") - -class LogicCell: - def __init__(self, tile, lcidx): - self.lut = ''.join(icebox.get_lutff_lut_bits(tile.data, lcidx)) - self.expr = lut_to_logic_expression( - self.lut, ('in_0', 'in_1', 'in_2', 'in_3')) - - self.options = [] - lutff_option_bits = ''.join(icebox.get_lutff_seq_bits(tile.data, lcidx)) - if lutff_option_bits[0] == '1': self.options.append('enable_carry') - if lutff_option_bits[1] == '1': self.options.append('enable_dff') - if lutff_option_bits[2] == '1': self.options.append('set_noreset') - if lutff_option_bits[3] == '1': self.options.append('async_setreset') - - self.buffer_and_routing0 = set() - self.buffer_and_routing1 = set() - for br in tuple(tile.buffer_and_routing): - if br[0] == 'lutff_%d/out' % lcidx: - self.buffer_and_routing1.add((br[0][8:], ) + br[1:]) - tile.used_buffer_and_routing.add(br) - elif br[-1].startswith('lutff_%d/' % lcidx): - self.buffer_and_routing0.add(br[:-1] + (br[-1][8:], )) - tile.used_buffer_and_routing.add(br) - - def get_hlc(self): - if self.lut == '0000000000000000' and not self.options: - t = [] - elif len(self.expr) > 64: - t = ['lut ' + self.lut] - else: - t = ['out = ' + self.expr] - return [' '.join(t) for t in sorted(self.buffer_and_routing0, - key = lambda x: x[-1])] + \ - t + self.options + \ - [' '.join(t) for t in sorted(self.buffer_and_routing1, - key = lambda x: x[-1])] - -class LogicTile(Tile): - def __init__(self, fabric, xy): - super().__init__(fabric, xy, fabric.ic.logic_tiles[xy], True) - self.cells = tuple(LogicCell(self, lcidx) for lcidx in range(8)) - - def get_hlc(self): - text = super().get_hlc() - - for i, cell in reversed(tuple(enumerate(self.cells))): - t = cell.get_hlc() - if t: - text = ['lutff_%d {' % i] + \ - [' %s' % s for s in t] + \ - ['}'] + \ - text - - return text - - def printout(self, options): - super().printout('logic_tile', options) - -class IOBlock: - def __init__(self): - # stored in the I/O tile where this block is located - self.pintype = 0 - - # stored in the I/O tile where this is an IE/REN block - self.enable_input = False - self.disable_pull_up = False - - # stored as an extra bit - self.padin_glb_netwk = False - -class IOTile(Tile): - def __init__(self, fabric, xy, io_blocks, ieren_blocks): - self.io_blocks = io_blocks - self.ieren_blocks = ieren_blocks - super().__init__(fabric, xy, fabric.ic.io_tiles[xy], False) - #self.cells = tuple(IOCell() for i in range(2)) - - for i, block in enumerate(io_blocks): - if block is None: - continue - block.buffer_and_routing0 = set() - block.buffer_and_routing1 = set() - for br in tuple(self.buffer_and_routing): - if br[0].startswith('io_%d/D_IN_' % i): - block.buffer_and_routing1.add((br[0][5:], ) + br[1:]) - self.used_buffer_and_routing.add(br) - elif br[-1].startswith('io_%d/' % i): - block.buffer_and_routing0.add(br[:-1] + (br[-1][5:], )) - self.used_buffer_and_routing.add(br) - - def get_hlc(self): - # if io_blocks[N] is None, this means there's no I/O pin there - - text = super().get_hlc() - for n in (1, 0): - block = self.io_blocks[n] - if block is None: - continue - - t = [] - input_pt = block.pintype & 3 - output_pt = block.pintype >> 2 & 15 - unknown_pt = block.pintype >> 6 - if input_pt != 0: - t.append('input_pin_type = %s' % ( - 'registered_pin', - 'simple_input_pin', - 'latched_registered_pin', - 'latched_pin')[input_pt]) - if output_pt != 0: - t.append('output_pin_type = %s' % ( - 'no_output', - '1', - '2', - '3', - 'DDR', - 'REGISTERED', - 'simple_output_pin', - 'REGISTERED_INVERTED', - 'DDR_ENABLE', - 'REGISTERED_ENABLE', - 'OUTPUT_TRISTATE', - 'REGISTERED_ENABLE_INVERTED', - 'DDR_ENABLE_REGISTERED', - 'REGISTERED_ENABLE_REGISTERED', - 'ENABLE_REGISTERED', - 'REGISTERED_ENABLE_REGISTERED_INVERTED')[output_pt]) - if unknown_pt != 0: - t.append('unknown_pin_type = %d' % unknown_pt) - if block.enable_input: - t.append('enable_input') - if block.disable_pull_up: - t.append('disable_pull_up') - - t += [' '.join(t) for t in sorted(block.buffer_and_routing0, - key = lambda x: x[-1])] - t += [' '.join(t) for t in sorted(block.buffer_and_routing1, - key = lambda x: x[0])] - if block.padin_glb_netwk: - t += ['GLOBAL_BUFFER_OUTPUT -> glb_netwk_%d' - % GLB_NETWK_EXTERNAL_BLOCKS.index(self.xy + (n, ))] - - if t: - text = ['io_%d {' % n] + \ - [' %s' % s for s in t] + \ - ['}'] + \ - text - - return text - - def printout(self, options): - super().printout('io_tile', options) - -class IOCell: - pass - -class RAMBTile(Tile): - def __init__(self, fabric, xy): - super().__init__(fabric, xy, fabric.ic.ramb_tiles[xy], False) - if xy in fabric.ic.ram_data: - self.data = fabric.ic.ram_data[xy] - else: - self.data = None - - def get_hlc(self): - text = super().get_hlc() - if self.data is not None: - text.append('') - text.append('data {') - for line in self.data: - text.append(' ' + line) - text.append('}') - return text - - def printout(self, options): - super().printout('ramb_tile', options) - -class RAMTTile(Tile): - def __init__(self, fabric, xy): - super().__init__(fabric, xy, fabric.ic.ramt_tiles[xy], False) - - def printout(self, options): - super().printout('ramt_tile', options) - - -class Options: - def __init__(self): - self.print_map = False - self.print_all = False - -def main(): - program_short_name = os.path.basename(sys.argv[0]) - options = Options() - - try: - opts, args = getopt.getopt(sys.argv[1:], 'mA', ['help', 'version']) - except getopt.GetoptError as e: - sys.stderr.write("%s: %s\n" % (program_short_name, e.msg)) - sys.stderr.write("Try `%s --help' for more information.\n" - % sys.argv[0]) - sys.exit(1) - - for opt, arg in opts: - if opt == '--help': - sys.stderr.write("""\ -Create a high-level representation from an ASCII bitstream. -Usage: %s [OPTION]... FILE - - -m print tile config bitmaps - -A don't skip uninteresting tiles - - --help display this help and exit - --version output version information and exit - -If you have a bug report, please file an issue on github: - https://github.com/rlutz/icestorm/issues -""" % sys.argv[0]) - sys.exit(0) - - if opt == '--version': - sys.stderr.write("""\ -icebox_asc2hlc - create a high-level representation from an ASCII bitstream -Copyright (C) 2017 Roland Lutz - -This program is free software: you can redistribute it and/or -modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of -the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. -""") - sys.exit(0) - - if opt == '-m': - options.print_map = True - elif opt == '-A': - options.print_all = True - - if not args: - sys.stderr.write("%s: missing argument\n" % (program_short_name)) - sys.stderr.write("Try `%s --help' for more information.\n" - % sys.argv[0]) - sys.exit(1) - - if len(args) != 1: - sys.stderr.write("%s: too many arguments\n" % (program_short_name)) - sys.stderr.write("Try `%s --help' for more information.\n" - % sys.argv[0]) - sys.exit(1) - - ic = icebox.iceconfig() - if args[0] == '-': - ic.read_file('/dev/stdin') - else: - ic.read_file(args[0]) - - fabric = Fabric(ic) - fabric.printout(options) - -if __name__ == '__main__': - main() diff --git a/icebox/icebox_hlc2asc.py b/icebox/icebox_hlc2asc.py deleted file mode 100755 index 54d6722..0000000 --- a/icebox/icebox_hlc2asc.py +++ /dev/null @@ -1,1052 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (C) 2017 Roland Lutz -# -# This program is free software: you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation, either version 3 of -# the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -import getopt, os, re, sys -import icebox - -GLB_NETWK_EXTERNAL_BLOCKS = [(13, 8, 1), (0, 8, 1), (7, 17, 0), (7, 0, 0), - (0, 9, 0), (13, 9, 0), (6, 0, 1), (6, 17, 1)] -GLB_NETWK_INTERNAL_TILES = [(7, 0), (7, 17), (13, 9), (0, 9), - (6, 17), (6, 0), (0, 8), (13, 8)] - - -## Get the tile-local name of a net. -# -# \param x, y coordinates of the tile to which the net belongs -# \param fw, fh width and height of the tile fabric (excluding I/O tiles) -# \param net global net name -# -# \return the tile-local name of the net if it is a span wire, -# otherwise the unmodified net name - -def untranslate_netname(x, y, fw, fh, net): - def index(g, i, group_size): - if g % 2 == 1: - i = i + 1 - (i % 2) * 2 - return g * group_size + i - - match = re.match(r'span4_y(\d+)_g(\d+)_(\d+)$', net) - if match is not None: - my = int(match.group(1)) - mw = int(match.group(2)) - mi = int(match.group(3)) - assert my == y - assert mi >= 0 and mi < 12 - - mg = x - mw + 4 - assert mg >= 0 and mg <= 4 - - if x == 0: - return 'span4_horz_%d' % index(mg, mi, 12) - if x == fw + 1: - return 'span4_horz_%d' % index(mg - 1, mi, 12) - - if mg == 4: - return 'sp4_h_l_%d' % index(mg - 1, mi, 12) - else: - return 'sp4_h_r_%d' % index(mg, mi, 12) - - match = re.match(r'span4_x(\d+)_g(\d+)_(\d+)$', net) - if match is not None: - mx = int(match.group(1)) - mw = int(match.group(2)) - mi = int(match.group(3)) - assert mi >= 0 and mi < 12 - mg = mw - y - assert mg >= 0 and mg <= 4 - - if y == 0: - return 'span4_vert_%d' % index(mg - 1, mi, 12) - if y == fh + 1: - return 'span4_vert_%d' % index(mg, mi, 12) - - if mx == x + 1: - assert mg < 4 - return 'sp4_r_v_b_%d' % index(mg, mi, 12) - - assert mx == x - if mg == 4: - return 'sp4_v_t_%d' % index(mg - 1, mi, 12) - else: - return 'sp4_v_b_%d' % index(mg, mi, 12) - - match = re.match(r'dummy_y(\d+)_g(\d+)_(\d+)$', net) - if match is not None: - my = int(match.group(1)) - mw = int(match.group(2)) - mi = int(match.group(3)) - assert my == y - - mg = mw - assert mg >= 0 and mg < 4 - - return 'sp4_r_v_b_%d' % index(mg, mi, 12) - - match = re.match(r'span12_y(\d+)_g(\d+)_(\d+)$', net) - if match is not None: - my = int(match.group(1)) - mw = int(match.group(2)) - mi = int(match.group(3)) - assert my == y - assert mi >= 0 and mi < 2 - - mg = x - mw + 12 - assert mg >= 0 and mg <= 12 - - if x == 0: - return 'span12_horz_%d' % index(mg, mi, 2) - if x == fw + 1: - return 'span12_horz_%d' % index(mg - 1, mi, 2) - - if mg == 12: - return 'sp12_h_l_%d' % index(mg - 1, mi, 2) - else: - return 'sp12_h_r_%d' % index(mg, mi, 2) - - match = re.match(r'span12_x(\d+)_g(\d+)_(\d+)$', net) - if match is not None: - mx = int(match.group(1)) - mw = int(match.group(2)) - mi = int(match.group(3)) - assert mx == x - assert mi >= 0 and mi < 2 - - mg = mw - y - assert mg >= 0 and mg <= 12 - - if y == 0: - return 'span12_vert_%d' % index(mg - 1, mi, 2) - if y == fh + 1: - return 'span12_vert_%d' % index(mg, mi, 2) - - if mg == 12: - return 'sp12_v_t_%d' % index(mg - 1, mi, 2) - else: - return 'sp12_v_b_%d' % index(mg, mi, 2) - - match = re.match(r'span4_bottom_g(\d+)_(\d+)$', net) - if match is not None: - mw = int(match.group(1)) - mi = int(match.group(2)) - assert mi >= 0 and mi < 4 - - if x == 0: - assert y != 0 - mg = -y + 5 - mw - assert y + mg - 3 < 0 - return 'span4_vert_b_%d' % (mg * 4 + mi) - else: - assert y == 0 - mg = x + 4 - mw - assert x - mg + 1 >= 0 - - if mg == 4: - return 'span4_horz_l_%d' % (mg * 4 + mi - 4) - else: - assert fw - x + mg - 4 >= 0 - return 'span4_horz_r_%d' % (mg * 4 + mi) - - match = re.match(r'span4_left_g(\d+)_(\d+)$', net) - if match is not None: - mw = int(match.group(1)) - mi = int(match.group(2)) - assert mi >= 0 and mi < 4 - - if y == 0: - assert x != 0 - mg = mw + x - 1 - assert x - mg + 1 < 0 - - if mg == 4: - return 'span4_horz_l_%d' % (mg * 4 + mi - 4) - else: - assert fw - x + mg - 4 >= 0 - return 'span4_horz_r_%d' % (mg * 4 + mi) - - else: - assert x == 0 - mg = mw - y - assert fh - y - mg >= 0 - - if mg == 4: - return 'span4_vert_t_%d' % (mg * 4 + mi - 4) - else: - assert y + mg - 3 >= 0 - return 'span4_vert_b_%d' % (mg * 4 + mi) - - match = re.match(r'span4_right_g(\d+)_(\d+)$', net) - if match is not None: - mw = int(match.group(1)) - mi = int(match.group(2)) - assert mi >= 0 and mi < 4 - - if y == fh + 1: - mg = mw - fh - fw + x - 1 - assert x - mg - 1 >= 0 - assert x - mg + 1 >= fw - return 'span4_horz_r_%d' % (mg * 4 + mi) - - assert x == fw + 1 - mg = mw - y - - if mg == 4: - assert y + mg - 1 < fh + 2 - return 'span4_vert_t_%d' % (mg * 4 + mi - 4) - else: - assert y + mg - 5 >= 0 - assert y + mg < fh + 3 - return 'span4_vert_b_%d' % (mg * 4 + mi) - - match = re.match(r'span4_top_g(\d+)_(\d+)$', net) - if match is not None: - mw = int(match.group(1)) - mi = int(match.group(2)) - assert mi >= 0 and mi < 4 - - if x == fw + 1: - assert y != 0 - mg = fw + fh + 5 - y - mw - assert y + mg >= fh + 3 - - if mg == 4: - return 'span4_vert_t_%d' % (mg * 4 + mi - 4) - else: - assert y + mg - 5 >= 0 - return 'span4_vert_b_%d' % (mg * 4 + mi) - - assert y != 0 - mg = x + 4 - mw - assert x - mg - 1 >= 0 - - if mg == 4: - return 'span4_horz_l_%d' % (mg * 4 + mi - 4) - else: - assert x - mg + 1 < fw - return 'span4_horz_r_%d' % (mg * 4 + mi) - - match = re.match(r'span4_bottomright(\d+)_(\d+)$', net) - if match is not None: - mw = int(match.group(1)) - mi = int(match.group(2)) - assert mw % 2 == 0 - assert mi >= 0 and mi < 4 - - if y == 0: - assert x != 0 - mg = mw // 2 - fw + x - 1 - assert fw - x + mg - 4 < 0 - return 'span4_horz_r_%d' % (mg * 4 + mi) - else: - assert x == fw + 1 - mg = mw // 2 - y - assert y + mg - 5 < 0 - return 'span4_vert_b_%d' % (mg * 4 + mi) - - match = re.match(r'span4_topleft(\d+)_(\d+)$', net) - if match is not None: - mw = int(match.group(1)) - mi = int(match.group(2)) - assert mw % 2 == 0 - assert mi >= 0 and mi < 4 - - if x == 0: - assert y != 0 - mg = fh + 5 - y - mw // 2 - assert fh - y - mg < 0 - - if mg == 4: - return 'span4_vert_t_%d' % (mg * 4 + mi - 4) - else: - return 'span4_vert_b_%d' % (mg * 4 + mi) - else: - assert y == fh + 1 - mg = x + 4 - mw // 2 - assert x - mg - 1 < 0 - - if mg == 4: - return 'span4_horz_l_%d' % (mg * 4 + mi - 4) - else: - return 'span4_horz_r_%d' % (mg * 4 + mi) - - return net - -## Check if the name of a destination net is the human-readable form -## of the \c fabout net of IO tile (x, y). -# -# \return \c 'fabout' if it is the \c fabout net, otherwise the -# unchanged net name - -def revert_to_fabout(x, y, net): - if net.startswith('glb_netwk_'): - for i, xy in enumerate(GLB_NETWK_INTERNAL_TILES): - if net == 'glb_netwk_%d' % i and (x, y) == xy: - return 'fabout' - raise ParseError - - return net - - -EXPR_AND, EXPR_XOR, EXPR_OR, EXPR_TERN, EXPR_NOT, EXPR_ZERO, EXPR_ONE = range(7) - -## Evaluate a list representation of a logic expression for given -## input values. -# -# This is a helper function for \ref logic_expression_to_lut. -# -# \param expr list representation of a logic expression (see below) -# \param args list of boolean values representing the input values -# -# \result \c False or \c True, depending on the expression and arguments -# -# Expression | Result -# ---------------------------------------+---------------------------------- -# i | value of argument \a i -# (EXPR_AND, [expr, ...]) | AND operation of all expressions -# (EXPR_XOR, [expr, ...]) | XOR operation of all expressions -# (EXPR_OR, [expr, ...]) | OR operation of all expressions -# (EXPR_TERN, ex_a, ex_b, ex_c) | result of \c ex_b if \c ex_a -# | evaluates to \c True, otherwise -# | result of \c ex_c -# (EXPR_NOT, expr) | negated result of \a expr -# (EXPR_ZERO, ) | \c False -# (EXPR_ONE, ) | \c True - -def evaluate(expr, args): - if type(expr) == int: - return args[expr] - - op = expr[0] - - if op == EXPR_AND: - assert len(expr) == 2 - for o in expr[1]: - if not evaluate(o, args): - return False - return True - - if op == EXPR_XOR: - assert len(expr) == 2 - result = False - for o in expr[1]: - if evaluate(o, args): - result = not result - return result - - if op == EXPR_OR: - assert len(expr) == 2 - for o in expr[1]: - if evaluate(o, args): - return True - return False - - if op == EXPR_TERN: - assert len(expr) == 4 - if evaluate(expr[1], args): - return evaluate(expr[2], args) - else: - return evaluate(expr[3], args) - - if op == EXPR_NOT: - assert len(expr) == 2 - return not evaluate(expr[1], args) - - if op == EXPR_ZERO: - assert len(expr) == 1 - return False - - if op == EXPR_ONE: - assert len(expr) == 1 - return True - - assert False # unknown operator - -## Convert a logic expression to a LUT string. -# -# \param lut string containing a human-readable logic expression -# \param args list of N strings containing the names of the arguments -# -# \return a string of 2^N `0' or `1' characters representing the logic -# of an Nx1 look-up table equivalent to the logic expression -# -# Example: logic_expression_to_lut('a & b & !c', ['a', 'b', 'c']) -> '00010000' - -def logic_expression_to_lut(s, args): - # make sure argument names are unique - assert len(set(args)) == len(args) - - stack = [[None, None, None], [[], None, None]] - stack[0][2] = l = []; stack[1][0].append((EXPR_OR, l)) - stack[0][1] = l = []; stack[0][2].append((EXPR_XOR, l)) - stack[0][0] = l = []; stack[0][1].append((EXPR_AND, l)) - expect_expr = True - negate_count = 0 - - i = 0 - while i < len(s): - if s[i] == ' ': - pass - elif s[i] == '!': - assert expect_expr - negate_count += 1 - elif s[i] == '&': - assert not expect_expr - - expect_expr = True - negate_count = 0 - elif s[i] == '^': - assert not expect_expr - - stack[0][0] = l = []; stack[0][1].append((EXPR_AND, l)) - - expect_expr = True - negate_count = 0 - elif s[i] == '|': - assert not expect_expr - - stack[0][1] = l = []; stack[0][2].append((EXPR_XOR, l)) - stack[0][0] = l = []; stack[0][1].append((EXPR_AND, l)) - - expect_expr = True - negate_count = 0 - elif s[i] == '?': - assert not expect_expr - assert stack[1][0][-1][0] == EXPR_OR - stack[1][0][-1] = (EXPR_TERN, stack[1][0][-1], (EXPR_OR, []), - (EXPR_OR, [])) - stack[0][2] = l = stack[1][0][-1][2][1] - stack[0][1] = l = []; stack[0][2].append((EXPR_XOR, l)) - stack[0][0] = l = []; stack[0][1].append((EXPR_AND, l)) - - expect_expr = True - negate_count = 0 - elif s[i] == ':': - assert not expect_expr - assert stack[1][0][-1][0] == EXPR_TERN - stack[0][2] = l = stack[1][0][-1][3][1] - stack[0][1] = l = []; stack[0][2].append((EXPR_XOR, l)) - stack[0][0] = l = []; stack[0][1].append((EXPR_AND, l)) - - expect_expr = True - negate_count = 0 - elif s[i] == '(': - assert expect_expr - - stack.insert(0, [None, None, None]) - - stack[0][2] = l = [] - if negate_count % 2: - stack[1][0].append((EXPR_NOT, (EXPR_OR, l))) - else: - stack[1][0].append((EXPR_OR, l)) - - stack[0][1] = l = []; stack[0][2].append((EXPR_XOR, l)) - stack[0][0] = l = []; stack[0][1].append((EXPR_AND, l)) - - expect_expr = True - negate_count = 0 - - elif s[i] == ')': - assert not expect_expr - stack.pop(0) - - elif s[i] == '0': - assert expect_expr - if negate_count % 2: - stack[0][0].append((EXPR_ONE, )) - else: - stack[0][0].append((EXPR_ZERO, )) - - expect_expr = False - negate_count = None - - elif s[i] == '1': - assert expect_expr - if negate_count % 2: - stack[0][0].append((EXPR_ZERO, )) - else: - stack[0][0].append((EXPR_ONE, )) - - expect_expr = False - negate_count = None - - else: - assert expect_expr - - found = None - for j, arg in enumerate(args): - if s.startswith(arg, i): - found = j - i += len(arg) - break - assert found is not None - - if negate_count % 2: - stack[0][0].append((EXPR_NOT, found)) - else: - stack[0][0].append(found) - - expect_expr = False - negate_count = None - continue - - i += 1 - - assert len(stack) == 2 - return ''.join('1' if evaluate(stack[1][0][0], - tuple(i & (1 << j) != 0 - for j in range(len(args)))) else '0' - for i in range(1 << len(args))) - - -class ParseError(Exception): - pass - -def parse_bool(s): - if s == 'on': - return True - if s == 'off': - return False - raise ParseError - -class Main: - def __init__(self): - self.ic = None - self.device = None - #self.coldboot = None - self.warmboot = None - self.tiles = {} - - def read(self, fields): - if fields[0] == 'device' and len(fields) == 4 \ - and len(fields[1]) >= 2 and fields[1][0] == '"' \ - and fields[1][-1] == '"' \ - and self.ic is None and self.device is None: - self.device = fields[1][1:-1] - if self.device == '1k': - self.ic = icebox.iceconfig() - self.ic.setup_empty_1k() - elif self.device == '8k': - self.ic = icebox.iceconfig() - self.ic.setup_empty_8k() - elif self.device == '384': - self.ic = icebox.iceconfig() - self.ic.setup_empty_384() - else: - raise ParseError - #elif fields[0] == 'coldboot' and fields[1] == '=' \ - # and self.coldboot is None: - # # parsed but ignored (can't be represented in IceStorm .asc format) - # self.coldboot = parse_bool(fields[2]) - elif fields[0] == 'warmboot' and fields[1] == '=' \ - and self.warmboot is None: - # parsed but ignored (can't be represented in IceStorm .asc format) - self.warmboot = parse_bool(fields[2]) - else: - raise ParseError - - def new_block(self, fields): - if len(fields) != 3: - raise ParseError - x = int(fields[1]) - y = int(fields[2]) - if (x, y) in self.tiles: - return self.tiles[x, y] - if fields[0] == 'logic_tile': - if (x, y) not in self.ic.logic_tiles: - raise ParseError - tile = LogicTile(self.ic, x, y) - elif fields[0] == 'ramb_tile': - if (x, y) not in self.ic.ramb_tiles: - raise ParseError - tile = RAMBTile(self.ic, x, y) - elif fields[0] == 'ramt_tile': - if (x, y) not in self.ic.ramt_tiles: - raise ParseError - tile = RAMTTile(self.ic, x, y) - elif fields[0] == 'io_tile': - if (x, y) not in self.ic.io_tiles: - raise ParseError - tile = IOTile(self.ic, x, y) - else: - raise ParseError - self.tiles[x, y] = tile - return tile - - def writeout(self): - if self.ic is None: - raise ParseError - - # fix up IE/REN bits - unused_ieren = set() - - for x in range(1, self.ic.max_x): - unused_ieren.add((x, 0, 0)) - unused_ieren.add((x, 0, 1)) - unused_ieren.add((x, self.ic.max_y, 0)) - unused_ieren.add((x, self.ic.max_y, 1)) - - for y in range(1, self.ic.max_y): - unused_ieren.add((0, y, 0)) - unused_ieren.add((0, y, 1)) - unused_ieren.add((self.ic.max_x, y, 0)) - unused_ieren.add((self.ic.max_x, y, 1)) - - for x0, y0, b0, x1, y1, b1 in self.ic.ieren_db(): - if (x0, y0) in self.tiles: - io_tile = self.tiles[x0, y0] - else: - io_tile = IOTile(self.ic, x0, y0) - self.tiles[x0, y0] = io_tile - if io_tile.blocks[b0] is not None: - io_block = io_tile.blocks[b0] - else: - io_block = IOBlock(io_tile, b0) - io_tile.blocks[b0] = io_block - - if (x1, y1) in self.tiles: - ieren_tile = self.tiles[x1, y1] - else: - ieren_tile = IOTile(self.ic, x1, y1) - self.tiles[x1, y1] = ieren_tile - - if io_block.enable_input != (self.ic.device == '1k'): - ieren_tile.apply_directive('IoCtrl', 'IE_%d' % b1) - if io_block.disable_pull_up: - ieren_tile.apply_directive('IoCtrl', 'REN_%d' % b1) - - unused_ieren.remove((x1, y1, b1)) - - if self.ic.device == '1k': - for x1, y1, b1 in unused_ieren: - if (x1, y1) in self.tiles: - ieren_tile = self.tiles[x1, y1] - else: - ieren_tile = IOTile(self.ic, x1, y1) - self.tiles[x1, y1] = ieren_tile - ieren_tile.apply_directive('IoCtrl', 'IE_%d' % b1) - - # fix up RAMB power-up bits - - for x, y in self.ic.ramb_tiles: - if (x, y) in self.tiles: - tile = self.tiles[x, y] - else: - tile = RAMBTile(self.ic, x, y) - self.tiles[x, y] = tile - - if tile.power_up != (self.ic.device == '1k'): - tile.apply_directive('RamConfig', 'PowerUp') - - # enable column buffers - colbuf_db = self.ic.colbuf_db() - for x, y in list(self.tiles): - for src, dst in self.tiles[x, y].buffers + \ - self.tiles[x, y].routings: - if not src.startswith('glb_netwk_'): - continue - driving_xy = [(src_x, src_y) - for src_x, src_y, dst_x, dst_y in colbuf_db - if dst_x == x and dst_y == y] - assert len(driving_xy) == 1 - driving_xy, = driving_xy - - if driving_xy not in self.tiles: - if driving_xy in self.ic.logic_tiles: - tile = LogicTile(self.ic, *driving_xy) - elif driving_xy in self.ic.ramb_tiles: - tile = RAMBTile(self.ic, *driving_xy) - elif driving_xy in self.ic.ramt_tiles: - tile = RAMTTile(self.ic, *driving_xy) - elif driving_xy in self.ic.io_tiles: - tile = IOTile(self.ic, *driving_xy) - else: - assert False - self.tiles[driving_xy] = tile - - self.tiles[driving_xy].apply_directive('ColBufCtrl', src) - - self.ic.write_file('/dev/stdout') - -class Tile: - def __init__(self, ic, x, y): - self.ic = ic - self.x = x - self.y = y - self.data = ic.tile(x, y) - self.db = ic.tile_db(x, y) - - self.buffers = [] - self.routings = [] - self.bits_set = set() - self.bits_cleared = set() - - def apply_directive(self, *fields): - fields = list(fields) - bits, = [entry[0] for entry in self.db if entry[1:] == fields] - self.set_bits(bits) - - def set_bits(self, bits): - bits_set = set() - bits_clear = set() - - for bit in bits: - match = re.match(r'(!?)B(\d+)\[(\d+)\]$', bit) - if not match: - raise ValueError("invalid bit description: %s" % bit) - if match.group(1): - bits_clear.add((int(match.group(2)), int(match.group(3)))) - else: - bits_set.add((int(match.group(2)), int(match.group(3)))) - - if set.intersection(bits_set, bits_clear): - raise ValueError("trying to set/clear the same bit(s) at once") - - if set.intersection(bits_set, self.bits_cleared) or \ - set.intersection(bits_clear, self.bits_set): - raise ParseError("conflicting bits") - - self.bits_set.update(bits_set) - self.bits_cleared.update(bits_clear) - - for row, col in bits_set: - assert row < len(self.data) - assert col < len(self.data[row]) - self.data[row] = self.data[row][:col] + '1' + \ - self.data[row][col + 1:] - - def read(self, fields): - if len(fields) == 3 and fields[1] == '->': - src = untranslate_netname(self.x, self.y, - self.ic.max_x - 1, - self.ic.max_y - 1, fields[0]) - dst = untranslate_netname(self.x, self.y, - self.ic.max_x - 1, - self.ic.max_y - 1, fields[2]) - dst = revert_to_fabout(self.x, self.y, dst) - if (src, dst) not in self.buffers: - self.buffers.append((src, dst)) - self.apply_directive('buffer', src, dst) - elif len(fields) == 3 and fields[1] == '<->': - src = untranslate_netname(self.x, self.y, - self.ic.max_x - 1, - self.ic.max_y - 1, fields[0]) - dst = untranslate_netname(self.x, self.y, - self.ic.max_x - 1, - self.ic.max_y - 1, fields[2]) - dst = revert_to_fabout(self.x, self.y, dst) - if (src, dst) not in self.routings: - self.routings.append((src, dst)) - self.apply_directive('routing', src, dst) - elif len(fields) >= 5 and (fields[1] == '->' or fields[1] == '<->'): - self.read(fields[:3]) - self.read(fields[2:]) - else: - raise ParseError - - def new_block(self, fields): - raise ParseError - -class LogicTile(Tile): - def __init__(self, ic, x, y): - super().__init__(ic, x, y) - self.cells = [None, None, None, None, None, None, None, None] - self.neg_clk = False - self.carry_in_set = False # not in global bit list?! - - def read(self, fields): - if fields == ['NegClk'] and not self.neg_clk: - self.neg_clk = True - self.apply_directive('NegClk') - elif fields == ['CarryInSet'] and not self.carry_in_set: - self.carry_in_set = True - self.apply_directive('CarryInSet') - else: - super().read(fields) - - def new_block(self, fields): - for i in range(8): - if fields == ['lutff_%d' % i] and self.cells[i] is None: - self.cells[i] = LogicCell(self, i) - return self.cells[i] - raise ParseError - -class LogicCell: - def __init__(self, tile, index): - self.tile = tile - self.index = index - self.lut_bits = None - self.seq_bits = ['0'] * 4 - - def read(self, fields): - if fields[0] == 'lut' and len(fields) == 2 and self.lut_bits is None: - self.lut_bits = fields[1] - elif fields[0] == 'out' and len(fields) >= 3 and fields[1] == '=': - self.lut_bits = logic_expression_to_lut( - ' '.join(fields[2:]), ('in_0', 'in_1', 'in_2', 'in_3')) - elif fields == ['enable_carry']: - self.seq_bits[0] = '1' - elif fields == ['enable_dff']: - self.seq_bits[1] = '1' - elif fields == ['set_noreset']: - self.seq_bits[2] = '1' - elif fields == ['async_setreset']: - self.seq_bits[3] = '1' - elif len(fields) >= 3 and (fields[1] == '->' or fields[1] == '<->'): - prefix = 'lutff_%d/' % self.index - if fields[0] == 'out': - self.tile.read([prefix + fields[0]] + fields[1:]) - elif fields[-1].startswith('in_'): - self.tile.read(fields[:-1] + [prefix + fields[-1]]) - else: - raise ParseError - return - - bits = ''.join([ - self.lut_bits[15], self.lut_bits[12], - self.lut_bits[11], self.lut_bits[ 8], - self.lut_bits[ 0], self.lut_bits[ 3], - self.lut_bits[ 4], self.lut_bits[ 7], - self.seq_bits[ 0], self.seq_bits[ 1], - self.lut_bits[14], self.lut_bits[13], - self.lut_bits[10], self.lut_bits[ 9], - self.lut_bits[ 1], self.lut_bits[ 2], - self.lut_bits[ 5], self.lut_bits[ 6], - self.seq_bits[ 2], self.seq_bits[ 3] - ]) - self.tile.data[self.index * 2] = \ - self.tile.data[self.index * 2][:36] + bits[:10] + \ - self.tile.data[self.index * 2][46:] - self.tile.data[self.index * 2 + 1] = \ - self.tile.data[self.index * 2 + 1][:36] + bits[10:] + \ - self.tile.data[self.index * 2 + 1][46:] - - def new_block(self, fields): - raise ParseError - -class RAMData: - def __init__(self, data): - self.data = data - - def read(self, fields): - if len(fields) == 1: - self.data.append(fields[0]) - else: - raise ParseError - - def new_block(self, fields): - raise ParseError - -class RAMBTile(Tile): - def __init__(self, ic, x, y): - super().__init__(ic, x, y) - self.power_up = False - - def read(self, fields): - if fields == ['power_up'] and not self.power_up: - self.power_up = True - else: - super().read(fields) - - def new_block(self, fields): - if fields == ['data'] and (self.x, self.y) not in self.ic.ram_data: - self.ic.ram_data[self.x, self.y] = data = [] - return RAMData(data) - raise ParseError - -class RAMTTile(Tile): - def __init__(self, ic, x, y): - super().__init__(ic, x, y) - - def read(self, fields): - if fields == ['NegClk'] or fields[0] == 'RamConfig': - self.apply_directive(*fields) # TODO - else: - super().read(fields) - -class IOTile(Tile): - def __init__(self, ic, x, y): - super().__init__(ic, x, y) - self.blocks = [None, None] - - def read(self, fields): - super().read(fields) - - def new_block(self, fields): - if fields == ['io_0'] and self.blocks[0] is None: - self.blocks[0] = IOBlock(self, 0) - return self.blocks[0] - if fields == ['io_1'] and self.blocks[1] is None: - self.blocks[1] = IOBlock(self, 1) - return self.blocks[1] - raise ParseError - -class IOBlock: - def __init__(self, tile, index): - self.tile = tile - self.index = index - self.input_pin_type = None - self.output_pin_type = None - self.enable_input = False - self.disable_pull_up = False - - def read(self, fields): - if fields[0] == 'input_pin_type' and fields[1] == '=' \ - and len(fields) == 3 and self.input_pin_type is None: - self.input_pin_type = [ - 'registered_pin', - 'simple_input_pin', - 'latched_registered_pin', - 'latched_pin'].index(fields[2]) - for i in range(2): - if self.input_pin_type & 1 << i: - self.tile.apply_directive('IOB_%d' % self.index, - 'PINTYPE_%d' % i) - elif fields[0] == 'output_pin_type' and fields[1] == '=' \ - and len(fields) == 3 and self.output_pin_type is None: - self.output_pin_type = [ - 'no_output', - '1', - '2', - '3', - 'DDR', - 'REGISTERED', - 'simple_output_pin', - 'REGISTERED_INVERTED', - 'DDR_ENABLE', - 'REGISTERED_ENABLE', - 'OUTPUT_TRISTATE', - 'REGISTERED_ENABLE_INVERTED', - 'DDR_ENABLE_REGISTERED', - 'REGISTERED_ENABLE_REGISTERED', - 'ENABLE_REGISTERED', - 'REGISTERED_ENABLE_REGISTERED_INVERTED'].index(fields[2]) - for i in range(4): - if self.output_pin_type & 1 << i: - self.tile.apply_directive('IOB_%d' % self.index, - 'PINTYPE_%d' % (i + 2)) - elif fields == ['enable_input'] and not self.enable_input: - self.enable_input = True - elif fields == ['disable_pull_up'] and not self.disable_pull_up: - self.disable_pull_up = True - elif fields[0] == 'GLOBAL_BUFFER_OUTPUT' and fields[1] == '->' \ - and fields[2].startswith('glb_netwk_'): - if GLB_NETWK_EXTERNAL_BLOCKS[int(fields[2][10:])] \ - != (self.tile.x, self.tile.y, self.index): - raise ParseError - bit = [bit for bit in self.tile.ic.extra_bits_db() - if self.tile.ic.extra_bits_db()[bit] - == ("padin_glb_netwk", fields[2][10:])] - assert len(bit) == 1 - self.tile.ic.extra_bits.add(bit[0]) - elif len(fields) >= 3 and (fields[1] == '->' or fields[1] == '<->'): - prefix = 'io_%d/' % self.index - if fields[0] in ('D_IN_0', 'D_IN_1'): - self.tile.read([prefix + fields[0]] + fields[1:]) - elif fields[-1] in ('CLOCK_ENABLE', - 'D_OUT_0', - 'D_OUT_1', - 'INPUT_CLK', - 'LATCH_INPUT_VALUE', - 'OUTPUT_CLK', - 'OUTPUT_ENABLE'): - self.tile.read(fields[:-1] + [prefix + fields[-1]]) - else: - raise ParseError - else: - raise ParseError - - def new_block(self, fields): - raise ParseError - -def main1(path): - f = open(path, 'r') - stack = [Main()] - for line in f: - fields = line.split('#')[0].split() - if not fields: - pass # empty line - elif fields == ['}']: - stack.pop() - if not stack: - raise ParseError - elif fields[-1] == '{': - stack.append(stack[-1].new_block(fields[:-1])) - else: - stack[-1].read(fields) - if len(stack) != 1: - raise ParseError - f.close() - - stack[0].writeout() - -def main(): - program_short_name = os.path.basename(sys.argv[0]) - - try: - opts, args = getopt.getopt(sys.argv[1:], '', ['help', 'version']) - except getopt.GetoptError as e: - sys.stderr.write("%s: %s\n" % (program_short_name, e.msg)) - sys.stderr.write("Try `%s --help' for more information.\n" - % sys.argv[0]) - sys.exit(1) - - for opt, arg in opts: - if opt == '--help': - sys.stderr.write("""\ -Create an ASCII bitstream from a high-level bitstream representation. -Usage: %s [OPTION]... FILE - - --help display this help and exit - --version output version information and exit - -If you have a bug report, please file an issue on github: - https://github.com/rlutz/icestorm/issues -""" % sys.argv[0]) - sys.exit(0) - - if opt == '--version': - sys.stderr.write("""\ -icebox_hlc2asc - create an ASCII bitstream from a high-level representation -Copyright (C) 2017 Roland Lutz - -This program is free software: you can redistribute it and/or -modify it under the terms of the GNU General Public License as -published by the Free Software Foundation, either version 3 of -the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. -""") - sys.exit(0) - - if not args: - sys.stderr.write("%s: missing argument\n" % (program_short_name)) - sys.stderr.write("Try `%s --help' for more information.\n" - % sys.argv[0]) - sys.exit(1) - - if len(args) != 1: - sys.stderr.write("%s: too many arguments\n" % (program_short_name)) - sys.stderr.write("Try `%s --help' for more information.\n" - % sys.argv[0]) - sys.exit(1) - - if args[0] == '-': - main1('/dev/stdin') - else: - main1(args[0]) - -if __name__ == '__main__': - main() diff --git a/icebox/tc_logic_xpr.py b/icebox/tc_logic_xpr.py deleted file mode 100644 index e557caf..0000000 --- a/icebox/tc_logic_xpr.py +++ /dev/null @@ -1,42 +0,0 @@ -# Test case for `icebox_asc2hlc' and `icebox_hlc2asc': Does conversion -# from LUT strings to logic expressions and back work correctly? -# Copyright (C) 2017 Roland Lutz -# -# This program is free software: you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation, either version 3 of -# the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -import sys -import icebox -from icebox_asc2hlc import lut_to_logic_expression -from icebox_hlc2asc import logic_expression_to_lut - -def main(): - sys.stderr.write("testing conversion from LUT strings " - "to logic expressions and back") - - for i in range(65536): - if i % 4096 == 0: - sys.stderr.write(".") - sys.stderr.flush() - - lut = bin(i)[2:].zfill(16) - s = lut_to_logic_expression(lut, ('a', 'b', 'c', 'd')) - l = logic_expression_to_lut(s, ('a', 'b', 'c', 'd')) - - if l != lut: - sys.stderr.write("\nERROR at LUT = %s\n" % lut) - sys.stderr.write("stringified = %s\n" % s) - sys.stderr.write("resulting LUT = %s\n" % l) - sys.exit(1) - - sys.stderr.write("\n") - -if __name__ == '__main__': - main() diff --git a/icebox/tc_rxlat_netnames.py b/icebox/tc_rxlat_netnames.py deleted file mode 100644 index 109dfa4..0000000 --- a/icebox/tc_rxlat_netnames.py +++ /dev/null @@ -1,69 +0,0 @@ -# Test case for `icebox_hlc2asc': Does net name translation work correctly? -# Copyright (C) 2017 Roland Lutz -# -# This program is free software: you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation, either version 3 of -# the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -import sys -import icebox -from icebox_asc2hlc import translate_netname -from icebox_hlc2asc import untranslate_netname - -def test_netname_translation(ic): - sys.stderr.write("testing backward netname translation " - "for the `%s' device...\n" % ic.device) - all_tiles = set() - for x in range(ic.max_x + 1): - for y in range(ic.max_y + 1): - if ic.tile(x, y) is not None: - all_tiles.add((x, y)) - - netnames = set() - failed = False - - for group in ic.group_segments(all_tiles, connect_gb = False): - is_span = set(net.startswith('sp') for x, y, net in group) - assert len(is_span) == 1 - if True not in is_span: - # only span nets are interesting here - continue - - netname = translate_netname(group[0][0], group[0][1], - ic.max_x - 1, ic.max_y - 1, group[0][2]) - if netname in netnames: - failed = True - print("duplicate netname: %s" % netname) - netnames.add(netname) - - for x, y, net in group: - s = untranslate_netname(x, y, ic.max_x - 1, ic.max_y - 1, netname) - if s != net: - failed = True - print("%-20s %s -> %s" % ("%d %d %s" % (x, y, net), netname, s)) - - if failed: - sys.stderr.write("ERROR\n") - sys.exit(1) - -def main(): - ic = icebox.iceconfig() - ic.setup_empty_384() - test_netname_translation(ic) - - ic = icebox.iceconfig() - ic.setup_empty_1k() - test_netname_translation(ic) - - ic = icebox.iceconfig() - ic.setup_empty_8k() - test_netname_translation(ic) - -if __name__ == '__main__': - main() diff --git a/icebox/tc_xlat_netnames.py b/icebox/tc_xlat_netnames.py deleted file mode 100644 index 53b73de..0000000 --- a/icebox/tc_xlat_netnames.py +++ /dev/null @@ -1,79 +0,0 @@ -# Test case for `icebox_asc2hlc': Does net name translation work correctly? -# Copyright (C) 2017 Roland Lutz -# -# This program is free software: you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation, either version 3 of -# the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -import sys -import icebox -from icebox_asc2hlc import translate_netname - -def test_netname_translation(ic): - sys.stderr.write("testing forward netname translation " - "for the `%s' device...\n" % ic.device) - all_tiles = set() - for x in range(ic.max_x + 1): - for y in range(ic.max_y + 1): - if ic.tile(x, y) is not None: - all_tiles.add((x, y)) - - netnames = set() - failed = False - - for group in ic.group_segments(all_tiles, connect_gb = False): - is_span = set(net.startswith('sp') for x, y, net in group) - assert len(is_span) == 1 - if True not in is_span: - # only span nets are interesting here - continue - - s = set() - for seg in group: - s.add(translate_netname(seg[0], seg[1], - ic.max_x - 1, ic.max_y - 1, seg[2])) - if len(s) != 1: - failed = True - print("translated netnames don't match") - for seg in group: - print("%d %d %s" % seg, "->", - translate_netname(seg[0], seg[1], - ic.max_x - 1, ic.max_y - 1, seg[2])) - print() - - for dulpicate_netname in netnames.intersection(s): - failed = True - print("duplicate netname: %s" % dulpicate_netname) - for seg in group: - print("%d %d %s" % seg, "->", - translate_netname(seg[0], seg[1], - ic.max_x - 1, ic.max_y - 1, seg[2])) - print() - - netnames.update(s) - - if failed: - sys.stderr.write("ERROR\n") - sys.exit(1) - -def main(): - ic = icebox.iceconfig() - ic.setup_empty_384() - test_netname_translation(ic) - - ic = icebox.iceconfig() - ic.setup_empty_1k() - test_netname_translation(ic) - - ic = icebox.iceconfig() - ic.setup_empty_8k() - test_netname_translation(ic) - -if __name__ == '__main__': - main() diff --git a/iceprog/Makefile b/iceprog/Makefile index d71a9b7..8739ba6 100644 --- a/iceprog/Makefile +++ b/iceprog/Makefile @@ -24,12 +24,9 @@ iceprog$(EXE): iceprog.o install: all mkdir -p $(DESTDIR)$(PREFIX)/bin cp iceprog$(EXE) $(DESTDIR)$(PREFIX)/bin/iceprog$(EXE) - mkdir -p $(DESTDIR)$(PREFIX)/share/man/man1 - install -c -m 644 iceprog.1 $(DESTDIR)$(PREFIX)/share/man/man1 uninstall: rm -f $(DESTDIR)$(PREFIX)/bin/iceprog$(EXE) - rm -f $(DESTDIR)$(PREFIX)/share/man/man1/iceprog.1 clean: rm -f iceprog diff --git a/iceprog/iceprog.1 b/iceprog/iceprog.1 deleted file mode 100644 index 22d3882..0000000 --- a/iceprog/iceprog.1 +++ /dev/null @@ -1,155 +0,0 @@ -.\" Manpage for iceprog(1) -.\" Copyright (C) 2017 Roland Lutz -.\" -.\" Permission is granted to copy, distribute and/or modify this document -.\" under the terms of the GNU Free Documentation License, Version 1.3 or -.\" any later version published by the Free Software Foundation; with no -.\" Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. -.\" -.TH ICEPROG "1" "June 2017" "IceStorm" "User Commands" -.SH NAME -iceprog \- simple programming tool for FTDI\-based Lattice iCE programmers -.SH SYNOPSIS -.B iceprog -[\-b|\-n|\-c] \fIINPUT\-FILE\fR - -.B iceprog -\-r|\-R\fI\,BYTES\fR \fIOUTPUT\-FILE\fR - -.B iceprog -\-S \fIINPUT\-FILE\fR - -.B iceprog -\-t -.SH DESCRIPTION -The \fBiceprog\fR program is a simple programming tool for FTDI\-based -Lattice iCE programmers which can read, write and erase the flash and -write the SRAM of an FPGA. It is typically invoked after the -bitstream has been converted by \fBicepack\fR to the iCE40 \fB.bin\fR -format as the last step of the build process to transfer the bitstream -to the FPGA. -.SS Operation mode -When no special option is given, \fBiceprog\fR erases all 64kB sectors -which would be touched by the written data, writes the data to the -flash, and then reads it back and verifies it. - -\fIPlease note:\fR If the data is not aligned to 64kB, some data -before (if \fB\-o\fR is used) and after the written data may be erased -as well. - -The way the flash is erased can be changed with the following options: -.TP -\fB\-b\fR -Bulk erase the entire flash before writing. When using this option, -\fBiceprog\fR can be invoked without an \fIINPUT\-FILE\fR; in this -case, the flash is just bulk erased, and nothing is written. -.TP -\fB\-n\fR -Don't erase the flash before writing. -.PP -Instead of the default erase/write/verify, \fBiceprog\fR can perform -some other operations: -.TP -\fB\-c\fR -Just read the data which would have been written from the flash and -verify it (`check'). -.TP -\fB\-r\fR -Read the first 256 kB from flash and write them to a file. -.TP -\fB\-R\fR \fISIZE\-IN\-BYTES\fR -Read the specified number of bytes from the flash and write them to a -file. You can append `\fBk\fR' to the size to specify it in kilobytes -and `\fBM\fR' to specify it in megabytes. -.TP -\fB\-S\fR -Perform SRAM programming. -.TP -\fB\-t\fR -Just read the flash ID sequence. -.PP -All of the above options are mutually exclusive. -.SS General options -.TP -\fB\-d\fR \fIDEVICE\-STRING\fR -Use the specified USB device instead of the default one (which is -vendor ID 0x0403 and device ID 0x6010). The supported notations for -\fIDEVICE\-STRING\fR are: - -\fBd:\,\f(BIdevicenode\fR \- path of the bus and device node within -USB device tree (usually at /proc/bus/usb/); e.g., `d:002/005' - -\fBi:\,\f(BIvendor\/\fB:\,\f(BIproduct\fR \- first device with given -vendor and product ID. IDs can be decimal, octal (preceded by -`\fB0\fR'), or hex (preceded by `\fB0x\fR'); e.g., `i:0x0403:0x6010' - -\fBi:\,\f(BIvendor\/\fB:\,\f(BIproduct\/\fB:\,\f(BIindex\fR \- same as -above, with index being the number of the device (starting with 0) if -there is more than one device with this vendor and product ID; e.g., -`i:0x0403:0x6010:0' - -\fBs:\,\f(BIvendor\/\fB:\,\f(BIproduct\/\fB:\,\f(BIserial\-string\fR -\- first device with given vendor ID, product ID and serial string. -.TP -\fB\-I\fR A|B|C|D -Connect to the specified interface on the FTDI chip. If this option -is omitted, interface A is used. -.TP -\fB\-o\fR \fIOFFSET\-IN\-BYTES\fR -Start reading/writing at address \fIOFFSET\-IN\-BYTES\fR instead of the -beginning of the memory. You can append `\fBk\fR' to the offset to -specify it in kilobytes and `\fBM\fR' to specify it in megabytes. -.TP -\fB\-v\fR -Write more verbose messages. -.TP -\fB\-\-help\fR -Display a help text and exit. -.SS Exit status -.TP -.B 0 -on success, -.TP -.B 1 -if a non\-hardware error occurred (e.g., failure to read from or write -to a file, or invoked with invalid options), -.TP -.B 2 -if communication with the hardware failed (e.g., cannot find the iCE -FTDI USB device), -.TP -.B 3 -if verification of the data failed. -.SS Notes for iCEstick (iCE40HX\-1k devel board) -An unmodified iCEstick can only be programmed via the serial flash. -Direct programming of the SRAM is not supported. For direct SRAM -programming the flash chip and one zero ohm resistor must be -desoldered and the FT2232H SI pin must be connected to the iCE SPI_SI -pin, as shown in this picture: - -.SS Notes for the iCE40\-HX8K Breakout Board -Make sure that the jumper settings on the board match the selected -mode (SRAM or FLASH). See the iCE40\-HX8K user manual for details. -.SH AUTHOR -Written by Clifford Wolf. -.SH REPORTING BUGS -If you have a bug report, please file an issue on github: - -.SH COPYRIGHT -Most of Project IceStorm is licensed under the ISC license: - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -.SH SEE ALSO -Full documentation at: -.br -or available locally via: info \(aq(icestorm) iceprog invocation\(aq -- cgit v1.2.3