diff options
-rw-r--r-- | README | 2 | ||||
-rw-r--r-- | config.mk | 2 | ||||
-rw-r--r-- | docs/format.html | 12 | ||||
-rw-r--r-- | docs/index.html | 2 | ||||
-rw-r--r-- | icebox/Makefile | 66 | ||||
-rw-r--r-- | icebox/icebox.py | 1 | ||||
-rw-r--r-- | icebram/.gitignore | 2 | ||||
-rw-r--r-- | icefuzz/Makefile | 40 | ||||
-rw-r--r-- | icemulti/.gitignore | 1 | ||||
-rw-r--r-- | icepack/.gitignore | 3 | ||||
-rw-r--r-- | icepll/.gitignore | 1 | ||||
-rw-r--r-- | iceprog/Makefile | 7 | ||||
-rw-r--r-- | iceprog/iceprog.c | 74 | ||||
-rw-r--r-- | icetime/Makefile | 4 | ||||
-rw-r--r-- | icetime/icetime.cc | 53 |
15 files changed, 187 insertions, 83 deletions
@@ -1,7 +1,7 @@ Project IceStorm aims at documenting the bitstream format of Lattice iCE40 FPGAs and providing simple tools for analyzing and creating bitstream files. -See http://www.clifford.at/icestorm/ for more information. +See http://bygone.clairexen.net/icestorm/ for more information. Most of Project IceStorm is licensed under the ISC license: @@ -40,3 +40,5 @@ PREFIX = / LDFLAGS = -O2 --memory-init-file 0 -s TOTAL_MEMORY=64*1024*1024 SUBDIRS = icebox icepack icemulti icepll icetime icebram endif + +PYTHON3 ?= python3 diff --git a/docs/format.html b/docs/format.html index 8d36151..ee7a655 100644 --- a/docs/format.html +++ b/docs/format.html @@ -47,8 +47,10 @@ The following commands are known: <table class="ctab"> <tr><th>Opcode</th><th>Description</th></tr> -<tr><td>0</td><td>payload=1: CRAM Data<br/> - payload=3: BRAM Data<br/> +<tr><td>0</td><td>payload=1: Write CRAM Data<br/> + payload=2: Read BRAM Data<br/> + payload=3: Write BRAM Data<br/> + payload=4: Read BRAM Data<br/> payload=5: Reset CRC<br/> payload=6: Wakeup<br/> payload=8: Reboot</td></tr> @@ -59,9 +61,9 @@ The following commands are known: payload=0: low<br/> payload=1: medium<br/> payload=2: high</td></tr> -<tr><td>6</td><td>Set bank width</td></tr> -<tr><td>7</td><td>Set bank height</td></tr> -<tr><td>8</td><td>Set bank offset</td></tr> +<tr><td>6</td><td>Set bank width (16-bits, MSB first)</td></tr> +<tr><td>7</td><td>Set bank height (16-bits, MSB first)</td></tr> +<tr><td>8</td><td>Set bank offset (16-bits, MSB first)</td></tr> <tr><td>9</td><td>payload=0: Disable warm boot<br/> payload=16: Enable cold boot<br/> payload=32: Enable warm boot</td></tr> diff --git a/docs/index.html b/docs/index.html index a667d87..9f6b6eb 100644 --- a/docs/index.html +++ b/docs/index.html @@ -183,7 +183,7 @@ sudo make install</pre> Installing <a href="https://github.com/YosysHQ/nextpnr">NextPNR</a> (place&route tool, Arachne-PNR replacement): </p> -<pre style="padding-left: 3em">git clone https://github.com/YosysHQ/nextpnr nextpnr +<pre style="padding-left: 3em">git clone --recursive https://github.com/YosysHQ/nextpnr nextpnr cd nextpnr cmake -DARCH=ice40 -DCMAKE_INSTALL_PREFIX=/usr/local . make -j$(nproc) diff --git a/icebox/Makefile b/icebox/Makefile index 2897dfb..ffe439a 100644 --- a/icebox/Makefile +++ b/icebox/Makefile @@ -1,35 +1,41 @@ include ../config.mk +ifneq ($(shell uname -s),Darwin) + SED_I = sed -i +else + SED_I = sed -i '' +endif + all: chipdb-384.txt chipdb-1k.txt chipdb-8k.txt chipdb-5k.txt chipdb-lm4k.txt chipdb-u4k.txt chipdb-384.txt: icebox.py iceboxdb.py icebox_chipdb.py - python3 icebox_chipdb.py -3 > chipdb-384.new + $(PYTHON3) icebox_chipdb.py -3 > chipdb-384.new mv chipdb-384.new chipdb-384.txt chipdb-1k.txt: icebox.py iceboxdb.py icebox_chipdb.py - python3 icebox_chipdb.py > chipdb-1k.new + $(PYTHON3) icebox_chipdb.py > chipdb-1k.new mv chipdb-1k.new chipdb-1k.txt chipdb-5k.txt: icebox.py iceboxdb.py icebox_chipdb.py - python3 icebox_chipdb.py -5 > chipdb-5k.new + $(PYTHON3) icebox_chipdb.py -5 > chipdb-5k.new mv chipdb-5k.new chipdb-5k.txt chipdb-u4k.txt: icebox.py iceboxdb.py icebox_chipdb.py - python3 icebox_chipdb.py -u > chipdb-u4k.new + $(PYTHON3) icebox_chipdb.py -u > chipdb-u4k.new mv chipdb-u4k.new chipdb-u4k.txt chipdb-lm4k.txt: icebox.py iceboxdb.py icebox_chipdb.py - python3 icebox_chipdb.py -4 > chipdb-lm4k.new + $(PYTHON3) icebox_chipdb.py -4 > chipdb-lm4k.new mv chipdb-lm4k.new chipdb-lm4k.txt chipdb-8k.txt: icebox.py iceboxdb.py icebox_chipdb.py - python3 icebox_chipdb.py -8 > chipdb-8k.new + $(PYTHON3) icebox_chipdb.py -8 > chipdb-8k.new mv chipdb-8k.new chipdb-8k.txt check: all - python3 tc_xlat_netnames.py - python3 tc_rxlat_netnames.py - python3 tc_logic_xpr.py + $(PYTHON3) tc_xlat_netnames.py + $(PYTHON3) tc_rxlat_netnames.py + $(PYTHON3) tc_logic_xpr.py clean: rm -f chipdb-1k.txt chipdb-8k.txt chipdb-384.txt chipdb-5k.txt chipdb-lm4k.txt chipdb-u4k.txt @@ -56,27 +62,27 @@ install: all cp icebox_maps.py $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_maps$(PY_EXE) cp icebox_vlog.py $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_vlog$(PY_EXE) cp icebox_stat.py $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_stat$(PY_EXE) - sed -i 's+import iceboxdb+import $(subst -,_,$(PROGRAM_PREFIX))iceboxdb as iceboxdb+g' $(DESTDIR)$(PREFIX)/bin/$(subst -,_,$(PROGRAM_PREFIX))icebox.py - sed -i 's+import icebox+import $(subst -,_,$(PROGRAM_PREFIX))icebox as icebox+g' $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_chipdb$(PY_EXE) - sed -i 's+import icebox+import $(subst -,_,$(PROGRAM_PREFIX))icebox as icebox+g' $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_diff$(PY_EXE) - sed -i 's+from icebox+from $(subst -,_,$(PROGRAM_PREFIX))icebox+g' $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_diff$(PY_EXE) - sed -i 's+import icebox+import $(subst -,_,$(PROGRAM_PREFIX))icebox as icebox+g' $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_explain$(PY_EXE) - sed -i 's+from icebox+from $(subst -,_,$(PROGRAM_PREFIX))icebox+g' $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_explain$(PY_EXE) - sed -i 's+import icebox+import $(subst -,_,$(PROGRAM_PREFIX))icebox as icebox+g' $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_asc2hlc$(PY_EXE) - sed -i 's+from icebox+from $(subst -,_,$(PROGRAM_PREFIX))icebox+g' $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_asc2hlc$(PY_EXE) - sed -i 's+import icebox+import $(subst -,_,$(PROGRAM_PREFIX))icebox as icebox+g' $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_hlc2asc$(PY_EXE) - sed -i 's+from icebox+from $(subst -,_,$(PROGRAM_PREFIX))icebox+g' $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_hlc2asc$(PY_EXE) - sed -i 's+import icebox+import $(subst -,_,$(PROGRAM_PREFIX))icebox as icebox+g' $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_colbuf$(PY_EXE) - sed -i 's+from icebox+from $(subst -,_,$(PROGRAM_PREFIX))icebox+g' $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_colbuf$(PY_EXE) - sed -i 's+import icebox+import $(subst -,_,$(PROGRAM_PREFIX))icebox as icebox+g' $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_html$(PY_EXE) - sed -i 's+from icebox+from $(subst -,_,$(PROGRAM_PREFIX))icebox+g' $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_html$(PY_EXE) - sed -i 's+import icebox+import $(subst -,_,$(PROGRAM_PREFIX))icebox as icebox+g' $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_maps$(PY_EXE) - sed -i 's+from icebox+from $(subst -,_,$(PROGRAM_PREFIX))icebox+g' $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_maps$(PY_EXE) - sed -i 's+import icebox+import $(subst -,_,$(PROGRAM_PREFIX))icebox as icebox+g' $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_vlog$(PY_EXE) - sed -i 's+from icebox+from $(subst -,_,$(PROGRAM_PREFIX))icebox+g' $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_vlog$(PY_EXE) - sed -i 's+/usr/local/share/icebox+$(PREFIX)/share/$(PROGRAM_PREFIX)icebox+g' $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_vlog$(PY_EXE) - sed -i 's+import icebox+import $(subst -,_,$(PROGRAM_PREFIX))icebox as icebox+g' $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_stat$(PY_EXE) - sed -i 's+from icebox+from $(subst -,_,$(PROGRAM_PREFIX))icebox+g' $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_stat$(PY_EXE) + $(SED_I) 's+import iceboxdb+import $(subst -,_,$(PROGRAM_PREFIX))iceboxdb as iceboxdb+g' $(DESTDIR)$(PREFIX)/bin/$(subst -,_,$(PROGRAM_PREFIX))icebox.py + $(SED_I) 's+import icebox+import $(subst -,_,$(PROGRAM_PREFIX))icebox as icebox+g' $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_chipdb$(PY_EXE) + $(SED_I) 's+import icebox+import $(subst -,_,$(PROGRAM_PREFIX))icebox as icebox+g' $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_diff$(PY_EXE) + $(SED_I) 's+from icebox+from $(subst -,_,$(PROGRAM_PREFIX))icebox+g' $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_diff$(PY_EXE) + $(SED_I) 's+import icebox+import $(subst -,_,$(PROGRAM_PREFIX))icebox as icebox+g' $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_explain$(PY_EXE) + $(SED_I) 's+from icebox+from $(subst -,_,$(PROGRAM_PREFIX))icebox+g' $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_explain$(PY_EXE) + $(SED_I) 's+import icebox+import $(subst -,_,$(PROGRAM_PREFIX))icebox as icebox+g' $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_asc2hlc$(PY_EXE) + $(SED_I) 's+from icebox+from $(subst -,_,$(PROGRAM_PREFIX))icebox+g' $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_asc2hlc$(PY_EXE) + $(SED_I) 's+import icebox+import $(subst -,_,$(PROGRAM_PREFIX))icebox as icebox+g' $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_hlc2asc$(PY_EXE) + $(SED_I) 's+from icebox+from $(subst -,_,$(PROGRAM_PREFIX))icebox+g' $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_hlc2asc$(PY_EXE) + $(SED_I) 's+import icebox+import $(subst -,_,$(PROGRAM_PREFIX))icebox as icebox+g' $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_colbuf$(PY_EXE) + $(SED_I) 's+from icebox+from $(subst -,_,$(PROGRAM_PREFIX))icebox+g' $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_colbuf$(PY_EXE) + $(SED_I) 's+import icebox+import $(subst -,_,$(PROGRAM_PREFIX))icebox as icebox+g' $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_html$(PY_EXE) + $(SED_I) 's+from icebox+from $(subst -,_,$(PROGRAM_PREFIX))icebox+g' $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_html$(PY_EXE) + $(SED_I) 's+import icebox+import $(subst -,_,$(PROGRAM_PREFIX))icebox as icebox+g' $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_maps$(PY_EXE) + $(SED_I) 's+from icebox+from $(subst -,_,$(PROGRAM_PREFIX))icebox+g' $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_maps$(PY_EXE) + $(SED_I) 's+import icebox+import $(subst -,_,$(PROGRAM_PREFIX))icebox as icebox+g' $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_vlog$(PY_EXE) + $(SED_I) 's+from icebox+from $(subst -,_,$(PROGRAM_PREFIX))icebox+g' $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_vlog$(PY_EXE) + $(SED_I) 's+/usr/local/share/icebox+$(PREFIX)/share/$(PROGRAM_PREFIX)icebox+g' $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_vlog$(PY_EXE) + $(SED_I) 's+import icebox+import $(subst -,_,$(PROGRAM_PREFIX))icebox as icebox+g' $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_stat$(PY_EXE) + $(SED_I) 's+from icebox+from $(subst -,_,$(PROGRAM_PREFIX))icebox+g' $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_stat$(PY_EXE) uninstall: rm -f $(DESTDIR)$(PREFIX)/bin/$(subst -,_,$(PROGRAM_PREFIX))cebox.py diff --git a/icebox/icebox.py b/icebox/icebox.py index a7631a2..ef5478b 100644 --- a/icebox/icebox.py +++ b/icebox/icebox.py @@ -1719,7 +1719,6 @@ noplls_db = { "8k-cm81:4k": [ "8k_1" ], "1k-qn48": [ "1k" ], "1k-cb81": [ "1k" ], - "1k-cb121": [ "1k" ], "1k-vq100": [ "1k" ], "384-qn32": [ "384" ], } diff --git a/icebram/.gitignore b/icebram/.gitignore index 10fbc8a..d329cf5 100644 --- a/icebram/.gitignore +++ b/icebram/.gitignore @@ -11,3 +11,5 @@ demo_tb.v icebram icebram.d icebram.o +icebram.exe +icebram.wasm diff --git a/icefuzz/Makefile b/icefuzz/Makefile index 9b8916e..91d0136 100644 --- a/icefuzz/Makefile +++ b/icefuzz/Makefile @@ -76,8 +76,8 @@ ifneq ($(RAM_SUFFIX),_5k) cp cached_dsp3_5k.txt bitdata_dsp3_5k.txt cp cached_ipcon_5k.txt bitdata_ipcon_5k.txt endif - ICEDEVICE=$(DEVICECLASS) python3 database.py - python3 export.py + ICEDEVICE=$(DEVICECLASS) $(PYTHON3) database.py + $(PYTHON3) export.py diff -U0 cached_io.txt bitdata_io.txt || cp -v bitdata_io.txt cached_io.txt diff -U0 cached_logic.txt bitdata_logic.txt || cp -v bitdata_logic.txt cached_logic.txt diff -U0 cached_ramb$(RAM_SUFFIX).txt bitdata_ramb$(RAM_SUFFIX).txt || cp -v bitdata_ramb$(RAM_SUFFIX).txt cached_ramb$(RAM_SUFFIX).txt @@ -91,53 +91,53 @@ endif timings: ifeq ($(DEVICECLASS),5k) cp tmedges.txt tmedges.tmp - set -e; for f in work_$(DEVICECLASS)_*/*.vsb; do echo $$f; sed '/defparam/d' < $$f > $$f.fixed; yosys -q -f verilog -s tmedges.ys $$f.fixed; python3 rename_dsps.py $$f; done + set -e; for f in work_$(DEVICECLASS)_*/*.vsb; do echo $$f; sed '/defparam/d' < $$f > $$f.fixed; yosys -q -f verilog -s tmedges.ys $$f.fixed; $(PYTHON3) rename_dsps.py $$f; done sort -u tmedges.tmp > tmedges.txt && rm -f tmedges.tmp - python3 timings.py -t timings_up5k.txt work_*/*.sdf > timings_up5k.new + $(PYTHON3) timings.py -t timings_up5k.txt work_*/*.sdf > timings_up5k.new mv timings_up5k.new timings_up5k.txt else ifeq ($(DEVICECLASS),u4k) cp tmedges.txt tmedges.tmp - set -e; for f in work_$(DEVICECLASS)_*/*.vsb; do echo $$f; sed '/defparam/d' < $$f > $$f.fixed; yosys -q -f verilog -s tmedges.ys $$f.fixed; python3 rename_dsps.py $$f; done + set -e; for f in work_$(DEVICECLASS)_*/*.vsb; do echo $$f; sed '/defparam/d' < $$f > $$f.fixed; yosys -q -f verilog -s tmedges.ys $$f.fixed; $(PYTHON3) rename_dsps.py $$f; done sort -u tmedges.tmp > tmedges.txt && rm -f tmedges.tmp - python3 timings.py -t timings_u4k.txt work_*/*.sdf > timings_u4k.new + $(PYTHON3) timings.py -t timings_u4k.txt work_*/*.sdf > timings_u4k.new mv timings_u4k.new timings_u4k.txt else ifeq ($(DEVICECLASS),8k) cp tmedges.txt tmedges.tmp set -e; for f in work_$(DEVICECLASS)_*/*.vsb; do echo $$f; yosys -q -f verilog -s tmedges.ys $$f; done sort -u tmedges.tmp > tmedges.txt && rm -f tmedges.tmp - python3 timings.py -t timings_hx8k.txt work_*/*.sdf > timings_hx8k.new + $(PYTHON3) timings.py -t timings_hx8k.txt work_*/*.sdf > timings_hx8k.new mv timings_hx8k.new timings_hx8k.txt - python3 timings.py -t timings_lp8k.txt work_*/*.slp > timings_lp8k.new + $(PYTHON3) timings.py -t timings_lp8k.txt work_*/*.slp > timings_lp8k.new mv timings_lp8k.new timings_lp8k.txt else ifeq ($(DEVICECLASS),384) cp tmedges.txt tmedges.tmp set -e; for f in work_$(DEVICECLASS)_*/*.vsb; do echo $$f; yosys -q -f verilog -s tmedges.ys $$f; done sort -u tmedges.tmp > tmedges.txt && rm -f tmedges.tmp - python3 timings.py -t timings_lp384.txt work_*/*.slp > timings_lp384.new + $(PYTHON3) timings.py -t timings_lp384.txt work_*/*.slp > timings_lp384.new mv timings_lp384.new timings_lp384.txt else cp tmedges.txt tmedges.tmp set -e; for f in work_$(DEVICECLASS)_*/*.vsb; do echo $$f; yosys -q -f verilog -s tmedges.ys $$f; done sort -u tmedges.tmp > tmedges.txt && rm -f tmedges.tmp - python3 timings.py -t timings_hx1k.txt work_*/*.sdf > timings_hx1k.new + $(PYTHON3) timings.py -t timings_hx1k.txt work_*/*.sdf > timings_hx1k.new mv timings_hx1k.new timings_hx1k.txt - python3 timings.py -t timings_lp1k.txt work_*/*.slp > timings_lp1k.new + $(PYTHON3) timings.py -t timings_lp1k.txt work_*/*.slp > timings_lp1k.new mv timings_lp1k.new timings_lp1k.txt endif endif endif endif timings_html: - python3 timings.py -h tmedges.txt -t timings_hx1k.txt -l "HX1K with default temp/volt settings" > timings_hx1k.html - python3 timings.py -h tmedges.txt -t timings_hx8k.txt -l "HX8K with default temp/volt settings" > timings_hx8k.html - python3 timings.py -h tmedges.txt -t timings_lp1k.txt -l "LP1K with default temp/volt settings" > timings_lp1k.html - python3 timings.py -h tmedges.txt -t timings_lp8k.txt -l "LP8K with default temp/volt settings" > timings_lp8k.html - python3 timings.py -h tmedges.txt -t timings_lp384.txt -l "LP384 with default temp/volt settings" > timings_lp384.html - python3 timings.py -h tmedges.txt -t timings_up5k.txt -l "UP5K with default temp/volt settings" > timings_up5k.html - python3 timings.py -h tmedges.txt -t timings_u4k.txt -l "U4K with default temp/volt settings" > timings_u4k.html + $(PYTHON3) timings.py -h tmedges.txt -t timings_hx1k.txt -l "HX1K with default temp/volt settings" > timings_hx1k.html + $(PYTHON3) timings.py -h tmedges.txt -t timings_hx8k.txt -l "HX8K with default temp/volt settings" > timings_hx8k.html + $(PYTHON3) timings.py -h tmedges.txt -t timings_lp1k.txt -l "LP1K with default temp/volt settings" > timings_lp1k.html + $(PYTHON3) timings.py -h tmedges.txt -t timings_lp8k.txt -l "LP8K with default temp/volt settings" > timings_lp8k.html + $(PYTHON3) timings.py -h tmedges.txt -t timings_lp384.txt -l "LP384 with default temp/volt settings" > timings_lp384.html + $(PYTHON3) timings.py -h tmedges.txt -t timings_up5k.txt -l "UP5K with default temp/volt settings" > timings_up5k.html + $(PYTHON3) timings.py -h tmedges.txt -t timings_u4k.txt -l "U4K with default temp/volt settings" > timings_u4k.html data_cached.txt: cached_io.txt cached_logic.txt cached_ramb$(RAM_SUFFIX).txt cached_ramt$(RAM_SUFFIX).txt cached_dsp0_5k.txt cached_dsp1_5k.txt cached_dsp2_5k.txt cached_dsp3_5k.txt cached_ipcon_5k.txt gawk '{ print "io", $$0; }' cached_io.txt > data_cached.new gawk '{ print "logic", $$0; }' cached_logic.txt >> data_cached.new @@ -186,9 +186,9 @@ datafiles: $(addprefix data_,$(addsuffix .txt,$(TESTS))) define data_template data_$(DEVICECLASS)_$(1).txt: make_$(1).py ../icepack/icepack - ICEDEVICE=$(DEVICECLASS) python3 make_$(1).py + ICEDEVICE=$(DEVICECLASS) $(PYTHON3) make_$(1).py +ICEDEV=$(DEVICE) $(MAKE) -C work_$(DEVICECLASS)_$(1) - ICEDEVICE=$(DEVICECLASS) python3 extract.py work_$(DEVICECLASS)_$(1)/*.glb > $$@ + ICEDEVICE=$(DEVICECLASS) $(PYTHON3) extract.py work_$(DEVICECLASS)_$(1)/*.glb > $$@ endef $(foreach test,$(TESTS),$(eval $(call data_template,$(test)))) diff --git a/icemulti/.gitignore b/icemulti/.gitignore index 9254c71..43ef5a2 100644 --- a/icemulti/.gitignore +++ b/icemulti/.gitignore @@ -1,4 +1,5 @@ icemulti icemulti.exe +icemulti.wasm icemulti.o icemulti.d diff --git a/icepack/.gitignore b/icepack/.gitignore index ef4173d..a277e88 100644 --- a/icepack/.gitignore +++ b/icepack/.gitignore @@ -1,5 +1,8 @@ icepack icepack.exe +icepack.wasm iceunpack +iceunpack.exe +iceunpack.wasm icepack.o icepack.d diff --git a/icepll/.gitignore b/icepll/.gitignore index 418d25b..8ed93c2 100644 --- a/icepll/.gitignore +++ b/icepll/.gitignore @@ -1,4 +1,5 @@ icepll icepll.exe +icepll.wasm icepll.o icepll.d diff --git a/iceprog/Makefile b/iceprog/Makefile index 3cb07b8..f41263e 100644 --- a/iceprog/Makefile +++ b/iceprog/Makefile @@ -1,12 +1,5 @@ include ../config.mk -ifneq ($(shell uname -s),Darwin) - LDLIBS = -L/usr/local/lib -lm -else - LIBFTDI_NAME = $(shell $(PKG_CONFIG) --exists libftdi1 && echo ftdi1 || echo ftdi) - LDLIBS = -L/usr/local/lib -l$(LIBFTDI_NAME) -lm -endif - ifeq ($(STATIC),1) LDFLAGS += -static LDLIBS += $(shell for pkg in libftdi1 libftdi; do $(PKG_CONFIG) --silence-errors --static --libs $$pkg && exit; done; echo -lftdi; ) diff --git a/iceprog/iceprog.c b/iceprog/iceprog.c index b04fe65..8ee6443 100644 --- a/iceprog/iceprog.c +++ b/iceprog/iceprog.c @@ -96,16 +96,16 @@ enum flash_cmd { static void set_cs_creset(int cs_b, int creset_b) { uint8_t gpio = 0; - uint8_t direction = 0x93; + uint8_t direction = 0x03; - if (cs_b) { + if (!cs_b) { // ADBUS4 (GPIOL0) - gpio |= 0x10; + direction |= 0x10; } - if (creset_b) { + if (!creset_b) { // ADBUS7 (GPIOL3) - gpio |= 0x80; + direction |= 0x80; } mpsse_set_gpio(gpio, direction); @@ -180,7 +180,7 @@ static void flash_read_id() if (data[4] == 0xFF) fprintf(stderr, "Extended Device String Length is 0xFF, " - "this is likely a read error. Ignorig...\n"); + "this is likely a read error. Ignoring...\n"); else { // Read extended JEDEC ID bytes if (data[4] != 0) { @@ -202,9 +202,15 @@ static void flash_reset() { uint8_t data[8] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + // This disables CRM is if it was enabled flash_chip_select(); mpsse_xfer_spi(data, 8); flash_chip_deselect(); + + // This disables QPI if it was enable + flash_chip_select(); + mpsse_xfer_spi_bits(0xFF, 2); + flash_chip_deselect(); } static void flash_power_up() @@ -446,6 +452,34 @@ static void flash_disable_protection() } +static void flash_enable_quad() +{ + fprintf(stderr, "Enabling Quad operation...\n"); + + // Allow write + flash_write_enable(); + + // Write Status Register 2 <- 0x02 + uint8_t data[2] = { FC_WSR2, 0x02 }; + flash_chip_select(); + mpsse_xfer_spi(data, 2); + flash_chip_deselect(); + + flash_wait(); + + // Read Status Register 1 + data[0] = FC_RSR2; + + flash_chip_select(); + mpsse_xfer_spi(data, 2); + flash_chip_deselect(); + + if ((data[1] & 0x02) != 0x02) + fprintf(stderr, "failed to set QE=1, SR2 now equal to 0x%02x (expected 0x%02x)\n", data[1], data[1] | 0x02); + + fprintf(stderr, "SR2: %08x\n", data[1]); +} + // --------------------------------------------------------- // iceprog implementation // --------------------------------------------------------- @@ -484,6 +518,7 @@ static void help(const char *progname) fprintf(stderr, " -c do not write flash, only verify (`check')\n"); fprintf(stderr, " -S perform SRAM programming\n"); fprintf(stderr, " -t just read the flash ID sequence\n"); + fprintf(stderr, " -Q just set the flash QE=1 bit\n"); fprintf(stderr, "\n"); fprintf(stderr, "Erase mode (only meaningful in default mode):\n"); fprintf(stderr, " [default] erase aligned chunks of 64kB in write mode\n"); @@ -543,7 +578,7 @@ int main(int argc, char **argv) bool bulk_erase = false; bool dont_erase = false; bool prog_sram = false; - bool test_mode = false; + int test_mode = 0; bool slow_clock = false; bool disable_protect = false; bool disable_verify = false; @@ -565,7 +600,7 @@ int main(int argc, char **argv) /* Decode command line parameters */ int opt; char *endptr; - while ((opt = getopt_long(argc, argv, "d:i:I:rR:e:o:cbnStvspXk", long_options, NULL)) != -1) { + while ((opt = getopt_long(argc, argv, "d:i:I:rR:e:o:cbnStQvspXk", long_options, NULL)) != -1) { switch (opt) { case 'd': /* device string */ devstr = optarg; @@ -653,7 +688,10 @@ int main(int argc, char **argv) prog_sram = true; break; case 't': /* just read flash id */ - test_mode = true; + test_mode = 1; + break; + case 'Q': /* just read flash id */ + test_mode = 2; break; case 'v': /* provide verbose output */ verbose = true; @@ -682,7 +720,7 @@ int main(int argc, char **argv) /* Make sure that the combination of provided parameters makes sense */ - if (read_mode + erase_mode + check_mode + prog_sram + test_mode > 1) { + if (read_mode + erase_mode + check_mode + prog_sram + !!test_mode > 1) { fprintf(stderr, "%s: options `-r'/`-R', `-e`, `-c', `-S', and `-t' are mutually exclusive\n", my_name); return EXIT_FAILURE; } @@ -840,7 +878,10 @@ int main(int argc, char **argv) flash_reset(); flash_power_up(); - flash_read_id(); + if (test_mode == 1) + flash_read_id(); + else + flash_enable_quad(); flash_power_down(); @@ -966,10 +1007,14 @@ int main(int argc, char **argv) rc = fread(buffer, 1, page_size, f); if (rc <= 0) break; + fprintf(stderr, " \r"); + fprintf(stderr, "addr 0x%06X %3ld%%\r", rw_offset + addr, 100 * addr / file_size); flash_write_enable(); flash_prog(rw_offset + addr, buffer, rc); flash_wait(); } + fprintf(stderr, " \r"); + fprintf(stderr, "done.\n"); /* seek to the beginning for second pass */ fseek(f, 0, SEEK_SET); @@ -984,9 +1029,13 @@ int main(int argc, char **argv) fprintf(stderr, "reading..\n"); for (int addr = 0; addr < read_size; addr += 256) { uint8_t buffer[256]; + fprintf(stderr, " \r"); + fprintf(stderr, "addr 0x%06X %3d%%\r", rw_offset + addr, 100 * addr / read_size); flash_read(rw_offset + addr, buffer, 256); fwrite(buffer, read_size - addr > 256 ? 256 : read_size - addr, 1, f); } + fprintf(stderr, " \r"); + fprintf(stderr, "done.\n"); } else if (!erase_mode && !disable_verify) { fprintf(stderr, "reading..\n"); for (int addr = 0; true; addr += 256) { @@ -994,6 +1043,8 @@ int main(int argc, char **argv) int rc = fread(buffer_file, 1, 256, f); if (rc <= 0) break; + fprintf(stderr, " \r"); + fprintf(stderr, "addr 0x%06X %3ld%%\r", rw_offset + addr, 100 * addr / file_size); flash_read(rw_offset + addr, buffer_flash, rc); if (memcmp(buffer_file, buffer_flash, rc)) { fprintf(stderr, "Found difference between flash and file!\n"); @@ -1001,6 +1052,7 @@ int main(int argc, char **argv) } } + fprintf(stderr, " \r"); fprintf(stderr, "VERIFY OK\n"); } diff --git a/icetime/Makefile b/icetime/Makefile index 7d0ca32..1dfc926 100644 --- a/icetime/Makefile +++ b/icetime/Makefile @@ -32,7 +32,7 @@ $(PROGRAM_PREFIX)icetime$(EXE): icetime.o iceutil.o $(addsuffix .o, $(addprefix $(CXX) -o $@ $(LDFLAGS) $^ $(LDLIBS) timings-%.cc: timings.py ../icefuzz/timings_%.txt - python3 timings.py $* > $@ + $(PYTHON3) timings.py $* > $@ .PRECIOUS: timings-%.cc @@ -51,7 +51,7 @@ uninstall: # yosys -qp 'read_verilog -lib cells.v; prep; show' test0_out.v test0 test1 test2 test3 test4 test5 test6 test7 test8 test9: icetime - test -f $@_ref.v || python3 mktest.py $@ + test -f $@_ref.v || $(PYTHON3) mktest.py $@ ./icetime -m -d hx1k -P tq144 -p $@.pcf -o $@_out.v $@.asc yosys $@.ys diff --git a/icetime/icetime.cc b/icetime/icetime.cc index d730fc6..fef65d2 100644 --- a/icetime/icetime.cc +++ b/icetime/icetime.cc @@ -59,6 +59,7 @@ std::set<std::tuple<int, int, int>> extra_bits; std::set<std::string> io_names; std::map<int, std::string> net_symbols; +std::map<std::string, unsigned> lc_lut_in_mask; bool get_config_bit(int tile_x, int tile_y, int bit_row, int bit_col) { @@ -221,10 +222,20 @@ void read_pcf(const char *filename) if (tok == nullptr || strcmp(tok, "set_io")) continue; + bool skip_next = false; std::vector<std::string> args; while ((tok = strtok(nullptr, " \t\r\n")) != nullptr) { + if(skip_next) { + skip_next = false; + continue; + } if (!strcmp(tok, "--warn-no-port")) continue; + if (!strcmp(tok, "-pullup") || !strcmp(tok, "-pullup_resistor")) { + skip_next = true; // skip argument + continue; + } + args.push_back(tok); } @@ -836,6 +847,15 @@ struct TimingAnalysis } if (driver_type == "LogicCell40" && (driver_port == "ltout" || driver_port == "lcout")) { + unsigned mask = lc_lut_in_mask.at(driver_cell); + if (inport == "in0" && ((mask & 0x1) == 0)) + continue; + if (inport == "in1" && ((mask & 0x2) == 0)) + continue; + if (inport == "in2" && ((mask & 0x4) == 0)) + continue; + if (inport == "in3" && ((mask & 0x8) == 0)) + continue; if (inport == "carryin") continue; } @@ -1221,14 +1241,37 @@ std::string make_lc40(int x, int y, int z) for (int i = 0; i < 20; i++) lcbits[i] = get_config_bit(x, y, lcbits_pos[i].first, lcbits_pos[i].second) ? '1' : '0'; + static const std::vector<int> lut_perm = { + 4, 14, 15, 5, 6, 16, 17, 7, 3, 13, 12, 2, 1, 11, 10, 0, + }; + + unsigned lut_init = 0; + for (unsigned i = 0; i < lut_perm.size(); i++) + if (lcbits[lut_perm[i]] == '1') + lut_init |= (1U << i); + // FIXME: fill in the '0' netlist_cell_params[cell]["C_ON"] = stringf("1'b%c", lcbits[8]); netlist_cell_params[cell]["SEQ_MODE"] = stringf("4'b%c%c%c%c", lcbits[9], '0', '0', '0'); - netlist_cell_params[cell]["LUT_INIT"] = stringf("16'b%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c", - lcbits[0], lcbits[10], lcbits[11], lcbits[1], - lcbits[2], lcbits[12], lcbits[13], lcbits[3], - lcbits[7], lcbits[17], lcbits[16], lcbits[6], - lcbits[5], lcbits[15], lcbits[14], lcbits[4]); + + std::string init = "16'b"; + for (int i = 15; i >= 0; i--) + init += ((lut_init >> i) & 0x1) ? '1' : '0'; + + netlist_cell_params[cell]["LUT_INIT"] = init; + + // Find which LUT inputs are "don't care" in the function, to avoid false paths for bits + // only affecting the carry. + lc_lut_in_mask[cell] = 0; + for (unsigned k = 0; k < 4; k++) { + for (unsigned i = 0; i < 16; i++) { + // If toggling the LUT input makes a difference it's not a don't care + if (((lut_init >> i) & 0x1U) != ((lut_init >> (i ^ (1U << k))) & 0x1U)) { + lc_lut_in_mask[cell] |= (1 << k); + break; + } + } + } if (lcbits[8] == '1') { |