[icestorm] 04/75: Import of icestorm-snapshot-150526.zip

Ruben Undheim rubund-guest at moszumanska.debian.org
Wed Oct 7 15:52:02 UTC 2015


This is an automated email from the git hooks/post-receive script.

rubund-guest pushed a commit to branch master
in repository icestorm.

commit 13e63e6b65e044e348356731b55610d02cb308b9
Author: Clifford Wolf <clifford at clifford.at>
Date:   Sat Jul 18 13:07:39 2015 +0200

    Import of icestorm-snapshot-150526.zip
---
 Makefile                |  18 ++
 icebox/Makefile         |  12 +-
 icebox/icebox.py        |  98 ++++++--
 icebox/icebox_chipdb.py | 113 ++++++++-
 icebox/icebox_diff.py   |  15 +-
 icebox/icebox_html.py   |   2 +
 icebox/iceboxdb.py      |   9 +
 icepack/Makefile        |   5 +-
 icepack/icepack.cc      | 159 ++++++++++++-
 iceprog/Makefile        |  22 ++
 iceprog/iceprog.c       | 598 ++++++++++++++++++++++++++++++++++++++++++++++++
 11 files changed, 1015 insertions(+), 36 deletions(-)

diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..a070dc3
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,18 @@
+
+all:
+	$(MAKE) -C icebox
+	$(MAKE) -C icepack
+	$(MAKE) -C iceprog
+
+install:
+	$(MAKE) -C icebox install
+	$(MAKE) -C icepack install
+	$(MAKE) -C iceprog install
+
+uninstall:
+	$(MAKE) -C icebox uninstall
+	$(MAKE) -C icepack uninstall
+	$(MAKE) -C iceprog uninstall
+
+.PHONY: all install uninstall
+
diff --git a/icebox/Makefile b/icebox/Makefile
index 3f74e18..64549b3 100644
--- a/icebox/Makefile
+++ b/icebox/Makefile
@@ -1,7 +1,13 @@
 
-all:
+chipdb: chipdb-1k.txt
 
-install:
+chipdb-1k.txt: icebox.py iceboxdb.py icebox_chipdb.py
+	python icebox_chipdb.py > chipdb-1k.new
+	mv chipdb-1k.new chipdb-1k.txt
+
+install: chipdb
+	mkdir -p /usr/local/share/icebox
+	cp chipdb-1k.txt     /usr/local/share/icebox/
 	cp icebox.py         /usr/local/bin/icebox.py
 	cp iceboxdb.py       /usr/local/bin/iceboxdb.py
 	cp icebox_chipdb.py  /usr/local/bin/icebox_chipdb
@@ -20,6 +26,8 @@ uninstall:
 	rm -f /usr/local/bin/icebox_html
 	rm -f /usr/local/bin/icebox_maps
 	rm -f /usr/local/bin/icebox_vlog
+	rm -f /usr/local/share/icebox/chipdb-1k.txt
+	-rmdir /usr/local/share/icebox
 
 .PHONY: install uninstall
 
diff --git a/icebox/icebox.py b/icebox/icebox.py
index 60b5dc2..cad6831 100644
--- a/icebox/icebox.py
+++ b/icebox/icebox.py
@@ -32,6 +32,7 @@ class iceconfig:
         self.io_tiles = dict()
         self.ramb_tiles = dict()
         self.ramt_tiles = dict()
+        self.ram_data = dict()
         self.extra_bits = set()
 
     def setup_empty_1k(self):
@@ -78,8 +79,8 @@ class iceconfig:
     def gbufin_db(self):
         return gbufin_db[self.device]
 
-    def icegate_db(self):
-        return icegate_db[self.device]
+    def iolatch_db(self):
+        return iolatch_db[self.device]
 
     def padin_pio_db(self):
         return padin_pio_db[self.device]
@@ -90,6 +91,21 @@ class iceconfig:
     def ieren_db(self):
         return ieren_db[self.device]
 
+    def colbuf_db(self):
+        assert self.device == "1k"
+        entries = list()
+        for x in range(self.max_x+1):
+            for y in range(self.max_y+1):
+                src_y = None
+                if  0 <= y <=  4: src_y =  4
+                if  5 <= y <=  8: src_y =  5
+                if  9 <= y <= 12: src_y = 12
+                if 13 <= y <= 17: src_y = 13
+                if x in [3, 10] and src_y ==  4: src_y =  3
+                if x in [3, 10] and src_y == 12: src_y = 11
+                entries.append((x, src_y, x, y))
+        return entries
+
     def tile_db(self, x, y):
         if x == 0: return iotile_l_db
         if y == 0: return iotile_b_db
@@ -307,7 +323,7 @@ class iceconfig:
                     neighbours.add((s[0], s[1], s[2]))
         return neighbours
 
-    def group_segments(self, all_from_tiles=set(), extra_connections=list(), extra_segments=list()):
+    def group_segments(self, all_from_tiles=set(), extra_connections=list(), extra_segments=list(), connect_gb=True):
         seed_segments = set()
         seen_segments = set()
         connected_segments = dict()
@@ -373,7 +389,7 @@ class iceconfig:
                 seed_segments.add(s1)
                 seed_segments.add(s2)
 
-        for entry in self.icegate_db():
+        for entry in self.iolatch_db():
             if entry[0] == 0 or entry[0] == self.max_x:
                 iocells = [(entry[0], i) for i in range(1, self.max_y)]
             if entry[1] == 0 or entry[1] == self.max_y:
@@ -388,14 +404,15 @@ class iceconfig:
                     seed_segments.add(s1)
                     seed_segments.add(s2)
 
-        for entry in self.gbufin_db():
-            s1 = (entry[0], entry[1], "wire_gbuf/in")
-            s2 = (entry[0], entry[1], "glb_netwk_%d" % entry[2])
-            if s1 in seed_segments or (pio[0], pio[1]) in all_from_tiles:
-                connected_segments.setdefault(s1, set()).add(s2)
-                connected_segments.setdefault(s2, set()).add(s1)
-                seed_segments.add(s1)
-                seed_segments.add(s2)
+        if connect_gb:
+            for entry in self.gbufin_db():
+                s1 = (entry[0], entry[1], "wire_gbuf/in")
+                s2 = (entry[0], entry[1], "glb_netwk_%d" % entry[2])
+                if s1 in seed_segments or (pio[0], pio[1]) in all_from_tiles:
+                    connected_segments.setdefault(s1, set()).add(s2)
+                    connected_segments.setdefault(s2, set()).add(s1)
+                    seed_segments.add(s1)
+                    seed_segments.add(s2)
 
         while seed_segments:
             queue = set()
@@ -444,7 +461,7 @@ class iceconfig:
                 if line[0][0] != ".":
                     if expected_data_lines == -1:
                         continue
