[icestorm] 02/75: Import of icestorm-snapshot-150401.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 0347c37d56374447d170e9a8f59e56f84cbefcce
Author: Clifford Wolf <clifford at clifford.at>
Date:   Sat Jul 18 13:05:51 2015 +0200

    Import of icestorm-snapshot-150401.zip
---
 icebox/icebox.py         |   27 +-
 icebox/icebox_explain.py |    6 +
 icepack/Makefile         |   20 +-
 icepack/icepack.cc       | 1031 ++++++++++++++++++++++++++++++++++++++++++++++
 icepack/iceunpack.c      |  368 -----------------
 5 files changed, 1074 insertions(+), 378 deletions(-)

diff --git a/icebox/icebox.py b/icebox/icebox.py
index f3dc113..01cda0d 100644
--- a/icebox/icebox.py
+++ b/icebox/icebox.py
@@ -27,10 +27,12 @@ class iceconfig:
     def clear(self):
         self.max_x = 0
         self.max_y = 0
+        self.device = ""
         self.logic_tiles = dict()
         self.io_tiles = dict()
         self.ram_tiles = dict()
         self.ram_init = dict()
+        self.extra_bits = set()
 
     def setup_empty_1k(self):
         self.clear()
@@ -52,6 +54,12 @@ class iceconfig:
             self.io_tiles[(0, y)] = ["0" * 18 for i in range(16)]
             self.io_tiles[(self.max_x, y)] = ["0" * 18 for i in range(16)]
 
+    def lookup_extra_bit(self, bit):
+        assert self.device in extra_bits_db
+        if bit in extra_bits_db[self.device]:
+            return extra_bits_db[self.device][bit]
+        return ("UNKNOWN_FUNCTION",)
+
     def tile(self, x, y):
         if (x, y) in self.io_tiles: return self.io_tiles[(x, y)]
         if (x, y) in self.logic_tiles: return self.logic_tiles[(x, y)]
@@ -354,6 +362,8 @@ class iceconfig:
                     assert expected_data_lines == 0
                     continue
                 if line[0][0] != ".":
+                    if expected_data_lines == -1:
+                        continue
                     if line[0][0] != "0" and line[0][0] != "1":
                         print("%sWarning: ignoring data block in line %d: %s" % (logprefix, linenum, linetext.strip()))
                         expected_data_lines = 0
@@ -362,7 +372,7 @@ class iceconfig:
                     current_data.append(line[0])
                     expected_data_lines -= 1
                     continue
-                assert expected_data_lines == 0
+                assert expected_data_lines <= 0
                 if line[0] in (".io_tile", ".logic_tile", ".ram_tile"):
                     current_data = list()
                     expected_data_lines = 16
