diff options
34 files changed, 1209 insertions, 248 deletions
@@ -1,6 +1,7 @@ PREFIX ?= /usr/local DEBUG ?= 0 ICEPROG ?= 1 +PROGRAM_PREFIX ?= CXX ?= clang++ CC ?= clang @@ -18,11 +19,11 @@ endif WARN_LEVEL ?= all LDLIBS = -lm -lstdc++ -CFLAGS += -MD -O$(OPT_LEVEL) $(DBG_LEVEL) -W$(WARN_LEVEL) -std=$(C_STD) -I$(PREFIX)/include -CXXFLAGS += -MD -O$(OPT_LEVEL) $(DBG_LEVEL) -W$(WARN_LEVEL) -std=$(CXX_STD) -I$(PREFIX)/include +CFLAGS += -MD -MP -O$(OPT_LEVEL) $(DBG_LEVEL) -W$(WARN_LEVEL) -std=$(C_STD) -I$(PREFIX)/include +CXXFLAGS += -MD -MP -O$(OPT_LEVEL) $(DBG_LEVEL) -W$(WARN_LEVEL) -std=$(CXX_STD) -I$(PREFIX)/include DESTDIR ?= -CHIPDB_SUBDIR ?= icebox +CHIPDB_SUBDIR ?= $(PROGRAM_PREFIX)icebox ifeq ($(MXE),1) EXE = .exe diff --git a/docs/index.html b/docs/index.html index 3ca1721..9f6b6eb 100644 --- a/docs/index.html +++ b/docs/index.html @@ -20,9 +20,9 @@ <b>2017-03-13:</b> Released support for LP384 chips (in all package variants).<br/> <b>2016-02-07:</b> Support for all package variants of LP1K, LP4K, LP8K and HX1K, HX4K, and HX8K.<br/> <b>2016-01-17:</b> First release of IceTime timing analysis. Video: <a href="https://youtu.be/IG5CpFJRnOk">https://youtu.be/IG5CpFJRnOk</a><br/> -<b>2015-12-27:</b> <a href="http://www.clifford.at/papers/2015/icestorm-flow/">Presentation</a> of the IceStorm flow at 32C3 (<a href="https://www.youtube.com/watch?v=SOn0g3k0FlE">Video on Youtube</a>).<br/> +<b>2015-12-27:</b> <a href="http://bygone.clairexen.net/papers/2015/icestorm-flow/">Presentation</a> of the IceStorm flow at 32C3 (<a href="https://www.youtube.com/watch?v=SOn0g3k0FlE">Video on Youtube</a>).<br/> <b>2015-07-19:</b> Released support for 8k chips. Moved IceStorm source code to GitHub.<br/> -<b>2015-05-27:</b> We have a working fully Open Source flow with <a href="http://www.clifford.at/yosys/">Yosys</a> and <a href="https://github.com/cseed/arachne-pnr">Arachne-pnr</a>! Video: <a href="http://youtu.be/yUiNlmvVOq8">http://youtu.be/yUiNlmvVOq8</a><br/> +<b>2015-05-27:</b> We have a working fully Open Source flow with <a href="http://bygone.clairexen.net/yosys/">Yosys</a> and <a href="https://github.com/cseed/arachne-pnr">Arachne-pnr</a>! Video: <a href="http://youtu.be/yUiNlmvVOq8">http://youtu.be/yUiNlmvVOq8</a><br/> <b>2015-04-13:</b> Complete rewrite of IceUnpack, added IcePack, some major documentation updates<br/> <b>2015-03-22:</b> First public release and short YouTube video demonstrating our work: <a href="http://youtu.be/u1ZHcSNDQMM">http://youtu.be/u1ZHcSNDQMM</a> </p> @@ -30,10 +30,10 @@ <h2>What is Project IceStorm?</h2> <p> -Project IceStorm aims at reverse engineering and documenting the bitstream +Project IceStorm aims at documenting the bitstream format of Lattice iCE40 FPGAs and providing simple tools for analyzing and creating bitstream files. The IceStorm flow (<a -href="http://www.clifford.at/yosys/">Yosys</a>, <a +href="http://bygone.clairexen.net/yosys/">Yosys</a>, <a href="https://github.com/cseed/arachne-pnr">Arachne-pnr</a>, and IceStorm) is a fully open source Verilog-to-Bitstream flow for iCE40 FPGAs. </p> @@ -49,8 +49,8 @@ and UltraLite parts are not yet supported. <p> It has a very minimalistic architecture with a very regular structure. There are not many -different kinds of tiles or special function units. This makes it both ideal for -reverse engineering and as a reference platform for general purpose FPGA tool development. +different kinds of tiles or special function units. This makes it both ideal for creating +bitstream documentations and as a reference platform for general purpose FPGA tool development. </p> <p> @@ -64,8 +64,8 @@ Breakout Board</a> featuring an HX8K chip.) <h2>What is the Status of the Project?</h2> <p> -We are pretty confident that we have the 1K and 8K devices completely reverse -engineered. For example, it seems we can create correct functional Verilog +We are pretty confident that we have the 1K and 8K devices completely +documented. For example, it seems we can create correct functional Verilog models for all bitstreams generated by Lattice iCEcube2 for the iCE40 HX1K-TQ144 and the iCE40 HX8K-CT256 using our <tt>icebox_vlog</tt> tool. </p> @@ -115,7 +115,7 @@ Current work focuses on further improving our timing analysis flow. <h2>How do I use the Fully Open Source iCE40 Flow?</h2> <p> -Synthesis for iCE40 FPGAs can be done with <a href="http://www.clifford.at/yosys/">Yosys</a>. +Synthesis for iCE40 FPGAs can be done with <a href="http://bygone.clairexen.net/yosys/">Yosys</a>. Place-and-route can be done with <a href="https://github.com/cseed/arachne-pnr">arachne-pnr</a>. Here is an example script for implementing and programming the <a href="https://github.com/cseed/arachne-pnr/tree/master/examples/rot">rot example from @@ -162,10 +162,10 @@ Note: All tools will be installed relative to /usr/local </p> <p> -Installing the <a href="https://github.com/cliffordwolf/icestorm">IceStorm Tools</a> (icepack, icebox, iceprog, icetime, chip databases): +Installing the <a href="https://github.com/YosysHQ/icestorm">IceStorm Tools</a> (icepack, icebox, iceprog, icetime, chip databases): </p> -<pre style="padding-left: 3em">git clone https://github.com/cliffordwolf/icestorm.git icestorm +<pre style="padding-left: 3em">git clone https://github.com/YosysHQ/icestorm.git icestorm cd icestorm make -j$(nproc) sudo make install</pre> @@ -183,17 +183,17 @@ 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) sudo make install</pre> <p> -Installing <a href="http://www.clifford.at/yosys/">Yosys</a> (Verilog synthesis): +Installing <a href="http://bygone.clairexen.net/yosys/">Yosys</a> (Verilog synthesis): </p> -<pre style="padding-left: 3em">git clone https://github.com/cliffordwolf/yosys.git yosys +<pre style="padding-left: 3em">git clone https://github.com/YosysHQ/yosys.git yosys cd yosys make -j$(nproc) sudo make install</pre> @@ -220,7 +220,7 @@ bit-streams to a Lattice iCEstick and/or a Lattice iCE40-HX8K Breakout Board as </p> <p> -Please <a href="https://github.com/cliffordwolf/icestorm/issues/new">file an issue on github</a> if you have additional notes to +Please <a href="https://github.com/YosysHQ/icestorm/issues/new">file an issue on github</a> if you have additional notes to share regarding the install procedures on the operating system of your choice. </p> @@ -229,9 +229,9 @@ share regarding the install procedures on the operating system of your choice. <p> The IceStorm Tools are a couple of small programs for working with iCE40 bitstream files and our ASCII representation of it. The complete Open Source iCE40 Flow consists of the <a -href="https://github.com/cliffordwolf/icestorm">IceStorm Tools</a>, <a +href="https://github.com/YosysHQ/icestorm">IceStorm Tools</a>, <a href="https://github.com/cseed/arachne-pnr">Arachne-PNR</a>, and <a -href="http://www.clifford.at/yosys/">Yosys</a>. +href="http://bygone.clairexen.net/yosys/">Yosys</a>. </p> <h3>IcePack/IceUnpack</h3> @@ -293,7 +293,7 @@ create an IceStorm ASCII file for the placed and routed design. </p> <p> -<i>IcePack/IceUnpack, IceBox, IceProg, IceTime, and IcePLL are written by Clifford Wolf. IcePack/IceUnpack is based on a reference implementation provided by Mathias Lasser. IceMulti is written by Marcus Comstedt.</i> +<i>IcePack/IceUnpack, IceBox, IceProg, IceTime, and IcePLL are written by Claire Wolf. IcePack/IceUnpack is based on a reference implementation provided by Mathias Lasser. IceMulti is written by Marcus Comstedt.</i> </p> <h2>Where do I get support or meet other IceStorm users?</h2> @@ -309,8 +309,8 @@ For general discussions go to the <a href="https://www.reddit.com/r/yosys/">Yosy </p> <p> -If you have a bug report please file an issue on github. (<a href="https://github.com/cliffordwolf/icestorm/issues">IceStorm Issue Tracker</a>, -<a href="https://github.com/cliffordwolf/yosys/issues">Yosys Issue Tracker</a>, <a href="https://github.com/cseed/arachne-pnr/issues">Arachne-PNR Issue Tracker</a>) +If you have a bug report please file an issue on github. (<a href="https://github.com/YosysHQ/icestorm/issues">IceStorm Issue Tracker</a>, +<a href="https://github.com/YosysHQ/yosys/issues">Yosys Issue Tracker</a>, <a href="https://github.com/cseed/arachne-pnr/issues">Arachne-PNR Issue Tracker</a>) </p> <h2 id="docs">Where is the Documentation?</h2> @@ -521,7 +521,7 @@ endmodule</pre> <h2>Links</h2> <p> -Links to related projects. Contact me at clifford@clifford.at if you have an interesting and relevant link. +Links to related projects. Contact me at claire@clairexen.net if you have an interesting and relevant link. </p> <ul> @@ -557,31 +557,33 @@ Links to related projects. Contact me at clifford@clifford.at if you have an int <li><a href="http://hedmen.org/icestorm-doc/icestorm.html">IceStorm Learner’s Documentation</a> </ul> -<h3>Other FPGA reverse engineering projects</h3> +<h3>Other FPGA bitstream documentation projects</h3> <ul> -<li><a href="https://github.com/Wolfgang-Spraul/fpgatools">Xilinx xc6slx9 reverse engineering, Wolfgang Spraul</a> +<li><a href="https://github.com/SymbiFlow/prjtrellis">ECP5 bitstream documentation (Project Trellis)</a> +<li><a href="https://github.com/SymbiFlow/prjxray">Xilinx 7-series bitstream documentation (Project X-Ray)</a> +<li><a href="https://github.com/Wolfgang-Spraul/fpgatools">Xilinx xc6slx9 documentation, Wolfgang Spraul</a> <li><a href="http://www.fabienm.eu/flf/wp-content/uploads/2014/11/Note2008.pdf">From the bitstream to the netlist, Jean-Baptiste Note and Éric Rannaud</a> -<li><a href="http://git.bfuser.eu/?p=marex/typhoon.git;a=commit">Cyclone IV EP4CE6 reverse engineering, Marek Vasut</a> +<li><a href="http://git.bfuser.eu/?p=marex/typhoon.git;a=commit">Cyclone IV EP4CE6 documentation, Marek Vasut</a> </ul> <hr> <p> -In papers and reports, please refer to Project IceStorm as follows: Clifford Wolf, Mathias Lasser. Project IceStorm. http://www.clifford.at/icestorm/, +In papers and reports, please refer to Project IceStorm as follows: Claire Wolf, Mathias Lasser. Project IceStorm. http://bygone.clairexen.net/icestorm/, e.g. using the following BibTeX code: </p> <pre>@MISC{IceStorm, - author = {Clifford Wolf and Mathias Lasser}, + author = {Claire Wolf and Mathias Lasser}, title = {Project IceStorm}, - howpublished = "\url{http://www.clifford.at/icestorm/}" + howpublished = "\url{http://bygone.clairexen.net/icestorm/}" }</pre> <hr> <p> -<i>Documentation mostly by Clifford Wolf <clifford@clifford.at> in 2015. Based on research by Mathias Lasser and Clifford Wolf.<br/> +<i>Documentation mostly by Claire Wolf <claire@clairexen.net> in 2015. Based on research by Mathias Lasser and Claire Wolf.<br/> Buy an <a href="http://www.latticesemi.com/icestick">iCEstick</a> or <a href="http://www.latticesemi.com/en/Products/DevelopmentBoardsAndKits/iCE40HX8KBreakoutBoard.aspx">iCE40-HX8K Breakout Board</a> from Lattice and see what you can do with the tools and information provided here.</i> </p> diff --git a/icebox/Makefile b/icebox/Makefile index 5088f46..38ec8a4 100644 --- a/icebox/Makefile +++ b/icebox/Makefile @@ -1,5 +1,11 @@ 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 @@ -36,45 +42,66 @@ clean: rm -f icebox.pyc iceboxdb.pyc install: all - mkdir -p $(DESTDIR)$(PREFIX)/share/icebox + mkdir -p $(DESTDIR)$(PREFIX)/share/$(PROGRAM_PREFIX)icebox mkdir -p $(DESTDIR)$(PREFIX)/bin - cp chipdb-384.txt $(DESTDIR)$(PREFIX)/share/icebox/ - cp chipdb-1k.txt $(DESTDIR)$(PREFIX)/share/icebox/ - cp chipdb-8k.txt $(DESTDIR)$(PREFIX)/share/icebox/ - cp chipdb-5k.txt $(DESTDIR)$(PREFIX)/share/icebox/ - cp chipdb-u4k.txt $(DESTDIR)$(PREFIX)/share/icebox/ - cp chipdb-lm4k.txt $(DESTDIR)$(PREFIX)/share/icebox/ - cp icebox.py $(DESTDIR)$(PREFIX)/bin/icebox.py - cp iceboxdb.py $(DESTDIR)$(PREFIX)/bin/iceboxdb.py - cp icebox_chipdb.py $(DESTDIR)$(PREFIX)/bin/icebox_chipdb$(PY_EXE) - cp icebox_diff.py $(DESTDIR)$(PREFIX)/bin/icebox_diff$(PY_EXE) - cp icebox_explain.py $(DESTDIR)$(PREFIX)/bin/icebox_explain$(PY_EXE) - cp icebox_asc2hlc.py $(DESTDIR)$(PREFIX)/bin/icebox_asc2hlc$(PY_EXE) - cp icebox_hlc2asc.py $(DESTDIR)$(PREFIX)/bin/icebox_hlc2asc$(PY_EXE) - cp icebox_colbuf.py $(DESTDIR)$(PREFIX)/bin/icebox_colbuf$(PY_EXE) - cp icebox_html.py $(DESTDIR)$(PREFIX)/bin/icebox_html$(PY_EXE) - cp icebox_maps.py $(DESTDIR)$(PREFIX)/bin/icebox_maps$(PY_EXE) - cp icebox_vlog.py $(DESTDIR)$(PREFIX)/bin/icebox_vlog$(PY_EXE) - cp icebox_stat.py $(DESTDIR)$(PREFIX)/bin/icebox_stat$(PY_EXE) + cp chipdb-384.txt $(DESTDIR)$(PREFIX)/share/$(PROGRAM_PREFIX)icebox/ + cp chipdb-1k.txt $(DESTDIR)$(PREFIX)/share/$(PROGRAM_PREFIX)icebox/ + cp chipdb-8k.txt $(DESTDIR)$(PREFIX)/share/$(PROGRAM_PREFIX)icebox/ + cp chipdb-5k.txt $(DESTDIR)$(PREFIX)/share/$(PROGRAM_PREFIX)icebox/ + cp chipdb-u4k.txt $(DESTDIR)$(PREFIX)/share/$(PROGRAM_PREFIX)icebox/ + cp chipdb-lm4k.txt $(DESTDIR)$(PREFIX)/share/$(PROGRAM_PREFIX)icebox/ + cp icebox.py $(DESTDIR)$(PREFIX)/bin/$(subst -,_,$(PROGRAM_PREFIX))icebox.py + cp iceboxdb.py $(DESTDIR)$(PREFIX)/bin/$(subst -,_,$(PROGRAM_PREFIX))iceboxdb.py + cp icebox_chipdb.py $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_chipdb$(PY_EXE) + cp icebox_diff.py $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_diff$(PY_EXE) + cp icebox_explain.py $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_explain$(PY_EXE) + cp icebox_asc2hlc.py $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_asc2hlc$(PY_EXE) + cp icebox_hlc2asc.py $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_hlc2asc$(PY_EXE) + cp icebox_colbuf.py $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_colbuf$(PY_EXE) + cp icebox_html.py $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_html$(PY_EXE) + 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) uninstall: - rm -f $(DESTDIR)$(PREFIX)/bin/icebox.py - rm -f $(DESTDIR)$(PREFIX)/bin/iceboxdb.py - rm -f $(DESTDIR)$(PREFIX)/bin/icebox_chipdb$(PY_EXE) - rm -f $(DESTDIR)$(PREFIX)/bin/icebox_diff$(PY_EXE) - rm -f $(DESTDIR)$(PREFIX)/bin/icebox_explain$(PY_EXE) - rm -f $(DESTDIR)$(PREFIX)/bin/icebox_asc2hlc$(PY_EXE) - rm -f $(DESTDIR)$(PREFIX)/bin/icebox_hlc2asc$(PY_EXE) - rm -f $(DESTDIR)$(PREFIX)/bin/icebox_colbuf$(PY_EXE) - rm -f $(DESTDIR)$(PREFIX)/bin/icebox_html$(PY_EXE) - rm -f $(DESTDIR)$(PREFIX)/bin/icebox_maps$(PY_EXE) - rm -f $(DESTDIR)$(PREFIX)/bin/icebox_vlog$(PY_EXE) - rm -f $(DESTDIR)$(PREFIX)/bin/icebox_stat$(PY_EXE) - rm -f $(DESTDIR)$(PREFIX)/share/icebox/chipdb-384.txt - rm -f $(DESTDIR)$(PREFIX)/share/icebox/chipdb-1k.txt - rm -f $(DESTDIR)$(PREFIX)/share/icebox/chipdb-8k.txt - rm -f $(DESTDIR)$(PREFIX)/share/icebox/chipdb-lm4k.txt - rm -f $(DESTDIR)$(PREFIX)/share/icebox/chipdb-u4k.txt - -rmdir $(DESTDIR)$(PREFIX)/share/icebox + rm -f $(DESTDIR)$(PREFIX)/bin/$(subst -,_,$(PROGRAM_PREFIX))cebox.py + rm -f $(DESTDIR)$(PREFIX)/bin/$(subst -,_,$(PROGRAM_PREFIX))iceboxdb.py + rm -f $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_chipdb$(PY_EXE) + rm -f $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_diff$(PY_EXE) + rm -f $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_explain$(PY_EXE) + rm -f $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_asc2hlc$(PY_EXE) + rm -f $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_hlc2asc$(PY_EXE) + rm -f $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_colbuf$(PY_EXE) + rm -f $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_html$(PY_EXE) + rm -f $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_maps$(PY_EXE) + rm -f $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_vlog$(PY_EXE) + rm -f $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebox_stat$(PY_EXE) + rm -f $(DESTDIR)$(PREFIX)/share/$(PROGRAM_PREFIX)icebox/chipdb-384.txt + rm -f $(DESTDIR)$(PREFIX)/share/$(PROGRAM_PREFIX)icebox/chipdb-1k.txt + rm -f $(DESTDIR)$(PREFIX)/share/$(PROGRAM_PREFIX)icebox/chipdb-8k.txt + rm -f $(DESTDIR)$(PREFIX)/share/$(PROGRAM_PREFIX)icebox/chipdb-lm4k.txt + rm -f $(DESTDIR)$(PREFIX)/share/$(PROGRAM_PREFIX)icebox/chipdb-u4k.txt + -rmdir $(DESTDIR)$(PREFIX)/share/$(PROGRAM_PREFIX)icebox .PHONY: all check clean install uninstall diff --git a/icebox/icebox.py b/icebox/icebox.py index 0422f13..a7631a2 100644 --- a/icebox/icebox.py +++ b/icebox/icebox.py @@ -1954,7 +1954,8 @@ pllinfo_db = { "PLLOUT_SELECT_B_1": (12, 31, "PLLCONFIG_3"), # Numeric Parameters - "SHIFTREG_DIV_MODE": (12, 31, "PLLCONFIG_4"), + "SHIFTREG_DIV_MODE_0": (12, 31, "PLLCONFIG_4"), + "SHIFTREG_DIV_MODE_1": (14, 31, "PLLCONFIG_6"), "FDA_FEEDBACK_0": (12, 31, "PLLCONFIG_9"), "FDA_FEEDBACK_1": (13, 31, "PLLCONFIG_1"), "FDA_FEEDBACK_2": (13, 31, "PLLCONFIG_2"), @@ -5785,6 +5786,198 @@ extra_cells_db = { }, "u4k" : { + ("SPI", (0, 0, 0)): { + "MCSNO0": (0, 3, "slf_op_1"), + "MCSNO1": (0, 3, "slf_op_3"), + "MCSNO2": (0, 3, "slf_op_6"), + "MCSNO3": (0, 4, "slf_op_0"), + "MCSNOE0": (0, 3, "slf_op_2"), + "MCSNOE1": (0, 3, "slf_op_4"), + "MCSNOE2": (0, 3, "slf_op_7"), + "MCSNOE3": (0, 4, "slf_op_1"), + "MI": (0, 2, "lutff_0/in_1"), + "MO": (0, 2, "slf_op_5"), + "MOE": (0, 2, "slf_op_6"), + "SBACKO": (0, 2, "slf_op_0"), + "SBADRI0": (0, 1, "lutff_1/in_1"), + "SBADRI1": (0, 1, "lutff_2/in_1"), + "SBADRI2": (0, 2, "lutff_0/in_3"), + "SBADRI3": (0, 2, "lutff_1/in_3"), + "SBADRI4": (0, 2, "lutff_2/in_3"), + "SBADRI5": (0, 2, "lutff_3/in_3"), + "SBADRI6": (0, 2, "lutff_4/in_3"), + "SBADRI7": (0, 2, "lutff_5/in_3"), + "SBCLKI": (0, 1, "clk"), + "SBDATI0": (0, 1, "lutff_1/in_3"), + "SBDATI1": (0, 1, "lutff_2/in_3"), + "SBDATI2": (0, 1, "lutff_3/in_3"), + "SBDATI3": (0, 1, "lutff_4/in_3"), + "SBDATI4": (0, 1, "lutff_5/in_3"), + "SBDATI5": (0, 1, "lutff_6/in_3"), + "SBDATI6": (0, 1, "lutff_7/in_3"), + "SBDATI7": (0, 1, "lutff_0/in_1"), + "SBDATO0": (0, 1, "slf_op_0"), + "SBDATO1": (0, 1, "slf_op_1"), + "SBDATO2": (0, 1, "slf_op_2"), + "SBDATO3": (0, 1, "slf_op_3"), + "SBDATO4": (0, 1, "slf_op_4"), + "SBDATO5": (0, 1, "slf_op_5"), + "SBDATO6": (0, 1, "slf_op_6"), + "SBDATO7": (0, 1, "slf_op_7"), + "SBRWI": (0, 1, "lutff_0/in_3"), + "SBSTBI": (0, 2, "lutff_6/in_3"), + "SCKI": (0, 2, "lutff_1/in_1"), + "SCKO": (0, 2, "slf_op_7"), + "SCKOE": (0, 3, "slf_op_0"), + "SCSNI": (0, 2, "lutff_2/in_1"), + "SI": (0, 2, "lutff_7/in_3"), + "SO": (0, 2, "slf_op_3"), + "SOE": (0, 2, "slf_op_4"), + "SPIIRQ": (0, 2, "slf_op_1"), + "SPIWKUP": (0, 2, "slf_op_2"), + "SPI_ENABLE_0": (7, 0, "cbit2usealt_in_0"), + "SPI_ENABLE_1": (6, 0, "cbit2usealt_in_0"), + "SPI_ENABLE_2": (7, 0, "cbit2usealt_in_1"), + "SPI_ENABLE_3": (6, 0, "cbit2usealt_in_1"), + }, + ("SPI", (25, 0, 1)): { + "MCSNO0": (25, 3, "slf_op_1"), + "MCSNO1": (25, 3, "slf_op_3"), + "MCSNO2": (25, 3, "slf_op_6"), + "MCSNO3": (25, 4, "slf_op_0"), + "MCSNOE0": (25, 3, "slf_op_2"), + "MCSNOE1": (25, 3, "slf_op_4"), + "MCSNOE2": (25, 3, "slf_op_7"), + "MCSNOE3": (25, 4, "slf_op_1"), + "MI": (25, 2, "lutff_0/in_1"), + "MO": (25, 2, "slf_op_5"), + "MOE": (25, 2, "slf_op_6"), + "SBACKO": (25, 2, "slf_op_0"), + "SBADRI0": (25, 1, "lutff_1/in_1"), + "SBADRI1": (25, 1, "lutff_2/in_1"), + "SBADRI2": (25, 2, "lutff_0/in_3"), + "SBADRI3": (25, 2, "lutff_1/in_3"), + "SBADRI4": (25, 2, "lutff_2/in_3"), + "SBADRI5": (25, 2, "lutff_3/in_3"), + "SBADRI6": (25, 2, "lutff_4/in_3"), + "SBADRI7": (25, 2, "lutff_5/in_3"), + "SBCLKI": (25, 1, "clk"), + "SBDATI0": (25, 1, "lutff_1/in_3"), + "SBDATI1": (25, 1, "lutff_2/in_3"), + "SBDATI2": (25, 1, "lutff_3/in_3"), + "SBDATI3": (25, 1, "lutff_4/in_3"), + "SBDATI4": (25, 1, "lutff_5/in_3"), + "SBDATI5": (25, 1, "lutff_6/in_3"), + "SBDATI6": (25, 1, "lutff_7/in_3"), + "SBDATI7": (25, 1, "lutff_0/in_1"), + "SBDATO0": (25, 1, "slf_op_0"), + "SBDATO1": (25, 1, "slf_op_1"), + "SBDATO2": (25, 1, "slf_op_2"), + "SBDATO3": (25, 1, "slf_op_3"), + "SBDATO4": (25, 1, "slf_op_4"), + "SBDATO5": (25, 1, "slf_op_5"), + "SBDATO6": (25, 1, "slf_op_6"), + "SBDATO7": (25, 1, "slf_op_7"), + "SBRWI": (25, 1, "lutff_0/in_3"), + "SBSTBI": (25, 2, "lutff_6/in_3"), + "SCKI": (25, 2, "lutff_1/in_1"), + "SCKO": (25, 2, "slf_op_7"), + "SCKOE": (25, 3, "slf_op_0"), + "SCSNI": (25, 2, "lutff_2/in_1"), + "SI": (25, 2, "lutff_7/in_3"), + "SO": (25, 2, "slf_op_3"), + "SOE": (25, 2, "slf_op_4"), + "SPIIRQ": (25, 2, "slf_op_1"), + "SPIWKUP": (25, 2, "slf_op_2"), + "SPI_ENABLE_0": (24, 0, "cbit2usealt_in_0"), + "SPI_ENABLE_1": (24, 0, "cbit2usealt_in_1"), + "SPI_ENABLE_2": (23, 0, "cbit2usealt_in_0"), + "SPI_ENABLE_3": (23, 0, "cbit2usealt_in_1"), + }, + ("I2C", (0, 21, 0)): { + "I2CIRQ": (0, 20, "slf_op_7"), + "I2CWKUP": (0, 19, "slf_op_5"), + "I2C_ENABLE_0": (13, 21, "cbit2usealt_in_0"), + "I2C_ENABLE_1": (12, 21, "cbit2usealt_in_1"), + "SBACKO": (0, 20, "slf_op_6"), + "SBADRI0": (0, 20, "lutff_1/in_0"), + "SBADRI1": (0, 20, "lutff_2/in_0"), + "SBADRI2": (0, 20, "lutff_3/in_0"), + "SBADRI3": (0, 20, "lutff_4/in_0"), + "SBADRI4": (0, 20, "lutff_5/in_0"), + "SBADRI5": (0, 20, "lutff_6/in_0"), + "SBADRI6": (0, 20, "lutff_7/in_0"), + "SBADRI7": (0, 19, "lutff_2/in_0"), + "SBCLKI": (0, 20, "clk"), + "SBDATI0": (0, 19, "lutff_5/in_0"), + "SBDATI1": (0, 19, "lutff_6/in_0"), + "SBDATI2": (0, 19, "lutff_7/in_0"), + "SBDATI3": (0, 20, "lutff_0/in_3"), + "SBDATI4": (0, 20, "lutff_5/in_1"), + "SBDATI5": (0, 20, "lutff_6/in_1"), + "SBDATI6": (0, 20, "lutff_7/in_1"), + "SBDATI7": (0, 20, "lutff_0/in_0"), + "SBDATO0": (0, 19, "slf_op_6"), + "SBDATO1": (0, 19, "slf_op_7"), + "SBDATO2": (0, 20, "slf_op_0"), + "SBDATO3": (0, 20, "slf_op_1"), + "SBDATO4": (0, 20, "slf_op_2"), + "SBDATO5": (0, 20, "slf_op_3"), + "SBDATO6": (0, 20, "slf_op_4"), + "SBDATO7": (0, 20, "slf_op_5"), + "SBRWI": (0, 19, "lutff_4/in_0"), + "SBSTBI": (0, 19, "lutff_3/in_0"), + "SCLI": (0, 19, "lutff_2/in_1"), + "SCLO": (0, 19, "slf_op_3"), + "SCLOE": (0, 19, "slf_op_4"), + "SDAI": (0, 19, "lutff_1/in_1"), + "SDAO": (0, 19, "slf_op_1"), + "SDAOE": (0, 19, "slf_op_2"), + "SDA_INPUT_DELAYED": (12, 21, "SDA_input_delay"), + "SDA_OUTPUT_DELAYED": (12, 21, "SDA_output_delay"), + }, + ("I2C", (25, 21, 0)): { + "I2CIRQ": (25, 20, "slf_op_7"), + "I2CWKUP": (25, 19, "slf_op_5"), + "I2C_ENABLE_0": (19, 21, "cbit2usealt_in_1"), + "I2C_ENABLE_1": (19, 21, "cbit2usealt_in_0"), + "SBACKO": (25, 20, "slf_op_6"), + "SBADRI0": (25, 20, "lutff_1/in_0"), + "SBADRI1": (25, 20, "lutff_2/in_0"), + "SBADRI2": (25, 20, "lutff_3/in_0"), + "SBADRI3": (25, 20, "lutff_4/in_0"), + "SBADRI4": (25, 20, "lutff_5/in_0"), + "SBADRI5": (25, 20, "lutff_6/in_0"), + "SBADRI6": (25, 20, "lutff_7/in_0"), + "SBADRI7": (25, 19, "lutff_2/in_0"), + "SBCLKI": (25, 20, "clk"), + "SBDATI0": (25, 19, "lutff_5/in_0"), + "SBDATI1": (25, 19, "lutff_6/in_0"), + "SBDATI2": (25, 19, "lutff_7/in_0"), + "SBDATI3": (25, 20, "lutff_0/in_3"), + "SBDATI4": (25, 20, "lutff_5/in_1"), + "SBDATI5": (25, 20, "lutff_6/in_1"), + "SBDATI6": (25, 20, "lutff_7/in_1"), + "SBDATI7": (25, 20, "lutff_0/in_0"), + "SBDATO0": (25, 19, "slf_op_6"), + "SBDATO1": (25, 19, "slf_op_7"), + "SBDATO2": (25, 20, "slf_op_0"), + "SBDATO3": (25, 20, "slf_op_1"), + "SBDATO4": (25, 20, "slf_op_2"), + "SBDATO5": (25, 20, "slf_op_3"), + "SBDATO6": (25, 20, "slf_op_4"), + "SBDATO7": (25, 20, "slf_op_5"), + "SBRWI": (25, 19, "lutff_4/in_0"), + "SBSTBI": (25, 19, "lutff_3/in_0"), + "SCLI": (25, 19, "lutff_2/in_1"), + "SCLO": (25, 19, "slf_op_3"), + "SCLOE": (25, 19, "slf_op_4"), + "SDAI": (25, 19, "lutff_1/in_1"), + "SDAO": (25, 19, "slf_op_1"), + "SDAOE": (25, 19, "slf_op_2"), + "SDA_INPUT_DELAYED": (19, 21, "SDA_input_delay"), + "SDA_OUTPUT_DELAYED": (19, 21, "SDA_output_delay"), + }, ("HFOSC", (0, 21, 1)) : { "CLKHFPU": (0, 19, "lutff_0/in_1"), "CLKHFEN": (0, 19, "lutff_7/in_3"), diff --git a/icebox/icebox_asc2hlc.py b/icebox/icebox_asc2hlc.py index 003106f..8e64997 100755 --- a/icebox/icebox_asc2hlc.py +++ b/icebox/icebox_asc2hlc.py @@ -1068,7 +1068,7 @@ def main(): except getopt.GetoptError as e: sys.stderr.write("%s: %s\n" % (program_short_name, e.msg)) sys.stderr.write("Try `%s --help' for more information.\n" - % sys.argv[0]) + % program_short_name) sys.exit(1) for opt, arg in opts: @@ -1085,7 +1085,7 @@ Usage: %s [OPTION]... FILE If you have a bug report, please file an issue on github: https://github.com/rlutz/icestorm/issues -""" % sys.argv[0]) +""" % program_short_name) sys.exit(0) if opt == '--version': @@ -1113,13 +1113,13 @@ GNU General Public License for more details. if not args: sys.stderr.write("%s: missing argument\n" % (program_short_name)) sys.stderr.write("Try `%s --help' for more information.\n" - % sys.argv[0]) + % program_short_name) sys.exit(1) if len(args) != 1: sys.stderr.write("%s: too many arguments\n" % (program_short_name)) sys.stderr.write("Try `%s --help' for more information.\n" - % sys.argv[0]) + % program_short_name) sys.exit(1) ic = icebox.iceconfig() diff --git a/icebox/icebox_chipdb.py b/icebox/icebox_chipdb.py index 9c8d6df..722ec37 100755 --- a/icebox/icebox_chipdb.py +++ b/icebox/icebox_chipdb.py @@ -16,7 +16,7 @@ # import icebox -import getopt, sys, re +import getopt, sys, re, os mode_384 = False mode_lm4k = False @@ -26,7 +26,7 @@ mode_8k = False def usage(): print(""" -Usage: icebox_chipdb [options] [bitmap.asc] +Usage: %s [options] [bitmap.asc] -3 create chipdb for 384 device @@ -42,7 +42,7 @@ Usage: icebox_chipdb [options] [bitmap.asc] -u create chipdb for u4k device -""") +""" % os.path.basename(sys.argv[0])) sys.exit(0) try: diff --git a/icebox/icebox_colbuf.py b/icebox/icebox_colbuf.py index ec6843e..3003a90 100755 --- a/icebox/icebox_colbuf.py +++ b/icebox/icebox_colbuf.py @@ -17,21 +17,21 @@ import icebox from icebox import re_match_cached -import getopt, sys, re +import getopt, sys, re, os check_mode = False fixup_mode = False def usage(): print(""" -Usage: icebox_colbuf [options] [input.asc [output.asc]] +Usage: %s [options] [input.asc [output.asc]] -c check colbuf bits -f fix colbuf bits -""") +""" % os.path.basename(sys.argv[0])) sys.exit(1) try: diff --git a/icebox/icebox_diff.py b/icebox/icebox_diff.py index 5252fc4..f433bcf 100755 --- a/icebox/icebox_diff.py +++ b/icebox/icebox_diff.py @@ -17,13 +17,13 @@ import icebox from icebox import re_match_cached -import sys +import sys, os import re if len(sys.argv) != 3: print(""" -Usage: icebox_diff bitmap1.asc bitmap2.asc -""") +Usage: %s bitmap1.asc bitmap2.asc +""" % os.path.basename(sys.argv[0])) sys.exit(0) print("Reading file '%s'.." % sys.argv[1]) diff --git a/icebox/icebox_explain.py b/icebox/icebox_explain.py index f843c09..25061ab 100755 --- a/icebox/icebox_explain.py +++ b/icebox/icebox_explain.py @@ -17,7 +17,7 @@ import icebox from icebox import re_match_cached, re_search_cached -import getopt, sys, re +import getopt, sys, re, os print_bits = False print_map = False @@ -26,7 +26,7 @@ print_all = False def usage(): print(""" -Usage: icebox_explain [options] [bitmap.asc] +Usage: %s [options] [bitmap.asc] -b print config bit names for each config statement @@ -39,7 +39,7 @@ Usage: icebox_explain [options] [bitmap.asc] -t '<x-coordinate> <y-coordinate>' print only the specified tile -""") +""" % os.path.basename(sys.argv[0])) sys.exit(0) try: diff --git a/icebox/icebox_hlc2asc.py b/icebox/icebox_hlc2asc.py index a95f610..59d2f69 100755 --- a/icebox/icebox_hlc2asc.py +++ b/icebox/icebox_hlc2asc.py @@ -1147,7 +1147,7 @@ def main(): except getopt.GetoptError as e: sys.stderr.write("%s: %s\n" % (program_short_name, e.msg)) sys.stderr.write("Try `%s --help' for more information.\n" - % sys.argv[0]) + % program_short_name) sys.exit(1) for opt, arg in opts: @@ -1161,7 +1161,7 @@ Usage: %s [OPTION]... FILE If you have a bug report, please file an issue on github: https://github.com/rlutz/icestorm/issues -""" % sys.argv[0]) +""" % program_short_name) sys.exit(0) if opt == '--version': @@ -1184,13 +1184,13 @@ GNU General Public License for more details. if not args: sys.stderr.write("%s: missing argument\n" % (program_short_name)) sys.stderr.write("Try `%s --help' for more information.\n" - % sys.argv[0]) + % program_short_name) sys.exit(1) if len(args) != 1: sys.stderr.write("%s: too many arguments\n" % (program_short_name)) sys.stderr.write("Try `%s --help' for more information.\n" - % sys.argv[0]) + % program_short_name) sys.exit(1) if args[0] == '-': diff --git a/icebox/icebox_html.py b/icebox/icebox_html.py index b710f61..3785a45 100755 --- a/icebox/icebox_html.py +++ b/icebox/icebox_html.py @@ -27,7 +27,7 @@ mode384 = False tx, ty = 0, 0 def usage(): - print("Usage: %s [options]" % sys.argv[0]) + print("Usage: %s [options]" % os.path.basename(sys.argv[0])) print(" -x tile_x_coordinate") print(" -y tile_y_coordinate") print(" -d outdir") diff --git a/icebox/icebox_maps.py b/icebox/icebox_maps.py index 35ff316..062335d 100755 --- a/icebox/icebox_maps.py +++ b/icebox/icebox_maps.py @@ -17,20 +17,21 @@ import icebox from icebox import re_match_cached -import getopt, sys, re +import getopt, sys, re, os mode = None def usage(): + program_short_name = os.path.basename(sys.argv[0]) print("Usage:") - print(" icebox_maps -m bitmaps") - print(" icebox_maps -m io_tile_nets_l") - print(" icebox_maps -m io_tile_nets_r") - print(" icebox_maps -m io_tile_nets_t") - print(" icebox_maps -m io_tile_nets_b") - print(" icebox_maps -m logic_tile_nets") - print(" icebox_maps -m ramb_tile_nets") - print(" icebox_maps -m ramt_tile_nets") + print(" %s -m bitmaps" % program_short_name) + print(" %s -m io_tile_nets_l" % program_short_name) + print(" %s -m io_tile_nets_r" % program_short_name) + print(" %s -m io_tile_nets_t" % program_short_name) + print(" %s -m io_tile_nets_b" % program_short_name) + print(" %s -m logic_tile_nets" % program_short_name) + print(" %s -m ramb_tile_nets" % program_short_name) + print(" %s -m ramt_tile_nets" % program_short_name) sys.exit(0) try: diff --git a/icebox/icebox_stat.py b/icebox/icebox_stat.py index ec404fb..5752267 100755 --- a/icebox/icebox_stat.py +++ b/icebox/icebox_stat.py @@ -17,18 +17,18 @@ import icebox from icebox import re_match_cached -import getopt, sys, re +import getopt, sys, re, os verbose = False def usage(): print(""" -Usage: icebox_stat [options] [bitmap.asc] +Usage: %s [options] [bitmap.asc] -v verbose output -""") +""" % os.path.basename(sys.argv[0])) sys.exit(0) try: diff --git a/icebox/icebox_vlog.py b/icebox/icebox_vlog.py index a2c7950..74ac3d3 100755 --- a/icebox/icebox_vlog.py +++ b/icebox/icebox_vlog.py @@ -17,7 +17,7 @@ import icebox from icebox import re_match_cached, re_sub_cached, re_search_cached -import getopt, sys, re +import getopt, sys, re, os strip_comments = False strip_interconn = False @@ -34,7 +34,7 @@ modname = "chip" def usage(): print(""" -Usage: icebox_vlog [options] [bitmap.asc] +Usage: %s [options] [bitmap.asc] -s strip comments from output @@ -70,7 +70,7 @@ Usage: icebox_vlog [options] [bitmap.asc] -D enable exactly-one-driver checks -""") +""" % os.path.basename(sys.argv[0])) sys.exit(0) try: @@ -477,7 +477,10 @@ for pllid in ic.pll_list(): if plltype != "100": text_func.append(" .PLLOUT_SELECT_PORTA(\"%s\")," % get_pll_outsel(pllinfo, "PLLOUT_SELECT_A")) text_func.append(" .PLLOUT_SELECT_PORTB(\"%s\")," % get_pll_outsel(pllinfo, "PLLOUT_SELECT_B")) - text_func.append(" .SHIFTREG_DIV_MODE(1'b%s)," % get_pll_bit(pllinfo, "SHIFTREG_DIV_MODE")) + if ic.device == "5k": + text_func.append(" .SHIFTREG_DIV_MODE(2'b%s)," % get_pll_bits(pllinfo, "SHIFTREG_DIV_MODE", 2)) + else: + text_func.append(" .SHIFTREG_DIV_MODE(1'b%s)," % get_pll_bit(pllinfo, "SHIFTREG_DIV_MODE")) text_func.append(" .FDA_FEEDBACK(4'b%s)," % get_pll_bits(pllinfo, "FDA_FEEDBACK", 4)) text_func.append(" .FDA_RELATIVE(4'b%s)," % get_pll_bits(pllinfo, "FDA_RELATIVE", 4)) text_func.append(" .DIVR(4'b%s)," % get_pll_bits(pllinfo, "DIVR", 4)) 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/icebram/Makefile b/icebram/Makefile index 34801da..219be59 100644 --- a/icebram/Makefile +++ b/icebram/Makefile @@ -4,24 +4,24 @@ ifeq ($(STATIC),1) LDFLAGS += -static endif -all: icebram$(EXE) +all: $(PROGRAM_PREFIX)icebram$(EXE) -icebram$(EXE): icebram.o +$(PROGRAM_PREFIX)icebram$(EXE): icebram.o $(CXX) -o $@ $(LDFLAGS) $^ $(LDLIBS) -test: icebram +test: $(PROGRAM_PREFIX)icebram bash rundemo.sh install: all mkdir -p $(DESTDIR)$(PREFIX)/bin - cp icebram$(EXE) $(DESTDIR)$(PREFIX)/bin/icebram$(EXE) + cp $(PROGRAM_PREFIX)icebram$(EXE) $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebram$(EXE) uninstall: - rm -f $(DESTDIR)$(PREFIX)/bin/icebram$(EXE) + rm -f $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icebram$(EXE) clean: - rm -f icebram$(EXE) - rm -f icebram.exe + rm -f $(PROGRAM_PREFIX)icebram$(EXE) + rm -f $(PROGRAM_PREFIX)icebram.exe rm -f demo.* demo_*.* rm -f *.o *.d diff --git a/icebram/icebram.cc b/icebram/icebram.cc index f585fcf..aacf00c 100644 --- a/icebram/icebram.cc +++ b/icebram/icebram.cc @@ -131,7 +131,7 @@ int main(int argc, char **argv) bool verbose = false; bool generate = false; bool seed = false; - uint32_t seed_nr = getpid(); + uint32_t seed_opt = 0; int opt; while ((opt = getopt(argc, argv, "vgs:")) != -1) @@ -146,7 +146,7 @@ int main(int argc, char **argv) break; case 's': seed = true; - seed_nr = atoi(optarg); + seed_opt = atoi(optarg); break; default: help(argv[0]); @@ -172,7 +172,21 @@ int main(int argc, char **argv) } if (verbose && seed) - fprintf(stderr, "Seed: %d\n", seed_nr); + fprintf(stderr, "Seed: %d\n", seed_opt); + + // If -s is provided: seed with the given value. + // If -s is not provided: seed with the PID and current time, which are unlikely + // to repeat simultaneously. + uint32_t seed_nr; + if (!seed) { +#if defined(__wasm) + seed_nr = 0; +#else + seed_nr = getpid(); +#endif + } else { + seed_nr = seed_opt; + } x = uint64_t(seed_nr) << 32; x ^= uint64_t(depth) << 16; @@ -182,16 +196,12 @@ int main(int argc, char **argv) xorshift64star(); xorshift64star(); - if (!seed){ + if (!seed) { struct timeval tv; gettimeofday(&tv, NULL); x ^= uint64_t(tv.tv_sec) << 20; x ^= uint64_t(tv.tv_usec); } - else { - x ^= uint64_t(seed) << 20; - x ^= uint64_t(seed); - } xorshift64star(); xorshift64star(); diff --git a/icefuzz/tests/ip/trace_ip_u4k.py b/icefuzz/tests/ip/trace_ip_u4k.py new file mode 100755 index 0000000..8e94faf --- /dev/null +++ b/icefuzz/tests/ip/trace_ip_u4k.py @@ -0,0 +1,347 @@ +#!/usr/bin/env python3 + +import os, sys, re + +device = "u4k" + +pins = "2 3 4 6 9 10 11 12 13 14 15 16 17 18 19 20 21 23 25 26 27 28 31 32 34 35 36 37 38 42 43 44 45 46 47 48".split() +#up5k +# pins = "2 3 4 6 9 10 11 12 13 18 19 20 21 25 26 27 28 31 32 34 35 36 37 38 42 43 44 45 46 47 48".split() + +# This is the master IP reverse engineering script for three similar IPs: I2C, SPI +ip_types = ["I2C", "SPI"] +ip_locs = { } +ip_locs["I2C"] = [(0, 21, 0), (25, 21, 0)] +ip_locs["SPI"] = [(0, 0, 0), (25, 0, 1)] +#spram_locs = [(0, 0, 1)] +ip_data = { } + +#up5k +# ip_types = ["I2C", "SPI", "LEDDA_IP"] +# ip_locs = { } +# ip_locs["I2C"] = [(0, 31, 0), (25, 31, 0)] +# ip_locs["SPI"] = [(0, 0, 0), (25, 0, 1)] +# ip_locs["LEDDA_IP"] = [(0, 31, 2)] +# #spram_locs = [(0, 0, 1)] +# ip_data = { } + +#signals[x][0] -> inputs, signals[x][1] ->outputs +ip_signals = {} +ip_signals["I2C"] = [["SBCLKI", "SBRWI", "SBSTBI", "SCLI", "SDAI"], + ["SBACKO", "I2CIRQ", "I2CWKUP", "SCLO", "SCLOE", "SDAO", "SDAOE"]] +ip_signals["SPI"] = [["SBCLKI", "SBRWI", "SBSTBI", "MI", "SI", "SCKI", "SCSNI"], + ["SBACKO", "SPIIRQ", "SPIWKUP", "SO", "SOE", "MO", "MOE", "SCKO", "SCKOE"]] + +fixed_cbits = {} + +fixed_cbits[("I2C", (0, 21, 0))] = ["BUS_ADDR74_0", "I2C_SLAVE_INIT_ADDR_0"] +fixed_cbits[("I2C", (25, 21, 0))] = ["BUS_ADDR74_0", "BUS_ADDR74_1", "I2C_SLAVE_INIT_ADDR_1"] + +fixed_cbits[("SPI", (0, 0, 0))] = [] +fixed_cbits[("SPI", (25, 0, 1))] = ["BUS_ADDR74_1"] # WARNING: this is documented as BUS_ADDR74_0, but this is wrong and will cause icecube to fail. May be the same across devices + +#up5k +# fixed_cbits[("I2C", (0, 31, 0))] = ["BUS_ADDR74_0", "I2C_SLAVE_INIT_ADDR_0"] +# fixed_cbits[("I2C", (25, 31, 0))] = ["BUS_ADDR74_0", "BUS_ADDR74_1", "I2C_SLAVE_INIT_ADDR_1"] + +# fixed_cbits[("SPI", (0, 10, 0))] = [] +# fixed_cbits[("SPI", (25, 10, 1))] = ["BUS_ADDR74_1"] # WARNING: this is documented as BUS_ADDR74_0, but this is wrong and will cause icecube to fail. May be the same across devices + +fuzz_cbits = {} +fuzz_cbits["I2C"] = ["SDA_INPUT_DELAYED", "SDA_OUTPUT_DELAYED"] + +# Don't add slave address to the list, despite confusing primitive declaration, +# it's only set in registers not the bitstream + +#for i in range(2, 10): + #fuzz_cbits["I2C"].append("I2C_SLAVE_INIT_ADDR_%d" % i) + +for i in range(8): + ip_signals["I2C"][0].append("SBADRI%d" % i) + ip_signals["SPI"][0].append("SBADRI%d" % i) + +for i in range(8): + ip_signals["I2C"][0].append("SBDATI%d" % i) + ip_signals["SPI"][0].append("SBDATI%d" % i) + +for i in range(8): + ip_signals["I2C"][1].append("SBDATO%d" % i) + ip_signals["SPI"][1].append("SBDATO%d" % i) + +for i in range(4): + ip_signals["SPI"][1].append("MCSNO%d" % i) + ip_signals["SPI"][1].append("MCSNOE%d" % i) + +fuzz_net_options = {} +fuzz_net_options["I2C"] = ["SBADRI", "SBDATI", "SBDATO"] +fuzz_net_options["SPI"] = ["SBADRI", "SBDATI", "SBDATO", "MCSN"] + +available_cbits = {} +available_cbits["I2C"] = [("BUS_ADDR74", 4), ("I2C_SLAVE_INIT_ADDR", 10)] +available_cbits["SPI"] = [("BUS_ADDR74", 4)] + +# Return a param value in "Lattice style" +def get_param_value(param_size, param_name, set_cbits): + val = "\"0b" + for i in range(param_size): + if param_name + "_" + str((param_size - 1) - i) in set_cbits: + val += "1" + else: + val += "0" + val += "\"" + return val + +# Build the output files for a given IP and config, returning +# the pin2net map +def make_ip(ip_type, ip_loc, fuzz_opt, set_cbits): + used_inputs = [ ] + used_outputs = [ ] + for insig in ip_signals[ip_type][0]: + ignore = False + for o in fuzz_net_options[ip_type]: + if o != fuzz_opt and insig.startswith(o): + ignore = True + if not ignore: + used_inputs.append(insig) + for outsig in ip_signals[ip_type][1]: + ignore = False + for o in fuzz_net_options[ip_type]: + if o != fuzz_opt and outsig.startswith(o): + ignore = True + if not ignore: + used_outputs.append(outsig) + all_sigs = used_inputs + used_outputs + all_cbits = set() + all_cbits.update(set_cbits) + if (ip_type, ip_loc) in fixed_cbits: + all_cbits.update(fixed_cbits[(ip_type, ip_loc)]) + with open("./work_ip/ip.v", "w") as f: + print("module top(", file=f) + for s in used_inputs: + print("input %s," % s, file=f) + for s in used_outputs[:-1]: + print("output %s," % s, file=f) + print("output %s);" % used_outputs[-1], file=f) + print("SB_%s" % ip_type, file=f) + if ip_type in available_cbits: + print("\t#(", file=f) + for p in available_cbits[ip_type]: + name, width = p + comma = "," if p != available_cbits[ip_type][-1] else "" + print("\t\t.%s(%s)%s" % (name, get_param_value(width, name, all_cbits), comma), file=f) + print("\t)", file=f) + print("\tip_inst (",file=f) + for sig in all_sigs[:-1]: + print("\t\t.%s(%s)," % (sig, sig), file=f) + print("\t\t.%s(%s)" % (all_sigs[-1], all_sigs[-1]), file=f) + print("\t)", file=f) + if "SDA_INPUT_DELAYED" in all_cbits: + print("\t/* synthesis SDA_INPUT_DELAYED=1 */", file=f) + else: + print("\t/* synthesis SDA_INPUT_DELAYED=0 */", file=f) + if "SDA_OUTPUT_DELAYED" in all_cbits: + print("\t/* synthesis SDA_OUTPUT_DELAYED=1 */", file=f) + else: + print("\t/* synthesis SDA_OUTPUT_DELAYED=0 */", file=f) + print(";", file=f) + print("endmodule", file=f) + pin2net = {} + with open("./work_ip/ip.pcf","w") as f: + temp_pins = list(pins) + for sig in all_sigs: + if len(temp_pins) == 0: + sys.stderr.write("ERROR: no remaining pins to alloc") + sys.exit(1) + pin = temp_pins.pop() + pin2net[pin] = sig + print("set_io %s %s" % (sig, pin), file=f) + print("set_location ip_inst %d %d %d" % ip_loc, file=f) + return pin2net + +def check_for_pin_assignment(pin): + out = None + with open("./work_ip/ip.vlog", "r") as f: + for l in f: + if l.startswith("assign pin_{}".format(pin)): + rhs = l.split("=") + o_cen = rhs[1].split(" ")[1] + out = rhs[1].split(" ")[3] + + return out + +#Parse the output of an icebox vlog file to determine connectivity +def parse_vlog(f, pin2net, net_map): + wires_to_check = dict() + + current_net = None + + for line in f: + if line == "\n": + current_net = None + + m = re.match(r"wire ([a-zA-Z0-9_]+);", line) + if m: + net = m.group(1) + mp = re.match(r"pin_([a-zA-Z0-9]+)", net) + if mp: + pin = mp.group(1) + if pin in pin2net: + current_net = pin2net[pin] + else: + current_net = None + + #search for assignment + data_input = check_for_pin_assignment(pin) + if data_input: + wires_to_check[data_input] = pin + + else: + current_net = None + elif current_net is not None: + m = re.match(r"// \((\d+), (\d+), '([a-zA-Z0-9_/]+)'\)", line) + if m: + x = int(m.group(1)) + y = int(m.group(2)) + net = m.group(3) + if not (net.startswith("sp") or net.startswith("glb") or net.startswith("neigh") or net.startswith("io") or net.startswith("local") or net.startswith("fabout")): + net_map[current_net].add((x, y, net)) + + f.seek(0) + for line in f: + if line == "\n": + current_net = None + + m = re.match(r"wire ([a-zA-Z0-9]+);", line) + if m: + net = m.group(1) + if net in wires_to_check: + pin = wires_to_check[net] + if pin in pin2net: + current_net = pin2net[pin] + else: + current_net = None + else: + current_net = None + elif current_net is not None: + m = re.match(r"// \((\d+), (\d+), '([a-zA-Z0-9_/]+)'\)", line) + if m: + x = int(m.group(1)) + y = int(m.group(2)) + net = m.group(3) + if not (net.startswith("sp") or net.startswith("glb") or net.startswith("neigh") or net.startswith("io") or net.startswith("local") or net.startswith("fabout")): + net_map[current_net].add((x, y, net)) + +def parse_exp(f): + current_x = 0 + current_y = 0 + bits = set() + for line in f: + splitline = line.split(' ') + if splitline[0].endswith("_tile"): + current_x = int(splitline[1]) + current_y = int(splitline[2]) + elif splitline[0] == "IpConfig": + bits.add((current_x, current_y, splitline[1].strip())) + return bits + +if not os.path.exists("./work_ip"): + os.mkdir("./work_ip") +for ip in ip_types: + ip_data[ip] = {} + for loc in ip_locs[ip]: + x, y, z = loc + net_cbit_map = {} + init_cbits = [] + for sig in ip_signals[ip][0]: + net_cbit_map[sig] = set() + for sig in ip_signals[ip][1]: + net_cbit_map[sig] = set() + first = True + for state in ["FUZZ_NETS", "FUZZ_CBITS"]: + fuzz_options = None + if state == "FUZZ_NETS": + fuzz_options = fuzz_net_options[ip] + else: + if ip in fuzz_cbits: + fuzz_options = fuzz_cbits[ip] + else: + fuzz_options = [] + for n in fuzz_options: + # if n != "SBDATO": + # continue + print("Fuzzing %s (%d, %d, %d) %s" % (ip, x, y, z, n)) + fuzz_nets = fuzz_net_options[ip][0] + if state == "FUZZ_NETS": + fuzz_nets = n + set_cbits = set() + if state == "FUZZ_CBITS": + set_cbits.add(n) + pin2net = make_ip(ip, loc, fuzz_nets, set_cbits) + retval = os.system("bash ../../icecube.sh -" + device + " ./work_ip/ip.v > ./work_ip/icecube.log 2>&1") + if retval != 0: + sys.stderr.write('ERROR: icecube returned non-zero error code\n') + sys.exit(1) + retval = os.system("../../../icebox/icebox_explain.py ./work_ip/ip.asc > ./work_ip/ip.exp") + if retval != 0: + sys.stderr.write('ERROR: icebox_explain returned non-zero error code\n') + sys.exit(1) + retval = os.system("../../../icebox/icebox_vlog.py -l ./work_ip/ip.asc > ./work_ip/ip.vlog") + if retval != 0: + sys.stderr.write('ERROR: icebox_vlog returned non-zero error code\n') + sys.exit(1) + with open("./work_ip/ip.vlog", "r") as f: + parse_vlog(f, pin2net, net_cbit_map) + bits = [] + with open("./work_ip/ip.exp", "r") as f: + bits = parse_exp(f) + if first: + idx = 0 + for bit in bits: + init_cbits.append(bit) + if len(bits) == 1: + net_cbit_map[ip + "_ENABLE"] = [bit] + else: + net_cbit_map[ip + "_ENABLE_" + str(idx)] = [bit] + idx += 1 + for bit in init_cbits: + if bit not in bits: + bx, by, bn = bit + print('WARNING: while fuzzing %s (%d, %d, %d) bit (%d, %d, %s) has unknown function (not always set)' % + (ip, x, y, z, bx, by, bn)) + new_bits = [] + for bit in bits: + if bit not in init_cbits: + new_bits.append(bit) + if state == "FUZZ_NETS" and len(new_bits) != 0: + for bit in new_bits: + bx, by, bn = bit + print('WARNING: while fuzzing %s (%d, %d, %d) bit (%d, %d, %s) has unknown function (not always set)' % + (ip, x, y, z, bx, by, bn)) + elif state == "FUZZ_CBITS": + if len(new_bits) == 0: + print('WARNING: while fuzzing %s (%d, %d, %d) param %s causes no change' % + (ip, x, y, z, n)) + else: + idx = 0 + for bit in new_bits: + if len(new_bits) == 1: + net_cbit_map[n] = [bit] + else: + net_cbit_map[n + "_" + str(idx)] = [bit] + idx += 1 + first = False + # if n == "SBDATO": + # exit() + ip_data[ip][loc] = net_cbit_map + + with open(device + "_" + ip + "_data.txt", "w") as f: + for loc in ip_data[ip]: + x, y, z = loc + print("\t(\"%s\", (%d, %d, %d)): {" % (ip, x, y, z), file=f) + data = ip_data[ip][loc] + for net in sorted(data): + cnets = [] + for cnet in data[net]: + cnets.append("(%d, %d, \"%s\")" % cnet) + print("\t\t%s %s, " % (("\"" + net.replace("[","_").replace("]","") + "\":").ljust(24), " ".join(cnets)), file=f) + print("\t},", file=f) diff --git a/icefuzz/tests/ip/u4k_I2C_data.txt b/icefuzz/tests/ip/u4k_I2C_data.txt new file mode 100644 index 0000000..6338608 --- /dev/null +++ b/icefuzz/tests/ip/u4k_I2C_data.txt @@ -0,0 +1,84 @@ + ("I2C", (0, 21, 0)): { + "I2CIRQ": (0, 20, "slf_op_7"), + "I2CWKUP": (0, 19, "slf_op_5"), + "I2C_ENABLE_0": (13, 21, "cbit2usealt_in_0"), + "I2C_ENABLE_1": (12, 21, "cbit2usealt_in_1"), + "SBACKO": (0, 20, "slf_op_6"), + "SBADRI0": (0, 20, "lutff_1/in_0"), + "SBADRI1": (0, 20, "lutff_2/in_0"), + "SBADRI2": (0, 20, "lutff_3/in_0"), + "SBADRI3": (0, 20, "lutff_4/in_0"), + "SBADRI4": (0, 20, "lutff_5/in_0"), + "SBADRI5": (0, 20, "lutff_6/in_0"), + "SBADRI6": (0, 20, "lutff_7/in_0"), + "SBADRI7": (0, 19, "lutff_2/in_0"), + "SBCLKI": (0, 20, "clk"), + "SBDATI0": (0, 19, "lutff_5/in_0"), + "SBDATI1": (0, 19, "lutff_6/in_0"), + "SBDATI2": (0, 19, "lutff_7/in_0"), + "SBDATI3": (0, 20, "lutff_0/in_3"), + "SBDATI4": (0, 20, "lutff_5/in_1"), + "SBDATI5": (0, 20, "lutff_6/in_1"), + "SBDATI6": (0, 20, "lutff_7/in_1"), + "SBDATI7": (0, 20, "lutff_0/in_0"), + "SBDATO0": (0, 19, "slf_op_6"), + "SBDATO1": (0, 19, "slf_op_7"), + "SBDATO2": (0, 20, "slf_op_0"), + "SBDATO3": (0, 20, "slf_op_1"), + "SBDATO4": (0, 20, "slf_op_2"), + "SBDATO5": (0, 20, "slf_op_3"), + "SBDATO6": (0, 20, "slf_op_4"), + "SBDATO7": (0, 20, "slf_op_5"), + "SBRWI": (0, 19, "lutff_4/in_0"), + "SBSTBI": (0, 19, "lutff_3/in_0"), + "SCLI": (0, 19, "lutff_2/in_1"), + "SCLO": (0, 19, "slf_op_3"), + "SCLOE": (0, 19, "slf_op_4"), + "SDAI": (0, 19, "lutff_1/in_1"), + "SDAO": (0, 19, "slf_op_1"), + "SDAOE": (0, 19, "slf_op_2"), + "SDA_INPUT_DELAYED": (12, 21, "SDA_input_delay"), + "SDA_OUTPUT_DELAYED": (12, 21, "SDA_output_delay"), + }, + ("I2C", (25, 21, 0)): { + "I2CIRQ": (25, 20, "slf_op_7"), + "I2CWKUP": (25, 19, "slf_op_5"), + "I2C_ENABLE_0": (19, 21, "cbit2usealt_in_1"), + "I2C_ENABLE_1": (19, 21, "cbit2usealt_in_0"), + "SBACKO": (25, 20, "slf_op_6"), + "SBADRI0": (25, 20, "lutff_1/in_0"), + "SBADRI1": (25, 20, "lutff_2/in_0"), + "SBADRI2": (25, 20, "lutff_3/in_0"), + "SBADRI3": (25, 20, "lutff_4/in_0"), + "SBADRI4": (25, 20, "lutff_5/in_0"), + "SBADRI5": (25, 20, "lutff_6/in_0"), + "SBADRI6": (25, 20, "lutff_7/in_0"), + "SBADRI7": (25, 19, "lutff_2/in_0"), + "SBCLKI": (25, 20, "clk"), + "SBDATI0": (25, 19, "lutff_5/in_0"), + "SBDATI1": (25, 19, "lutff_6/in_0"), + "SBDATI2": (25, 19, "lutff_7/in_0"), + "SBDATI3": (25, 20, "lutff_0/in_3"), + "SBDATI4": (25, 20, "lutff_5/in_1"), + "SBDATI5": (25, 20, "lutff_6/in_1"), + "SBDATI6": (25, 20, "lutff_7/in_1"), + "SBDATI7": (25, 20, "lutff_0/in_0"), + "SBDATO0": (25, 19, "slf_op_6"), + "SBDATO1": (25, 19, "slf_op_7"), + "SBDATO2": (25, 20, "slf_op_0"), + "SBDATO3": (25, 20, "slf_op_1"), + "SBDATO4": (25, 20, "slf_op_2"), + "SBDATO5": (25, 20, "slf_op_3"), + "SBDATO6": (25, 20, "slf_op_4"), + "SBDATO7": (25, 20, "slf_op_5"), + "SBRWI": (25, 19, "lutff_4/in_0"), + "SBSTBI": (25, 19, "lutff_3/in_0"), + "SCLI": (25, 19, "lutff_2/in_1"), + "SCLO": (25, 19, "slf_op_3"), + "SCLOE": (25, 19, "slf_op_4"), + "SDAI": (25, 19, "lutff_1/in_1"), + "SDAO": (25, 19, "slf_op_1"), + "SDAOE": (25, 19, "slf_op_2"), + "SDA_INPUT_DELAYED": (19, 21, "SDA_input_delay"), + "SDA_OUTPUT_DELAYED": (19, 21, "SDA_output_delay"), + }, diff --git a/icefuzz/tests/ip/u4k_SPI_data.txt b/icefuzz/tests/ip/u4k_SPI_data.txt new file mode 100644 index 0000000..b6463a7 --- /dev/null +++ b/icefuzz/tests/ip/u4k_SPI_data.txt @@ -0,0 +1,108 @@ + ("SPI", (0, 0, 0)): { + "MCSNO0": (0, 3, "slf_op_1"), + "MCSNO1": (0, 3, "slf_op_3"), + "MCSNO2": (0, 3, "slf_op_6"), + "MCSNO3": (0, 4, "slf_op_0"), + "MCSNOE0": (0, 3, "slf_op_2"), + "MCSNOE1": (0, 3, "slf_op_4"), + "MCSNOE2": (0, 3, "slf_op_7"), + "MCSNOE3": (0, 4, "slf_op_1"), + "MI": (0, 2, "lutff_0/in_1"), + "MO": (0, 2, "slf_op_5"), + "MOE": (0, 2, "slf_op_6"), + "SBACKO": (0, 2, "slf_op_0"), + "SBADRI0": (0, 1, "lutff_1/in_1"), + "SBADRI1": (0, 1, "lutff_2/in_1"), + "SBADRI2": (0, 2, "lutff_0/in_3"), + "SBADRI3": (0, 2, "lutff_1/in_3"), + "SBADRI4": (0, 2, "lutff_2/in_3"), + "SBADRI5": (0, 2, "lutff_3/in_3"), + "SBADRI6": (0, 2, "lutff_4/in_3"), + "SBADRI7": (0, 2, "lutff_5/in_3"), + "SBCLKI": (0, 1, "clk"), + "SBDATI0": (0, 1, "lutff_1/in_3"), + "SBDATI1": (0, 1, "lutff_2/in_3"), + "SBDATI2": (0, 1, "lutff_3/in_3"), + "SBDATI3": (0, 1, "lutff_4/in_3"), + "SBDATI4": (0, 1, "lutff_5/in_3"), + "SBDATI5": (0, 1, "lutff_6/in_3"), + "SBDATI6": (0, 1, "lutff_7/in_3"), + "SBDATI7": (0, 1, "lutff_0/in_1"), + "SBDATO0": (0, 1, "slf_op_0"), + "SBDATO1": (0, 1, "slf_op_1"), + "SBDATO2": (0, 1, "slf_op_2"), + "SBDATO3": (0, 1, "slf_op_3"), + "SBDATO4": (0, 1, "slf_op_4"), + "SBDATO5": (0, 1, "slf_op_5"), + "SBDATO6": (0, 1, "slf_op_6"), + "SBDATO7": (0, 1, "slf_op_7"), + "SBRWI": (0, 1, "lutff_0/in_3"), + "SBSTBI": (0, 2, "lutff_6/in_3"), + "SCKI": (0, 2, "lutff_1/in_1"), + "SCKO": (0, 2, "slf_op_7"), + "SCKOE": (0, 3, "slf_op_0"), + "SCSNI": (0, 2, "lutff_2/in_1"), + "SI": (0, 2, "lutff_7/in_3"), + "SO": (0, 2, "slf_op_3"), + "SOE": (0, 2, "slf_op_4"), + "SPIIRQ": (0, 2, "slf_op_1"), + "SPIWKUP": (0, 2, "slf_op_2"), + "SPI_ENABLE_0": (7, 0, "cbit2usealt_in_0"), + "SPI_ENABLE_1": (6, 0, "cbit2usealt_in_0"), + "SPI_ENABLE_2": (7, 0, "cbit2usealt_in_1"), + "SPI_ENABLE_3": (6, 0, "cbit2usealt_in_1"), + }, + ("SPI", (25, 0, 1)): { + "MCSNO0": (25, 3, "slf_op_1"), + "MCSNO1": (25, 3, "slf_op_3"), + "MCSNO2": (25, 3, "slf_op_6"), + "MCSNO3": (25, 4, "slf_op_0"), + "MCSNOE0": (25, 3, "slf_op_2"), + "MCSNOE1": (25, 3, "slf_op_4"), + "MCSNOE2": (25, 3, "slf_op_7"), + "MCSNOE3": (25, 4, "slf_op_1"), + "MI": (25, 2, "lutff_0/in_1"), + "MO": (25, 2, "slf_op_5"), + "MOE": (25, 2, "slf_op_6"), + "SBACKO": (25, 2, "slf_op_0"), + "SBADRI0": (25, 1, "lutff_1/in_1"), + "SBADRI1": (25, 1, "lutff_2/in_1"), + "SBADRI2": (25, 2, "lutff_0/in_3"), + "SBADRI3": (25, 2, "lutff_1/in_3"), + "SBADRI4": (25, 2, "lutff_2/in_3"), + "SBADRI5": (25, 2, "lutff_3/in_3"), + "SBADRI6": (25, 2, "lutff_4/in_3"), + "SBADRI7": (25, 2, "lutff_5/in_3"), + "SBCLKI": (25, 1, "clk"), + "SBDATI0": (25, 1, "lutff_1/in_3"), + "SBDATI1": (25, 1, "lutff_2/in_3"), + "SBDATI2": (25, 1, "lutff_3/in_3"), + "SBDATI3": (25, 1, "lutff_4/in_3"), + "SBDATI4": (25, 1, "lutff_5/in_3"), + "SBDATI5": (25, 1, "lutff_6/in_3"), + "SBDATI6": (25, 1, "lutff_7/in_3"), + "SBDATI7": (25, 1, "lutff_0/in_1"), + "SBDATO0": (25, 1, "slf_op_0"), + "SBDATO1": (25, 1, "slf_op_1"), + "SBDATO2": (25, 1, "slf_op_2"), + "SBDATO3": (25, 1, "slf_op_3"), + "SBDATO4": (25, 1, "slf_op_4"), + "SBDATO5": (25, 1, "slf_op_5"), + "SBDATO6": (25, 1, "slf_op_6"), + "SBDATO7": (25, 1, "slf_op_7"), + "SBRWI": (25, 1, "lutff_0/in_3"), + "SBSTBI": (25, 2, "lutff_6/in_3"), + "SCKI": (25, 2, "lutff_1/in_1"), + "SCKO": (25, 2, "slf_op_7"), + "SCKOE": (25, 3, "slf_op_0"), + "SCSNI": (25, 2, "lutff_2/in_1"), + "SI": (25, 2, "lutff_7/in_3"), + "SO": (25, 2, "slf_op_3"), + "SOE": (25, 2, "slf_op_4"), + "SPIIRQ": (25, 2, "slf_op_1"), + "SPIWKUP": (25, 2, "slf_op_2"), + "SPI_ENABLE_0": (24, 0, "cbit2usealt_in_0"), + "SPI_ENABLE_1": (24, 0, "cbit2usealt_in_1"), + "SPI_ENABLE_2": (23, 0, "cbit2usealt_in_0"), + "SPI_ENABLE_3": (23, 0, "cbit2usealt_in_1"), + }, 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/icemulti/Makefile b/icemulti/Makefile index 7e2fe1c..1719f39 100644 --- a/icemulti/Makefile +++ b/icemulti/Makefile @@ -4,21 +4,21 @@ ifeq ($(STATIC),1) LDFLAGS += -static endif -all: icemulti$(EXE) +all: $(PROGRAM_PREFIX)icemulti$(EXE) -icemulti$(EXE): icemulti.o +$(PROGRAM_PREFIX)icemulti$(EXE): icemulti.o $(CXX) -o $@ $(LDFLAGS) $^ $(LDLIBS) install: all mkdir -p $(DESTDIR)$(PREFIX)/bin - cp icemulti$(EXE) $(DESTDIR)$(PREFIX)/bin/icemulti$(EXE) + cp $(PROGRAM_PREFIX)icemulti$(EXE) $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icemulti$(EXE) uninstall: - rm -f $(DESTDIR)$(PREFIX)/bin/icemulti$(EXE) + rm -f $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icemulti$(EXE) clean: - rm -f icemulti$(EXE) - rm -f icemulti.exe + rm -f $(PROGRAM_PREFIX)icemulti$(EXE) + rm -f $(PROGRAM_PREFIX)icemulti.exe rm -f *.o *.d -include *.d diff --git a/icemulti/icemulti.cc b/icemulti/icemulti.cc index 4bc0919..52a7800 100644 --- a/icemulti/icemulti.cc +++ b/icemulti/icemulti.cc @@ -157,10 +157,10 @@ static void write_header(std::ostream &ofs, uint32_t &file_offset, write_byte(ofs, file_offset, 0x00); } -void usage() +void usage(const char *cmd) { log("\n"); - log("Usage: icemulti [options] input-files\n"); + log("Usage: %s [options] input-files\n", cmd); log("\n"); log(" -c\n"); log(" coldboot mode, power on reset image is selected by CBSEL0/CBSEL1\n"); @@ -252,12 +252,12 @@ int main(int argc, char **argv) print_offsets = true; break; default: - usage(); + usage(argv[0]); } if (optind == argc) { fprintf(stderr, "%s: missing argument\n", program_short_name); - usage(); + usage(argv[0]); } while (optind != argc) { 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/icepack/Makefile b/icepack/Makefile index 3e8c774..46f2410 100644 --- a/icepack/Makefile +++ b/icepack/Makefile @@ -5,30 +5,30 @@ ifeq ($(STATIC),1) LDFLAGS += -static endif -all: icepack$(EXE) iceunpack$(EXE) +all: $(PROGRAM_PREFIX)icepack$(EXE) $(PROGRAM_PREFIX)iceunpack$(EXE) -icepack$(EXE): icepack.o +$(PROGRAM_PREFIX)icepack$(EXE): icepack.o $(CXX) -o $@ $(LDFLAGS) $^ $(LDLIBS) -iceunpack$(EXE): icepack$(EXE) - ln -sf icepack$(EXE) iceunpack$(EXE) +$(PROGRAM_PREFIX)iceunpack$(EXE): $(PROGRAM_PREFIX)icepack$(EXE) + ln -sf $(PROGRAM_PREFIX)icepack$(EXE) $(PROGRAM_PREFIX)iceunpack$(EXE) -iceunpack.exe: +$(PROGRAM_PREFIX)iceunpack.exe: # no iceunpack.exe, use icepack -u install: all mkdir -p $(DESTDIR)$(PREFIX)/bin - cp icepack$(EXE) $(DESTDIR)$(PREFIX)/bin/icepack$(EXE) - ln -sf icepack$(EXE) $(DESTDIR)$(PREFIX)/bin/iceunpack$(EXE) + cp $(PROGRAM_PREFIX)icepack$(EXE) $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icepack$(EXE) + ln -sf $(PROGRAM_PREFIX)icepack$(EXE) $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)iceunpack$(EXE) uninstall: - rm -f $(DESTDIR)$(PREFIX)/bin/icepack$(EXE) - rm -f $(DESTDIR)$(PREFIX)/bin/iceunpack$(EXE) + rm -f $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icepack$(EXE) + rm -f $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)iceunpack$(EXE) clean: - rm -f icepack$(EXE) - rm -f iceunpack$(EXE) - rm -f icepack.exe + rm -f $(PROGRAM_PREFIX)icepack$(EXE) + rm -f $(PROGRAM_PREFIX)iceunpack$(EXE) + rm -f $(PROGRAM_PREFIX)icepack.exe rm -f *.o *.d -include *.d diff --git a/icepack/icepack.cc b/icepack/icepack.cc index 9b38ab5..565d5f9 100644 --- a/icepack/icepack.cc +++ b/icepack/icepack.cc @@ -968,7 +968,17 @@ void FpgaConfig::write_cram_pbm(std::ostream &ofs, int bank_num) const ofs << "P3\n"; ofs << stringf("%d %d\n", 2*this->cram_width, 2*this->cram_height); ofs << "255\n"; - uint32_t tile_type[4][this->cram_width][this->cram_height]; + + vector<vector<uint32_t>> tile_type[4]; + + // We require random access to tile_type, so ensure that each column of each + // bank is initialised so that all possible indices are valid + for (int bank = 0; bank < 4; bank++) { + tile_type[bank].resize(this->cram_width); + for (int x = 0; x < this->cram_width; x++) + tile_type[bank][x].resize(this->cram_height); + } + for (int y = 0; y <= this->chip_height()+1; y++) for (int x = 0; x <= this->chip_width()+1; x++) { @@ -1321,10 +1331,10 @@ void BramIndexConverter::get_bram_index(int bit_x, int bit_y, int &bram_bank, in // ================================================================== // Main program -void usage() +void usage(const char *cmd) { log("\n"); - log("Usage: icepack [options] [input-file [output-file]]\n"); + log("Usage: %s [options] [input-file [output-file]]\n", cmd); log("\n"); log(" -u\n"); log(" unpack mode (implied when called as 'iceunpack')\n"); @@ -1416,7 +1426,7 @@ int main(int argc, char **argv) } else if (arg[i] == 'n') { skip_bram_initialization = true; } else - usage(); + usage(argv[0]); continue; } @@ -1448,7 +1458,7 @@ int main(int argc, char **argv) } if (parameters.size() > 2) - usage(); + usage(argv[0]); FpgaConfig fpga_config; 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/icepll/Makefile b/icepll/Makefile index 13a1d81..6e9467b 100644 --- a/icepll/Makefile +++ b/icepll/Makefile @@ -4,21 +4,21 @@ ifeq ($(STATIC),1) LDFLAGS += -static endif -all: icepll$(EXE) +all: $(PROGRAM_PREFIX)icepll$(EXE) -icepll$(EXE): icepll.o +$(PROGRAM_PREFIX)icepll$(EXE): icepll.o $(CXX) -o $@ $(LDFLAGS) $^ $(LDLIBS) install: all mkdir -p $(DESTDIR)$(PREFIX)/bin - cp icepll$(EXE) $(DESTDIR)$(PREFIX)/bin/icepll$(EXE) + cp $(PROGRAM_PREFIX)icepll$(EXE) $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icepll$(EXE) uninstall: - rm -f $(DESTDIR)$(PREFIX)/bin/icepll$(EXE) + rm -f $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icepll$(EXE) clean: - rm -f icepll$(EXE) - rm -f icepll.exe + rm -f $(PROGRAM_PREFIX)icepll$(EXE) + rm -f $(PROGRAM_PREFIX)icepll.exe rm -f *.o *.d -include *.d diff --git a/icepll/icepll.cc b/icepll/icepll.cc index f9ebecf..398b545 100644 --- a/icepll/icepll.cc +++ b/icepll/icepll.cc @@ -51,6 +51,14 @@ void help(const char *cmd) printf(" -S\n"); printf(" Disable SIMPLE feedback path mode\n"); printf("\n"); + printf(" -b\n"); + printf(" Find best input frequency for desired PLL Output frequency\n"); + printf(" using the normally stocked oscillators at Mouser\n"); + printf("\n"); + printf(" -B <filename>\n"); + printf(" Find best input frequency for desired PLL Output frequency\n"); + printf(" using frequencies read from <filename>\n"); + printf("\n"); printf(" -f <filename>\n"); printf(" Save PLL configuration as Verilog to file\n"); printf(" If <filename> is - then the Verilog is written to stdout.\n"); @@ -67,6 +75,119 @@ void help(const char *cmd) exit(1); } +bool analyze( + bool simple_feedback, double f_pllin, double f_pllout, + double *best_fout, int *best_divr, int *best_divf, int *best_divq + ) +{ + bool found_something = false; + *best_fout = 0; + *best_divr = 0; + *best_divf = 0; + *best_divq = 0; + + int divf_max = simple_feedback ? 127 : 63; + // The documentation in the iCE40 PLL Usage Guide incorrectly lists the + // maximum value of DIVF as 63, when it is only limited to 63 when using + // feedback modes other that SIMPLE. + + if (f_pllin < 10 || f_pllin > 133) { + fprintf(stderr, "Error: PLL input frequency %.3f MHz is outside range 10 MHz - 133 MHz!\n", f_pllin); + exit(1); + } + + if (f_pllout < 16 || f_pllout > 275) { + fprintf(stderr, "Error: PLL output frequency %.3f MHz is outside range 16 MHz - 275 MHz!\n", f_pllout); + exit(1); + } + + for (int divr = 0; divr <= 15; divr++) + { + double f_pfd = f_pllin / (divr + 1); + if (f_pfd < 10 || f_pfd > 133) continue; + + for (int divf = 0; divf <= divf_max; divf++) + { + if (simple_feedback) + { + double f_vco = f_pfd * (divf + 1); + if (f_vco < 533 || f_vco > 1066) continue; + + for (int divq = 1; divq <= 6; divq++) + { + double fout = f_vco * exp2(-divq); + + if (fabs(fout - f_pllout) < fabs(*best_fout - f_pllout) || !found_something) { + *best_fout = fout; + *best_divr = divr; + *best_divf = divf; + *best_divq = divq; + found_something = true; + } + } + } + else + { + for (int divq = 1; divq <= 6; divq++) + { + double f_vco = f_pfd * (divf + 1) * exp2(divq); + if (f_vco < 533 || f_vco > 1066) continue; + + double fout = f_vco * exp2(-divq); + + if (fabs(fout - f_pllout) < fabs(*best_fout - f_pllout) || !found_something) { + *best_fout = fout; + *best_divr = divr; + *best_divf = divf; + *best_divq = divq; + found_something = true; + } + } + } + } + } + + return found_something; +} + + // Table of frequencies to test in "best" mode defaults to ABRACOM Crystal + // oscillators "Normally stocked" at Mouser + double freq_table[100] = + { + 10, 11.0592, 11.2896, 11.7846, 12, 12.288, 12.352, 12.5, 13, 13.5, 13.6, 14.31818, 14.7456, 15, 16, 16.384, 17.2032, 18.432, 19.2, 19.44, 19.6608, + 20, 24, 24.576, 25, 26, 27, 27.12, 28.63636, 28.9, 29.4912, + 30, 32, 32.768, 33, 33.206, 33.333, 35.328, 36, 37.03, 37.4, 38.4, 38.88, + 40, 40.95, 40.97, 44, 44.736, 48, + 50, 54, 57.692, + 60, 64, 65, 66, 66.666, 68, + 70, 72, 75, 76.8, + 80, 80.92, + 92.16, 96, 98.304, + 100, 104, 106.25, 108, + 114.285, + 120, 122.88, 125, + 0 + }; + +void readfreqfile(const char *filename) { + FILE *f; + f = fopen(filename, "r"); + if (f == NULL) { + fprintf(stderr, "Error: Can't open file %s!\n",filename); + exit(1); + } + + // Clear and overwrite the default values in the table + memset(freq_table, 0, sizeof(freq_table)); + int i = 0; + double freq=0; + while((i < int(sizeof(freq_table)/sizeof(double))) && (fscanf(f, "%lf", &freq) > 0)) + { + freq_table[i++] = freq; + } + fclose(f); +} + int main(int argc, char **argv) { #ifdef __EMSCRIPTEN__ @@ -88,10 +209,12 @@ int main(int argc, char **argv) bool file_stdout = false; const char* module_name = NULL; bool save_as_module = false; + bool best_mode = false; + const char* freqfile = NULL; bool quiet = false; int opt; - while ((opt = getopt(argc, argv, "i:o:Smf:n:q")) != -1) + while ((opt = getopt(argc, argv, "i:o:Smf:n:bB:q")) != -1) { switch (opt) { @@ -113,6 +236,13 @@ int main(int argc, char **argv) case 'n': module_name = optarg; break; + case 'b': + best_mode = true; + break; + case 'B': + best_mode = true; + freqfile = optarg; + break; case 'q': quiet = true; break; @@ -137,68 +267,37 @@ int main(int argc, char **argv) quiet = true; } + if (freqfile) { + readfreqfile(freqfile); + } + bool found_something = false; double best_fout = 0; int best_divr = 0; int best_divf = 0; int best_divq = 0; - // The documentation in the iCE40 PLL Usage Guide incorrectly lists the - // maximum value of DIVF as 63, when it is only limited to 63 when using - // feedback modes other that SIMPLE. - int divf_max = simple_feedback ? 127 : 63; - - if (f_pllin < 10 || f_pllin > 133) { - fprintf(stderr, "Error: PLL input frequency %.3f MHz is outside range 10 MHz - 133 MHz!\n", f_pllin); - exit(1); - } - - if (f_pllout < 16 || f_pllout > 275) { - fprintf(stderr, "Error: PLL output frequency %.3f MHz is outside range 16 MHz - 275 MHz!\n", f_pllout); - exit(1); - } - - for (int divr = 0; divr <= 15; divr++) - { - double f_pfd = f_pllin / (divr + 1); - if (f_pfd < 10 || f_pfd > 133) continue; - - for (int divf = 0; divf <= divf_max; divf++) + if (!best_mode) { + // Use only specified input frequency + found_something = analyze(simple_feedback, f_pllin, f_pllout, &best_fout, &best_divr, &best_divf, &best_divq); + } else { + // Iterate over all standard crystal frequencies and select the best + for (int i = 0; freq_table[i]>0.0 ; i++) { - if (simple_feedback) - { - double f_vco = f_pfd * (divf + 1); - if (f_vco < 533 || f_vco > 1066) continue; - - for (int divq = 1; divq <= 6; divq++) - { - double fout = f_vco * exp2(-divq); - - if (fabs(fout - f_pllout) < fabs(best_fout - f_pllout) || !found_something) { - best_fout = fout; - best_divr = divr; - best_divf = divf; - best_divq = divq; - found_something = true; - } - } - } - else + double fout = 0; + int divr = 0; + int divf = 0; + int divq = 0; + if (analyze(simple_feedback, freq_table[i], f_pllout, &fout, &divr, &divf, &divq)) { - for (int divq = 1; divq <= 6; divq++) + found_something = true; + if (abs(fout - f_pllout) < abs(best_fout - f_pllout)) { - double f_vco = f_pfd * (divf + 1) * exp2(divq); - if (f_vco < 533 || f_vco > 1066) continue; - - double fout = f_vco * exp2(-divq); - - if (fabs(fout - f_pllout) < fabs(best_fout - f_pllout) || !found_something) { - best_fout = fout; - best_divr = divr; - best_divf = divf; - best_divq = divq; - found_something = true; - } + f_pllin = freq_table[i]; + best_fout = fout; + best_divr = divr; + best_divf = divf; + best_divq = divq; } } } diff --git a/iceprog/Makefile b/iceprog/Makefile index 9727257..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; ) @@ -16,21 +9,21 @@ LDLIBS += $(shell for pkg in libftdi1 libftdi; do $(PKG_CONFIG) --silence-errors CFLAGS += $(shell for pkg in libftdi1 libftdi; do $(PKG_CONFIG) --silence-errors --cflags $$pkg && exit; done; ) endif -all: iceprog$(EXE) +all: $(PROGRAM_PREFIX)iceprog$(EXE) -iceprog$(EXE): iceprog.o mpsse.o +$(PROGRAM_PREFIX)iceprog$(EXE): iceprog.o mpsse.o $(CC) -o $@ $(LDFLAGS) $^ $(LDLIBS) install: all mkdir -p $(DESTDIR)$(PREFIX)/bin - cp iceprog$(EXE) $(DESTDIR)$(PREFIX)/bin/iceprog$(EXE) + cp $(PROGRAM_PREFIX)iceprog$(EXE) $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)iceprog$(EXE) uninstall: - rm -f $(DESTDIR)$(PREFIX)/bin/iceprog$(EXE) + rm -f $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)iceprog$(EXE) clean: - rm -f iceprog - rm -f iceprog.exe + rm -f $(PROGRAM_PREFIX)iceprog + rm -f $(PROGRAM_PREFIX)iceprog.exe rm -f *.o *.d -include *.d diff --git a/iceprog/iceprog.c b/iceprog/iceprog.c index f38b133..c5243b9 100644 --- a/iceprog/iceprog.c +++ b/iceprog/iceprog.c @@ -310,6 +310,28 @@ static void flash_bulk_erase() flash_chip_deselect(); } +static void flash_4kB_sector_erase(int addr) +{ + fprintf(stderr, "erase 4kB sector at 0x%06X..\n", addr); + + uint8_t command[4] = { FC_SE, (uint8_t)(addr >> 16), (uint8_t)(addr >> 8), (uint8_t)addr }; + + flash_chip_select(); + mpsse_send_spi(command, 4); + flash_chip_deselect(); +} + +static void flash_32kB_sector_erase(int addr) +{ + fprintf(stderr, "erase 64kB sector at 0x%06X..\n", addr); + + uint8_t command[4] = { FC_BE32, (uint8_t)(addr >> 16), (uint8_t)(addr >> 8), (uint8_t)addr }; + + flash_chip_select(); + mpsse_send_spi(command, 4); + flash_chip_deselect(); +} + static void flash_64kB_sector_erase(int addr) { fprintf(stderr, "erase 64kB sector at 0x%06X..\n", addr); @@ -448,7 +470,9 @@ static void help(const char *progname) fprintf(stderr, " (append 'k' to the argument for size in kilobytes,\n"); fprintf(stderr, " or 'M' for size in megabytes)\n"); fprintf(stderr, " -s slow SPI (50 kHz instead of 6 MHz)\n"); + fprintf(stderr, " -k keep flash in powered up state (i.e. skip power down command)\n"); fprintf(stderr, " -v verbose output\n"); + fprintf(stderr, " -i [4,32,64] select erase block size [default: 64k]\n"); fprintf(stderr, "\n"); fprintf(stderr, "Mode of operation:\n"); fprintf(stderr, " [default] write file contents to flash, then verify\n"); @@ -509,6 +533,7 @@ int main(int argc, char **argv) my_name = argv[0] + i + 1; int read_size = 256 * 1024; + int erase_block_size = 64; int erase_size = 0; int rw_offset = 0; @@ -522,6 +547,7 @@ int main(int argc, char **argv) bool slow_clock = false; bool disable_protect = false; bool disable_verify = false; + bool disable_powerdown = false; const char *filename = NULL; const char *devstr = NULL; int ifnum = 0; @@ -539,11 +565,23 @@ int main(int argc, char **argv) /* Decode command line parameters */ int opt; char *endptr; - while ((opt = getopt_long(argc, argv, "d:I:rR:e:o:cbnStvspX", long_options, NULL)) != -1) { + while ((opt = getopt_long(argc, argv, "d:i:I:rR:e:o:cbnStvspXk", long_options, NULL)) != -1) { switch (opt) { case 'd': /* device string */ devstr = optarg; break; + case 'i': /* block erase size */ + if (!strcmp(optarg, "4")) + erase_block_size = 4; + else if (!strcmp(optarg, "32")) + erase_block_size = 32; + else if (!strcmp(optarg, "64")) + erase_block_size = 64; + else { + fprintf(stderr, "%s: `%s' is not a valid erase block size (must be `4', `32' or `64')\n", my_name, optarg); + return EXIT_FAILURE; + } + break; case 'I': /* FTDI Chip interface select */ if (!strcmp(optarg, "A")) ifnum = 0; @@ -629,6 +667,9 @@ int main(int argc, char **argv) case 'X': /* disable verification */ disable_verify = true; break; + case 'k': /* disable power down command */ + disable_powerdown = true; + break; case -2: help(argv[0]); return EXIT_SUCCESS; @@ -888,12 +929,24 @@ int main(int argc, char **argv) { fprintf(stderr, "file size: %ld\n", file_size); - int begin_addr = rw_offset & ~0xffff; - int end_addr = (rw_offset + file_size + 0xffff) & ~0xffff; + int block_size = erase_block_size << 10; + int block_mask = block_size - 1; + int begin_addr = rw_offset & ~block_mask; + int end_addr = (rw_offset + file_size + block_mask) & ~block_mask; - for (int addr = begin_addr; addr < end_addr; addr += 0x10000) { + for (int addr = begin_addr; addr < end_addr; addr += block_size) { flash_write_enable(); - flash_64kB_sector_erase(addr); + switch(erase_block_size) { + case 4: + flash_4kB_sector_erase(addr); + break; + case 32: + flash_32kB_sector_erase(addr); + break; + case 64: + flash_64kB_sector_erase(addr); + break; + } if (verbose) { fprintf(stderr, "Status after block erase:\n"); flash_read_status(); @@ -913,10 +966,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, addr / (file_size / 100)); 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); @@ -931,9 +988,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, addr / (read_size / 100)); 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) { @@ -941,6 +1002,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, addr / (file_size / 100)); flash_read(rw_offset + addr, buffer_flash, rc); if (memcmp(buffer_file, buffer_flash, rc)) { fprintf(stderr, "Found difference between flash and file!\n"); @@ -948,6 +1011,7 @@ int main(int argc, char **argv) } } + fprintf(stderr, " \r"); fprintf(stderr, "VERIFY OK\n"); } @@ -956,7 +1020,8 @@ int main(int argc, char **argv) // Reset // --------------------------------------------------------- - flash_power_down(); + if (!disable_powerdown) + flash_power_down(); set_cs_creset(1, 1); usleep(250000); diff --git a/icetime/Makefile b/icetime/Makefile index acf5b8f..4834709 100644 --- a/icetime/Makefile +++ b/icetime/Makefile @@ -6,12 +6,12 @@ ifeq ($(STATIC),1) LDFLAGS += -static endif -all: icetime$(EXE) +all: $(PROGRAM_PREFIX)icetime$(EXE) -CHIPS=lp384 lp1k lp8k hx1k hx8k up5k +CHIPS=lp384 lp1k lp8k hx1k hx8k up5k u4k ifeq ($(EXE),.js) -icetime$(EXE): | share/$(CHIPDB_SUBDIR)/chipdb-384.txt share/$(CHIPDB_SUBDIR)/chipdb-1k.txt share/$(CHIPDB_SUBDIR)/chipdb-8k.txt share/$(CHIPDB_SUBDIR)/chipdb-5k.txt +$(PROGRAM_PREFIX)icetime$(EXE): | share/$(CHIPDB_SUBDIR)/chipdb-384.txt share/$(CHIPDB_SUBDIR)/chipdb-1k.txt share/$(CHIPDB_SUBDIR)/chipdb-8k.txt share/$(CHIPDB_SUBDIR)/chipdb-5k.txt share/$(CHIPDB_SUBDIR)/chipdb-384.txt: ../icebox/chipdb-384.txt mkdir -p share/$(CHIPDB_SUBDIR) @@ -28,20 +28,22 @@ share/$(CHIPDB_SUBDIR)/chipdb-5k.txt: ../icebox/chipdb-5k.txt override LDFLAGS += --embed-file share endif -icetime$(EXE): icetime.o iceutil.o $(addsuffix .o, $(addprefix timings-, $(CHIPS))) +$(PROGRAM_PREFIX)icetime$(EXE): icetime.o iceutil.o $(addsuffix .o, $(addprefix timings-, $(CHIPS))) $(CXX) -o $@ $(LDFLAGS) $^ $(LDLIBS) timings-%.cc: timings.py ../icefuzz/timings_%.txt $(PYTHON) timings.py $* > $@ +.PRECIOUS: timings-%.cc + install: all mkdir -p $(DESTDIR)$(PREFIX)/bin - mkdir -p $(DESTDIR)$(PREFIX)/share/icebox - cp icetime$(EXE) $(DESTDIR)$(PREFIX)/bin/icetime$(EXE) - cp ../icefuzz/timings_*.txt $(DESTDIR)$(PREFIX)/share/icebox/ + mkdir -p $(DESTDIR)$(PREFIX)/share/$(PROGRAM_PREFIX)icebox + cp $(PROGRAM_PREFIX)icetime$(EXE) $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icetime$(EXE) + cp ../icefuzz/timings_*.txt $(DESTDIR)$(PREFIX)/share/$(PROGRAM_PREFIX)icebox/ uninstall: - rm -f $(DESTDIR)$(PREFIX)/bin/icetime$(EXE) + rm -f $(DESTDIR)$(PREFIX)/bin/$(PROGRAM_PREFIX)icetime$(EXE) # View timing netlist: @@ -65,7 +67,7 @@ test: test0 test1 test2 test3 test4 test5 test6 test7 test8 test9 show: show0 show1 show2 show3 show4 show5 show6 show7 show8 show9 clean: - rm -f icetime$(EXE) icetime.exe *.o *.d timings-*.cc + rm -f $(PROGRAM_PREFIX)icetime$(EXE) $(PROGRAM_PREFIX)icetime.exe *.o *.d timings-*.cc rm -rf test[0-9]* -include *.d diff --git a/icetime/icetime.cc b/icetime/icetime.cc index cc37625..d730fc6 100644 --- a/icetime/icetime.cc +++ b/icetime/icetime.cc @@ -30,6 +30,7 @@ #include <functional> #include <map> #include <set> +#include <stdexcept> #include <string> #include <tuple> #include <vector> @@ -61,16 +62,16 @@ std::map<int, std::string> net_symbols; bool get_config_bit(int tile_x, int tile_y, int bit_row, int bit_col) { - if (int(config_bits.size()) < tile_x) + if (int(config_bits.size()) <= tile_x) return false; - if (int(config_bits[tile_x].size()) < tile_y) + if (int(config_bits[tile_x].size()) <= tile_y) return false; - if (int(config_bits[tile_x][tile_y].size()) < bit_row) + if (int(config_bits[tile_x][tile_y].size()) <= bit_row) return false; - if (int(config_bits[tile_x][tile_y][bit_row].size()) < bit_col) + if (int(config_bits[tile_x][tile_y][bit_row].size()) <= bit_col) return false; return config_bits[tile_x][tile_y][bit_row][bit_col]; @@ -752,6 +753,7 @@ double get_delay_lp8k(std::string cell_type, std::string in_port, std::string ou double get_delay_hx1k(std::string cell_type, std::string in_port, std::string out_port); double get_delay_hx8k(std::string cell_type, std::string in_port, std::string out_port); double get_delay_up5k(std::string cell_type, std::string in_port, std::string out_port); +double get_delay_u4k(std::string cell_type, std::string in_port, std::string out_port); double get_delay(std::string cell_type, std::string in_port, std::string out_port) { @@ -764,17 +766,20 @@ double get_delay(std::string cell_type, std::string in_port, std::string out_por if (device_type == "lp1k") return get_delay_lp1k(cell_type, in_port, out_port); - if (device_type == "lp8k") + if (device_type == "lp8k" || device_type == "lp4k") return get_delay_lp8k(cell_type, in_port, out_port); if (device_type == "hx1k") return get_delay_hx1k(cell_type, in_port, out_port); - if (device_type == "hx8k") + if (device_type == "hx8k" || device_type == "hx4k") return get_delay_hx8k(cell_type, in_port, out_port); - if (device_type == "up5k") + if (device_type == "up5k" || device_type == "up3k") return get_delay_up5k(cell_type, in_port, out_port); + + if (device_type == "u4k" || device_type == "u1k" || device_type == "u2k") + return get_delay_u4k(cell_type, in_port, out_port); fprintf(stderr, "No built-in timing database for '%s' devices!\n", device_type.c_str()); exit(1); } @@ -1593,7 +1598,7 @@ void make_seg_cell(int net, const net_segment_t &seg) if (sscanf(seg.name.c_str(), "lutff_%d/in_%d", &a, &b) == 2) { //"logic" wires at the side of the device are actually IP or DSP - if(device_type == "up5k" && ((seg.x == 0) || (seg.x == int(config_tile_type.size()) - 1))) { + if((device_type == "up5k" || device_type == "up3k") && ((seg.x == 0) || (seg.x == int(config_tile_type.size()) - 1))) { std::string primnet; auto cell = make_dsp_ip(seg.x, seg.y, seg.name, primnet); if(cell != "") { @@ -2209,7 +2214,7 @@ void help(const char *cmd) printf(" -j <output_file>\n"); printf(" write timing report in json format to the file\n"); printf("\n"); - printf(" -d lp384|lp1k|hx1k|lp8k|hx8k|up5k\n"); + printf(" -d lp384|lp1k|hx1k|lp4k|hx4k|lp8k|hx8k|up3k|up5k|u1k|u2k|u4k\n"); printf(" select the device type (default = lp variant)\n"); printf("\n"); printf(" -C <chipdb-file>\n"); @@ -2366,13 +2371,17 @@ int main(int argc, char **argv) if (config_device != "1k") goto device_chip_mismatch; } else - if (device_type == "lp8k" || device_type == "hx8k") { + if (device_type == "lp8k" || device_type == "hx8k" || device_type == "lp4k" || device_type == "hx4k") { if (config_device != "8k") goto device_chip_mismatch; } else - if (device_type == "up5k") { + if (device_type == "up5k" || device_type == "up3k") { if (config_device != "5k") goto device_chip_mismatch; + } else + if (device_type == "u4k" || device_type == "u1k" || device_type == "u2k") { + if (config_device != "u4k") + goto device_chip_mismatch; } else { fprintf(stderr, "Error: Invalid device type '%s'.\n", device_type.c_str()); exit(1); diff --git a/icetime/iceutil.cc b/icetime/iceutil.cc index ad8d662..440b9a8 100644 --- a/icetime/iceutil.cc +++ b/icetime/iceutil.cc @@ -155,7 +155,7 @@ std::string find_chipdb(std::string config_device) #else homepath += getenv("HOME"); #endif - homepath += std::string(PREFIX + 1) + "/" CHIPDB_SUBDIR "/chipdb-" + config_device + ".txt"; + homepath += std::string(&PREFIX[1]) + "/" CHIPDB_SUBDIR "/chipdb-" + config_device + ".txt"; if (verbose) fprintf(stderr, "Looking for chipdb '%s' at %s\n", config_device.c_str(), homepath.c_str()); if (file_test_open(homepath)) |