diff options
-rw-r--r-- | examples/hx8kboard/example.v | 2 | ||||
-rw-r--r-- | examples/hx8kboard/hx8kboard.pcf | 18 | ||||
-rw-r--r-- | examples/iceblink/example.v | 2 | ||||
-rw-r--r-- | examples/iceblink/iceblink.pcf | 10 | ||||
-rw-r--r-- | examples/icestick/Makefile | 2 | ||||
-rw-r--r-- | examples/icestick/example.v | 2 | ||||
-rw-r--r-- | examples/icestick/icestick.pcf | 22 | ||||
-rw-r--r-- | examples/icestick/rs232demo.v | 48 | ||||
-rw-r--r-- | examples/icezum/example.v | 2 | ||||
-rw-r--r-- | examples/icezum/icezum.pcf | 18 | ||||
-rw-r--r-- | icebox/Makefile | 2 | ||||
-rwxr-xr-x | icebox/icebox_stat.py | 139 | ||||
-rw-r--r-- | icecompr/.gitignore | 5 | ||||
-rw-r--r-- | icecompr/Makefile | 31 | ||||
-rw-r--r-- | icecompr/README | 52 | ||||
-rw-r--r-- | icecompr/example_1k.bin | bin | 0 -> 32220 bytes | |||
-rw-r--r-- | icecompr/example_8k.bin | bin | 0 -> 135100 bytes | |||
-rw-r--r-- | icecompr/icecompr.cc | 316 | ||||
-rw-r--r-- | icecompr/iceuncompr.c | 162 | ||||
-rw-r--r-- | icefuzz/icecube.sh | 4 | ||||
-rw-r--r-- | icefuzz/tests/bitop.pcf | 6 | ||||
-rw-r--r-- | icefuzz/tests/example_hx8kboard.pcf | 18 | ||||
-rw-r--r-- | icefuzz/tests/example_icestick.pcf | 12 |
23 files changed, 790 insertions, 83 deletions
diff --git a/examples/hx8kboard/example.v b/examples/hx8kboard/example.v index accbc2e..69a446f 100644 --- a/examples/hx8kboard/example.v +++ b/examples/hx8kboard/example.v @@ -16,7 +16,7 @@ module top ( reg [BITS+LOG2DELAY-1:0] counter = 0; reg [BITS-1:0] outcnt; - always@(posedge clk) begin + always @(posedge clk) begin counter <= counter + 1; outcnt <= counter >> LOG2DELAY; end diff --git a/examples/hx8kboard/hx8kboard.pcf b/examples/hx8kboard/hx8kboard.pcf index 417ca01..503eb36 100644 --- a/examples/hx8kboard/hx8kboard.pcf +++ b/examples/hx8kboard/hx8kboard.pcf @@ -1,9 +1,9 @@ -set_io LED0 B5
-set_io LED1 B4
-set_io LED2 A2
-set_io LED3 A1
-set_io LED4 C5
-set_io LED5 C4
-set_io LED6 B3
-set_io LED7 C3
-set_io clk J3
+set_io LED0 B5 +set_io LED1 B4 +set_io LED2 A2 +set_io LED3 A1 +set_io LED4 C5 +set_io LED5 C4 +set_io LED6 B3 +set_io LED7 C3 +set_io clk J3 diff --git a/examples/iceblink/example.v b/examples/iceblink/example.v index 6bccc1e..4642ef2 100644 --- a/examples/iceblink/example.v +++ b/examples/iceblink/example.v @@ -15,7 +15,7 @@ module top ( reg [BITS+LOG2DELAY-1:0] counter = 0; reg [BITS-1:0] outcnt; - always@(posedge clk) begin + always @(posedge clk) begin counter <= counter + 1; outcnt <= counter >> LOG2DELAY; end diff --git a/examples/iceblink/iceblink.pcf b/examples/iceblink/iceblink.pcf index 0d5e6c1..e737772 100644 --- a/examples/iceblink/iceblink.pcf +++ b/examples/iceblink/iceblink.pcf @@ -1,5 +1,5 @@ -set_io LED2 59
-set_io LED3 56
-set_io LED4 53
-set_io LED5 51
-set_io clk 13
+set_io LED2 59 +set_io LED3 56 +set_io LED4 53 +set_io LED5 51 +set_io clk 13 diff --git a/examples/icestick/Makefile b/examples/icestick/Makefile index f40c8a3..9294608 100644 --- a/examples/icestick/Makefile +++ b/examples/icestick/Makefile @@ -1,4 +1,6 @@ PROJ = example +# PROJ = rs232demo + PIN_DEF = icestick.pcf DEVICE = hx1k diff --git a/examples/icestick/example.v b/examples/icestick/example.v index a934400..3eb7007 100644 --- a/examples/icestick/example.v +++ b/examples/icestick/example.v @@ -13,7 +13,7 @@ module top ( reg [BITS+LOG2DELAY-1:0] counter = 0; reg [BITS-1:0] outcnt; - always@(posedge clk) begin + always @(posedge clk) begin counter <= counter + 1; outcnt <= counter >> LOG2DELAY; end diff --git a/examples/icestick/icestick.pcf b/examples/icestick/icestick.pcf index 23067be..8bf462e 100644 --- a/examples/icestick/icestick.pcf +++ b/examples/icestick/icestick.pcf @@ -1,11 +1,11 @@ -# full iCEstick pinout:
-# http://www.pighixxx.com/test/portfolio-items/icestick/
-
-set_io --warn-no-port RX 9
-set_io --warn-no-port TX 8
-set_io LED1 99
-set_io LED2 98
-set_io LED3 97
-set_io LED4 96
-set_io LED5 95
-set_io clk 21
+# full iCEstick pinout: +# http://www.pighixxx.com/test/portfolio-items/icestick/ + +set_io --warn-no-port RX 9 +set_io --warn-no-port TX 8 +set_io LED1 99 +set_io LED2 98 +set_io LED3 97 +set_io LED4 96 +set_io LED5 95 +set_io clk 21 diff --git a/examples/icestick/rs232demo.v b/examples/icestick/rs232demo.v index fc7a770..f9e7546 100644 --- a/examples/icestick/rs232demo.v +++ b/examples/icestick/rs232demo.v @@ -12,46 +12,44 @@ module top ( parameter integer CLOCK_FREQ_HZ = 12000000; localparam integer HALF_PERIOD = CLOCK_FREQ_HZ / (2 * BAUD_RATE); - reg [9:0] buffer; + reg [7:0] buffer; reg buffer_valid; reg [$clog2(3*HALF_PERIOD):0] cycle_cnt; reg [3:0] bit_cnt = 0; - reg [0:0] state = 0; + reg recv = 0; always @(posedge clk) begin buffer_valid <= 0; - case (state) - 0: begin - if (!RX) begin - cycle_cnt <= HALF_PERIOD; - bit_cnt <= 0; - state <= 1; - end + if (!recv) begin + if (!RX) begin + cycle_cnt <= HALF_PERIOD; + bit_cnt <= 0; + recv <= 1; end - 1: begin - if (cycle_cnt == 2*HALF_PERIOD) begin - cycle_cnt <= 0; - buffer[bit_cnt] <= RX; - bit_cnt <= bit_cnt + 1; - if (bit_cnt == 9) begin - buffer_valid <= 1; - state <= 0; - end + end else begin + if (cycle_cnt == 2*HALF_PERIOD) begin + cycle_cnt <= 0; + bit_cnt <= bit_cnt + 1; + if (bit_cnt == 9) begin + buffer_valid <= 1; + recv <= 0; end else begin - cycle_cnt <= cycle_cnt + 1; + buffer <= {RX, buffer[7:1]}; end + end else begin + cycle_cnt <= cycle_cnt + 1; end - endcase + end end always @(posedge clk) begin if (buffer_valid) begin - if (buffer[8:1] == "1") LED1 <= !LED1; - if (buffer[8:1] == "2") LED2 <= !LED2; - if (buffer[8:1] == "3") LED3 <= !LED3; - if (buffer[8:1] == "4") LED4 <= !LED4; - if (buffer[8:1] == "5") LED5 <= !LED5; + if (buffer == "1") LED1 <= !LED1; + if (buffer == "2") LED2 <= !LED2; + if (buffer == "3") LED3 <= !LED3; + if (buffer == "4") LED4 <= !LED4; + if (buffer == "5") LED5 <= !LED5; end end diff --git a/examples/icezum/example.v b/examples/icezum/example.v index 9bdf587..1274e69 100644 --- a/examples/icezum/example.v +++ b/examples/icezum/example.v @@ -16,7 +16,7 @@ module top ( reg [BITS+LOG2DELAY-1:0] counter = 0; reg [BITS-1:0] outcnt; - always@(posedge clk) begin + always @(posedge clk) begin counter <= counter + 1; outcnt <= counter >> LOG2DELAY; end diff --git a/examples/icezum/icezum.pcf b/examples/icezum/icezum.pcf index 4139e7f..bafdbd9 100644 --- a/examples/icezum/icezum.pcf +++ b/examples/icezum/icezum.pcf @@ -1,9 +1,9 @@ -set_io LED0 95
-set_io LED1 96
-set_io LED2 97
-set_io LED3 98
-set_io LED4 99
-set_io LED5 101
-set_io LED6 102
-set_io LED7 104
-set_io clk 21
+set_io LED0 95 +set_io LED1 96 +set_io LED2 97 +set_io LED3 98 +set_io LED4 99 +set_io LED5 101 +set_io LED6 102 +set_io LED7 104 +set_io clk 21 diff --git a/icebox/Makefile b/icebox/Makefile index 43d4664..3db1a50 100644 --- a/icebox/Makefile +++ b/icebox/Makefile @@ -28,6 +28,7 @@ install: all cp icebox_html.py $(DESTDIR)$(PREFIX)/bin/icebox_html cp icebox_maps.py $(DESTDIR)$(PREFIX)/bin/icebox_maps cp icebox_vlog.py $(DESTDIR)$(PREFIX)/bin/icebox_vlog + cp icebox_stat.py $(DESTDIR)$(PREFIX)/bin/icebox_stat uninstall: rm -f $(DESTDIR)$(PREFIX)/bin/icebox.py @@ -39,6 +40,7 @@ uninstall: rm -f $(DESTDIR)$(PREFIX)/bin/icebox_html rm -f $(DESTDIR)$(PREFIX)/bin/icebox_maps rm -f $(DESTDIR)$(PREFIX)/bin/icebox_vlog + rm -f $(DESTDIR)$(PREFIX)/bin/icebox_stat rm -f $(DESTDIR)$(PREFIX)/share/icebox/chipdb-1k.txt rm -f $(DESTDIR)$(PREFIX)/share/icebox/chipdb-8k.txt -rmdir $(DESTDIR)$(PREFIX)/share/icebox diff --git a/icebox/icebox_stat.py b/icebox/icebox_stat.py new file mode 100755 index 0000000..ffb7b6a --- /dev/null +++ b/icebox/icebox_stat.py @@ -0,0 +1,139 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2015 Clifford Wolf <clifford@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. +# + +import icebox +import getopt, sys, re + +verbose = False + +def usage(): + print(""" +Usage: icebox_stat [options] [bitmap.asc] + + -v + verbose output + +""") + sys.exit(0) + +try: + opts, args = getopt.getopt(sys.argv[1:], "v") +except: + usage() + +for o, a in opts: + if o == "-v": + verbose = True + else: + usage() + +if len(args) == 0: + args.append("/dev/stdin") + +if len(args) != 1: + usage() + +if verbose: + print("Reading input file.") + +ic = icebox.iceconfig() +ic.read_file(args[0]) + +dff_locations = set() +lut_locations = set() +carry_locations = set() +bram_locations = set() +io_locations = set() +pll_locations = set() +global_nets = set() + +if verbose: + print("Analyzing connectivity.") + +connections = sorted(ic.group_segments()) + +if verbose: + print("Counting resources.") + +for segs in connections: + for seg in segs: + if ic.tile_type(seg[0], seg[1]) == "IO" and seg[2].startswith("io_"): + match = re.match("io_(\d+)/D_(IN|OUT)_(\d+)", seg[2]) + if match: + loc = (seg[0], seg[1], int(match.group(1))) + io_locations.add(loc) + + if ic.tile_type(seg[0], seg[1]) == "LOGIC" and seg[2].startswith("lutff_"): + match = re.match("lutff_(\d)/in_\d", seg[2]) + if match: + loc = (seg[0], seg[1], int(match.group(1))) + lut_locations.add(loc) + + match = re.match("lutff_(\d)/cout", seg[2]) + if match: + loc = (seg[0], seg[1], int(match.group(1))) + carry_locations.add(loc) + + match = re.match("lutff_(\d)/out", seg[2]) + if match: + loc = (seg[0], seg[1], int(match.group(1))) + seq_bits = icebox.get_lutff_seq_bits(ic.tile(loc[0], loc[1]), loc[2]) + if seq_bits[1] == "1": + dff_locations.add(loc) + + if ic.tile_type(seg[0], seg[1]) in ("RAMB", "RAMT") and seg[2].startswith("ram/"): + loc = (seg[0], seg[1] - (seg[1] % 2)) + bram_locations.add(loc) + + if seg[2].startswith("glb_netwk_"): + match = re.match("glb_netwk_(\d)", seg[2]) + if match: + global_nets.add(int(match.group(1))) + +pll_config_bitidx = dict() + +for entry in icebox.iotile_l_db: + if entry[1] == "PLL": + match = re.match(r"B(\d+)\[(\d+)\]", entry[0][0]); + assert match + pll_config_bitidx[entry[2]] = (int(match.group(1)), int(match.group(2))) + +def get_pll_bit(pllinfo, name): + bit = pllinfo[name] + assert bit[2] in pll_config_bitidx + return ic.tile(bit[0], bit[1])[pll_config_bitidx[bit[2]][0]][pll_config_bitidx[bit[2]][1]] + +def get_pll_bits(pllinfo, name, n): + return "".join([get_pll_bit(pllinfo, "%s_%d" % (name, i)) for i in range(n-1, -1, -1)]) + +for pllid in ic.pll_list(): + pllinfo = icebox.pllinfo_db[pllid] + plltype = get_pll_bits(pllinfo, "PLLTYPE", 3) + if plltype != "000": + pll_locations.add(pllid) + +if verbose: + print() + +print("DFFs: %4d" % len(dff_locations)) +print("LUTs: %4d" % len(lut_locations)) +print("CARRYs: %4d" % len(carry_locations)) +print("BRAMs: %4d" % len(bram_locations)) +print("IOBs: %4d" % len(io_locations)) +print("PLLs: %4d" % len(pll_locations)) +print("GLBs: %4d" % len(global_nets)) + diff --git a/icecompr/.gitignore b/icecompr/.gitignore new file mode 100644 index 0000000..1ebf48a --- /dev/null +++ b/icecompr/.gitignore @@ -0,0 +1,5 @@ +icecompr +iceuncompr +example_?k.compr +example_?k.ok +example_?k.uncompr diff --git a/icecompr/Makefile b/icecompr/Makefile new file mode 100644 index 0000000..88512f0 --- /dev/null +++ b/icecompr/Makefile @@ -0,0 +1,31 @@ + +all: icecompr iceuncompr + +test: example_1k.ok example_8k.ok + +icecompr: icecompr.cc + clang++ -o icecompr -Wall -Wextra -std=c++11 icecompr.cc + +iceuncompr: iceuncompr.c + clang -o iceuncompr -Wall -Wextra iceuncompr.c + +%.compr: %.bin icecompr + ./icecompr -v $< $@ + + +%.uncompr: %.compr iceuncompr + ./iceuncompr $< $@ + +%.ok: %.uncompr %.bin + cmp $^ + touch $@ + +clean: + rm -f icecompr iceuncompr + rm -f example_1k.compr example_8k.compr + rm -f example_1k.uncompr example_8k.uncompr + rm -f example_1k.ok example_8k.ok + +.SECONDARY: +.PHONY: all test clean + diff --git a/icecompr/README b/icecompr/README new file mode 100644 index 0000000..5e04bb5 --- /dev/null +++ b/icecompr/README @@ -0,0 +1,52 @@ + +A simple compression algorithm for iCE40 bit-streams +==================================================== + +This directory contains tools for compressing and uncompressing +iCE40 bit-streams. The motivation is to reduce the bandwidth +requirements for bit-stream upload. + +Note that iCE40 FPGAs can not uncompress this compressed bit-streams! +Uncompression must be performed by e.g. a uC on the FPGA board. + +This compression algorithm uses the fact that most bits in an iCE40 +bit-stream are cleared. + +The bit-stream is encoded as the distances between set bits (i.e. +the length of runs of ZERO bits between two ONE bits). This sequence +of integers is stored using a simple prefix code to spend fewer bits +on smaller (more frequent) numbers. + +The algorithm includes an escape-mechanism to mix uncompressed binary +data with compressed bit-streams. This is useful when the bit-stream +contains sections that do not compress well with this algorithm, for +example in BRAM initialization data. + +The compressed bitstream starts with the ASCII string "ICECOMPR", i.e. +the hex values 0x49434543 and 0x4f4d5052 (stored as big-endian numbers). + +After the 8 bytes magic the compressed bitstream is a stream of the +following opcodes that must be interpreted by the decompressor. The +notation ZERO and ONE is used for zero and one bits. The notation foo[N] +is used for an N bit value "foo", transmitted MSB first. + + ONE count[2] + ZERO ONE count[5] + ZERO ZERO ONE count[8] + ZERO ZERO ZERO ZERO ONE count[23] + output count ZERO bits followed by a single ONE bit + + ZERO ZERO ZERO ONE count[6] data[count] + output the count data bits followed by a single ONE bit + + ZERO ZERO ZERO ZERO ZERO count[23] + output count ZERO bits and stop decompressing. (end of file) + +The program "icecompr" (C++11, ISC license) contains an implementation of a +compressor and a decompressor. The decompressor in this program however is +only used for integrity checking the compressed bit-stream. + +The program "iceuncompr" (plain C, public domain) contains an implementation +of a stand-alone decompressor. Simply copy&paste this implementation into +your uC firmware. + diff --git a/icecompr/example_1k.bin b/icecompr/example_1k.bin Binary files differnew file mode 100644 index 0000000..0321b9a --- /dev/null +++ b/icecompr/example_1k.bin diff --git a/icecompr/example_8k.bin b/icecompr/example_8k.bin Binary files differnew file mode 100644 index 0000000..8b6c7c5 --- /dev/null +++ b/icecompr/example_8k.bin diff --git a/icecompr/icecompr.cc b/icecompr/icecompr.cc new file mode 100644 index 0000000..322de9a --- /dev/null +++ b/icecompr/icecompr.cc @@ -0,0 +1,316 @@ +/* + * IceCompr -- A simple compressor for iCE40 bit-streams + * + * Copyright (C) 2017 Clifford Wolf <clifford@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. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <vector> +#include <map> + +int verbose = 0; + +static void push_int_bits(std::vector<bool> &outbits, int value, int bits) +{ + while (bits-- > 0) + outbits.push_back((value >> bits) & 1); +} + +static void push_zero_bits(std::vector<bool> &outbits, int bits) +{ + while (bits-- > 0) + outbits.push_back(false); +} + +static int decode_int_from_bits(const std::vector<bool> &inbits, int &cursor, int bits) +{ + int ret = 0; + while (bits-- > 0) + if (inbits.at(cursor++)) + ret |= 1 << bits; + return ret; +} + +void ice_compress(std::vector<bool> &outbits, const std::vector<bool> &inbits) +{ + int opcode_stats_d4 = 0; + int opcode_stats_d32 = 0; + int opcode_stats_d256 = 0; + int opcode_stats_raw = 0; + int opcode_stats_d8M = 0; + int opcode_stats_end = 0; + + std::vector<int> deltas; + int numzeros = 0; + + for (auto bit : inbits) + { + if (bit) { + deltas.push_back(numzeros); + numzeros = 0; + } else { + numzeros++; + } + } + + for (int i = 0; i < int(deltas.size()); i++) + { + int raw_len = 0; + int compr_len = 0; + int best_compr_raw_diff = -1; + int best_compr_raw_idx = -1; + int best_compr_raw_len = -1; + + for (int j = 0; j+i < int(deltas.size()); j++) + { + int delta = deltas.at(i + j); + raw_len += delta + 1; + + if (delta < 4) + compr_len += 3; + else if (delta < 32) + compr_len += 7; + else if (delta < 256) + compr_len += 11; + else + compr_len += 26; + + if (compr_len - raw_len < std::max(best_compr_raw_diff - 4, 0) || raw_len > 64) + break; + + if (compr_len - raw_len > best_compr_raw_diff) { + best_compr_raw_diff = compr_len - raw_len; + best_compr_raw_idx = j; + best_compr_raw_len = raw_len; + } + } + + if (best_compr_raw_diff > 9) + { + opcode_stats_raw++; + outbits.push_back(false); + outbits.push_back(false); + outbits.push_back(false); + outbits.push_back(true); + push_int_bits(outbits, best_compr_raw_len-1, 6); + + for (int j = 0; j <= best_compr_raw_idx; j++) { + int delta = deltas.at(i + j); + for (int k = 0; k < delta; k++) + outbits.push_back(false); + if (j < best_compr_raw_idx) + outbits.push_back(true); + } + + i += best_compr_raw_idx; + continue; + } + + int delta = deltas.at(i); + + if (delta < 4) { + opcode_stats_d4++; + outbits.push_back(true); + push_int_bits(outbits, delta, 2); + } else + if (delta < 32) { + opcode_stats_d32++; + outbits.push_back(false); + outbits.push_back(true); + push_int_bits(outbits, delta, 5); + } else + if (delta < 256) { + opcode_stats_d256++; + outbits.push_back(false); + outbits.push_back(false); + outbits.push_back(true); + push_int_bits(outbits, delta, 8); + } else { + opcode_stats_d8M++; + outbits.push_back(false); + outbits.push_back(false); + outbits.push_back(false); + outbits.push_back(false); + outbits.push_back(true); + push_int_bits(outbits, delta, 23); + } + } + + opcode_stats_end++; + outbits.push_back(false); + outbits.push_back(false); + outbits.push_back(false); + outbits.push_back(false); + outbits.push_back(false); + push_int_bits(outbits, numzeros, 23); + + if (verbose > 1) { + fprintf(stderr, "opcode d4 %5d\n", opcode_stats_d4); + fprintf(stderr, "opcode d32 %5d\n", opcode_stats_d32); + fprintf(stderr, "opcode d256 %5d\n", opcode_stats_d256); + fprintf(stderr, "opcode raw %5d\n", opcode_stats_raw); + fprintf(stderr, "opcode d8M %5d\n", opcode_stats_d8M); + fprintf(stderr, "opcode end %5d\n", opcode_stats_end); + } +} + +void ice_uncompress(std::vector<bool> &outbits, const std::vector<bool> &inbits) +{ + int cursor = 0; + + while (cursor < int(inbits.size())) + { + if (inbits.at(cursor++)) { + int zeros = decode_int_from_bits(inbits, cursor, 2); + push_zero_bits(outbits, zeros); + outbits.push_back(true); + } else + if (inbits.at(cursor++)) { + int zeros = decode_int_from_bits(inbits, cursor, 5); + push_zero_bits(outbits, zeros); + outbits.push_back(true); + } else + if (inbits.at(cursor++)) { + int zeros = decode_int_from_bits(inbits, cursor, 8); + push_zero_bits(outbits, zeros); + outbits.push_back(true); + } else + if (inbits.at(cursor++)) { + int raw_len = decode_int_from_bits(inbits, cursor, 6); + while (raw_len--) + outbits.push_back(inbits.at(cursor++)); + outbits.push_back(true); + } else + if (inbits.at(cursor++)) { + int zeros = decode_int_from_bits(inbits, cursor, 23); + push_zero_bits(outbits, zeros); + outbits.push_back(true); + } else { + int zeros = decode_int_from_bits(inbits, cursor, 23); + push_zero_bits(outbits, zeros); + } + } +} + +void help() +{ + printf("\n"); + printf("Usage: icecompr [-v] [input-file [output-file]]\n"); + printf("\n"); + exit(1); +} + +int main(int argc, char **argv) +{ + FILE *input_file = stdin; + FILE *output_file = stdout; + + int opt; + while ((opt = getopt(argc, argv, "v")) != -1) + { + switch (opt) + { + case 'v': + verbose++; + break; + default: + help(); + } + } + + if (optind < argc) { + input_file = fopen(argv[optind], "rb"); + if (input_file == NULL) { + fprintf(stderr, "Failed to open input file `%s': %s\n", argv[optind], strerror(errno)); + return 1; + } + optind++; + } + + if (optind < argc) { + output_file = fopen(argv[optind], "wb"); + if (output_file == NULL) { + fprintf(stderr, "Failed to open output file `%s': %s\n", argv[optind], strerror(errno)); + return 1; + } + optind++; + } + + if (optind != argc) + help(); + + std::vector<bool> original_bits; + int count_set_bits = 0; + + while (1) + { + int byte = fgetc(input_file); + + if (byte < 0) + break; + + // MSB first + for (int i = 7; i >= 0; i--) { + bool bit = (byte >> i) & 1; + if (bit) count_set_bits++; + original_bits.push_back(bit); + } + } + + int uncompressed_size = original_bits.size(); + + if (verbose > 0) { + fprintf(stderr, "Percentage of set bits: %.2f%%\n", (100.0*count_set_bits) / uncompressed_size); + fprintf(stderr, "Uncompressed size: %8d bits\n", uncompressed_size); + } + + std::vector<bool> compressed_bits; + ice_compress(compressed_bits, original_bits); + + int compressed_size = compressed_bits.size(); + + if (verbose > 0) { + fprintf(stderr, "Compressed size: %8d bits\n", compressed_size); + fprintf(stderr, "Space savings: %.2f%%\n", 100 - (100.0*compressed_size) / uncompressed_size); + } + + std::vector<bool> uncompressed_bits; + ice_uncompress(uncompressed_bits, compressed_bits); + + bool check_ok = original_bits == uncompressed_bits; + + if (verbose > 0 || !check_ok) { + fprintf(stderr, "Integrity check: %s\n", check_ok ? "OK" : "ERROR"); + if (!check_ok) + return 1; + } + + fprintf(output_file, "ICECOMPR"); + for (int i = 0; i < int(compressed_bits.size()); i += 8) { + int value = 0; + for (int j = 0; j < 8 && i+j < int(compressed_bits.size()); j++) + if (compressed_bits.at(i+j)) + value |= 1 << (7-j); + fputc(value, output_file); + } + + return 0; +} + diff --git a/icecompr/iceuncompr.c b/icecompr/iceuncompr.c new file mode 100644 index 0000000..04e7dc8 --- /dev/null +++ b/icecompr/iceuncompr.c @@ -0,0 +1,162 @@ +// This is free and unencumbered software released into the public domain. +// +// Anyone is free to copy, modify, publish, use, compile, sell, or +// distribute this software, either in source code form or as a compiled +// binary, for any purpose, commercial or non-commercial, and by any +// means. + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> + +FILE *input_file; +FILE *output_file; + +int read_bitcounter; +int read_buffer; + +int write_bitcounter; +int write_buffer; + +static int read_bit() +{ + if (read_bitcounter == 0) { + read_bitcounter = 8; + read_buffer = fgetc(input_file); + } + + read_bitcounter--; + return (read_buffer >> read_bitcounter) & 1; +} + +static void write_bit(int value) +{ + write_bitcounter--; + + if (value) + write_buffer |= 1 << write_bitcounter; + + if (write_bitcounter == 0) { + fputc(write_buffer, output_file); + write_bitcounter = 8; + write_buffer = 0; + } +} + +static int read_int(int bits) +{ + int ret = 0; + while (bits-- > 0) + if (read_bit()) + ret |= 1 << bits; + return ret; +} + +static void write_zeros(int bits) +{ + while (bits-- > 0) + write_bit(0); +} + +int ice_uncompress() +{ + read_bitcounter = 0; + read_buffer = 0; + + write_bitcounter = 8; + write_buffer = 0; + + int magic1_ok = read_int(32) == 0x49434543; + int magic2_ok = read_int(32) == 0x4f4d5052; + + if (!magic1_ok || !magic2_ok) { + fprintf(stderr, "Missing ICECOMPR magic. Abort!\n"); + return 1; + } + + while (1) + { + if (read_bit()) { + write_zeros(read_int(2)); + write_bit(1); + } else + if (read_bit()) { + write_zeros(read_int(5)); + write_bit(1); + } else + if (read_bit()) { + write_zeros(read_int(8)); + write_bit(1); + } else + if (read_bit()) { + int n = read_int(6); + while (n--) + write_bit(read_bit()); + write_bit(1); + } else + if (read_bit()) { + write_zeros(read_int(23)); + write_bit(1); + } else { + write_zeros(read_int(23)); + break; + } + } + + return 0; +} + +void help() +{ + printf("\n"); + printf("Usage: iceuncompr [input-file [output-file]]\n"); + printf("\n"); + exit(1); +} + +int main(int argc, char **argv) +{ + input_file = stdin; + output_file = stdout; + + int opt; + while ((opt = getopt(argc, argv, "v")) != -1) + { + switch (opt) + { + case 'v': + break; + default: + help(); + } + } + + if (optind < argc) { + input_file = fopen(argv[optind], "rb"); + if (input_file == NULL) { + fprintf(stderr, "Failed to open input file `%s': %s\n", argv[optind], strerror(errno)); + return 1; + } + optind++; + } + + if (optind < argc) { + output_file = fopen(argv[optind], "wb"); + if (output_file == NULL) { + fprintf(stderr, "Failed to open output file `%s': %s\n", argv[optind], strerror(errno)); + return 1; + } + optind++; + } + + if (optind != argc) + help(); + + if (optind != argc) + help(); + + return ice_uncompress(); +} + diff --git a/icefuzz/icecube.sh b/icefuzz/icecube.sh index 809d437..2154b87 100644 --- a/icefuzz/icecube.sh +++ b/icefuzz/icecube.sh @@ -16,9 +16,9 @@ # # Additional notes for installing iCEcube2 on 64 Bit Ubuntu: # -# sudo apt-get install ibc6-i386 zlib1g:i386 libxext6:i386 libpng12-0:i386 libsm6:i386 +# sudo apt-get install libc6-i386 zlib1g:i386 libxext6:i386 libpng12-0:i386 libsm6:i386 # sudo apt-get install libxi6:i386 libxrender1:i386 libxrandr2:i386 libxfixes3:i386 -# sudo apt-get install libxcursor1:i386 libXinerama.so.1:i386 libXinerama1:i386 libfreetype6:i386 +# sudo apt-get install libxcursor1:i386 libxinerama1:i386 libfreetype6:i386 # sudo apt-get install libfontconfig1:i386 libglib2.0-0:i386 libstdc++6:i386 libelf1:i386 # # icecubedir="/opt/lscc/iCEcube2.2015.08" diff --git a/icefuzz/tests/bitop.pcf b/icefuzz/tests/bitop.pcf index 143632e..8a80285 100644 --- a/icefuzz/tests/bitop.pcf +++ b/icefuzz/tests/bitop.pcf @@ -1,3 +1,3 @@ -set_io a 1
-set_io b 10
-set_io y 11
+set_io a 1 +set_io b 10 +set_io y 11 diff --git a/icefuzz/tests/example_hx8kboard.pcf b/icefuzz/tests/example_hx8kboard.pcf index 417ca01..503eb36 100644 --- a/icefuzz/tests/example_hx8kboard.pcf +++ b/icefuzz/tests/example_hx8kboard.pcf @@ -1,9 +1,9 @@ -set_io LED0 B5
-set_io LED1 B4
-set_io LED2 A2
-set_io LED3 A1
-set_io LED4 C5
-set_io LED5 C4
-set_io LED6 B3
-set_io LED7 C3
-set_io clk J3
+set_io LED0 B5 +set_io LED1 B4 +set_io LED2 A2 +set_io LED3 A1 +set_io LED4 C5 +set_io LED5 C4 +set_io LED6 B3 +set_io LED7 C3 +set_io clk J3 diff --git a/icefuzz/tests/example_icestick.pcf b/icefuzz/tests/example_icestick.pcf index a1693eb..de06f5d 100644 --- a/icefuzz/tests/example_icestick.pcf +++ b/icefuzz/tests/example_icestick.pcf @@ -1,6 +1,6 @@ -set_io LED1 99
-set_io LED2 98
-set_io LED3 97
-set_io LED4 96
-set_io LED5 95
-set_io clk 21
+set_io LED1 99 +set_io LED2 98 +set_io LED3 97 +set_io LED4 96 +set_io LED5 95 +set_io clk 21 |