-                    if line[0][0] != "0" and line[0][0] != "1":
+                    if line[0][0] not in "0123456789abcdef":
                         print("%sWarning: ignoring data block in line %d: %s" % (logprefix, linenum, linetext.strip()))
                         expected_data_lines = 0
                         continue
@@ -453,7 +470,7 @@ class iceconfig:
                     expected_data_lines -= 1
                     continue
                 assert expected_data_lines <= 0
-                if line[0] in (".io_tile", ".logic_tile", ".ramb_tile", ".ramt_tile"):
+                if line[0] in (".io_tile", ".logic_tile", ".ramb_tile", ".ramt_tile", ".ram_data"):
                     current_data = list()
                     expected_data_lines = 16
                     self.max_x = max(self.max_x, int(line[1]))
@@ -470,6 +487,9 @@ class iceconfig:
                 if line[0] == ".ramt_tile":
                     self.ramt_tiles[(int(line[1]), int(line[2]))] = current_data
                     continue
+                if line[0] == ".ram_data":
+                    self.ram_data[(int(line[1]), int(line[2]))] = current_data
+                    continue
                 if line[0] == ".extra_bit":
                     self.extra_bits.add((int(line[1]), int(line[2]), int(line[3])))
                     continue
@@ -481,6 +501,7 @@ class iceconfig:
                     expected_data_lines = -1
                     continue
                 print("%sWarning: ignoring line %d: %s" % (logprefix, linenum, linetext.strip()))
+                expected_data_lines = -1
 
 class tileconfig:
     def __init__(self, tile):
@@ -905,7 +926,7 @@ gbufin_db = {
     ]
 }
 