@@ -377,8 +387,15 @@ class iceconfig:
                 if line[0] == ".ram_tile":
                     self.ram_tiles[(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
                 if line[0] == ".device":
-                    assert line[1] == "1k"
+                    assert line[1] in ["1k"]
+                    self.device = line[1]
+                    continue
+                if line[0] == ".comment":
+                    expected_data_lines = -1
                     continue
                 print("%sWarning: ignoring line %d: %s" % (logprefix, linenum, linetext.strip()))
 
@@ -770,6 +787,12 @@ def parse_db(text):
         db.append(line)
     return db
 
+extra_bits_db = {
+    "1k": {
+        (0, 331, 142): ("routing", "padin_1", "glb_netwk_1")
+    }
+}
+
 iotile_full_db = parse_db(iceboxdb.database_io_txt)
 logictile_db = parse_db(iceboxdb.database_logic_txt)
 ramtile_db = parse_db(iceboxdb.database_ram_txt)
diff --git a/icebox/icebox_explain.py b/icebox/icebox_explain.py
index 26575f1..e2ca0e8 100755
--- a/icebox/icebox_explain.py
+++ b/icebox/icebox_explain.py
@@ -153,5 +153,11 @@ for idx in ic.logic_tiles:
 
 for idx in ic.ram_tiles:
     print_tile(".ram_tile %d %d" % idx, ic, idx[0], idx[1], ic.ram_tiles[idx], ic.tile_db(idx[0], idx[1]))
+
+for bit in ic.extra_bits:
+    print()
+    print(".extra_bit %d %d %d" % bit)
+    print(" ".join(ic.lookup_extra_bit(bit)))
+
 print()
 
diff --git a/icepack/Makefile b/icepack/Makefile
index 06aeaeb..75f81e7 100644
--- a/icepack/Makefile
+++ b/icepack/Makefile
@@ -1,25 +1,29 @@
 
-CC = clang
 CXX = clang
-LDFLAGS = -lm -lstdc++
-CFLAGS = -MD -Os -Wall -std=c99
-CXXFLAGS = -MD -Os -Wall -std=c99
+LDLIBS = -lm -lstdc++
+CXXFLAGS = -MD -O0 -ggdb -Wall -std=c++11
 
-all: iceunpack
+all: icepack iceunpack
 
-iceunpack: iceunpack.o
+icepack: icepack.o
+
+iceunpack: icepack
+	ln -sf icepack iceunpack
 
 install: all
-	cp iceunpack /usr/local/bin/iceunpack
+	cp icepack /usr/local/bin/icepack
+	ln -s icepack /usr/local/bin/iceunpack
 
 uninstall:
+	rm -f /usr/local/bin/icepack
 	rm -f /usr/local/bin/iceunpack
 
 clean:
+	rm -f icepack
 	rm -f iceunpack
 	rm -f *.o *.d
 
 -include *.d
 
-.PHONY: install uninstall clean
+.PHONY: all install uninstall clean
 
diff --git a/icepack/icepack.cc b/icepack/icepack.cc
new file mode 100644
index 0000000..1614c5e
--- /dev/null
+++ b/icepack/icepack.cc
@@ -0,0 +1,1031 @@
+//
+//  Copyright (C) 2015  Clifford Wolf <clifford at clifford.at>
+//
+//  Based on a reference implementation provided by Mathias Lasser
+//
+//  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.
+//
+
+#include <set>
+#include <tuple>
+#include <vector>
+#include <string>
+#include <fstream>
+#include <iostream>
+#include <sstream>
+#include <cstdint>
+
+#include <stdio.h>
+#include <stdarg.h>
+
+using std::vector;
+using std::string;
+
+int log_level = 0;
+#define log(...) fprintf(stderr, __VA_ARGS__);
+#define info(...) do { if (log_level > 0) fprintf(stderr, __VA_ARGS__); } while (0)
+#define debug(...) do { if (log_level > 1) fprintf(stderr, __VA_ARGS__); } while (0)
+#define error(...) do { fprintf(stderr, "Error: " __VA_ARGS__); exit(1); } while (0)
+#define panic(fmt, ...) do { fprintf(stderr, "Internal Error at %s:%d: " fmt, __FILE__, __LINE__, ##__VA_ARGS__); abort(); } while (0)
+
+string vstringf(const char *fmt, va_list ap)
+{
+	string string;
+	char *str = NULL;
+
+#ifdef _WIN32
+	int sz = 64, rc;
+	while (1) {
+		va_list apc;
+		va_copy(apc, ap);
+		str = (char*)realloc(str, sz);
+		rc = vsnprintf(str, sz, fmt, apc);
+		va_end(apc);
+		if (rc >= 0 && rc < sz)
+			break;
+		sz *= 2;
+	}
+#else
+	if (vasprintf(&str, fmt, ap) < 0)
+		str = NULL;
+#endif
+
+	if (str != NULL) {
+		string = str;
+		free(str);
+	}
+
+	return string;
+}
+
+string stringf(const char *fmt, ...)
+{
+	string string;
+	va_list ap;
+
+	va_start(ap, fmt);
+	string = vstringf(fmt, ap);
+	va_end(ap);
+
+	return string;
+}
+
+// ==================================================================
+// FpgaConfig stuff
+
+struct FpgaConfig
+{
+	string device;
+	string freqrange;
+	string warmboot;
+
+	// cram[BANK][X][Y]
+	int cram_width, cram_height;
+	vector<vector<vector<bool>>> cram;
+
+	// bram[BANK][X][Y]
+	int bram_width, bram_height;
+	vector<vector<vector<bool>>> bram;
+
+	// data before preamble
+	vector<uint8_t> initblop;
+
+	// bitstream i/o
+	void read_bits(std::istream &ifs);
+	void write_bits(std::ostream &ofs) const;
+
+	// icebox i/o
+	void read_ascii(std::istream &ifs);
+	void write_ascii(std::ostream &ofs) const;
+
+	// netpbm i/o
+	void write_cram_pbm(std::ostream &ofs, int bank_num = -1) const;
+
+	// query chip type metadata
+	int chip_width() const;
+	int chip_height() const;
+	vector<int> chip_cols() const;
+
+	// query tile metadata
+	string tile_type(int x, int y) const;
+	int tile_width(const string &type) const;
+
+	// cram bit manipulation
+	void cram_clear();
+	void cram_fill_tiles();
+	void cram_checkerboard(int m = 0);
+};
+
+struct CramIndexConverter
+{
+	const FpgaConfig *fpga;
+	int tile_x, tile_y;
+
+	string tile_type;
+	int tile_width;
+	int column_width;
+
+	bool left_right_io;
+	bool right_half;
+	bool top_half;
+
+	int bank_num;
+	int bank_tx;
+	int bank_ty;
+	int bank_xoff;
+	int bank_yoff;
+
+	CramIndexConverter(const FpgaConfig *fpga, int tile_x, int tile_y);
+	void get_cram_index(int bit_x, int bit_y, int &cram_bank, int &cram_x, int &cram_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;
+		crc = (crc << 1) ^ xor_value;
+	}
+}
+
+static uint8_t read_byte(std::istream &ifs, uint16_t &crc_value, int &file_offset)
+{
+	int byte = ifs.get();
+
+	if (byte < 0)
+		error("Unexpected end of file.\n");
+
+	file_offset++;
+	update_crc16(crc_value, byte);
+
+	return byte;
+}
+
+static void write_byte(std::ostream &ofs, uint16_t &crc_value, int &file_offset, uint8_t byte)
+{
+	ofs << byte;
+	file_offset++;
+	update_crc16(crc_value, byte);
+}
+
+void FpgaConfig::read_bits(std::istream &ifs)
+{
+	int file_offset = 0;
+	uint16_t crc_value = 0;
+
+	debug("## %s\n", __PRETTY_FUNCTION__);
+	info("Parsing bitstream file..\n");
+
+	// skip initial comments until preamble is found
+
+	uint32_t preamble = 0;
+
+	while (1)
+	{
+		uint8_t byte = read_byte(ifs, crc_value, file_offset);
+		preamble = (preamble << 8) | byte;
+		if (preamble == 0xffffffff)
+			error("No preamble found in bitstream.\n");
+		if (preamble == 0x7EAA997E) {
+			info("Found preamble at offset %d.\n", file_offset-4);
+			break;
+		}
+		initblop.push_back(byte);
+	}
+
+	initblop.pop_back();
+	initblop.pop_back();
+	initblop.pop_back();
+
+	// main parser loop
+
+	int current_bank = 0;
+	int current_width = 0;
+	int current_height = 0;
+	int current_offset = 0;
+	bool wakeup = false;
+
+	this->cram_width = 0;
+	this->cram_height = 0;
+
+	this->bram_width = 0;
+	this->bram_height = 0;
+
+	while (!wakeup)
+	{
+		// one command byte. the lower 4 bits of the command byte specify
+		// the length of the command payload.
+		
+		uint8_t command = read_byte(ifs, crc_value, file_offset);
+		uint32_t payload = 0;
+
+		for (int i = 0; i < (command & 0x0f); i++)
+			payload = (payload << 8) | read_byte(ifs, crc_value, file_offset);
+
+		debug("Next command at offset %d: 0x%02x 0x%0*x\n", file_offset - 1 - (command & 0x0f),
+				command, 2*(command & 0x0f), payload);
+
+		uint16_t end_token;
+
+		switch (command & 0xf0)
+		{
+		case 0x00:
+			switch (payload)
+			{
+			case 0x01:
+				info("CRAM Data [%d]: %d x %d bits = %d bits = %d bytes\n",
+						current_bank, current_width, current_height,
+						current_height*current_width, (current_height*current_width)/8);
+
+				this->cram_width = std::max(this->cram_width, current_width);
+				this->cram_height = std::max(this->cram_height, current_offset + current_height);
+
+				this->cram.resize(4);
+				this->cram[current_bank].resize(this->cram_width);
+				for (int x = 0; x < current_width; x++)
+					this->cram[current_bank][x].resize(this->cram_height);
+
+				for (int i = 0; i < (current_height*current_width)/8; i++) {
+					uint8_t byte = read_byte(ifs, crc_value, file_offset);
+					for (int j = 0; j < 8; j++) {
+						int x = (i*8 + j) % current_width;
+						int y = (i*8 + j) / current_width + current_offset;
+						this->cram[current_bank][x][y] = ((byte << j) & 0x80) != 0;
+					}
+				}
+
+				end_token = read_byte(ifs, crc_value, file_offset);
+				end_token = (end_token << 8) | read_byte(ifs, crc_value, file_offset);
+				if (end_token)
+					error("Expeded 0x0000 after CRAM data, got 0x%04x\n", end_token);
+				break;
+
+			case 0x03:
+				info("BRAM Data [%d]: %d x %d bits = %d bits = %d bytes\n",
+						current_bank, current_width, current_height,
+						current_height*current_width, (current_height*current_width)/8);
+
+				this->bram_width = std::max(this->bram_width, current_width);
+				this->bram_height = std::max(this->bram_height, current_offset + current_height);
+
+				this->bram.resize(4);
+				this->bram[current_bank].resize(this->bram_width);
+				for (int x = 0; x < current_width; x++)
+					this->bram[current_bank][x].resize(this->bram_height);
+
+				for (int i = 0; i < (current_height*current_width)/8; i++) {
+					uint8_t byte = read_byte(ifs, crc_value, file_offset);
+					for (int j = 0; j < 8; j++) {
+						int x = (i*8 + j) % current_width;
+						int y = (i*8 + j) / current_width + current_offset;
+						this->bram[current_bank][x][y] = ((byte << j) & 0x80) != 0;
+					}
+				}
+
+				end_token = read_byte(ifs, crc_value, file_offset);
+				end_token = (end_token << 8) | read_byte(ifs, crc_value, file_offset);
+				if (end_token)
+					error("Expeded 0x0000 after BRAM data, got 0x%04x\n", end_token);
+				break;
+
+			case 0x05:
+				debug("Resetting CRC.\n");
+				crc_value = 0xffff;
+				break;
+
+			case 0x06:
+				info("Wakeup.\n");
+				wakeup = true;
+				break;
+
+			default:
+				error("Unkown command: 0x%02x 0x%02x\n", command, payload);
+			}
+			break;
+
+		case 0x10:
+			current_bank = payload;
+			debug("Set bank to %d.\n", current_bank);
+			break;
+
+		case 0x20:
+			if (crc_value != 0)
+				error("CRC Check FAILED.\n");
+			info("CRC Check OK.\n");
+			break;
+
+		case 0x50:
+			if (payload == 0)
+				this->freqrange = "low";
+			else if (payload == 1)
+				this->freqrange = "medium";
+			else if (payload == 2)
+				this->freqrange = "high";
+			else
+				error("Unknown freqrange payload 0x%02x\n", payload);
+			info("Setting freqrange to '%s'.\n", this->freqrange.c_str());
+			break;
+
+		case 0x60:
+			current_width = payload + 1;
+			debug("Setting bank width to %d.\n", current_width);
+			break;
+
+		case 0x70:
+			current_height = payload;
+			debug("Setting bank height to %d.\n", current_height);
+			break;
+
+		case 0x80:
+			current_offset = payload;
+			debug("Setting bank offset to %d.\n", current_offset);
+			break;
+
+		case 0x90:
+			if (payload == 0)
+				this->warmboot = "disabled";
+			else if (payload == 32)
+				this->warmboot = "enabled";
+			else
+				error("Unknown warmboot payload 0x%02x\n", payload);
+			info("Setting warmboot to '%s'.\n", this->warmboot.c_str());
+			break;
+
+		default:
+			error("Unkown command: 0x%02x 0x%02x\n", command, payload);
+		}
+	}
+
+	if (this->cram_width == 182 && this->cram_height == 80)
+		this->device = "384";
+	else if (this->cram_width == 332 && this->cram_height == 144)
+		this->device = "1k";
+	else if (this->cram_width == 872 && this->cram_height == 272)
+		this->device = "4k8k";
+	else
+		error("Failed to detect chip type.\n");
+	
+	info("Chip type is '%s'.\n", this->device.c_str());
+}
+
+void FpgaConfig::write_bits(std::ostream &ofs) const
+{
+	int file_offset = 0;
+	uint16_t crc_value = 0;
+
+	debug("## %s\n", __PRETTY_FUNCTION__);
+	info("Writing bitstream file..\n");
+
+	for (auto byte : this->initblop)
+		ofs << byte;
+
+	debug("Writing preamble.\n");
+	write_byte(ofs, crc_value, file_offset, 0x7E);
+	write_byte(ofs, crc_value, file_offset, 0xAA);
+	write_byte(ofs, crc_value, file_offset, 0x99);
+	write_byte(ofs, crc_value, file_offset, 0x7E);
+
+	debug("Setting freqrange to '%s'.\n", this->freqrange.c_str());
+	write_byte(ofs, crc_value, file_offset, 0x51);
+	if (this->freqrange == "low")
+		write_byte(ofs, crc_value, file_offset, 0x00);
+	else if (this->freqrange == "medium")
+		write_byte(ofs, crc_value, file_offset, 0x01);
+	else if (this->freqrange == "high")
+		write_byte(ofs, crc_value, file_offset, 0x02);
+	else
+		error("Unknown freqrange '%s'.\n", this->freqrange.c_str());
+
+	debug("Resetting CRC.\n");
+	write_byte(ofs, crc_value, file_offset, 0x01);
+	write_byte(ofs, crc_value, file_offset, 0x05);
+	crc_value = 0xffff;
+
+	debug("Setting warmboot to '%s'.\n", this->warmboot.c_str());
+	write_byte(ofs, crc_value, file_offset, 0x92);
+	write_byte(ofs, crc_value, file_offset, 0x00);
+	if (this->warmboot == "disabled")
+		write_byte(ofs, crc_value, file_offset, 0x00);
+	else if (this->warmboot == "enabled")
+		write_byte(ofs, crc_value, file_offset, 0x20);
+	else
+		error("Unknown warmboot setting '%s'.\n", this->warmboot.c_str());
+
+	debug("CRAM: Setting bank width to %d.\n", this->cram_width);
+	write_byte(ofs, crc_value, file_offset, 0x62);
+	write_byte(ofs, crc_value, file_offset, (this->cram_width-1) >> 8);
+	write_byte(ofs, crc_value, file_offset, (this->cram_width-1));
+
+	debug("CRAM: Setting bank height to %d.\n", this->cram_height);
+	write_byte(ofs, crc_value, file_offset, 0x72);
+	write_byte(ofs, crc_value, file_offset, this->cram_height >> 8);
+	write_byte(ofs, crc_value, file_offset, this->cram_height);
+
+	debug("CRAM: Setting bank offset to 0.\n");
+	write_byte(ofs, crc_value, file_offset, 0x82);
+	write_byte(ofs, crc_value, file_offset, 0x00);
+	write_byte(ofs, crc_value, file_offset, 0x00);
+
+	for (int cram_bank = 0; cram_bank < 4; cram_bank++)
+	{
+		vector<bool> cram_bits;
+		for (int cram_y = 0; cram_y < this->cram_height; cram_y++)
+		for (int cram_x = 0; cram_x < this->cram_width; cram_x++)
+			cram_bits.push_back(this->cram[cram_bank][cram_x][cram_y]);
+
+		debug("CRAM: Setting bank %d.\n", cram_bank);
+		write_byte(ofs, crc_value, file_offset, 0x11);
+		write_byte(ofs, crc_value, file_offset, cram_bank);
+
+		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) {
+			uint8_t byte = 0;
+			for (int j = 0; j < 8; j++)
+				byte = (byte << 1) | (cram_bits[i+j] ? 1 : 0);
+			write_byte(ofs, crc_value, file_offset, byte);
+		}
+
+		write_byte(ofs, crc_value, file_offset, 0x00);
+		write_byte(ofs, crc_value, file_offset, 0x00);
+	}
+
+	int bram_chunk_size = 128;
+
+	debug("BRAM: Setting bank width to %d.\n", this->bram_width);
+	write_byte(ofs, crc_value, file_offset, 0x62);
+	write_byte(ofs, crc_value, file_offset, (this->bram_width-1) >> 8);
+	write_byte(ofs, crc_value, file_offset, (this->bram_width-1));
+
+	debug("BRAM: Setting bank height to %d.\n", this->bram_height);
+	write_byte(ofs, crc_value, file_offset, 0x72);
+	write_byte(ofs, crc_value, file_offset, bram_chunk_size >> 8);
+	write_byte(ofs, crc_value, file_offset, bram_chunk_size);
+
+	for (int bram_bank = 0; bram_bank < 4; bram_bank++)
+	{
+		debug("BRAM: Setting bank %d.\n", bram_bank);
+		write_byte(ofs, crc_value, file_offset, 0x11);
+		write_byte(ofs, crc_value, file_offset, bram_bank);
+
+		for (int offset = 0; offset < this->bram_height; offset += bram_chunk_size)
+		{
+			vector<bool> bram_bits;
+			for (int bram_y = 0; bram_y < bram_chunk_size; bram_y++)
+			for (int bram_x = 0; bram_x < this->bram_width; bram_x++)
+				bram_bits.push_back(this->bram[bram_bank][bram_x][bram_y+offset]);
+
+			debug("BRAM: Setting bank offset to %d.\n", offset);
+			write_byte(ofs, crc_value, file_offset, 0x82);
+			write_byte(ofs, crc_value, file_offset, offset >> 8);
+			write_byte(ofs, crc_value, file_offset, offset);
+
+			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) {
+				uint8_t byte = 0;
+				for (int j = 0; j < 8; j++)
+					byte = (byte << 1) | (bram_bits[i+j] ? 1 : 0);
+				write_byte(ofs, crc_value, file_offset, byte);
+			}
+
+			write_byte(ofs, crc_value, file_offset, 0x00);
+			write_byte(ofs, crc_value, file_offset, 0x00);
+		}
+	}
+
+	debug("Writing CRC value.\n");
+	write_byte(ofs, crc_value, file_offset, 0x22);
+	uint8_t crc_hi = crc_value >> 8, crc_lo = crc_value;
+	write_byte(ofs, crc_value, file_offset, crc_hi);
+	write_byte(ofs, crc_value, file_offset, crc_lo);
+
+	debug("Wakeup.\n");
+	write_byte(ofs, crc_value, file_offset, 0x01);
+	write_byte(ofs, crc_value, file_offset, 0x06);
+
+	debug("Padding byte.\n");
+	write_byte(ofs, crc_value, file_offset, 0x00);
+}
+
+void FpgaConfig::read_ascii(std::istream &ifs)
+{
+	debug("## %s\n", __PRETTY_FUNCTION__);
+	info("Parsing ascii file..\n");
+
+	bool got_device = false;
+	this->cram.clear();
+	this->bram.clear();
+	this->freqrange = "low";
+	this->warmboot = "enabled";
+
+	bool reuse_line = true;
+	string line, command;
+
+	while (reuse_line || getline(ifs, line))
+	{
+		reuse_line = false;
+
+		std::istringstream is(line);
+		is >> command;
+
+		if (command.empty())
+			continue;
+
+		debug("Next command: %s\n", line.c_str());
+
+		if (command == ".comment")
+		{
+			this->initblop.clear();
+			this->initblop.push_back(0xff);
+			this->initblop.push_back(0x00);
+
+			while (getline(ifs, line))
+			{
+				if (line.substr(0, 1) == ".") {
+					reuse_line = true;
+					break;
+				}
+
+				for (auto ch : line)
+					this->initblop.push_back(ch);
+				this->initblop.push_back(0);
+			}
+
+			this->initblop.push_back(0x00);
+			this->initblop.push_back(0xff);
+			continue;
+		}
+
+		if (command == ".device")
+		{
+			is >> this->device;
+
+			if (this->device == "1k") {
+				this->cram_width = 332;
+				this->cram_height = 144;
+				this->bram_width = 64;
+				this->bram_height = 2 * 128;
+			} else
+				error("Unsupported chip type '%s'.\n", this->device.c_str());
+
+			this->cram.resize(4);
+			for (int i = 0; i < 4; i++) {
+				this->cram[i].resize(this->cram_width);
+				for (int x = 0; x < this->cram_width; x++)
+					this->cram[i][x].resize(this->cram_height);
+			}
+
+			this->bram.resize(4);
+			for (int i = 0; i < 4; i++) {
+				this->bram[i].resize(this->bram_width);
+				for (int x = 0; x < this->bram_width; x++)
+					this->bram[i][x].resize(this->bram_height);
+			}
+
+			got_device = true;
+			continue;
+		}
+
+		if (command == ".io_tile" || command == ".logic_tile" || command == ".ram_tile")
+		{
+			if (!got_device)
+				error("Missing .device statement before %s.\n", command.c_str());
+
+			int tile_x, tile_y;
+			is >> tile_x >> tile_y;
+
+			CramIndexConverter cic(this, tile_x, tile_y);
+
+			if (("." + cic.tile_type + "_tile") != command)
+				error("Got %s statement for %s tile %d %d.\n",
+						command.c_str(), cic.tile_type.c_str(), 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 = 0; bit_x < 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);
+						this->cram[cram_bank][cram_x][cram_y] = true;
+					}
+			}
+
+			continue;
+		}
+
+		if (command == ".extra_bit")
+		{
+			if (!got_device)
+				error("Missing .device statement before %s.\n", command.c_str());
+
+			int cram_bank, cram_x, cram_y;
+			is >> cram_bank >> cram_x >> cram_y;
+			this->cram[cram_bank][cram_x][cram_y] = true;
+
+			continue;
+		}
+
+		if (command.substr(0, 1) == ".")
+			error("Unknown statement: %s\n", command.c_str());
+		error("Unexpected data line: %s\n", line.c_str());
+	}
+}
+
+void FpgaConfig::write_ascii(std::ostream &ofs) const
+{
+	debug("## %s\n", __PRETTY_FUNCTION__);
+	info("Writing ascii file..\n");
+
+	ofs << ".comment";
+	bool insert_newline = true;
+	for (auto ch : this->initblop) {
+		if (ch == 0) {
+			insert_newline = true;
+		} else if (ch == 0xff) {
+			insert_newline = false;
+		} else {
+			if (insert_newline)
+				ofs << '\n';
+			ofs << ch;
+			insert_newline = false;
+		}
+	}
+
+	ofs << stringf("\n.device %s\n", this->device.c_str());
+
+	typedef std::tuple<int, int, int> tile_bit_t;
+	std::set<tile_bit_t> tile_bits;
+
+	for (int y = 0; y <= this->chip_height()+1; y++)
+	for (int x = 0; x <= this->chip_width()+1; x++)
+	{
+		CramIndexConverter cic(this, x, y);
+
+		if (cic.tile_type == "corner")
+			continue;
+
+		ofs << stringf(".%s_tile %d %d\n", cic.tile_type.c_str(), x, y);
+
+		for (int bit_y = 0; bit_y < 16; bit_y++) {
+			for (int bit_x = 0; bit_x < cic.tile_width; bit_x++) {
+				int cram_bank, cram_x, cram_y;
+				cic.get_cram_index(bit_x, bit_y, cram_bank, cram_x, cram_y);
+				tile_bits.insert(tile_bit_t(cram_bank, cram_x, cram_y));
+				ofs << (this->cram[cram_bank][cram_x][cram_y] ? '1' : '0');
+			}
+			ofs << '\n';
+		}
+	}
+
+	for (int i = 0; i < 4; i++)
+	for (int x = 0; x < this->cram_width; x++)
+	for (int y = 0; y < this->cram_height; y++)
+		if (this->cram[i][x][y] && tile_bits.count(tile_bit_t(i, x, y)) == 0)
+			ofs << stringf(".extra_bit %d %d %d\n", i, x, y);
+
+#if 0
+	for (int i = 0; i < 4; i++) {
+		ofs << stringf(".bram_bank %d\n", i);
+		for (int x = 0; x < this->bram_width; x++) {
+			for (int y = 0; y < this->bram_height; y += 4)
+				ofs << "0123456789abcdef"[(this->bram[i][x][y] ? 1 : 0) + (this->bram[i][x][y+1] ? 2 : 0) +
+						(this->bram[i][x][y+2] ? 4 : 0) + (this->bram[i][x][y+3] ? 8 : 0)];
+			ofs << '\n';
+		}
+	}
+#endif
+}
+
+void FpgaConfig::write_cram_pbm(std::ostream &ofs, int bank_num) const
+{
+	debug("## %s\n", __PRETTY_FUNCTION__);
+	info("Writing pbm file..\n");
+
+	ofs << "P1\n";
+	ofs << stringf("%d %d\n", 2*this->cram_width, 2*this->cram_height);
+	for (int y = 2*this->cram_height-1; y >= 0; y--) {
+		for (int x = 0; x < 2*this->cram_width; x++) {
+			int bank = 0, bank_x = x, bank_y = y;
+			if (bank_x >= this->cram_width)
+				bank |= 1, bank_x = 2*this->cram_width - bank_x - 1;
+			if (bank_y >= this->cram_height)
+				bank |= 2, bank_y = 2*this->cram_height - bank_y - 1;
+			if (bank_num >= 0 && bank != bank_num)
+				ofs << " 0";
+			else
+				ofs << (this->cram[bank][bank_x][bank_y] ? " 1" : " 0");
+		}
+		ofs << '\n';
+	}
+}
+
+int FpgaConfig::chip_width() const
+{
+	if (this->device == "384")  return 6;
+	if (this->device == "1k")   return 12;
+	if (this->device == "4k8k") return 32;
+	panic("Unkown chip type '%s'.\n", this->device.c_str());
+}
+
+int FpgaConfig::chip_height() const
+{
+	if (this->device == "384")  return 8;
+	if (this->device == "1k")   return 16;
+	if (this->device == "4k8k") return 32;
+	panic("Unkown chip type '%s'.\n", this->device.c_str());
+}
+
+vector<int> FpgaConfig::chip_cols() const
+{
+	if (this->device == "384")  return vector<int>({18, 54, 54, 54});
+	if (this->device == "1k")   return vector<int>({18, 54, 54, 42, 54, 54, 54});
+	if (this->device == "4k8k") return vector<int>({18,  2, 54, 54, 54, 54, 54, 54, 54, 42, 54, 54, 54, 54, 54, 54, 54, 54});
+	panic("Unkown chip type '%s'.\n", this->device.c_str());
+}
+
+string FpgaConfig::tile_type(int x, int y) const
+{
+	if (this->device == "1k") {
+		if ((x == 0 || x == this->chip_width()+1) && (y == 0 || y == this->chip_height()+1)) return "corner";
+		if ((x == 0 || x == this->chip_width()+1) || (y == 0 || y == this->chip_height()+1)) return "io";
+		if (x == 3 || x == 10) return "ram";
+		return "logic";
+	}
+	panic("Unkown chip type '%s'.\n", this->device.c_str());
+}
+
+int FpgaConfig::tile_width(const string &type) const
+{
+	if (type == "corner") return 0;
+	if (type == "logic")  return 54;
+	if (type == "ram")    return 42;
+	if (type == "io")     return 18;
+	panic("Unkown tile type '%s'.\n", type.c_str());
+}
+
+void FpgaConfig::cram_clear()
+{
+	for (int i = 0; i < 4; i++)
+	for (int x = 0; x < this->cram_width; x++)
+	for (int y = 0; y < this->cram_height; y++)
+		this->cram[i][x][y] = false;
+}
+
+void FpgaConfig::cram_fill_tiles()
+{
+	for (int y = 0; y <= this->chip_height()+1; y++)
+	for (int x = 0; x <= this->chip_width()+1; x++)
+	{
+		CramIndexConverter cic(this, x, y);
+
+		for (int bit_y = 0; bit_y < 16; bit_y++)
+		for (int bit_x = 0; bit_x < cic.tile_width; bit_x++) {
+			int cram_bank, cram_x, cram_y;
+			cic.get_cram_index(bit_x, bit_y, cram_bank, cram_x, cram_y);
+			this->cram[cram_bank][cram_x][cram_y] = true;
+		}
+	}
+}
+
+void FpgaConfig::cram_checkerboard(int m)
+{
+	for (int y = 0; y <= this->chip_height()+1; y++)
+	for (int x = 0; x <= this->chip_width()+1; x++)
+	{
+		if ((x+y) % 2 == m)
+			continue;
+			
+		CramIndexConverter cic(this, x, y);
+
+		for (int bit_y = 0; bit_y < 16; bit_y++)
+		for (int bit_x = 0; bit_x < cic.tile_width; bit_x++) {
+			int cram_bank, cram_x, cram_y;
+			cic.get_cram_index(bit_x, bit_y, cram_bank, cram_x, cram_y);
+			this->cram[cram_bank][cram_x][cram_y] = true;
+		}
+	}
+}
+
+CramIndexConverter::CramIndexConverter(const FpgaConfig *fpga, int tile_x, int tile_y)
+{
+	this->fpga = fpga;
+	this->tile_x = tile_x;
+	this->tile_y = tile_y;
+
+
+	this->tile_type = fpga->tile_type(this->tile_x, this->tile_y);
+	this->tile_width = fpga->tile_width(this->tile_type);
+
+	auto chip_width = fpga->chip_width();
+	auto chip_height = fpga->chip_height();
+	auto chip_cols = fpga->chip_cols();
+
+	this->left_right_io = this->tile_x == 0 || this->tile_x == chip_width+1;
+	this->right_half = this->tile_x > chip_width / 2;
+	this->top_half = this->tile_y > chip_height / 2;
+
+	this->bank_num = 0;
+	if (this->top_half) this->bank_num |= 1;
+	if (this->right_half) this->bank_num |= 2;
+
+	this->bank_tx = this->right_half ? chip_width  + 1 - this->tile_x : this->tile_x;
+	this->bank_ty = this->top_half   ? chip_height + 1 - this->tile_y : this->tile_y;
+
+	this->bank_xoff = 0;
+	for (int i = 0; i < this->bank_tx; i++)
+		this->bank_xoff += chip_cols.at(i);
+
+	this->bank_yoff = 16 * this->bank_ty;
+
+	this->column_width = chip_cols.at(this->bank_tx);
+}
+
+void CramIndexConverter::get_cram_index(int bit_x, int bit_y, int &cram_bank, int &cram_x, int &cram_y) const
+{
+	static const int io_top_bottom_permx[18] = {23, 25, 26, 27, 16, 17, 18, 19, 20, 14, 32, 33, 34, 35, 36, 37, 4, 5};
+	static const int io_top_bottom_permy[16] = {0, 1, 3, 2, 4, 5, 7, 6, 8, 9, 11, 10, 12, 13, 15, 14};
+
+	cram_bank = bank_num;
+
+	if (tile_type == "io")
+	{
+		if (left_right_io)
+		{
+			cram_x = bank_xoff + column_width - 1 - bit_x;
+
+			if (top_half)
+				cram_y = bank_yoff + 15 - bit_y;
+			else
+				cram_y = bank_yoff + bit_y;
+		}
+		else
+		{
+			cram_y = bank_yoff + 15 - io_top_bottom_permy[bit_y];
+
+			if (right_half)
+				cram_x = bank_xoff + column_width - 1 - io_top_bottom_permx[bit_x];
+			else
+				cram_x = bank_xoff + io_top_bottom_permx[bit_x];
+		}
+	}
+	else
+	{
+		if (right_half)
+			cram_x = bank_xoff + column_width - 1 - bit_x;
+		else
+			cram_x = bank_xoff + bit_x;
+		
+		if (top_half)
+			cram_y = bank_yoff + (15 - bit_y);
+		else
+			cram_y = bank_yoff + bit_y;
+	}
+}
+
+
+// ==================================================================
+// Main program
+
+void usage()
+{
+	log("\n");
+	log("Usage: icepack [options] [input-file [output-file]]\n");
+	log("\n");
+	log("    -u\n");
+	log("        unpack mode (implied when called as 'iceunpack')\n");
+	log("\n");
+	log("    -v\n");
+	log("        verbose (repeat to increase verbosity)\n");
+	log("\n");
+	log("    -b\n");
+	log("        write cram bitmap as netpbm file\n");
+	log("\n");
+	log("    -f\n");
+	log("        write cram bitmap (fill tiles) as netpbm file\n");
+	log("\n");
+	log("    -c\n");
+	log("        write cram bitmap (checkerboard) as netpbm file\n");
+	log("        repeat to flip the selection of tiles\n");
+	log("\n");
+	log("    -B0, -B1, -B2, -B3\n");
+	log("        only include the specified bank in the netpbm file\n");
+	log("\n");
+	exit(1);
+}
+
+int main(int argc, char **argv)
+{
+	vector<string> parameters;
+	bool unpack_mode = false;
+	bool netpbm_mode = false;
+	bool netpbm_fill_tiles = false;
+	bool netpbm_checkerboard = false;
+	int netpbm_banknum = -1;
+	int checkerboard_m = 1;
+
+	for (int i = 0; argv[0][i]; i++)
+		if (string(argv[0]+i) == "iceunpack")
+			unpack_mode = true;
+
+	for (int i = 1; i < argc; i++)
+	{
+		string arg(argv[i]);
+
+		if (arg[0] == '-' && arg.size() > 1) {
+			for (int i = 1; i < arg.size(); i++)
+				if (arg[i] == 'u') {
+					unpack_mode = true;
+				} else if (arg[i] == 'b') {
+					netpbm_mode = true;
+				} else if (arg[i] == 'f') {
+					netpbm_mode = true;
+					netpbm_fill_tiles = true;
+				} else if (arg[i] == 'c') {
+					netpbm_mode = true;
+					netpbm_checkerboard = true;
+					checkerboard_m = !checkerboard_m;
+				} else if (arg[i] == 'B') {
+					netpbm_mode = true;
+					netpbm_banknum = arg[++i] - '0';
+				} else if (arg[i] == 'v') {
+					log_level++;
+				} else
+					usage();
+			continue;
+		}
+
+		parameters.push_back(arg);
+	}
+
+	std::ifstream ifs;
+	std::ofstream ofs;
+
+	std::istream *isp;
+	std::ostream *osp;
+
+	if (parameters.size() >= 1 && parameters[0] != "-") {
+		ifs.open(parameters[0]);
+		if (!ifs.is_open())
+			error("Failed to open input file.\n");
+		isp = &ifs;
+	} else {
+		isp = &std::cin;
+	}
+
+	if (parameters.size() >= 2 && parameters[1] != "-") {
+		ofs.open(parameters[1]);
+		if (!ofs.is_open())
+			error("Failed to open output file.\n");
+		osp = &ofs;
+	} else {
+		osp = &std::cout;
+	}
+
+	if (parameters.size() > 2)
+		usage();
+
+	FpgaConfig fpga_config;
+
+	if (unpack_mode) {
+		fpga_config.read_bits(*isp);
+		if (!netpbm_mode)
+			fpga_config.write_ascii(*osp);
+	} else {
+		fpga_config.read_ascii(*isp);
+		if (!netpbm_mode)
+			fpga_config.write_bits(*osp);
+	}
+
+	if (netpbm_checkerboard) {
+		fpga_config.cram_clear();
+		fpga_config.cram_checkerboard(checkerboard_m);
+	}
+
+	if (netpbm_fill_tiles)
+		fpga_config.cram_fill_tiles();
+
+	if (netpbm_mode)
+		fpga_config.write_cram_pbm(*osp, netpbm_banknum);
+
+	info("Done.\n");
+	return 0;
+}
+
diff --git a/icepack/iceunpack.c b/icepack/iceunpack.c
deleted file mode 100644
index ce8a2fa..0000000
--- a/icepack/iceunpack.c
+++ /dev/null
@@ -1,368 +0,0 @@
-// Written by Mathias Lasser
-// License terms are unclear at the moment
-
-#include<stdio.h>
-#include<stdbool.h>
-#include<stdlib.h>
-#include<stdint.h>
-#include<string.h>
-
-int enable_debug=0;
-#define debugf(...) do{if(enable_debug)fprintf(stderr,__VA_ARGS__);}while(0)
-
-#pragma pack(2)
-
-typedef struct 
-{
-    uint16_t    bfType;
-    uint32_t   bfSize;
-    uint16_t    bfReserved1;
-    uint16_t    bfReserved2;
-    uint32_t   bfOffBits;
-}BITMAPFILEHEADER;
-
-typedef struct 
-{
-    uint32_t    biSize;
-    uint32_t    biWidth;
-    uint32_t    biHeight;
-    uint16_t    biPlanes;
-    uint16_t    biBitCount;
-    uint32_t    biCompression;
-    uint32_t    biSizeImage;
-    uint32_t    biXPelsPerMeter;
-    uint32_t    biYPelsPerMeter;
-    uint32_t    biClrUsed;
-    uint32_t    biClrImportant;
-}BITMAPINFOHEADER;
-
-typedef struct{
- uint16_t boot_mode;
- uint16_t crc;
- uint8_t freq;
- uint8_t bank;
- uint32_t write_pointer;
- 
- uint32_t CRAM_rowsize;
- uint32_t CRAM_colsize;
- uint8_t* CRAM[4];
- uint32_t BRAM_rowsize;
- uint32_t BRAM_colsize;
- uint8_t* BRAM[4];
-}FPGA_t;
-
-typedef struct{
- uint32_t len;
- uint32_t pointer;
- uint16_t crc;
- uint8_t payload[0];
-}bitstream_t;
-
-typedef union{
- struct{
-  uint8_t lo:4;
-  uint8_t hi:4;
- };
- uint8_t full;
-}nibble_t;
-
-const char* freq_settings[]={"low","medium","high"};
-const char* boot_settings[]={"Disable","Enable"};
-
-uint16_t crc16(uint32_t crc,uint8_t in){
- for(int i=7;i>=0;i--){
-  crc<<=1;
-  if((crc^(in<<(16-i)))&0x10000)
-   crc^=0x1021;
- }
- return crc;
-}
-
-uint32_t get_byte(bitstream_t* bitstream){
- if(bitstream->pointer>=bitstream->len)return 0xFFFFFF;
- uint8_t data=bitstream->payload[bitstream->pointer++];
- bitstream->crc=crc16(bitstream->crc,data);
- return data;
-}
-
-uint32_t get_payload(bitstream_t* bitstream,int len){
- uint32_t ret=get_byte(bitstream);
- for(int i=1;i<len&&ret!=0xFFFFFFFF;i++){
-  ret<<=8;
-  ret|=get_byte(bitstream);
- }
- return ret;
-}
-
-void FPGA_write(FPGA_t* FPGA,bitstream_t* bitstream){
- int n=FPGA->CRAM_colsize*FPGA->CRAM_rowsize/8;
- uint8_t* temp=(uint8_t*)malloc(n);
- for(int i=0;i<n;i++)
-  temp[i]=get_byte(bitstream);
- FPGA->CRAM[FPGA->bank]=temp;
-}
-
-void FPGA_EBR_write(FPGA_t* FPGA,bitstream_t* bitstream){
- int n=FPGA->BRAM_colsize*FPGA->BRAM_rowsize/8;
- uint8_t* temp=(uint8_t*)malloc(FPGA->write_pointer+n);
- if(FPGA->write_pointer!=0){
-  uint8_t* old_data=FPGA->BRAM[FPGA->bank];
-  memcpy(temp,old_data,FPGA->write_pointer);
-  free(old_data);
- }
- for(int i=0;i<n;i++)temp[FPGA->write_pointer++]=get_byte(bitstream);
- FPGA->BRAM[FPGA->bank]=temp;
-}
-
-int parse(bitstream_t* bitstream, FPGA_t* FPGA) {
- uint32_t preamble=0;
- while(1){
-  preamble<<=8;
-  preamble|=get_byte(bitstream);
-  if(preamble==0x7EAA997E){
-   debugf("Got preamble\n");
-   break;
-  }
-  if(preamble==0xFFFFFFFF){
-   fprintf(stderr,"Error: could not find preamble...\n");
-   return -1;
-  }
- }
- nibble_t command;
- uint32_t payload;
- uint16_t crc;
- while(1){
-  crc=bitstream->crc;
-  command.full=get_byte(bitstream);
-  if(command.full==0xFF){
-   payload=get_byte(bitstream);
-   if(payload!=0x00)goto err;
-   char*comment=(char*)&bitstream->payload[bitstream->pointer];
-   debugf("Got comment section start\n");
-   while(1){
-    payload<<=8;
-    payload|=get_byte(bitstream);
-    if((payload&0xFFFF)==0x00FF)break;
-    if(payload==0xFFFFFFFF){
-     fprintf(stderr,"Error: could not find comment section end\n");
-     return -1;
-    }
-   }
-   debugf("\n%s\n\n",comment);
-   debugf("Got comment section end\n");
-   continue;
-  }
-  payload=get_payload(bitstream,command.lo);
-  switch(command.hi){
-  case 0x0:
-   if(command.lo!=0x01)goto err;
-   switch(payload){
-   case 0x01:
-    debugf("Write to CRAM!!!\n");
-    FPGA_write(FPGA,bitstream);
-    get_payload(bitstream,2);
-    break;
-   case 0x03:
-    debugf("Write to BRAM!!!\n");
-    FPGA_EBR_write(FPGA,bitstream);
-    get_payload(bitstream,2);
-    break;
-   case 0x05:
-    debugf("Resetting CRC\n");
-    bitstream->crc=0;
-    break;
-   case 0x06:
-    debugf("Wake up\n");
-    return 0;
-   default:
-    goto err;
-   }
-   break;
-  case 0x1:
-   if(command.lo!=0x01)goto err;
-   if(payload>3){
-    fprintf(stderr,"Error: bank %u does not exist...\n",payload);
-   }
-   debugf("Set bank to %u\n",payload);
-   FPGA->bank=payload;
-   break;
-  case 0x2:
-   if(command.lo!=0x02)goto err;
-   debugf("CRC check: %04X %04X\n",payload,crc);
-   break;
-  case 0x5:
-   if(command.lo!=0x01)goto err;
-   if(payload>2){
-    fprintf(stderr,"Error: unknown frequency setting...\n");
-    return -1;
-   }
-   debugf("Boot frequency set to %s\n",freq_settings[payload]);
-   FPGA->freq=payload;
-   break;
-  case 0x6:
-   if(command.lo!=0x02)goto err;
-   payload++;
-   debugf("Row size:    %i\n",payload);
-   if(FPGA->CRAM_rowsize)FPGA->BRAM_rowsize=payload;
-   else FPGA->CRAM_rowsize=payload;
-   break;
-  case 0x7:
-   if(command.lo!=0x02)goto err;
-   debugf("Column size: %i\n",payload);
-   if(FPGA->CRAM_colsize)FPGA->BRAM_colsize=payload;
-   else FPGA->CRAM_colsize=payload;
-   break;
-  case 0x8:
-   if(command.lo!=0x02)goto err;
-   if(payload==0x0000){
-    debugf("Reset write pointer\n");
-    FPGA->write_pointer=0;
-   }
-   else if(payload==0x0080){
-    debugf("Don't reset write pointer\n");
-   }
-   else goto err;
-   break;
-  case 0x9:
-   if(command.lo!=0x02)goto err;
-   if(payload&0xFFDF){
-    fprintf(stderr,"Error: Unknown warmboot setting... %04X\n",payload);
-    return -1;
-   }
-   debugf("%s warmboot\n",boot_settings[payload?1:0]);
-   FPGA->boot_mode=payload;
-   break;
-  default:
-   goto err;
-  }
- }
-err:
- fprintf(stderr,"Error: unkown command... %08X\n",bitstream->pointer);
- return -1;
-}
-
-uint8_t get_CRAM_bit_from_sector(FPGA_t* FPGA,int bank,int x,int y){
- if(x<0||x>=FPGA->CRAM_rowsize)return 0xFF;
- if(y<0||y>=FPGA->CRAM_colsize)return 0xFF;
- if(bank<0||bank>=4)return 0xFF;
-
-
- int bit=y*FPGA->CRAM_rowsize+x;
- int pointer=bit>>3;
- int shifts=7-(bit&7);
- return (FPGA->CRAM[bank][pointer]>>shifts)&1;
-}
-
-int tiles[2][20]={
- {18,54,54,42,54,54,54},
- {18,2,54,54,54,54,54,54,54,42,54,54,54,54,54,54,54,54}
-};
-
-int permx[2][18]={
- {23,25,26,27,16,17,18,19,20,14,32,33,34,35,36,37,4,5},
- {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17}};
-int permy[4][16]={
- {0,1,3,2,4,5,7,6,8,9,11,10,12,13,15,14},
- {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15},
-};
-
-int tile_row_size[2]={7,17};
-int tile_col_size[2]={9,17};
-
-void print_tile(FPGA_t* FPGA,int x,int y){
- int type=FPGA->CRAM_rowsize==872;
- int dirx=0;
- int diry=0;
- int tx=x;
- int ty=y;
-
- int corner_flags=0;
- if(x==0)corner_flags|=1;
- if(y==0)corner_flags|=2;
- if(x==tile_row_size[type]*2-1)corner_flags|=4;
- if(y==tile_col_size[type]*2-1)corner_flags|=8;
- if(corner_flags&(corner_flags-1))
-  return;
-
- if(x>=tile_row_size[type]){
-  dirx=1;
-  tx=tile_row_size[type]*2-1-x;
- }
- if(y>=tile_col_size[type]){
-  diry=1;
-  ty=tile_col_size[type]*2-1-y;
- }
- int sector=(diry|dirx<<1);
- int offx=0;for(int i=0;i<tx;i++)offx+=tiles[type][i];
- if(corner_flags){
-  printf(".io_tile %i %i\n",x,y);
-  for(int cy=0;cy<16;cy++){
-   for(int cx=0;cx<18;cx++){
-    int val;
-    if(corner_flags&5){
-     if(diry){
-      val=get_CRAM_bit_from_sector(FPGA,sector,offx+tiles[type][tx]-1-permx[1][cx],ty*16+15-permy[1][cy]);
-     }else{
-      val=get_CRAM_bit_from_sector(FPGA,sector,offx+tiles[type][tx]-1-permx[1][cx],ty*16+permy[1][cy]);
-     }
-    }else{
-     if(dirx){
-      val=get_CRAM_bit_from_sector(FPGA,sector,offx+tiles[type][tx]-1-permx[0][cx],ty*16+15-permy[0][cy]);
-     }else{
-      val=get_CRAM_bit_from_sector(FPGA,sector,offx+permx[0][cx],ty*16+15-permy[0][cy]);
-     }
-    }
-    printf("%i",val);
-   }
-   printf("\n");
-  }
- }
- else{
-  if(tiles[type][tx]==20)printf(".io_tile %i %i\n",x,y);
-  if(tiles[type][tx]==42)printf(".ram_tile %i %i\n",x,y);
-  if(tiles[type][tx]==54)printf(".logic_tile %i %i\n",x,y);
-  for(int cy=0;cy<16;cy++){
-   for(int cx=0;cx<tiles[type][tx];cx++){
-    printf("%i",get_CRAM_bit_from_sector(FPGA,sector,(dirx?(offx+tiles[type][tx]-1-cx):(offx+cx)),(diry?(ty*16+(15-cy)):(ty*16+cy))));
-   }
-   printf("\n");
-  }
- }
-}
-
-int main(int argc,char**argv) {
- if(argc>=2&&!strcmp(argv[1], "-v")) {
-  enable_debug=1;
-  argc--;
-  argv++;
- }
- if(argc!=2) {
-  fprintf(stderr,"iceunpack [-v] input\n");
-  return 1;
- }
-
- FILE*r_file=fopen(argv[1],"rb");
- if(r_file==NULL) {
-  fprintf(stderr,"could not open %s\n",argv[1]);
-  return 1;
- }
- fseek(r_file,0,SEEK_END);
- size_t r_size=ftell(r_file);
- fseek(r_file,0,SEEK_SET);
-
- bitstream_t* bitstream=(bitstream_t*)malloc(sizeof(bitstream_t)+r_size);
- bitstream->len=r_size;
- bitstream->pointer=0;
- fread(bitstream->payload,1,r_size,r_file);
- fclose(r_file);
-
- FPGA_t FPGA;
- memset(&FPGA,0,sizeof(FPGA));
-
- parse(bitstream,&FPGA);
- free(bitstream);
-
- printf(".device 1k\n");
- for(int y=0;y<18;y++)for(int x=0;x<14;x++)print_tile(&FPGA,x,y);
- 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