-icegate_db = {
+iolatch_db = {
     "1k": [
         ( 0,  7),
         (13, 10),
@@ -914,6 +935,39 @@ icegate_db = {
     ]
 }
 
+pllinfo_db = {
+    "1k": {
+        "SHIFTREG_DIV_MODE": (0, 3, "B2[2]"),
+        "FDA_FEEDBACK_0": (0, 3, "B7[3]"),
+        "FDA_FEEDBACK_1": (0, 4, "B0[2]"),
+        "FDA_FEEDBACK_2": (0, 4, "B0[3]"),
+        "FDA_FEEDBACK_3": (0, 4, "B3[3]"),
+        "FDA_RELATIVE_0": (0, 4, "B2[3]"),
+        "FDA_RELATIVE_1": (0, 4, "B5[3]"),
+        "FDA_RELATIVE_2": (0, 4, "B4[2]"),
+        "FDA_RELATIVE_3": (0, 4, "B4[3]"),
+        "DIVR_0": (0, 1, "B0[2]"),
+        "DIVR_1": (0, 1, "B0[3]"),
+        "DIVR_2": (0, 1, "B3[3]"),
+        "DIVR_3": (0, 1, "B2[2]"),
+        "DIVF_0": (0, 1, "B2[3]"),
+        "DIVF_1": (0, 1, "B5[3]"),
+        "DIVF_2": (0, 1, "B4[2]"),
+        "DIVF_3": (0, 1, "B4[3]"),
+        "DIVF_4": (0, 1, "B7[3]"),
+        "DIVF_5": (0, 2, "B0[2]"),
+        "DIVF_6": (0, 2, "B0[3]"),
+        "DIVQ_0": (0, 0, "?"),
+        "DIVQ_1": (0, 0, "?"),
+        "DIVQ_2": (0, 0, "?"),
+        "FILTER_RANGE_0": (0, 2, "B5[3]"),
+        "FILTER_RANGE_1": (0, 2, "B4[2]"),
+        "FILTER_RANGE_2": (0, 2, "B4[3]"),
+        "ENABLE_ICEGATE": (0, 0, "?"),
+        "TEST_MODE": (0, 3, "B4[3]"),
+    }
+}
+
 padin_pio_db = {
     "1k": [
         (13,  8, 1),  # glb_netwk_0
@@ -941,6 +995,8 @@ ieren_db = {
         ( 0, 10,  1,  0, 10,  0),
         ( 0, 10,  0,  0, 10,  1),
         ( 0,  9,  1,  0,  9,  0),
+        ( 0,  9,  0,  0,  9,  1),
+        ( 0,  8,  1,  0,  8,  0),
         ( 0,  8,  0,  0,  8,  1),
         ( 0,  6,  1,  0,  6,  0),
         ( 0,  6,  0,  0,  6,  1),
@@ -954,6 +1010,7 @@ ieren_db = {
         ( 0,  2,  0,  0,  2,  1),
         ( 1,  0,  0,  1,  0,  0),
         ( 1,  0,  1,  1,  0,  1),
+        ( 2,  0,  0,  2,  0,  0),
         ( 2,  0,  1,  2,  0,  1),
         ( 3,  0,  0,  3,  0,  0),
         ( 3,  0,  1,  3,  0,  1),
@@ -961,6 +1018,8 @@ ieren_db = {
         ( 4,  0,  1,  4,  0,  1),
         ( 5,  0,  0,  5,  0,  0),
         ( 5,  0,  1,  5,  0,  1),
+        ( 6,  0,  1,  6,  0,  0),
+        ( 7,  0,  0,  6,  0,  1),
         ( 6,  0,  0,  7,  0,  0),
         ( 7,  0,  1,  7,  0,  1),
         ( 8,  0,  0,  8,  0,  0),
@@ -969,6 +1028,10 @@ ieren_db = {
         ( 9,  0,  1,  9,  0,  1),
         (10,  0,  0, 10,  0,  0),
         (10,  0,  1, 10,  0,  1),
+        (11,  0,  0, 11,  0,  0),
+        (11,  0,  1, 11,  0,  1),
+        (12,  0,  0, 12,  0,  0),
+        (12,  0,  1, 12,  0,  1),
         (13,  1,  0, 13,  1,  0),
         (13,  1,  1, 13,  1,  1),
         (13,  2,  0, 13,  2,  0),
@@ -981,10 +1044,13 @@ ieren_db = {
         (13,  7,  0, 13,  7,  0),
         (13,  7,  1, 13,  7,  1),
         (13,  8,  0, 13,  8,  0),
+        (13,  8,  1, 13,  8,  1),
+        (13,  9,  0, 13,  9,  0),
         (13,  9,  1, 13,  9,  1),
         (13, 11,  0, 13, 10,  0),
         (13, 11,  1, 13, 10,  1),
         (13, 12,  0, 13, 11,  0),
+        (13, 12,  1, 13, 11,  1),
         (13, 13,  0, 13, 13,  0),
         (13, 13,  1, 13, 13,  1),
         (13, 14,  0, 13, 14,  0),
@@ -1002,6 +1068,8 @@ ieren_db = {
         ( 8, 17,  1,  8, 17,  1),
         ( 8, 17,  0,  8, 17,  0),
         ( 7, 17,  1,  7, 17,  1),
+        ( 7, 17,  0,  7, 17,  0),
+        ( 6, 17,  1,  6, 17,  1),
         ( 5, 17,  1,  5, 17,  1),
         ( 5, 17,  0,  5, 17,  0),
         ( 4, 17,  1,  4, 17,  1),
diff --git a/icebox/icebox_chipdb.py b/icebox/icebox_chipdb.py
index 12ccfa8..c673f54 100755
--- a/icebox/icebox_chipdb.py
+++ b/icebox/icebox_chipdb.py
@@ -40,16 +40,44 @@ print("""#
 # Quick File Format Reference:
 # ----------------------------
 #
-# .device DEVICE
+# .device DEVICE WIDTH HEIGHT NUM_NETS
 #
 #    declares the device type (e.g. "1k")
 #
 #
 # .pins PACKAGE
-# PIN_NUM TILE_X TILE_Y PIO_NUM PADIN_NUM
+# PIN_NUM TILE_X TILE_Y PIO_NUM GLB_NUM
 # ...
 #
-#    associates a package pin with an IO tile and block
+#    associates a package pin with an IO tile and block, and global network
+#
+#
+# .gbufin
+# TILE_X TILE_Y GLB_NUM
+# ...
+#
+#    associates an IO tile with the global network it drives via wire_gbuf/in
+#
+#
+# .iolatch
+# TILE_X TILE_Y
+# ...
+#
+#    specifies the IO tiles that drive the latch signal for the bank via wire_gbuf/in
+#
+#
+# .ieren
+# PIO_TILE_X PIO_TILE_Y PIO_NUM IEREN_TILE_X IEREN_TILE_Y IEREN_NUM
+# ...
+#
+#    associates an IO block with an IeRen-block
+#
+#
+# .colbuf
+# SOURCE_TILE_X SOURCE_TILE_Y DEST_TILE_X DEST_TILE_Y
+# ...
+#
+#    declares the positions of the column buffers
 #
 #
 # .io_tile X Y
@@ -60,6 +88,24 @@ print("""#
 #    declares the existence of a IO/LOGIC/RAM tile with the given coordinates
 #
 #
+# .io_tile_bits COLUMNS ROWS
+# .logic_tile_bits COLUMNS ROWS
+# .ramb_tile_bits COLUMNS ROWS
+# .ramt_tile_bits COLUMNS ROWS
+# FUNCTION_1 CONFIG_BITS_NAMES_1
+# FUNCTION_2 CONFIG_BITS_NAMES_2
+# ...
+#
+#    declares non-routing configuration bits of IO/LOGIC/RAM tiles
+#
+#
+# .extra_bits
+# FUNCTION BANK_NUM ADDR_X ADDR_Y
+# ...
+#
+#    declares non-routing global configuration bits
+#
+#
 # .net NET_INDEX
 # X1 Y1 name1
 # X2 Y2 name2
@@ -85,7 +131,9 @@ print("""#
 #
 """)
 
-print(".device 1k")
+all_group_segments = ic.group_segments(all_tiles, connect_gb=False)
+
+print(".device 1k %d %d %d" % (ic.max_x+1, ic.max_y+1, len(all_group_segments)))
 print()
 
 print(".pins tq144")
@@ -97,6 +145,26 @@ for entry in sorted(ic.pinloc_db()):
     print("%d %d %d %d %d" % tuple(entry + [pio_to_padin[pio] if pio in pio_to_padin else -1]))
 print()
 
+print(".gbufin")
+for entry in sorted(ic.gbufin_db()):
+    print(" ".join(["%d" % k for k in entry]))
+print()
+
+print(".iolatch")
+for entry in sorted(ic.iolatch_db()):
+    print(" ".join(["%d" % k for k in entry]))
+print()
+
+print(".ieren")
+for entry in sorted(ic.ieren_db()):
+    print(" ".join(["%d" % k for k in entry]))
+print()
+
+print(".colbuf")
+for entry in sorted(ic.colbuf_db()):
+    print(" ".join(["%d" % k for k in entry]))
+print()
+
 for idx in sorted(ic.io_tiles):
     print(".io_tile %d %d" % idx)
 print()
@@ -113,7 +181,42 @@ for idx in sorted(ic.ramt_tiles):
     print(".ramt_tile %d %d" % idx)
 print()
 
-for group in sorted(ic.group_segments(all_tiles)):
+def print_tile_nonrouting_bits(tile_type, idx):
+    tx = idx[0]
+    ty = idx[1]
+    
+    tile = ic.tile(tx, ty)
+    
+    print(".%s_tile_bits %d %d" % (tile_type, len(tile[0]), len(tile)))
+    
+    function_bits = dict()
+    for entry in ic.tile_db(tx, ty):
+        if not ic.tile_has_entry(tx, ty, entry):
+            continue
+        if entry[1] in ("routing", "buffer"):
+            continue
+        
+        func = ".".join(entry[1:])
+        function_bits[func] = entry[0]
+    
+    for x in sorted(function_bits):
+        print(" ".join([x] + function_bits[x]))
+    print()
+
+print_tile_nonrouting_bits("logic", ic.logic_tiles.keys()[0])
+print_tile_nonrouting_bits("io", ic.io_tiles.keys()[0])
+print_tile_nonrouting_bits("ramb", ic.ramb_tiles.keys()[0])
+print_tile_nonrouting_bits("ramt", ic.ramt_tiles.keys()[0])
+
+print(".extra_bits")
+extra_bits = dict()
+for idx in sorted(ic.extra_bits_db()):
+    extra_bits[".".join(ic.extra_bits_db()[idx])] = " ".join(["%d" % k for k in idx])
+for idx in sorted(extra_bits):
+    print("%s %s" % (idx, extra_bits[idx]))
+print()
+
+for group in sorted(all_group_segments):
     netidx = len(net_to_segs)
     net_to_segs.append(group)
     print(".net %d" % netidx)
diff --git a/icebox/icebox_diff.py b/icebox/icebox_diff.py
index da7962b..59fa0a8 100755
--- a/icebox/icebox_diff.py
+++ b/icebox/icebox_diff.py
@@ -29,6 +29,17 @@ print("Reading file '%s'.." % sys.argv[2])
 ic2 = icebox.iceconfig()
 ic2.read_file(sys.argv[2])
 
+def format_bits(line_nr, this_line, other_line):
+    text = ""
+    for i in range(len(this_line)):
+        if this_line[i] != other_line[i]:
+            if this_line[i] == "1":
+                text += "%8s" % ("B%d[%d]" % (line_nr, i))
+            else:
+                text += "%8s" % ""
+    return text
+        
+
 def diff_tiles(stmt, tiles1, tiles2):
     for i in sorted(set(tiles1.keys() + tiles2.keys())):
         if not i in tiles1:
@@ -48,8 +59,8 @@ def diff_tiles(stmt, tiles1, tiles2):
             if tiles1[i][c] == tiles2[i][c]:
                 print("  %s" % tiles1[i][c])
             else:
-                print("- %s" % tiles1[i][c])
-                print("+ %s" % tiles2[i][c])
+                print("- %s%s" % (tiles1[i][c], format_bits(c, tiles1[i][c], tiles2[i][c])))
+                print("+ %s%s" % (tiles2[i][c], format_bits(c, tiles2[i][c], tiles1[i][c])))
 
 diff_tiles(".io_tile", ic1.io_tiles, ic2.io_tiles)
 diff_tiles(".logic_tile", ic1.logic_tiles, ic2.logic_tiles)
diff --git a/icebox/icebox_html.py b/icebox/icebox_html.py
index 880714f..d3779ab 100755
--- a/icebox/icebox_html.py
+++ b/icebox/icebox_html.py
@@ -218,6 +218,8 @@ configuration bits it has and how it is connected to its neighbourhood.</p>""" %
                     bitmap_cells[idx1][idx2]["label"] = "A"
                 elif entry[1].startswith("RamConfig"):
                     bitmap_cells[idx1][idx2]["label"] = "M"
+                elif entry[1].startswith("PLL"):
+                    bitmap_cells[idx1][idx2]["label"] = "P"
                 else:
                     assert False
             bitmap_cells[idx1][idx2]["label"] = '<a style="color:#666; text-decoration:none" href="#B.%d.%d">%s</a>' % (idx1, idx2, bitmap_cells[idx1][idx2]["label"])
diff --git a/icebox/iceboxdb.py b/icebox/iceboxdb.py
index 2159b8d..52aa3d0 100644
--- a/icebox/iceboxdb.py
+++ b/icebox/iceboxdb.py
@@ -26,6 +26,15 @@ B8[2]	IoCtrl	LVDS
 B6[2]	IoCtrl	REN_0
 B1[3]	IoCtrl	REN_1
 B9[13],B15[13]	NegClk
+B0[2]	PLL	pll_cf_bit_1
+B0[3]	PLL	pll_cf_bit_2
+B3[3]	PLL	pll_cf_bit_3
+B2[2]	PLL	pll_cf_bit_4
+B2[3]	PLL	pll_cf_bit_5
+B5[3]	PLL	pll_cf_bit_6
+B4[2]	PLL	pll_cf_bit_7
+B4[3]	PLL	pll_cf_bit_8
+B7[3]	PLL	pll_cf_bit_9
 B0[4],!B1[4],!B1[5],!B1[6],B1[7]	buffer	IO_B.logic_op_tnl_0	lc_trk_g0_0
 B8[4],!B9[4],!B9[5],!B9[6],B9[7]	buffer	IO_B.logic_op_tnl_0	lc_trk_g1_0
 !B0[5],!B0[6],B0[7],B0[8],!B1[8]	buffer	IO_B.logic_op_tnl_1	lc_trk_g0_1
diff --git a/icepack/Makefile b/icepack/Makefile
index 75f81e7..469e34a 100644
--- a/icepack/Makefile
+++ b/icepack/Makefile
@@ -1,5 +1,4 @@
-
-CXX = clang
+# CXX = clang
 LDLIBS = -lm -lstdc++
 CXXFLAGS = -MD -O0 -ggdb -Wall -std=c++11
 
@@ -12,7 +11,7 @@ iceunpack: icepack
 
 install: all
 	cp icepack /usr/local/bin/icepack
-	ln -s icepack /usr/local/bin/iceunpack
+	ln -sf icepack /usr/local/bin/iceunpack
 
 uninstall:
 	rm -f /usr/local/bin/icepack
diff --git a/icepack/icepack.cc b/icepack/icepack.cc
index f243e15..85531b1 100644
--- a/icepack/icepack.cc
+++ b/icepack/icepack.cc
@@ -110,6 +110,7 @@ struct FpgaConfig
 
 	// netpbm i/o
 	void write_cram_pbm(std::ostream &ofs, int bank_num = -1) const;
+	void write_bram_pbm(std::ostream &ofs, int bank_num = -1) const;
 
 	// query chip type metadata
 	int chip_width() const;
@@ -149,11 +150,23 @@ struct CramIndexConverter
 	void get_cram_index(int bit_x, int bit_y, int &cram_bank, int &cram_x, int &cram_y) const;
 };
 
+struct BramIndexConverter
+{
+	const FpgaConfig *fpga;
+	int tile_x, tile_y;
+
+	int bank_num;
+	int bank_off;
+
+	BramIndexConverter(const FpgaConfig *fpga, int tile_x, int tile_y);
+	void get_bram_index(int bit_x, int bit_y, int &bram_bank, int &bram_x, int &bram_y) const;
+};
+
 static void update_crc16(uint16_t &crc, uint8_t byte)
 {
 	// CRC-16-CCITT, Initialize to 0xFFFF, No zero padding
 	for (int i = 7; i >= 0; i--) {
-		uint16_t xor_value = ((crc >> 15) ^ (byte >> i) & 1) ? 0x1021 : 0;
+		uint16_t xor_value = ((crc >> 15) ^ ((byte >> i) & 1)) ? 0x1021 : 0;
 		crc = (crc << 1) ^ xor_value;
 	}
 }
@@ -450,7 +463,7 @@ void FpgaConfig::write_bits(std::ostream &ofs) const
 		debug("CRAM: Writing bank %d data.\n", cram_bank);
 		write_byte(ofs, crc_value, file_offset, 0x01);
 		write_byte(ofs, crc_value, file_offset, 0x01);
-		for (int i = 0; i < cram_bits.size(); i += 8) {
+		for (int i = 0; i < int(cram_bits.size()); i += 8) {
 			uint8_t byte = 0;
 			for (int j = 0; j < 8; j++)
 				byte = (byte << 1) | (cram_bits[i+j] ? 1 : 0);
@@ -494,7 +507,7 @@ void FpgaConfig::write_bits(std::ostream &ofs) const
 			debug("BRAM: Writing bank %d data.\n", bram_bank);
 			write_byte(ofs, crc_value, file_offset, 0x01);
 			write_byte(ofs, crc_value, file_offset, 0x03);
-			for (int i = 0; i < bram_bits.size(); i += 8) {
+			for (int i = 0; i < int(bram_bits.size()); i += 8) {
 				uint8_t byte = 0;
 				for (int j = 0; j < 8; j++)
 					byte = (byte << 1) | (bram_bits[i+j] ? 1 : 0);
@@ -571,6 +584,9 @@ void FpgaConfig::read_ascii(std::istream &ifs)
 
 		if (command == ".device")
 		{
+			if (got_device)
+				error("More than one .device statement.\n");
+
 			is >> this->device;
 
 			if (this->device == "1k") {
@@ -620,7 +636,7 @@ void FpgaConfig::read_ascii(std::istream &ifs)
 					break;
 				}
 
-				for (int bit_x = 0; bit_x < line.size() && bit_x < cic.tile_width; bit_x++)
+				for (int bit_x = 0; bit_x < int(line.size()) && bit_x < cic.tile_width; bit_x++)
 					if (line[bit_x] == '1') {
 						int cram_bank, cram_x, cram_y;
 						cic.get_cram_index(bit_x, bit_y, cram_bank, cram_x, cram_y);
@@ -631,6 +647,47 @@ void FpgaConfig::read_ascii(std::istream &ifs)
 			continue;
 		}
 
+		if (command == ".ram_data")
+		{
+			if (!got_device)
+				error("Missing .device statement before %s.\n", command.c_str());
+
+			int tile_x, tile_y;
+			is >> tile_x >> tile_y;
+
+			BramIndexConverter bic(this, tile_x, tile_y);
+
+			for (int bit_y = 0; bit_y < 16 && getline(ifs, line); bit_y++)
+			{
+				if (line.substr(0, 1) == ".") {
+					reuse_line = true;
+					break;
+				}
+
+				for (int bit_x = 256-4, ch_idx = 0; ch_idx < int(line.size()) && bit_x >= 0; bit_x -= 4, ch_idx++)
+				{
+					int value = -1;
+					if ('0' <= line[ch_idx] && line[ch_idx] <= '9')
+						value = line[ch_idx] - '0';
+					if ('a' <= line[ch_idx] && line[ch_idx] <= 'f')
+						value = line[ch_idx] - 'a' + 10;
+					if ('A' <= line[ch_idx] && line[ch_idx] <= 'F')
+						value = line[ch_idx] - 'A' + 10;
+					if (value < 0)
+						error("Not a hex character: '%c' (in line '%s')\n", line[ch_idx], line.c_str());
+
+					for (int i = 0; i < 4; i++)
+						if ((value & (1 << i)) != 0) {
+							int bram_bank, bram_x, bram_y;
+							bic.get_bram_index(bit_x+i, bit_y, bram_bank, bram_x, bram_y);
+							this->bram[bram_bank][bram_x][bram_y] = true;
+						}
+				}
+			}
+
+			continue;
+		}
+
 		if (command == ".extra_bit")
 		{
 			if (!got_device)
@@ -642,7 +699,10 @@ void FpgaConfig::read_ascii(std::istream &ifs)
 
 			continue;
 		}
-
+		
+		if (command == ".sym")
+		  continue;
+		
 		if (command.substr(0, 1) == ".")
 			error("Unknown statement: %s\n", command.c_str());
 		error("Unexpected data line: %s\n", line.c_str());
@@ -693,6 +753,26 @@ void FpgaConfig::write_ascii(std::ostream &ofs) const
 			}
 			ofs << '\n';
 		}
+
+		if (cic.tile_type == "ramb")
+		{
+			BramIndexConverter bic(this, x, y);
+			ofs << stringf(".ram_data %d %d\n", x, y);
+
+			for (int bit_y = 0; bit_y < 16; bit_y++) {
+				for (int bit_x = 256-4; bit_x >= 0; bit_x -= 4) {
+					int value = 0;
+					for (int i = 0; i < 4; i++) {
+						int bram_bank, bram_x, bram_y;
+						bic.get_bram_index(bit_x+i, bit_y, bram_bank, bram_x, bram_y);
+						if (this->bram[bram_bank][bram_x][bram_y])
+							value += 1 << i;
+					}
+					ofs << "0123456789abcdef"[value];
+				}
+				ofs << '\n';
+			}
+		}
 	}
 
 	for (int i = 0; i < 4; i++)
@@ -717,7 +797,7 @@ void FpgaConfig::write_ascii(std::ostream &ofs) const
 void FpgaConfig::write_cram_pbm(std::ostream &ofs, int bank_num) const
 {
 	debug("## %s\n", __PRETTY_FUNCTION__);
-	info("Writing pbm file..\n");
+	info("Writing cram pbm file..\n");
 
 	ofs << "P1\n";
 	ofs << stringf("%d %d\n", 2*this->cram_width, 2*this->cram_height);
@@ -737,6 +817,29 @@ void FpgaConfig::write_cram_pbm(std::ostream &ofs, int bank_num) const
 	}
 }
 
+void FpgaConfig::write_bram_pbm(std::ostream &ofs, int bank_num) const
+{
+	debug("## %s\n", __PRETTY_FUNCTION__);
+	info("Writing bram pbm file..\n");
+
+	ofs << "P1\n";
+	ofs << stringf("%d %d\n", 2*this->bram_width, 2*this->bram_height);
+	for (int y = 2*this->bram_height-1; y >= 0; y--) {
+		for (int x = 0; x < 2*this->bram_width; x++) {
+			int bank = 0, bank_x = x, bank_y = y;
+			if (bank_x >= this->bram_width)
+				bank |= 1, bank_x = 2*this->bram_width - bank_x - 1;
+			if (bank_y >= this->bram_height)
+				bank |= 2, bank_y = 2*this->bram_height - bank_y - 1;
+			if (bank_num >= 0 && bank != bank_num)
+				ofs << " 0";
+			else
+				ofs << (this->bram[bank][bank_x][bank_y] ? " 1" : " 0");
+		}
+		ofs << '\n';
+	}
+}
+
 int FpgaConfig::chip_width() const
 {
 	if (this->device == "384")  return 6;
@@ -901,6 +1004,33 @@ void CramIndexConverter::get_cram_index(int bit_x, int bit_y, int &cram_bank, in
 	}
 }
 
+BramIndexConverter::BramIndexConverter(const FpgaConfig *fpga, int tile_x, int tile_y)
+{
+	this->fpga = fpga;
+	this->tile_x = tile_x;
+	this->tile_y = tile_y;
+
+	auto chip_width = fpga->chip_width();
+	auto chip_height = fpga->chip_height();
+
+	bool right_half = this->tile_x > chip_width / 2;
+	bool top_half = this->tile_y > chip_height / 2;
+
+	this->bank_num = 0;
+	if (top_half) this->bank_num |= 1;
+	if (right_half) this->bank_num |= 2;
+
+	this->bank_off = 16 * ((top_half ? this->tile_y - chip_height / 2 : this->tile_y - 1) / 2);
+}
+
+void BramIndexConverter::get_bram_index(int bit_x, int bit_y, int &bram_bank, int &bram_x, int &bram_y) const
+{
+	int index = 256 * bit_y + (16*(bit_x/16) + 15 - bit_x%16);
+	bram_bank = bank_num;
+	bram_x = bank_off + index % 16;
+	bram_y = index / 16;
+}
+
 
 // ==================================================================
 // Main program
@@ -926,6 +1056,9 @@ void usage()
 	log("        write cram bitmap (checkerboard) as netpbm file\n");
 	log("        repeat to flip the selection of tiles\n");
 	log("\n");
+	log("    -r\n");
+	log("        write bram data, not cram, to the netpbm file\n");
+	log("\n");
 	log("    -B0, -B1, -B2, -B3\n");
 	log("        only include the specified bank in the netpbm file\n");
 	log("\n");
@@ -937,6 +1070,7 @@ int main(int argc, char **argv)
 	vector<string> parameters;
 	bool unpack_mode = false;
 	bool netpbm_mode = false;
+	bool netpbm_bram = false;
 	bool netpbm_fill_tiles = false;
 	bool netpbm_checkerboard = false;
 	int netpbm_banknum = -1;
@@ -951,11 +1085,14 @@ int main(int argc, char **argv)
 		string arg(argv[i]);
 
 		if (arg[0] == '-' && arg.size() > 1) {
-			for (int i = 1; i < arg.size(); i++)
+			for (int i = 1; i < int(arg.size()); i++)
 				if (arg[i] == 'u') {
 					unpack_mode = true;
 				} else if (arg[i] == 'b') {
 					netpbm_mode = true;
+				} else if (arg[i] == 'r') {
+					netpbm_mode = true;
+					netpbm_bram = true;
 				} else if (arg[i] == 'f') {
 					netpbm_mode = true;
 					netpbm_fill_tiles = true;
@@ -1023,8 +1160,12 @@ int main(int argc, char **argv)
 	if (netpbm_fill_tiles)
 		fpga_config.cram_fill_tiles();
 
-	if (netpbm_mode)
-		fpga_config.write_cram_pbm(*osp, netpbm_banknum);
+	if (netpbm_mode) {
+		if (netpbm_bram)
+			fpga_config.write_bram_pbm(*osp, netpbm_banknum);
+		else
+			fpga_config.write_cram_pbm(*osp, netpbm_banknum);
+	}
 
 	info("Done.\n");
 	return 0;
diff --git a/iceprog/Makefile b/iceprog/Makefile
new file mode 100644
index 0000000..b0d735a
--- /dev/null
+++ b/iceprog/Makefile
@@ -0,0 +1,22 @@
+# CC = clang
+LDLIBS = -lftdi -lm
+CFLAGS = -MD -O0 -ggdb -Wall -std=c99
+
+all: iceprog
+
+iceprog: iceprog.o
+
+install: all
+	cp iceprog /usr/local/bin/iceprog
+
+uninstall:
+	rm -f /usr/local/bin/iceprog
+
+clean:
+	rm -f iceprog
+	rm -f *.o *.d
+
+-include *.d
+
+.PHONY: all install uninstall clean
+
diff --git a/iceprog/iceprog.c b/iceprog/iceprog.c
new file mode 100644
index 0000000..5d03dc9
--- /dev/null
+++ b/iceprog/iceprog.c
@@ -0,0 +1,598 @@
+/*
+ *  iceprog -- simple programming tool for FTDI-based Lattice iCE programmers
+ *
+ *  Copyright (C) 2015  Clifford Wolf <clifford at clifford.at>
+ *  
+ *  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.
+ *
+ *  Relevant Documents:
+ *  -------------------
+ *  http://www.latticesemi.com/~/media/Documents/UserManuals/EI/icestickusermanual.pdf
+ *  http://www.micron.com/~/media/documents/products/data-sheet/nor-flash/serial-nor/n25q/n25q_32mb_3v_65nm.pdf
+ *  http://www.ftdichip.com/Support/Documents/AppNotes/AN_108_Command_Processor_for_MPSSE_and_MCU_Host_Bus_Emulation_Modes.pdf
+ */
+
+#define _GNU_SOURCE
+
+#include <ftdi.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+struct ftdi_context ftdic;
+bool ftdic_open = false;
+bool verbose = false;
+
+void check_rx()
+{
+	while (1) {
+		uint8_t data;
+		int rc = ftdi_read_data(&ftdic, &data, 1);
+		if (rc <= 0) break;
+		printf("unexpected rx byte: %02X\n", data);
+	}
+}
+
+void error()
+{
+	check_rx();
+	printf("ABORT.\n");
+	if (ftdic_open)
+		ftdi_usb_close(&ftdic);
+	ftdi_deinit(&ftdic);
+	exit(1);
+}
+
+uint8_t recv_byte()
+{
+	uint8_t data;
+	while (1) {
+		int rc = ftdi_read_data(&ftdic, &data, 1);
+		if (rc < 0) {
+			printf("Read error.\n");
+			error();
+		}
+		if (rc == 1)
+			break;
+		usleep(100);
+	}
+	return data;
+}
+
+void send_byte(uint8_t data)
+{
+	int rc = ftdi_write_data(&ftdic, &data, 1);
+	if (rc != 1) {
+		printf("Write error (single byte, rc=%d, expected %d).\n", rc, 1);
+		error();
+	}
+}
+
+void send_spi(uint8_t *data, int n)
+{
+	if (n < 1)
+		return;
+
+	send_byte(0x11);
+	send_byte(n-1);
+	send_byte((n-1) >> 8);
+
+	int rc = ftdi_write_data(&ftdic, data, n);
+	if (rc != n) {
+		printf("Write error (chunk, rc=%d, expected %d).\n", rc, n);
+		error();
+	}
+}
+
+void xfer_spi(uint8_t *data, int n)
+{
+	if (n < 1)
+		return;
+
+	send_byte(0x31);
+	send_byte(n-1);
+	send_byte((n-1) >> 8);
+
+	int rc = ftdi_write_data(&ftdic, data, n);
+	if (rc != n) {
+		printf("Write error (chunk, rc=%d, expected %d).\n", rc, n);
+		error();
+	}
+
+	for (int i = 0; i < n; i++)
+		data[i] = recv_byte();
+}
+
+void set_gpio(int slavesel_b, int creset_b)
+{
+	uint8_t gpio = 1;
+
+	if (slavesel_b) {
+		// ADBUS4 (GPIOL0)
+		gpio |= 0x10;
+	}
+
+	if (creset_b) {
+		// ADBUS7 (GPIOL3)
+		gpio |= 0x80;
+	}
+
+	send_byte(0x80);
+	send_byte(gpio);
+	send_byte(0x93);
+}
+
+int get_cdone()
+{
+	uint8_t data;
+	send_byte(0x81);
+	data = recv_byte();
+	// ADBUS6 (GPIOL2)
+	return (data & 0x40) != 0;
+}
+
+void flash_read_id()
+{
+	// printf("read flash ID..\n");
+
+	uint8_t data[21] = { 0x9E };
+	set_gpio(0, 0);
+	xfer_spi(data, 21);
+	set_gpio(1, 0);
+
+	printf("flash ID:");
+	for (int i = 1; i < 21; i++)
+		printf(" 0x%02X", data[i]);
+	printf("\n");
+}
+
+void flash_write_enable()
+{
+	if (verbose)
+		printf("write enable..\n");
+
+	uint8_t data[1] = { 0x06 };
+	set_gpio(0, 0);
+	xfer_spi(data, 1);
+	set_gpio(1, 0);
+}
+
+void flash_bulk_erase()
+{
+	printf("bulk erase..\n");
+
+	uint8_t data[1] = { 0xc7 };
+	set_gpio(0, 0);
+	xfer_spi(data, 1);
+	set_gpio(1, 0);
+}
+
+void flash_sector_erase(int addr)
+{
+	printf("sector erase 0x%06X..\n", addr);
+
+	uint8_t command[4] = { 0xd8, addr >> 16, addr >> 8, addr };
+	set_gpio(0, 0);
+	send_spi(command, 4);
+	set_gpio(1, 0);
+}
+
+void flash_prog(int addr, uint8_t *data, int n)
+{
+	if (verbose)
+		printf("prog 0x%06X +0x%03X..\n", addr, n);
+
+	uint8_t command[4] = { 0x02, addr >> 16, addr >> 8, addr };
+	set_gpio(0, 0);
+	send_spi(command, 4);
+	send_spi(data, n);
+	set_gpio(1, 0);
+
+	if (verbose)
+		for (int i = 0; i < n; i++)
+			printf("%02x%c", data[i], i == n-1 || i % 32 == 31 ? '\n' : ' ');
+}
+
+void flash_read(int addr, uint8_t *data, int n)
+{
+	if (verbose)
+		printf("read 0x%06X +0x%03X..\n", addr, n);
+
+	uint8_t command[4] = { 0x03, addr >> 16, addr >> 8, addr };
+	set_gpio(0, 0);
+	send_spi(command, 4);
+	memset(data, 0, n);
+	xfer_spi(data, n);
+	set_gpio(1, 0);
+
+	if (verbose)
+		for (int i = 0; i < n; i++)
+			printf("%02x%c", data[i], i == n-1 || i % 32 == 31 ? '\n' : ' ');
+}
+
+void flash_wait()
+{
+	if (verbose)
+		printf("waiting..");
+
+	while (1)
+	{
+		uint8_t data[2] = { 0x05 };
+
+		set_gpio(0, 0);
+		xfer_spi(data, 2);
+		set_gpio(1, 0);
+
+		if ((data[1] & 0x01) == 0)
+			break;
+
+		if (verbose) {
+			printf(".");
+			fflush(stdout);
+		}
+		usleep(250000);
+	}
+
+	if (verbose)
+		printf("\n");
+}
+
+void help(const char *progname)
+{
+	fprintf(stderr, "\n");
+	fprintf(stderr, "iceprog -- simple programming tool for FTDI-based Lattice iCE programmers\n");
+	fprintf(stderr, "\n");
+	fprintf(stderr, "\n");
+	fprintf(stderr, "Notes for iCEstick (iCE40HX-1k devel board):\n");
+	fprintf(stderr, "  An unmodified iCEstick can only be programmed via the serial flash.\n");
+	fprintf(stderr, "  Direct programming of the SRAM is not supported. For direct SRAM\n");
+	fprintf(stderr, "  programming the flash chip and one zero ohm resistor must be desoldered\n");
+	fprintf(stderr, "  and the FT2232H SI pin must be connected to the iCE SPI_SI pin, as shown\n");
+	fprintf(stderr, "  in this picture: http://www.clifford.at/gallery/2014-elektronik/IMG_20141115_183838\n");
+	fprintf(stderr, "\n");
+	fprintf(stderr, "\n");
+	fprintf(stderr, "Notes for the iCE40-HX8K Breakout Board:\n");
+	fprintf(stderr, "  Make sure that the jumper settings on the board match the selected\n");
+	fprintf(stderr, "  mode (SRAM or FLASH). See the iCE40-HX8K user manual for details.\n");
+	fprintf(stderr, "\n");
+	fprintf(stderr, "\n");
+	fprintf(stderr, "Usage: %s [options] <filename>\n", progname);
+	fprintf(stderr, "\n");
+	fprintf(stderr, "    -d <device-string>\n");
+	fprintf(stderr, "        use the specified USB device:\n");
+	fprintf(stderr, "\n");
+	fprintf(stderr, "            d:<devicenode>                (e.g. d:002/005)\n");
+	fprintf(stderr, "            i:<vendor>:<product>          (e.g. i:0x0403:0x6010)\n");
+	fprintf(stderr, "            i:<vendor>:<product>:<index>  (e.g. i:0x0403:0x6010:0)\n");
+	fprintf(stderr, "            s:<vendor>:<product>:<serial-string>\n");
+	fprintf(stderr, "\n");
+	fprintf(stderr, "    -r\n");
+	fprintf(stderr, "        read entire flash (32Mb / 4MB) and write to file\n");
+	fprintf(stderr, "\n");
+	fprintf(stderr, "    -R\n");
+	fprintf(stderr, "        read first 256 kB from flash and write to file\n");
+	fprintf(stderr, "\n");
+	fprintf(stderr, "    -c\n");
+	fprintf(stderr, "        do not write flash, only verify (check)\n");
+	fprintf(stderr, "\n");
+	fprintf(stderr, "    -b\n");
+	fprintf(stderr, "        bulk erase entire flash before writing\n");
+	fprintf(stderr, "\n");
+	fprintf(stderr, "    -n\n");
+	fprintf(stderr, "        do not erase flash before writing\n");
+	fprintf(stderr, "\n");
+	fprintf(stderr, "    -S\n");
+	fprintf(stderr, "        perform SRAM programming\n");
+	fprintf(stderr, "\n");
+	fprintf(stderr, "    -v\n");
+	fprintf(stderr, "        verbose output\n");
+	fprintf(stderr, "\n");
+	exit(1);
+}
+
+int main(int argc, char **argv)
+{
+	int max_read_size = 4 * 1024 * 1024;
+	bool read_mode = false;
+	bool check_mode = false;
+	bool bulk_erase = false;
+	bool dont_erase = false;
+	bool prog_sram = false;
+	const char *filename = NULL;
+	const char *devstr = NULL;
+
+	int opt;
+	while ((opt = getopt(argc, argv, "d:rRcbnSv")) != -1)
+	{
+		switch (opt)
+		{
+		case 'd':
+			devstr = optarg;
+			break;
+		case 'r':
+			read_mode = true;
+			break;
+		case 'R':
+			read_mode = true;
+			max_read_size = 256 * 1024;
+			break;
+		case 'c':
+			check_mode = true;
+			break;
+		case 'b':
+			bulk_erase = true;
+			break;
+		case 'n':
+			dont_erase = true;
+			break;
+		case 'S':
+			prog_sram = true;
+			break;
+		case 'v':
+			verbose = true;
+			break;
+		default:
+			help(argv[0]);
+		}
+	}
+
+	if (read_mode && check_mode)
+		help(argv[0]);
+
+	if (bulk_erase && dont_erase)
+		help(argv[0]);
+
+	if (optind+1 != argc)
+		help(argv[0]);
+
+	filename = argv[optind];
+
+	// ---------------------------------------------------------
+	// Initialize USB connection to FT2232H
+	// ---------------------------------------------------------
+
+	printf("init..\n");
+
+	ftdi_init(&ftdic);
+	ftdi_set_interface(&ftdic, INTERFACE_A);
+
+	if (devstr != NULL) {
+		if (ftdi_usb_open_string(&ftdic, devstr)) {
+			printf("Can't find iCE FTDI USB device (device string %s).\n", devstr);
+			error();
+		}
+	} else {
+		if (ftdi_usb_open(&ftdic, 0x0403, 0x6010)) {
+			printf("Can't find iCE FTDI USB device (vedor_id 0x0403, device_id 0x6010).\n");
+			error();
+		}
+	}
+
+	ftdic_open = true;
+
+	if (ftdi_usb_reset(&ftdic)) {
+		printf("Failed to reset iCE FTDI USB device.\n");
+		error();
+	}
+
+	if (ftdi_usb_purge_buffers(&ftdic)) {
+		printf("Failed to purge buffers on iCE FTDI USB device.\n");
+		error();
+	}
+
+	if (ftdi_set_bitmode(&ftdic, 0xff, BITMODE_MPSSE) < 0) {
+		printf("Failed set BITMODE_MPSSE on iCE FTDI USB device.\n");
+		error();
+	}
+
+	// enable clock divide by 5
+	send_byte(0x8b);
+
+	// set 6 MHz clock
+	send_byte(0x86);
+	send_byte(0x00);
+	send_byte(0x00);
+
+	printf("cdone: %s\n", get_cdone() ? "high" : "low");
+
+	set_gpio(1, 1);
+	usleep(100000);
+
+
+	if (prog_sram)
+	{
+		// ---------------------------------------------------------
+		// Reset
+		// ---------------------------------------------------------
+
+		printf("reset..\n");
+
+		set_gpio(0, 0);
+		usleep(100);
+
+		set_gpio(0, 1);
+		usleep(2000);
+
+		printf("cdone: %s\n", get_cdone() ? "high" : "low");
+
+
+		// ---------------------------------------------------------
+		// Program
+		// ---------------------------------------------------------
+
+		FILE *f = fopen(filename, "r");
+		if (f == NULL) {
+			fprintf(stderr, "Error: Can't open '%s' for reading: %s\n", filename, strerror(errno));
+			error();
+		}
+
+		printf("programming..\n");
+		while (1)
+		{
+			static unsigned char buffer[4096];
+			int rc = fread(buffer, 1, 4096, f);
+			if (rc <= 0) break;
+			if (verbose)
+				printf("sending %d bytes.\n", rc);
+			send_spi(buffer, rc);
+		}
+
+		fclose(f);
+
+		// add 48 dummy bits
+		send_byte(0x8f);
+		send_byte(0x05);
+		send_byte(0x00);
+
+		// add 1 more dummy bit
+		send_byte(0x8e);
+		send_byte(0x00);
+
+		printf("cdone: %s\n", get_cdone() ? "high" : "low");
+	}
+	else
+	{
+		// ---------------------------------------------------------
+		// Reset
+		// ---------------------------------------------------------
+
+		printf("reset..\n");
+
+		set_gpio(1, 0);
+		usleep(250000);
+
+		printf("cdone: %s\n", get_cdone() ? "high" : "low");
+
+		flash_read_id();
+
+
+		// ---------------------------------------------------------
+		// Program
+		// ---------------------------------------------------------
+
+		if (!read_mode && !check_mode)
+		{
+			FILE *f = fopen(filename, "r");
+			if (f == NULL) {
+				fprintf(stderr, "Error: Can't open '%s' for reading: %s\n", filename, strerror(errno));
+				error();
+			}
+
+			if (!dont_erase)
+			{
+				if (bulk_erase)
+				{
+					flash_write_enable();
+					flash_bulk_erase();
+					flash_wait();
+				}
+				else
+				{
+					fseek(f, SEEK_END, 0);
+					int file_size = ftell(f);
+					rewind(f);
+
+					for (int addr = 0; addr < file_size; addr += 0x1000) {
+						flash_write_enable();
+						flash_sector_erase(addr);
+						flash_wait();
+					}
+				}
+			}
+
+			printf("programming..\n");
+			for (int addr = 0; true; addr += 256) {
+				uint8_t buffer[256];
+				int rc = fread(buffer, 1, 256, f);
+				if (rc <= 0) break;
+				flash_write_enable();
+				flash_prog(addr, buffer, rc);
+				flash_wait();
+			}
+
+			fclose(f);
+		}
+
+
+		// ---------------------------------------------------------
+		// Read/Verify
+		// ---------------------------------------------------------
+
+		if (read_mode)
+		{
+			FILE *f = fopen(filename, "w");
+			if (f == NULL) {
+				fprintf(stderr, "Error: Can't open '%s' for writing: %s\n", filename, strerror(errno));
+				error();
+			}
+
+			printf("reading..\n");
+			for (int addr = 0; addr < max_read_size; addr += 256) {
+				uint8_t buffer[256];
+				flash_read(addr, buffer, 256);
+				fwrite(buffer, 256, 1, f);
+			}
+
+			fclose(f);
+		}
+		else
+		{
+			FILE *f = fopen(filename, "r");
+			if (f == NULL) {
+				fprintf(stderr, "Error: Can't open '%s' for reading: %s\n", filename, strerror(errno));
+				error();
+			}
+
+			printf("reading..\n");
+			for (int addr = 0; true; addr += 256) {
+				uint8_t buffer_flash[256], buffer_file[256];
+				int rc = fread(buffer_file, 1, 256, f);
+				if (rc <= 0) break;
+				flash_read(addr, buffer_flash, 256);
+				if (memcmp(buffer_file, buffer_flash, rc)) {
+					fprintf(stderr, "Found difference between flash and file!\n");
+					error();
+				}
+			}
+
+			printf("VERIFY OK\n");
+
+			fclose(f);
+		}
+
+
+		// ---------------------------------------------------------
+		// Reset
+		// ---------------------------------------------------------
+
+		set_gpio(1, 1);
+		usleep(250000);
+
+		printf("cdone: %s\n", get_cdone() ? "high" : "low");
+	}
+
+
+	// ---------------------------------------------------------
+	// Exit
+	// ---------------------------------------------------------
+
+	printf("Bye.\n");
+	ftdi_disable_bitbang(&ftdic);
+	ftdi_usb_close(&ftdic);
+	ftdi_deinit(&ftdic);
+	return 0;
+}
+

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/icestorm.git



More information about the debian-science-commits mailing list