aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/format.html2
-rw-r--r--docs/index.html16
-rw-r--r--docs/logic_tile.html6
-rw-r--r--icebox/.gitignore1
-rw-r--r--icebox/Makefile10
-rw-r--r--icebox/icebox.py495
-rwxr-xr-xicebox/icebox_chipdb.py14
-rwxr-xr-xicebox/icebox_vlog.py11
-rw-r--r--icebram/icebram.cc16
-rw-r--r--icefuzz/Makefile5
-rw-r--r--icefuzz/fuzzconfig.py19
-rw-r--r--icefuzz/icecube.sh56
-rw-r--r--icefuzz/tests/colbuf_io_lm4k.sh41
-rw-r--r--icefuzz/tests/colbuf_logic_lm4k.sh29
-rwxr-xr-xicefuzz/tests/colbuf_ram_lm4k.sh56
-rw-r--r--icefuzz/tests/io_latched_lm4k.sh31
-rw-r--r--icefuzz/tests/ioctrl_lm4k.py21
-rwxr-xr-xicefuzz/tests/ioctrl_lm4k.sh33
-rwxr-xr-xicefuzz/tests/pllauto/pllauto.py3
-rw-r--r--icemulti/icemulti.cc16
-rw-r--r--icepack/icepack.cc55
-rw-r--r--icepll/icepll.cc29
-rw-r--r--iceprog/iceprog.c157
-rw-r--r--icetime/icetime.cc42
24 files changed, 1096 insertions, 68 deletions
diff --git a/docs/format.html b/docs/format.html
index 698a321..8d36151 100644
--- a/docs/format.html
+++ b/docs/format.html
@@ -96,7 +96,7 @@ in the FPGA. The following sequence is used to program an SRAM cell:
<p>
The bank width and height parameters reflect the width and height of the SRAM bank. A large SRAM can
-be written in smaller junks. In this case height parameter may be smaller and the offset parameter
+be written in smaller chunks. In this case height parameter may be smaller and the offset parameter
reflects the vertical start position.
</p>
diff --git a/docs/index.html b/docs/index.html
index 6b3ff5e..919122e 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -16,6 +16,7 @@
<h1>Project IceStorm</h1>
<p>
+<b>2018-01-30:</b> Released support for iCE40 UltraPlus devices.<br/>
<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/>
@@ -39,7 +40,9 @@ fully open source Verilog-to-Bitstream flow for iCE40 FPGAs.
<p>
The focus of the project is on the iCE40 LP/HX 1K/4K/8K chips. (Most of the
-work was done on HX1K-TQ144 and HX8K-CT256 parts.)
+work was done on HX1K-TQ144 and HX8K-CT256 parts.) The iCE40 UltraPlus parts
+are also supported, including DSPs, oscillators, RGB and SPRAM. iCE40 LM, Ultra
+and UltraLite parts are not yet supported.
</p>
<h2>Why the Lattice iCE40?</h2>
@@ -74,6 +77,8 @@ Here is a list of currently supported parts and the corresponding options for ar
<table class="ctab">
<tr><th>Part</th><th>Package</th><th>Pin Spacing</th><th>I/Os</th><th>arachne-pnr opts</th><th>icetime opts</th></tr>
<tr><td>iCE40-LP1K-SWG16TR</td><td>16-ball WLCSP (1.40 x 1.48 mm)</td><td>0.35 mm</td><td>10</td><td>-d 1k -P swg16tr</td><td>-d lp1k</td></tr>
+<tr><td>iCE40-UP3K-UWG30</td><td>30-ball WLCSP (2.15 x 2.55 mm)</td><td>0.40 mm</td><td>21</td><td>-d 5k -P uwg30</td><td>-d up5k</td></tr>
+<tr><td>iCE40-UP5K-UWG30</td><td>30-ball WLCSP (2.15 x 2.55 mm)</td><td>0.40 mm</td><td>21</td><td>-d 5k -P uwg30</td><td>-d up5k</td></tr>
<tr><td>iCE40-LP384-CM36</td><td>36-ball ucBGA (2.5 x 2.5 mm)</td><td>0.40 mm</td><td>25</td><td>-d 384 -P cm36</td><td>-d lp384</td></tr>
<tr><td>iCE40-LP1K-CM36</td><td>36-ball ucBGA (2.5 x 2.5 mm)</td><td>0.40 mm</td><td>25</td><td>-d 1k -P cm36</td><td>-d lp1k</td></tr>
<tr><td>iCE40-LP384-CM49</td><td>49-ball ucBGA (3 x 3 mm)</td><td>0.40 mm</td><td>37</td><td>-d 384 -P cm49</td><td>-d lp384</td></tr>
@@ -88,6 +93,7 @@ Here is a list of currently supported parts and the corresponding options for ar
<tr><td>iCE40-LP8K-CM225</td><td>225-ball ucBGA (7 x 7 mm)</td><td>0.40 mm</td><td>178</td><td>-d 8k -P cm225</td><td>-d lp8k</td></tr>
<tr><td>iCE40-HX8K-CM225</td><td>225-ball ucBGA (7 x 7 mm)</td><td>0.40 mm</td><td>178</td><td>-d 8k -P cm225</td><td>-d hx8k</td></tr>
<tr><td>iCE40-LP384-QN32</td><td>32-pin QFN (5 x 5 mm)</td><td>0.50 mm</td><td>21</td><td>-d 384 -P qn32</td><td>-d lp384</td></tr>
+<tr><td>iCE40-UP5K-SG48</td><td>48-pin QFN (7 x 7 mm)</td><td>0.50 mm</td><td>39</td><td>-d 5k -P sg48</td><td>-d up5k</td></tr>
<tr><td>iCE40-LP1K-QN84</td><td>84-pin QFNS (7 x 7 mm)</td><td>0.50 mm</td><td>67</td><td>-d 1k -P qn84</td><td>-d lp1k</td></tr>
<tr><td>iCE40-LP1K-CB81</td><td>81-ball csBGA (5 x 5 mm)</td><td>0.50 mm</td><td>62</td><td>-d 1k -P cb81</td><td>-d lp1k</td></tr>
<tr><td>iCE40-LP1K-CB121</td><td>121-ball csBGA (6 x 6 mm)</td><td>0.50 mm</td><td>92</td><td>-d 1k -P cb121</td><td>-d lp1k</td></tr>
@@ -97,15 +103,12 @@ Here is a list of currently supported parts and the corresponding options for ar
<tr><td>iCE40-HX1K-VQ100</td><td>100-pin VQFP (14 x 14 mm)</td><td>0.50 mm</td><td>72</td><td>-d 1k -P vq100</td><td>-d hx1k</td></tr>
<tr><td>iCE40-HX1K-TQ144</td><td>144-pin TQFP (20 x 20 mm)</td><td>0.50 mm</td><td>96</td><td>-d 1k -P tq144</td><td>-d hx1k</td></tr>
<tr><td>iCE40-HX4K-TQ144</td><td>144-pin TQFP (20 x 20 mm)</td><td>0.50 mm</td><td>107</td><td>-d 8k -P tq144:4k</td><td>-d hx8k</td></tr>
+<tr><td>iCE40-HX4K-BG121</td><td>121-ball caBGA (9 x 9 mm)</td><td>0.80 mm</td><td>93</td><td>-d 8k -P bg121:4k</td><td>-d hx8k</td></tr>
+<tr><td>iCE40-HX8K-BG121</td><td>121-ball caBGA (9 x 9 mm)</td><td>0.80 mm</td><td>93</td><td>-d 8k -P bg121</td><td>-d hx8k</td></tr>
<tr><td>iCE40-HX8K-CT256</td><td>256-ball caBGA (14 x 14 mm)</td><td>0.80 mm</td><td>206</td><td>-d 8k -P ct256</td><td>-d hx8k</td></tr>
</table>
<p>
- Experimental support is also included for one iCE40 UltraPlus device, the iCE40-UP5K-SG48, including support for some of
- the new UltraPlus features such as DSPs, SPRAM and internal oscillators.
-</p>
-
-<p>
Current work focuses on further improving our timing analysis flow.
</p>
@@ -534,6 +537,7 @@ Links to related projects. Contact me at clifford@clifford.at if you have an int
<li><a href="https://media.ccc.de/v/32c3-7139-a_free_and_open_source_verilog-to-bitstream_flow_for_ice40_fpgas">A Free and Open Source Verilog-to-Bitstream Flow for iCE40 FPGAs [32c3]</a>
<li><a href="https://www.youtube.com/watch?v=s7fNTF8nd8A">Synthesizing Verilog for Lattice ICE40 FPGAs (Paul Martin)</a>
<li><a href="https://github.com/Obijuan/open-fpga-verilog-tutorial/wiki">A Spanish FPGA Tutorial using IceStorm</a>
+<li><a href="http://hedmen.org/icestorm-doc/icestorm.html">IceStorm Learner’s Documentation</a>
</ul>
<h3>Other FPGA reverse engineering projects</h3>
diff --git a/docs/logic_tile.html b/docs/logic_tile.html
index 982b25d..ab9adc7 100644
--- a/docs/logic_tile.html
+++ b/docs/logic_tile.html
@@ -29,7 +29,7 @@ The <i>span-4</i> and <i>span-12</i> wires are the main interconnect resource in
</p>
<p>
-The bits marked <span style="font-family:monospace">routing</span> in the bitstream do enable switches (transfer gates) that can
+The bits marked <span style="font-family:monospace">routing</span> in the bitstream enable switches (transfer gates) that can
be used to connect wire segments bidirectionally to each other in order to create larger
segments. The bits marked <span style="font-family:monospace">buffer</span> in the bitstream enable tristate buffers that drive
the signal in one direction from one wire to another. Both types of bits exist for routing between
@@ -56,7 +56,7 @@ for this wire names.) The wires connecting the left and right horizontal span-4
</p>
<p>
-The wires <span style="font-family:monospace">sp4_h_l_36</span> to <span style="font-family:monospace">sp4_h_l_47</span> terminate in the cell, so do the wires <span style="font-family:monospace">sp4_h_r_0</span> to <span style="font-family:monospace">sp4_h_r_11</span>.
+The wires <span style="font-family:monospace">sp4_h_l_36</span> to <span style="font-family:monospace">sp4_h_l_47</span> terminate in the cell as do the wires <span style="font-family:monospace">sp4_h_r_0</span> to <span style="font-family:monospace">sp4_h_r_11</span>.
</p>
<p>
@@ -150,7 +150,7 @@ Each logic tile has 32 local tracks. They are organized in 4 groups of 8 wires e
<p>
The span wires, global signals, and neighbour outputs can be routed to the local tracks. But not
-every of those signals can be routed to every of the local tracks. Instead there is a different
+all of those signals can be routed to all of the local tracks. Instead there is a different
mix of 16 signals for each local track.
</p>
diff --git a/icebox/.gitignore b/icebox/.gitignore
index 035ca9c..0cd67f6 100644
--- a/icebox/.gitignore
+++ b/icebox/.gitignore
@@ -1,5 +1,6 @@
chipdb-1k.txt
chipdb-5k.txt
+chipdb-lm4k.txt
chipdb-8k.txt
chipdb-384.txt
__pycache__
diff --git a/icebox/Makefile b/icebox/Makefile
index a26d80c..5f4d47a 100644
--- a/icebox/Makefile
+++ b/icebox/Makefile
@@ -1,6 +1,6 @@
include ../config.mk
-all: chipdb-384.txt chipdb-1k.txt chipdb-8k.txt chipdb-5k.txt
+all: chipdb-384.txt chipdb-1k.txt chipdb-8k.txt chipdb-5k.txt chipdb-lm4k.txt
chipdb-384.txt: icebox.py iceboxdb.py icebox_chipdb.py
python3 icebox_chipdb.py -3 > chipdb-384.new
@@ -14,6 +14,10 @@ chipdb-5k.txt: icebox.py iceboxdb.py icebox_chipdb.py
python3 icebox_chipdb.py -5 > chipdb-5k.new
mv chipdb-5k.new chipdb-5k.txt
+chipdb-lm4k.txt: icebox.py iceboxdb.py icebox_chipdb.py
+ 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
mv chipdb-8k.new chipdb-8k.txt
@@ -24,7 +28,7 @@ check: all
python3 tc_logic_xpr.py
clean:
- rm -f chipdb-1k.txt chipdb-8k.txt chipdb-384.txt chipdb-5k.txt
+ rm -f chipdb-1k.txt chipdb-8k.txt chipdb-384.txt chipdb-5k.txt chipdb-lm4k.txt
rm -f icebox.pyc iceboxdb.pyc
install: all
@@ -34,6 +38,7 @@ install: all
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-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)
@@ -63,6 +68,7 @@ uninstall:
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
-rmdir $(DESTDIR)$(PREFIX)/share/icebox
.PHONY: all check clean install uninstall
diff --git a/icebox/icebox.py b/icebox/icebox.py
index 198b5f2..27bd243 100644
--- a/icebox/icebox.py
+++ b/icebox/icebox.py
@@ -79,6 +79,30 @@ class iceconfig:
self.io_tiles[(0, y)] = ["0" * 18 for i in range(16)]
self.io_tiles[(self.max_x, y)] = ["0" * 18 for i in range(16)]
+ def setup_empty_lm4k(self):
+ self.clear()
+ self.device = "lm4k"
+ self.max_x = 25
+ self.max_y = 21
+
+ for x in range(1, self.max_x):
+ for y in range(1, self.max_y):
+ if x in (6, 19):
+ if y % 2 == 1:
+ self.ramb_tiles[(x, y)] = ["0" * 42 for i in range(16)]
+ else:
+ self.ramt_tiles[(x, y)] = ["0" * 42 for i in range(16)]
+ else:
+ self.logic_tiles[(x, y)] = ["0" * 54 for i in range(16)]
+
+ for x in range(1, self.max_x):
+ self.io_tiles[(x, 0)] = ["0" * 18 for i in range(16)]
+ self.io_tiles[(x, self.max_y)] = ["0" * 18 for i in range(16)]
+
+ for y in range(1, self.max_y):
+ self.io_tiles[(0, y)] = ["0" * 18 for i in range(16)]
+ self.io_tiles[(self.max_x, y)] = ["0" * 18 for i in range(16)]
+
def setup_empty_5k(self):
self.clear()
self.device = "5k"
@@ -150,11 +174,15 @@ class iceconfig:
if (x, y) in self.ipcon_tiles: return self.ipcon_tiles[(x, y)]
return None
- def pinloc_db(self):
- if self.device == "384": return pinloc_db["384-qn32"]
- if self.device == "1k": return pinloc_db["1k-tq144"]
- if self.device == "5k": return pinloc_db["5k-sg48"]
- if self.device == "8k": return pinloc_db["8k-ct256"]
+ def pinloc_db(self, package = None):
+ if package is None:
+ if self.device == "384": return pinloc_db["384-qn32"]
+ if self.device == "1k": return pinloc_db["1k-tq144"]
+ if self.device == "lm4k": return pinloc_db["lm4k-cm49"]
+ if self.device == "5k": return pinloc_db["5k-sg48"]
+ if self.device == "8k": return pinloc_db["8k-ct256"]
+ else:
+ return pinloc_db[self.device + "-" + package]
assert False
def gbufin_db(self):
@@ -175,6 +203,8 @@ class iceconfig:
def pll_list(self):
if self.device == "1k":
return ["1k"]
+ if self.device == "lm4k":
+ return ["lm4k"]
if self.device == "5k":
return ["5k"]
if self.device == "8k":
@@ -203,6 +233,19 @@ class iceconfig:
entries.append((x, src_y, x, y))
return entries
+ # TODO(awygle) - actually capture 0 and 21 here
+ if self.device == "lm4k":
+ entries = list()
+ for x in range(self.max_x+1):
+ for y in range(self.max_y+1):
+ src_y = None
+ if 0 <= y <= 4: src_y = 4
+ if 5 <= y <= 10: src_y = 5
+ if 11 <= y <= 16: src_y = 16
+ if 17 <= y <= 21: src_y = 17
+ entries.append((x, src_y, x, y))
+ return entries
+
if self.device == "8k":
entries = list()
for x in range(self.max_x+1):
@@ -302,7 +345,7 @@ class iceconfig:
def tile_db(self, x, y):
# Only these devices have IO on the left and right sides.
- if self.device in ["384", "1k", "8k"]:
+ if self.device in ["384", "1k", "lm4k", "8k"]:
if x == 0: return iotile_l_db
if x == self.max_x: return iotile_r_db
# The 5k needs an IO db including the extra bits
@@ -326,7 +369,7 @@ class iceconfig:
if (x, y) in self.dsp_tiles[2]: return dsp2_5k_db
if (x, y) in self.dsp_tiles[3]: return dsp3_5k_db
- elif self.device == "8k":
+ elif self.device == "8k" or self.device == "lm4k":
if (x, y) in self.logic_tiles: return logictile_8k_db
if (x, y) in self.ramb_tiles: return rambtile_8k_db
if (x, y) in self.ramt_tiles: return ramttile_8k_db
@@ -449,7 +492,7 @@ class iceconfig:
return (nx, ny, "ram/RDATA_%d" % func)
elif self.device == "5k":
return (nx, ny, "ram/RDATA_%d" % (15-func))
- elif self.device == "8k":
+ elif self.device == "8k" or self.device == "lm4k":
return (nx, ny, "ram/RDATA_%d" % (15-func))
else:
assert False
@@ -458,7 +501,7 @@ class iceconfig:
return (nx, ny, "ram/RDATA_%d" % (8+func))
elif self.device == "5k":
return (nx, ny, "ram/RDATA_%d" % (7-func))
- elif self.device == "8k":
+ elif self.device == "8k" or self.device == "lm4k":
return (nx, ny, "ram/RDATA_%d" % (7-func))
else:
assert False
@@ -500,7 +543,7 @@ class iceconfig:
funcnets |= self.follow_funcnet(x, y, int(match.group(1)) % 8)
elif self.device == "5k":
funcnets |= self.follow_funcnet(x, y, 7 - int(match.group(1)) % 8)
- elif self.device == "8k":
+ elif self.device == "8k" or self.device == "lm4k":
funcnets |= self.follow_funcnet(x, y, 7 - int(match.group(1)) % 8)
else:
assert False
@@ -714,7 +757,7 @@ class iceconfig:
add_seed_segments(idx, tile, logictile_db)
elif self.device == "5k":
add_seed_segments(idx, tile, logictile_5k_db)
- elif self.device == "8k":
+ elif self.device == "8k" or self.device == "lm4k":
add_seed_segments(idx, tile, logictile_8k_db)
elif self.device == "384":
add_seed_segments(idx, tile, logictile_384_db)
@@ -726,7 +769,7 @@ class iceconfig:
add_seed_segments(idx, tile, rambtile_db)
elif self.device == "5k":
add_seed_segments(idx, tile, rambtile_8k_db)
- elif self.device == "8k":
+ elif self.device == "8k" or self.device == "lm4k":
add_seed_segments(idx, tile, rambtile_8k_db)
else:
assert False
@@ -736,7 +779,7 @@ class iceconfig:
add_seed_segments(idx, tile, ramttile_db)
elif self.device == "5k":
add_seed_segments(idx, tile, ramttile_8k_db)
- elif self.device == "8k":
+ elif self.device == "8k" or self.device == "lm4k":
add_seed_segments(idx, tile, ramttile_8k_db)
else:
assert False
@@ -881,7 +924,7 @@ class iceconfig:
self.extra_bits.add((int(line[1]), int(line[2]), int(line[3])))
continue
if line[0] == ".device":
- assert line[1] in ["1k", "5k", "8k", "384"]
+ assert line[1] in ["1k", "lm4k", "5k", "8k", "384"]
self.device = line[1]
continue
if line[0] == ".warmboot":
@@ -1303,7 +1346,8 @@ def run_checks_neigh():
print("Running consistency checks on neighbour finder..")
ic = iceconfig()
# ic.setup_empty_1k()
- ic.setup_empty_5k()
+ ic.setup_empty_lm4k()
+ # ic.setup_empty_5k()
# ic.setup_empty_8k()
# ic.setup_empty_384()
@@ -1353,7 +1397,8 @@ def parse_db(text, device="1k"):
continue
line = line_1k
elif line_8k != line:
- if device != "8k" and device != "5k": # global network is the same for 8k and 5k
+ # global network is the same for 8k, 5k, and lm4k
+ if device != "8k" and device != "5k" and device != "lm4k":
continue
line = line_8k
elif line_384 != line:
@@ -1378,6 +1423,16 @@ extra_bits_db = {
(0, 330, 143): ("padin_glb_netwk", "6"), # (0 0) (330 143) (330 143) routing T_0_0.padin_6 <X> T_0_0.glb_netwk_6
(0, 331, 143): ("padin_glb_netwk", "7"),
},
+ "lm4k": {
+ (0, 654, 174): ("padin_glb_netwk", "0"),
+ (0, 655, 174): ("padin_glb_netwk", "1"),
+ (1, 654, 175): ("padin_glb_netwk", "2"),
+ (1, 655, 175): ("padin_glb_netwk", "3"),
+ (1, 654, 174): ("padin_glb_netwk", "4"), # HSOSC
+ (1, 655, 174): ("padin_glb_netwk", "5"), # LSOSC
+ (0, 654, 175): ("padin_glb_netwk", "6"),
+ (0, 655, 175): ("padin_glb_netwk", "7"),
+ },
"5k": {
(0, 690, 334): ("padin_glb_netwk", "0"), # check
(0, 691, 334): ("padin_glb_netwk", "1"), # good
@@ -1431,6 +1486,16 @@ gbufin_db = {
(13, 31, 1), #checked
(19, 31, 2), #checked
],
+ "lm4k": [
+ ( 6, 0, 6),
+ (12, 0, 5),
+ (13, 0, 0),
+ (19, 0, 7),
+ ( 6, 21, 3),
+ (12, 21, 4),
+ (13, 21, 1),
+ (19, 21, 2),
+ ],
"8k": [
(33, 16, 7),
( 0, 16, 6),
@@ -1468,6 +1533,10 @@ iolatch_db = {
( 5, 0),
( 8, 17),
],
+ "lm4k": [
+ (14, 0),
+ (14, 21)
+ ],
"5k": [
(14, 0),
(14, 31),
@@ -1500,6 +1569,12 @@ warmbootinfo_db = {
"S0": ( 23, 0, "fabout" ),
"S1": ( 24, 0, "fabout" ),
},
+ "lm4k": {
+ # These are the right locations but may be the wrong order.
+ "BOOT": ( 23, 0, "fabout" ),
+ "S0": ( 24, 0, "fabout" ),
+ "S1": ( 25, 1, "fabout" ),
+ },
"8k": {
"BOOT": ( 31, 0, "fabout" ),
"S0": ( 33, 1, "fabout" ),
@@ -1619,6 +1694,99 @@ pllinfo_db = {
"SDI": ( 4, 0, "fabout"),
"SCLK": ( 3, 0, "fabout"),
},
+ "lm4k": {
+ "LOC" : (12, 0),
+
+ # 3'b000 = "DISABLED"
+ # 3'b010 = "SB_PLL40_PAD"
+ # 3'b100 = "SB_PLL40_2_PAD"
+ # 3'b110 = "SB_PLL40_2F_PAD"
+ # 3'b011 = "SB_PLL40_CORE"
+ # 3'b111 = "SB_PLL40_2F_CORE"
+ "PLLTYPE_0": (12, 0, "PLLCONFIG_5"),
+ "PLLTYPE_1": (14, 0, "PLLCONFIG_1"),
+ "PLLTYPE_2": (14, 0, "PLLCONFIG_3"),
+
+ # 3'b000 = "DELAY"
+ # 3'b001 = "SIMPLE"
+ # 3'b010 = "PHASE_AND_DELAY"
+ # 3'b110 = "EXTERNAL"
+ "FEEDBACK_PATH_0": (14, 0, "PLLCONFIG_5"),
+ "FEEDBACK_PATH_1": (11, 0, "PLLCONFIG_9"),
+ "FEEDBACK_PATH_2": (12, 0, "PLLCONFIG_1"),
+
+ # 1'b0 = "FIXED"
+ # 1'b1 = "DYNAMIC" (also set FDA_FEEDBACK=4'b1111)
+ "DELAY_ADJMODE_FB": (13, 0, "PLLCONFIG_4"),
+
+ # 1'b0 = "FIXED"
+ # 1'b1 = "DYNAMIC" (also set FDA_RELATIVE=4'b1111)
+ "DELAY_ADJMODE_REL": (13, 0, "PLLCONFIG_9"),
+
+ # 2'b00 = "GENCLK"
+ # 2'b01 = "GENCLK_HALF"
+ # 2'b10 = "SHIFTREG_90deg"
+ # 2'b11 = "SHIFTREG_0deg"
+ "PLLOUT_SELECT_A_0": (12, 0, "PLLCONFIG_6"),
+ "PLLOUT_SELECT_A_1": (12, 0, "PLLCONFIG_7"),
+ # 2'b00 = "GENCLK"
+ # 2'b01 = "GENCLK_HALF"
+ # 2'b10 = "SHIFTREG_90deg"
+ # 2'b11 = "SHIFTREG_0deg"
+ "PLLOUT_SELECT_B_0": (12, 0, "PLLCONFIG_2"),
+ "PLLOUT_SELECT_B_1": (12, 0, "PLLCONFIG_3"),
+
+ # Numeric Parameters
+ "SHIFTREG_DIV_MODE": (12, 0, "PLLCONFIG_4"),
+ "FDA_FEEDBACK_0": (12, 0, "PLLCONFIG_9"),
+ "FDA_FEEDBACK_1": (13, 0, "PLLCONFIG_1"),
+ "FDA_FEEDBACK_2": (13, 0, "PLLCONFIG_2"),
+ "FDA_FEEDBACK_3": (13, 0, "PLLCONFIG_3"),
+ "FDA_RELATIVE_0": (13, 0, "PLLCONFIG_5"),
+ "FDA_RELATIVE_1": (13, 0, "PLLCONFIG_6"),
+ "FDA_RELATIVE_2": (13, 0, "PLLCONFIG_7"),
+ "FDA_RELATIVE_3": (13, 0, "PLLCONFIG_8"),
+ "DIVR_0": (10, 0, "PLLCONFIG_1"),
+ "DIVR_1": (10, 0, "PLLCONFIG_2"),
+ "DIVR_2": (10, 0, "PLLCONFIG_3"),
+ "DIVR_3": (10, 0, "PLLCONFIG_4"),
+ "DIVF_0": (10, 0, "PLLCONFIG_5"),
+ "DIVF_1": (10, 0, "PLLCONFIG_6"),
+ "DIVF_2": (10, 0, "PLLCONFIG_7"),
+ "DIVF_3": (10, 0, "PLLCONFIG_8"),
+ "DIVF_4": (10, 0, "PLLCONFIG_9"),
+ "DIVF_5": (11, 0, "PLLCONFIG_1"),
+ "DIVF_6": (11, 0, "PLLCONFIG_2"),
+ "DIVQ_0": (11, 0, "PLLCONFIG_3"),
+ "DIVQ_1": (11, 0, "PLLCONFIG_4"),
+ "DIVQ_2": (11, 0, "PLLCONFIG_5"),
+ "FILTER_RANGE_0": (11, 0, "PLLCONFIG_6"),
+ "FILTER_RANGE_1": (11, 0, "PLLCONFIG_7"),
+ "FILTER_RANGE_2": (11, 0, "PLLCONFIG_8"),
+ "TEST_MODE": (12, 0, "PLLCONFIG_8"),
+
+ # PLL Ports
+ # TODO(awygle) confirm these
+ "PLLOUT_A": ( 12, 0, 1),
+ "PLLOUT_B": ( 13, 0, 0),
+ "REFERENCECLK": ( 10, 0, "fabout"),
+ "EXTFEEDBACK": ( 11, 0, "fabout"),
+ "DYNAMICDELAY_0": ( 1, 0, "fabout"),
+ "DYNAMICDELAY_1": ( 2, 0, "fabout"),
+ "DYNAMICDELAY_2": ( 3, 0, "fabout"),
+ "DYNAMICDELAY_3": ( 4, 0, "fabout"),
+ "DYNAMICDELAY_4": ( 5, 0, "fabout"),
+ "DYNAMICDELAY_5": ( 7, 0, "fabout"),
+ "DYNAMICDELAY_6": ( 8, 0, "fabout"),
+ "DYNAMICDELAY_7": ( 9, 0, "fabout"),
+ "LOCK": ( 1, 1, "neigh_op_bnl_1"), #check?
+ "BYPASS": ( 15, 0, "fabout"),
+ "RESETB": ( 16, 0, "fabout"),
+ "LATCHINPUTVALUE": ( 14, 0, "fabout"),
+ "SDO": ( 24, 1, "neigh_op_bnr_3"), #check?
+ "SDI": ( 18, 0, "fabout"),
+ "SCLK": ( 17, 0, "fabout"),
+ },
"5k": {
"LOC" : (12, 31),
@@ -1910,6 +2078,18 @@ padin_pio_db = {
( 6, 0, 1), # glb_netwk_6
( 6, 17, 1), # glb_netwk_7
],
+ "lm4k": [
+ (19, 0, 0), #0 fixed
+ ( 6, 0, 1), #1 fixed
+ (13, 21, 0), #2 fixed
+ (13, 0, 0), #3 fixed
+
+ (19, 21, 0), #These two are questionable, but keep the order correct
+ ( 6, 21, 0), #They may need to be fixed if other package options are added.
+
+ (12, 0, 1), #6 fixed
+ (12, 21, 1), #7 fixed
+ ],
"5k": [
(19, 0, 1), #0 fixed
( 6, 0, 1), #1 fixed
@@ -2308,6 +2488,45 @@ ieren_db = {
( 7, 6, 0, 7, 6, 1),
( 7, 6, 1, 7, 6, 0),
],
+ "lm4k": [
+ ( 6, 0, 0, 6, 0, 1),
+ ( 6, 0, 1, 6, 0, 0),
+ ( 7, 0, 0, 7, 0, 1),
+ ( 7, 0, 1, 7, 0, 0),
+ ( 8, 0, 0, 8, 0, 1),
+ ( 8, 0, 1, 8, 0, 0),
+ (10, 0, 0, 10, 0, 1),
+ (12, 0, 0, 12, 0, 1),
+ (12, 0, 1, 12, 0, 0),
+ (13, 0, 0, 13, 0, 1),
+ (13, 0, 1, 13, 0, 0),
+ (19, 0, 0, 19, 0, 1),
+ (19, 0, 1, 19, 0, 0),
+ (21, 0, 0, 21, 0, 1),
+ (21, 0, 1, 21, 0, 0),
+ (22, 0, 0, 22, 0, 1),
+ (23, 0, 0, 23, 0, 1),
+ (23, 0, 1, 23, 0, 0),
+ (24, 0, 0, 24, 0, 1),
+ (24, 0, 1, 24, 0, 0),
+ ( 4, 21, 0, 4, 21, 1),
+ ( 4, 21, 1, 4, 21, 0),
+ ( 5, 21, 1, 5, 21, 0),
+ ( 6, 21, 0, 6, 21, 1),
+ ( 7, 21, 1, 7, 21, 0),
+ ( 9, 21, 0, 9, 21, 1),
+ (12, 21, 1, 12, 21, 0),
+ (13, 21, 0, 13, 21, 1),
+ (15, 21, 0, 15, 21, 1),
+ (17, 21, 1, 17, 21, 0),
+ (18, 21, 0, 18, 21, 1),
+ (19, 21, 0, 19, 21, 1),
+ (19, 21, 1, 19, 21, 0),
+ (21, 21, 1, 21, 21, 0),
+ (22, 21, 1, 22, 21, 0),
+ (23, 21, 0, 23, 21, 1),
+ (23, 21, 1, 23, 21, 0),
+ ],
"5k": [
( 8, 0, 0, 8, 0, 1),
( 9, 0, 1, 9, 0, 0),
@@ -3459,6 +3678,101 @@ pinloc_db = {
( "L8", 29, 0, 0),
("L10", 31, 0, 0),
],
+ "8k-bg121:4k": [
+ ( "A1", 2, 33, 0),
+ ( "A2", 3, 33, 1),
+ ( "A3", 3, 33, 0),
+ ( "A4", 9, 33, 0),
+ ( "A5", 11, 33, 0),
+ ( "A6", 11, 33, 1),
+ ( "A7", 19, 33, 1),
+ ( "A8", 20, 33, 1),
+ ( "A9", 26, 33, 1),
+ ("A10", 30, 33, 1),
+ ("A11", 31, 33, 1),
+ ( "B1", 0, 30, 1),
+ ( "B2", 0, 30, 0),
+ ( "B3", 4, 33, 0),
+ ( "B4", 5, 33, 0),
+ ( "B5", 10, 33, 1),
+ ( "B6", 16, 33, 1),
+ ( "B7", 17, 33, 0),
+ ( "B8", 27, 33, 0),
+ ( "B9", 28, 33, 1),
+ ("B11", 33, 28, 0),
+ ( "C1", 0, 25, 0),
+ ( "C2", 0, 25, 1),
+ ( "C3", 0, 27, 0),
+ ( "C4", 0, 27, 1),
+ ( "C7", 20, 33, 0),
+ ( "C8", 26, 33, 0),
+ ( "C9", 29, 33, 1),
+ ("C11", 33, 27, 1),
+ ( "D1", 0, 22, 0),
+ ( "D2", 0, 21, 1),
+ ( "D3", 0, 21, 0),
+ ( "D5", 8, 33, 1),
+ ( "D7", 25, 33, 0),
+ ( "D9", 33, 21, 0),
+ ("D10", 33, 24, 1),
+ ("D11", 33, 23, 1),
+ ( "E1", 0, 22, 1),
+ ( "E2", 0, 20, 1),
+ ( "E3", 0, 20, 0),
+ ( "E8", 33, 20, 1),
+ ( "E9", 33, 19, 1),
+ ("E10", 33, 17, 0),
+ ("E11", 33, 21, 1),
+ ( "F1", 0, 18, 1),
+ ( "F2", 0, 18, 0),
+ ( "F3", 0, 17, 0),
+ ( "F4", 0, 17, 1),
+ ( "F9", 33, 15, 0),
+ ("F10", 33, 14, 1),
+ ("F11", 33, 16, 1),
+ ( "G1", 0, 16, 1),
+ ( "G2", 0, 16, 0),
+ ( "G3", 0, 12, 1),
+ ( "G8", 33, 5, 1),
+ ( "G9", 33, 10, 1),
+ ("G10", 33, 6, 1),
+ ("G11", 33, 11, 0),
+ ( "H1", 0, 11, 1),
+ ( "H2", 0, 11, 0),
+ ( "H3", 0, 12, 0),
+ ( "H7", 20, 0, 1),
+ ( "H9", 29, 0, 1),
+ ("H10", 33, 4, 1),
+ ("H11", 33, 6, 0),
+ ( "J1", 0, 6, 1),
+ ( "J2", 0, 4, 0),
+ ( "J3", 4, 0, 1),
+ ( "J4", 8, 0, 0),
+ ( "J5", 15, 0, 0),
+ ( "J7", 20, 0, 0),
+ ( "J8", 22, 0, 1),
+ ( "J9", 30, 0, 1),
+ ("J10", 33, 5, 0),
+ ("J11", 33, 3, 1),
+ ( "K1", 0, 6, 0),
+ ( "K2", 0, 4, 1),
+ ( "K3", 7, 0, 1),
+ ( "K4", 12, 0, 1),
+ ( "K5", 15, 0, 1),
+ ( "K6", 17, 0, 0),
+ ( "K7", 21, 0, 1),
+ ( "K9", 30, 0, 0),
+ ("K10", 31, 0, 1),
+ ("K11", 33, 4, 0),
+ ( "L1", 4, 0, 0),
+ ( "L2", 6, 0, 1),
+ ( "L3", 11, 0, 1),
+ ( "L4", 12, 0, 0),
+ ( "L5", 16, 0, 1),
+ ( "L7", 24, 0, 0),
+ ( "L8", 29, 0, 0),
+ ("L10", 31, 0, 0),
+ ],
"8k-cm225:4k": [
( "A1", 1, 33, 1),
( "A2", 3, 33, 1),
@@ -3788,6 +4102,101 @@ pinloc_db = {
( "L8", 29, 0, 0),
("L10", 31, 0, 0),
],
+ "8k-bg121": [
+ ( "A1", 2, 33, 0),
+ ( "A2", 3, 33, 1),
+ ( "A3", 3, 33, 0),
+ ( "A4", 9, 33, 0),
+ ( "A5", 11, 33, 0),
+ ( "A6", 11, 33, 1),
+ ( "A7", 19, 33, 1),
+ ( "A8", 20, 33, 1),
+ ( "A9", 26, 33, 1),
+ ("A10", 30, 33, 1),
+ ("A11", 31, 33, 1),
+ ( "B1", 0, 30, 1),
+ ( "B2", 0, 30, 0),
+ ( "B3", 4, 33, 0),
+ ( "B4", 5, 33, 0),
+ ( "B5", 10, 33, 1),
+ ( "B6", 16, 33, 1),
+ ( "B7", 17, 33, 0),
+ ( "B8", 27, 33, 0),
+ ( "B9", 28, 33, 1),
+ ("B11", 33, 28, 0),
+ ( "C1", 0, 25, 0),
+ ( "C2", 0, 25, 1),
+ ( "C3", 0, 27, 0),
+ ( "C4", 0, 27, 1),
+ ( "C7", 20, 33, 0),
+ ( "C8", 26, 33, 0),
+ ( "C9", 29, 33, 1),
+ ("C11", 33, 27, 1),
+ ( "D1", 0, 22, 0),
+ ( "D2", 0, 21, 1),
+ ( "D3", 0, 21, 0),
+ ( "D5", 8, 33, 1),
+ ( "D7", 25, 33, 0),
+ ( "D9", 33, 21, 0),
+ ("D10", 33, 24, 1),
+ ("D11", 33, 23, 1),
+ ( "E1", 0, 22, 1),
+ ( "E2", 0, 20, 1),
+ ( "E3", 0, 20, 0),
+ ( "E8", 33, 20, 1),
+ ( "E9", 33, 19, 1),
+ ("E10", 33, 17, 0),
+ ("E11", 33, 21, 1),
+ ( "F1", 0, 18, 1),
+ ( "F2", 0, 18, 0),
+ ( "F3", 0, 17, 0),
+ ( "F4", 0, 17, 1),
+ ( "F9", 33, 15, 0),
+ ("F10", 33, 14, 1),
+ ("F11", 33, 16, 1),
+ ( "G1", 0, 16, 1),
+ ( "G2", 0, 16, 0),
+ ( "G3", 0, 12, 1),
+ ( "G8", 33, 5, 1),
+ ( "G9", 33, 10, 1),
+ ("G10", 33, 6, 1),
+ ("G11", 33, 11, 0),
+ ( "H1", 0, 11, 1),
+ ( "H2", 0, 11, 0),
+ ( "H3", 0, 12, 0),
+ ( "H7", 20, 0, 1),
+ ( "H9", 29, 0, 1),
+ ("H10", 33, 4, 1),
+ ("H11", 33, 6, 0),
+ ( "J1", 0, 6, 1),
+ ( "J2", 0, 4, 0),
+ ( "J3", 4, 0, 1),
+ ( "J4", 8, 0, 0),
+ ( "J5", 15, 0, 0),
+ ( "J7", 20, 0, 0),
+ ( "J8", 22, 0, 1),
+ ( "J9", 30, 0, 1),
+ ("J10", 33, 5, 0),
+ ("J11", 33, 3, 1),
+ ( "K1", 0, 6, 0),
+ ( "K2", 0, 4, 1),
+ ( "K3", 7, 0, 1),
+ ( "K4", 12, 0, 1),
+ ( "K5", 15, 0, 1),
+ ( "K6", 17, 0, 0),
+ ( "K7", 21, 0, 1),
+ ( "K9", 30, 0, 0),
+ ("K10", 31, 0, 1),
+ ("K11", 33, 4, 0),
+ ( "L1", 4, 0, 0),
+ ( "L2", 6, 0, 1),
+ ( "L3", 11, 0, 1),
+ ( "L4", 12, 0, 0),
+ ( "L5", 16, 0, 1),
+ ( "L7", 24, 0, 0),
+ ( "L8", 29, 0, 0),
+ ("L10", 31, 0, 0),
+ ],
"8k-cm225": [
( "A1", 1, 33, 1),
( "A2", 3, 33, 1),
@@ -4425,6 +4834,45 @@ pinloc_db = {
( "F2", 19, 0, 1),
( "F4", 12, 0, 1),
( "F5", 6, 0, 1),
+ ],
+ "lm4k-cm49": [
+ ( "A1", 5, 21, 1),
+ ( "A2", 6, 21, 0),
+ ( "A3", 12, 21, 1),
+ ( "A4", 13, 21, 0),
+ ( "A5", 17, 21, 1),
+ ( "A6", 19, 21, 1),
+ ( "A7", 22, 21, 1),
+ ( "B1", 4, 21, 1),
+ ( "B2", 7, 21, 1),
+ ( "B4", 15, 21, 0),
+ ( "B6", 18, 21, 0),
+ ( "B7", 23, 21, 1),
+ ( "C1", 4, 21, 0),
+ ( "C3", 9, 21, 0),
+ ( "C4", 19, 21, 0),
+ ( "C6", 21, 21, 1),
+ ( "C7", 23, 21, 0),
+ ( "D1", 7, 0, 1),
+ ( "D2", 6, 0, 1),
+ ( "D3", 10, 0, 0),
+ ( "D6", 19, 0, 1),
+ ( "D7", 21, 0, 0),
+ ( "E1", 6, 0, 0),
+ ( "E2", 12, 0, 1),
+ ( "E3", 7, 0, 0),
+ ( "E4", 12, 0, 0),
+ ( "E5", 19, 0, 0),
+ ( "E6", 24, 0, 1),
+ ( "E7", 22, 0, 0),
+ ( "F2", 8, 0, 1),
+ ( "F3", 8, 0, 0),
+ ( "F4", 13, 0, 1),
+ ( "F5", 23, 0, 0),
+ ( "F6", 24, 0, 0),
+ ( "F7", 21, 0, 1),
+ ( "G3", 13, 0, 0),
+ ( "G6", 23, 0, 1),
]
}
@@ -4769,6 +5217,10 @@ extra_cells_db = {
"RGB2_CURRENT_5": (0, 30, "CBIT_7"),
"CURRENT_MODE": (0, 28, "CBIT_4"),
+ "RGB0": (4, 31, 0),
+ "RGB1": (5, 31, 0),
+ "RGB2": (6, 31, 0),
+
},
("I2C", (0, 31, 0)): {
"I2CIRQ": (0, 30, "slf_op_7"),
@@ -4984,7 +5436,16 @@ extra_cells_db = {
"PWMOUT1": (0, 28, "slf_op_5"),
"PWMOUT2": (0, 28, "slf_op_6"),
},
-
+ ("IO_I3C", (25, 27, 0)): {
+ "PU_ENB": (25, 27, "lutff_6/in_0"),
+ "WEAK_PU_ENB": (25, 27, "lutff_4/in_0"),
+ "PACKAGE_PIN": (19, 31, 0)
+ },
+ ("IO_I3C", (25, 27, 1)): {
+ "PU_ENB": (25, 27, "lutff_7/in_0"),
+ "WEAK_PU_ENB": (25, 27, "lutff_5/in_0"),
+ "PACKAGE_PIN": (19, 31, 1)
+ }
}
}
diff --git a/icebox/icebox_chipdb.py b/icebox/icebox_chipdb.py
index fc25403..6497ae2 100755
--- a/icebox/icebox_chipdb.py
+++ b/icebox/icebox_chipdb.py
@@ -19,6 +19,7 @@ import icebox
import getopt, sys, re
mode_384 = False
+mode_lm4k = False
mode_5k = False
mode_8k = False
@@ -34,11 +35,14 @@ Usage: icebox_chipdb [options] [bitmap.asc]
-8
create chipdb for 8k device
+
+ -4
+ create chipdb for lm4k device
""")
sys.exit(0)
try:
- opts, args = getopt.getopt(sys.argv[1:], "358")
+ opts, args = getopt.getopt(sys.argv[1:], "3584")
except:
usage()
@@ -49,6 +53,8 @@ for o, a in opts:
mode_5k = True
elif o == "-3":
mode_384 = True
+ elif o == "-4":
+ mode_lm4k = True
else:
usage()
@@ -59,6 +65,8 @@ elif mode_5k:
ic.setup_empty_5k()
elif mode_384:
ic.setup_empty_384()
+elif mode_lm4k:
+ ic.setup_empty_lm4k()
else:
ic.setup_empty_1k()
@@ -319,7 +327,7 @@ for dsploc in ic.dsp_tiles[0]:
print()
if ic.device in icebox.extra_cells_db:
- for cell in icebox.extra_cells_db[ic.device]:
+ for cell in sorted(icebox.extra_cells_db[ic.device]):
name, loc = cell
x, y, z = loc
print(".extra_cell %d %d %d %s" % (x, y, z, name))
@@ -329,7 +337,7 @@ if ic.device in icebox.extra_cells_db:
print()
if ic.device in icebox.spram_db:
- for cell in icebox.spram_db[ic.device]:
+ for cell in sorted(icebox.spram_db[ic.device]):
loc = cell
x, y, z = loc
print(".extra_cell %d %d %d SPRAM" % (x, y, z))
diff --git a/icebox/icebox_vlog.py b/icebox/icebox_vlog.py
index 873e4b2..5736011 100755
--- a/icebox/icebox_vlog.py
+++ b/icebox/icebox_vlog.py
@@ -25,6 +25,7 @@ check_ieren = False
check_driver = False
lookup_symbols = False
do_collect = False
+package = None
pcf_data = dict()
portnames = set()
unmatched_ports = set()
@@ -56,6 +57,10 @@ Usage: icebox_vlog [options] [bitmap.asc]
like -p, enable some hacks for pcf files created
by the iCEcube2 placer.
+ -d <package>
+ use the given package to obtain chip pin numbers,
+ rather than the default for a device
+
-c
collect multi-bit ports
@@ -68,7 +73,7 @@ Usage: icebox_vlog [options] [bitmap.asc]
sys.exit(0)
try:
- opts, args = getopt.getopt(sys.argv[1:], "sSlLap:P:n:cRD")
+ opts, args = getopt.getopt(sys.argv[1:], "sSlLap:P:n:d:cRD")
except:
usage()
@@ -111,6 +116,8 @@ for o, a in opts:
else:
pinloc = (line[2],)
pcf_data[pinloc] = p
+ elif o == "-d":
+ package = a
elif o == "-c":
do_collect = True
elif o == "-R":
@@ -285,7 +292,7 @@ for segs in sorted(ic.group_segments(extra_connections=extra_connections, extra_
idx = (s[0], s[1], int(match.group(1)))
p = "io_%d_%d_%d" % idx
if lookup_pins or pcf_data:
- for entry in ic.pinloc_db():
+ for entry in ic.pinloc_db(package):
if idx[0] == entry[1] and idx[1] == entry[2] and idx[2] == entry[3]:
if (entry[0],) in pcf_data:
p = pcf_data[(entry[0],)]
diff --git a/icebram/icebram.cc b/icebram/icebram.cc
index 245a0ab..a796f92 100644
--- a/icebram/icebram.cc
+++ b/icebram/icebram.cc
@@ -28,6 +28,10 @@
#include <fstream>
#include <iostream>
+#ifdef __EMSCRIPTEN__
+#include <emscripten.h>
+#endif
+
using std::map;
using std::pair;
using std::vector;
@@ -109,6 +113,18 @@ void help(const char *cmd)
int main(int argc, char **argv)
{
+#ifdef __EMSCRIPTEN__
+ EM_ASM(
+ if (ENVIRONMENT_IS_NODE)
+ {
+ FS.mkdir('/hostcwd');
+ FS.mount(NODEFS, { root: '.' }, '/hostcwd');
+ FS.mkdir('/hostfs');
+ FS.mount(NODEFS, { root: '/' }, '/hostfs');
+ }
+ );
+#endif
+
bool verbose = false;
bool generate = false;
diff --git a/icefuzz/Makefile b/icefuzz/Makefile
index a2a40b4..ea9f3e0 100644
--- a/icefuzz/Makefile
+++ b/icefuzz/Makefile
@@ -18,6 +18,11 @@ ifeq ($(DEVICECLASS), 5k)
RAM_SUFFIX := _8k
endif
+ifeq ($(DEVICECLASS), 4k)
+ DEVICE := lm4k-cm49
+ RAM_SUFFIX := _8k
+endif
+
ifeq ($(DEVICECLASS), 8k)
DEVICE := hx8k-ct256
RAM_SUFFIX = _8k
diff --git a/icefuzz/fuzzconfig.py b/icefuzz/fuzzconfig.py
index a50cce5..f03c815 100644
--- a/icefuzz/fuzzconfig.py
+++ b/icefuzz/fuzzconfig.py
@@ -60,6 +60,25 @@ elif device_class == "1k":
""".split()
gpins = "20 21 49 50 93 94 128 129".split()
+
+elif device_class == "4k":
+ num_ramb40 = 20
+ num_iobanks = 2
+ num_dsp = 0
+
+ # TODO(awygle) add F5 G6 F6 E6 which are constrained to (config) SPI.
+ pins = """
+ A1 A2 A3 A4 A5 A6 A7
+ B1 B2 B4 B6 B7
+ C1 C3 C4 C6 C7
+ D1 D2 D3 D6 D7
+ E1 E2 E3 E4 E5 E7
+ F2 F3 F4 F7
+ G3
+ """.split()
+
+ gpins = "A3 A4 D2 E2 E5 G3".split()
+
elif device_class == "5k":
num_ramb40 = 30
num_iobanks = 2
diff --git a/icefuzz/icecube.sh b/icefuzz/icecube.sh
index 5a1a7f2..832c15e 100644
--- a/icefuzz/icecube.sh
+++ b/icefuzz/icecube.sh
@@ -56,6 +56,11 @@ if [ "$1" == "-up5k" ]; then
shift
fi
+if [ "$1" == "-lm4k" ]; then
+ ICEDEV=lm4k-cm49
+ shift
+fi
+
set -ex
set -- ${1%.v}
icecubedir="${ICECUBEDIR:-/opt/lscc/iCEcube2.2015.08}"
@@ -187,6 +192,42 @@ case "${ICEDEV:-hx1k-tq144}" in
iCEPACKAGE="UWG30"
iCE40DEV="iCE40UP5K"
;;
+ lm4k-cm49)
+ iCEPACKAGE="CM49"
+ iCE40DEV="iCE40LM4K"
+ ;;
+ lm4k-cm36)
+ iCEPACKAGE="CM36"
+ iCE40DEV="iCE40LM4K"
+ ;;
+ lm4k-swg25tr)
+ iCEPACKAGE="SWG25TR"
+ iCE40DEV="iCE40LM4K"
+ ;;
+ lm2k-cm49)
+ iCEPACKAGE="CM49"
+ iCE40DEV="iCE40LM2K"
+ ;;
+ lm2k-cm36)
+ iCEPACKAGE="CM36"
+ iCE40DEV="iCE40LM2K"
+ ;;
+ lm2k-swg25tr)
+ iCEPACKAGE="SWG25TR"
+ iCE40DEV="iCE40LM2K"
+ ;;
+ lm1k-cm49)
+ iCEPACKAGE="CM49"
+ iCE40DEV="iCE40LM1K"
+ ;;
+ lm1k-cm36)
+ iCEPACKAGE="CM36"
+ iCE40DEV="iCE40LM1K"
+ ;;
+ lm1k-swg25tr)
+ iCEPACKAGE="SWG25TR"
+ iCE40DEV="iCE40LM1K"
+ ;;
*)
echo "ERROR: Invalid \$ICEDEV device config '$ICEDEV'."
exit 1
@@ -238,6 +279,21 @@ case "$iCE40DEV" in
libfile="ice40UP5K.lib"
devfile="ICE40T05.dev"
;;
+ iCE40LM1K)
+ icetech="SBTiCE40LM"
+ libfile="ice40LM4K.lib"
+ devfile="ICE40R04.dev"
+ ;;
+ iCE40LM2K)
+ icetech="SBTiCE40LM"
+ libfile="ice40LM4K.lib"
+ devfile="ICE40R04.dev"
+ ;;
+ iCE40LM4K)
+ icetech="SBTiCE40LM"
+ libfile="ice40LM4K.lib"
+ devfile="ICE40R04.dev"
+ ;;
esac
(
diff --git a/icefuzz/tests/colbuf_io_lm4k.sh b/icefuzz/tests/colbuf_io_lm4k.sh
new file mode 100644
index 0000000..80d2f64
--- /dev/null
+++ b/icefuzz/tests/colbuf_io_lm4k.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+
+set -ex
+
+mkdir -p colbuf_io_lm4k.work
+cd colbuf_io_lm4k.work
+
+glb_pins="A3 A4 D2 E2 E5 G3"
+
+pins="
+ A1 A2 A3 A4 A5 A6 A7
+ B1 B2 B4 B6 B7
+ C1 C3 C4 C6 C7
+ D1 D2 D3 D6 D7
+ E1 E2 E3 E4 E5 E7
+ F2 F3 F4 F7
+ G3
+"
+pins="$( echo $pins )"
+
+for pin in $pins; do
+ pf="colbuf_io_lm4k_$pin"
+ gpin=$( echo $glb_pins | tr ' ' '\n' | grep -v $pin | sort -R | head -n1; )
+ cat > ${pf}.v <<- EOT
+ module top (input clk, data, output pin);
+ SB_IO #(
+ .PIN_TYPE(6'b 0101_00)
+ ) pin_obuf (
+ .PACKAGE_PIN(pin),
+ .OUTPUT_CLK(clk),
+ .D_OUT_0(data)
+ );
+ endmodule
+ EOT
+ echo "set_io pin $pin" > ${pf}.pcf
+ echo "set_io clk $gpin" >> ${pf}.pcf
+ ICEDEV=lm4k-cm49 bash ../../icecube.sh ${pf}.v > ${pf}.log 2>&1
+ ../../../icebox/icebox_explain.py ${pf}.asc > ${pf}.exp
+ rm -rf ${pf}.tmp
+done
+
diff --git a/icefuzz/tests/colbuf_logic_lm4k.sh b/icefuzz/tests/colbuf_logic_lm4k.sh
new file mode 100644
index 0000000..d1dc681
--- /dev/null
+++ b/icefuzz/tests/colbuf_logic_lm4k.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+set -ex
+
+mkdir -p colbuf_logic_lm4k.work
+cd colbuf_logic_lm4k.work
+
+glb_pins="A3 A4 D2 E2 E5 G3"
+
+for y in {1..32}; do
+for y in {1..20}; do
+ pf="colbuf_logic_lm4k_${x}_${y}"
+ gpin=$( echo $glb_pins | tr ' ' '\n' | sort -R | head -n1; )
+ cat > ${pf}.v <<- EOT
+ module top (input c, d, output q);
+ SB_DFF dff (
+ .C(c),
+ .D(d),
+ .Q(q)
+ );
+ endmodule
+ EOT
+ echo "set_location dff $x $y 0" > ${pf}.pcf
+ echo "set_io c $gpin" >> ${pf}.pcf
+ ICEDEV=lm4k-cm49 bash ../../icecube.sh ${pf}.v > ${pf}.log 2>&1
+ ../../../icebox/icebox_explain.py ${pf}.asc > ${pf}.exp
+ rm -rf ${pf}.tmp
+done; done
+
diff --git a/icefuzz/tests/colbuf_ram_lm4k.sh b/icefuzz/tests/colbuf_ram_lm4k.sh
new file mode 100755
index 0000000..86fb08a
--- /dev/null
+++ b/icefuzz/tests/colbuf_ram_lm4k.sh
@@ -0,0 +1,56 @@
+#!/bin/bash
+
+set -ex
+
+mkdir -p colbuf_ram_lm4k.work
+cd colbuf_ram_lm4k.work
+
+glb_pins="A3 A4 D2 E2 E5 G3"
+
+for x in 6 19; do
+for y in {1..20}; do
+ pf="colbuf_ram_lm4k_${x}_${y}"
+ gpin=$( echo $glb_pins | tr ' ' '\n' | sort -R | head -n1; )
+ if [ $((y % 2)) == 1 ]; then
+ clkport="WCLK"
+ other_clkport="RCLK"
+ else
+ clkport="RCLK"
+ other_clkport="WCLK"
+ fi
+ cat > ${pf}.v <<- EOT
+ module top (input c, oc, input [1:0] d, output [1:0] q);
+ wire gc;
+ SB_GB_IO #(
+ .PIN_TYPE(6'b 0000_00),
+ .PULLUP(1'b0),
+ .NEG_TRIGGER(1'b0),
+ .IO_STANDARD("SB_LVCMOS")
+ ) gbuf (
+ .PACKAGE_PIN(c),
+ .GLOBAL_BUFFER_OUTPUT(gc)
+ );
+ SB_RAM40_4K #(
+ .READ_MODE(3),
+ .WRITE_MODE(3)
+ ) ram40 (
+ .WADDR(11'b0),
+ .RADDR(11'b0),
+ .$clkport(gc),
+ .$other_clkport(oc),
+ .RDATA(q),
+ .WDATA(d),
+ .WE(1'b1),
+ .WCLKE(1'b1),
+ .RE(1'b1),
+ .RCLKE(1'b1)
+ );
+ endmodule
+ EOT
+ echo "set_location ram40 $x $((y - (1 - y%2))) 0" > ${pf}.pcf
+ echo "set_io oc 1" >> ${pf}.pcf
+ echo "set_io c $gpin" >> ${pf}.pcf
+ ICEDEV=lm4k-cm49 bash ../../icecube.sh ${pf}.v > ${pf}.log 2>&1
+ ../../../icebox/icebox_explain.py ${pf}.asc > ${pf}.exp
+ rm -rf ${pf}.tmp
+done; done
diff --git a/icefuzz/tests/io_latched_lm4k.sh b/icefuzz/tests/io_latched_lm4k.sh
new file mode 100644
index 0000000..5e6b63c
--- /dev/null
+++ b/icefuzz/tests/io_latched_lm4k.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+set -ex
+
+mkdir -p io_latched_lm4k.work
+cd io_latched_lm4k.work
+
+pins="
+ A1 A2 A3 A4 A5 A6 A7
+ B1 B2 B4 B6 B7
+ C1 C3 C4 C6 C7
+ D1 D2 D3 D6 D7
+ E1 E2 E3 E4 E5 E7
+ F2 F3 F4 F7
+ G3
+"
+pins="$( echo $pins )"
+
+for pin in $pins; do
+ pf="io_latched_$pin"
+ cp ../io_latched.v ${pf}.v
+ read pin_latch pin_data < <( echo $pins | tr ' ' '\n' | grep -v $pin | sort -R; )
+ {
+ echo "set_io pin $pin"
+ echo "set_io latch_in $pin_latch"
+ echo "set_io data_out $pin_data"
+ } > ${pf}.pcf
+ ICEDEV=lm4k-cm49 bash ../../icecube.sh ${pf}.v
+ ../../../icebox/icebox_vlog.py -SP ${pf}.psb ${pf}.asc > ${pf}.ve
+done
+
diff --git a/icefuzz/tests/ioctrl_lm4k.py b/icefuzz/tests/ioctrl_lm4k.py
new file mode 100644
index 0000000..67c0c6d
--- /dev/null
+++ b/icefuzz/tests/ioctrl_lm4k.py
@@ -0,0 +1,21 @@
+#!/usr/bin/env python3
+
+import fileinput
+
+for line in fileinput.input():
+ line = line.split()
+ if len(line) == 0:
+ continue
+ if line[0] == ".io_tile":
+ current_tile = (int(line[1]), int(line[2]))
+ if line[0] == "IoCtrl" and line[1] == "REN_0":
+ ren = (current_tile[0], current_tile[1], 0)
+ if line[0] == "IoCtrl" and line[1] == "REN_1":
+ ren = (current_tile[0], current_tile[1], 1)
+ if line[0] == "IOB_0":
+ iob = (current_tile[0], current_tile[1], 0)
+ if line[0] == "IOB_1":
+ iob = (current_tile[0], current_tile[1], 1)
+
+print("(%2d, %2d, %2d, %2d, %2d, %2d)," % (iob[0], iob[1], iob[2], ren[0], ren[1], ren[2]))
+
diff --git a/icefuzz/tests/ioctrl_lm4k.sh b/icefuzz/tests/ioctrl_lm4k.sh
new file mode 100755
index 0000000..9722038
--- /dev/null
+++ b/icefuzz/tests/ioctrl_lm4k.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+
+set -ex
+
+mkdir -p ioctrl.work
+cd ioctrl.work
+
+pins="
+ A1 A2 A3 A4 A5 A6 A7
+ B1 B2 B4 B6 B7
+ C1 C3 C4 C6 C7
+ D1 D2 D3 D6 D7
+ E1 E2 E3 E4 E5 E6 E7
+ F2 F3 F4 F5 F6 F7
+ G3 G6
+"
+
+pins="$( echo $pins )"
+
+for pin in $pins; do
+ pf="ioctrl_$pin"
+ echo "module top (output pin); assign pin = 1; endmodule" > ${pf}.v
+ echo "set_io pin $pin" > ${pf}.pcf
+ bash ../../icecube.sh -lm4k ${pf}.v > ${pf}.log 2>&1
+ ../../../icebox/icebox_explain.py ${pf}.asc > ${pf}.exp
+done
+
+set +x
+echo "--snip--"
+for pin in $pins; do
+ python3 ../ioctrl_5k.py ioctrl_${pin}.exp
+done | tee ioctrl_db.txt
+echo "--snap--"
diff --git a/icefuzz/tests/pllauto/pllauto.py b/icefuzz/tests/pllauto/pllauto.py
index 647be29..517417d 100755
--- a/icefuzz/tests/pllauto/pllauto.py
+++ b/icefuzz/tests/pllauto/pllauto.py
@@ -209,7 +209,8 @@ device = "up5k" #TODO: environment variable?
#and look for the stuck bit)
#TODO: clever code could get rid of this
divq_bit0 = {
- "up5k" : (11, 31, 3)
+ "up5k" : (11, 31, 3),
+ "lm4k" : (11, 0, 3)
}
#Return a list of PLL config bits in the format (x, y, bit)
diff --git a/icemulti/icemulti.cc b/icemulti/icemulti.cc
index 65ae6b6..4bc0919 100644
--- a/icemulti/icemulti.cc
+++ b/icemulti/icemulti.cc
@@ -24,6 +24,10 @@
#include <stdlib.h>
#include <string.h>
+#ifdef __EMSCRIPTEN__
+#include <emscripten.h>
+#endif
+
#define log(...) fprintf(stderr, __VA_ARGS__);
#define error(...) do { fprintf(stderr, "%s: ", program_short_name); fprintf(stderr, __VA_ARGS__); exit(EXIT_FAILURE); } while (0)
@@ -178,6 +182,18 @@ void usage()
int main(int argc, char **argv)
{
+#ifdef __EMSCRIPTEN__
+ EM_ASM(
+ if (ENVIRONMENT_IS_NODE)
+ {
+ FS.mkdir('/hostcwd');
+ FS.mount(NODEFS, { root: '.' }, '/hostcwd');
+ FS.mkdir('/hostfs');
+ FS.mount(NODEFS, { root: '/' }, '/hostfs');
+ }
+ );
+#endif
+
int c;
char *endptr = NULL;
bool coldboot = false;
diff --git a/icepack/icepack.cc b/icepack/icepack.cc
index ac3e8c6..325c853 100644
--- a/icepack/icepack.cc
+++ b/icepack/icepack.cc
@@ -34,6 +34,10 @@
#include <stdio.h>
#include <stdarg.h>
+#ifdef __EMSCRIPTEN__
+#include <emscripten.h>
+#endif
+
#ifdef _WIN32
#define __PRETTY_FUNCTION__ __FUNCTION__
#endif
@@ -414,6 +418,10 @@ void FpgaConfig::read_bits(std::istream &ifs)
this->device = "8k";
else if (this->cram_width == 692 && this->cram_height == 336)
this->device = "5k";
+ else if (this->cram_width == 692 && this->cram_height == 176)
+ this->device = "u4k";
+ else if (this->cram_width == 656 && this->cram_height == 176)
+ this->device = "lm4k";
else
error("Failed to detect chip type.\n");
@@ -681,6 +689,18 @@ void FpgaConfig::read_ascii(std::istream &ifs, bool nosleep)
this->bram_width = 160;
this->bram_height = 2 * 128;
} else
+ if (this->device == "u4k") {
+ this->cram_width = 692;
+ this->cram_height = 176;
+ this->bram_width = 80;
+ this->bram_height = 2 * 128;
+ } else
+ if (this->device == "lm4k") {
+ this->cram_width = 656;
+ this->cram_height = 176;
+ this->bram_width = 80;
+ this->bram_height = 2 * 128;
+ } else
error("Unsupported chip type '%s'.\n", this->device.c_str());
this->cram.resize(4);
@@ -1035,6 +1055,8 @@ int FpgaConfig::chip_width() const
if (this->device == "384") return 6;
if (this->device == "1k") return 12;
if (this->device == "5k") return 24;
+ if (this->device == "u4k") return 24;
+ if (this->device == "lm4k") return 24;
if (this->device == "8k") return 32;
panic("Unknown chip type '%s'.\n", this->device.c_str());
}
@@ -1044,6 +1066,8 @@ int FpgaConfig::chip_height() const
if (this->device == "384") return 8;
if (this->device == "1k") return 16;
if (this->device == "5k") return 30;
+ if (this->device == "u4k") return 20;
+ if (this->device == "lm4k") return 20;
if (this->device == "8k") return 32;
panic("Unknown chip type '%s'.\n", this->device.c_str());
}
@@ -1052,6 +1076,8 @@ vector<int> FpgaConfig::chip_cols() const
{
if (this->device == "384") return vector<int>({18, 54, 54, 54, 54});
if (this->device == "1k") return vector<int>({18, 54, 54, 42, 54, 54, 54});
+ if (this->device == "u4k") return vector<int>({54, 54, 54, 54, 54, 54, 42, 54, 54, 54, 54, 54, 54});
+ if (this->device == "lm4k") return vector<int>({18, 54, 54, 54, 54, 54, 42, 54, 54, 54, 54, 54, 54});
// Its IPConnect or Mutiplier block, five logic, ram, six logic.
if (this->device == "5k") return vector<int>({54, 54, 54, 54, 54, 54, 42, 54, 54, 54, 54, 54, 54});
if (this->device == "8k") return vector<int>({18, 54, 54, 54, 54, 54, 54, 54, 42, 54, 54, 54, 54, 54, 54, 54, 54});
@@ -1063,7 +1089,7 @@ string FpgaConfig::tile_type(int x, int y) const
if ((x == 0 || x == this->chip_width()+1) && (y == 0 || y == this->chip_height()+1)) return "corner";
// The sides on the 5k devices are IPConnect or DSP tiles
if (this->device == "5k" && (x == 0 || x == this->chip_width()+1)) {
- if( (y == 5) || (y == 10) || (y == 15) || (y == 23)) //check ordering here, tile 23-26 might be reversed
+ if( (y == 5) || (y == 10) || (y == 15) || (y == 23))
return "dsp0";
if( (y == 6) || (y == 11) || (y == 16) || (y == 24))
return "dsp1";
@@ -1073,6 +1099,19 @@ string FpgaConfig::tile_type(int x, int y) const
return "dsp3";
return "ipcon";
}
+
+ if (this->device == "u4k" && (x == 0 || x == this->chip_width()+1)) {
+ if( (y == 5) || (y == 13))
+ return "dsp0";
+ if( (y == 6) || (y == 14))
+ return "dsp1";
+ if( (y == 7) || (y == 15))
+ return "dsp2";
+ if( (y == 8) || (y == 16))
+ return "dsp3";
+ return "ipcon";
+ }
+
if ((x == 0 || x == this->chip_width()+1) || (y == 0 || y == this->chip_height()+1)) return "io";
if (this->device == "384") return "logic";
@@ -1082,7 +1121,7 @@ string FpgaConfig::tile_type(int x, int y) const
return "logic";
}
- if (this->device == "5k") {
+ if (this->device == "5k" || this->device == "u4k" || this->device == "lm4k") {
if (x == 6 || x == 19) return y % 2 == 1 ? "ramb" : "ramt";
return "logic";
}
@@ -1314,6 +1353,18 @@ void usage()
int main(int argc, char **argv)
{
+#ifdef __EMSCRIPTEN__
+ EM_ASM(
+ if (ENVIRONMENT_IS_NODE)
+ {
+ FS.mkdir('/hostcwd');
+ FS.mount(NODEFS, { root: '.' }, '/hostcwd');
+ FS.mkdir('/hostfs');
+ FS.mount(NODEFS, { root: '/' }, '/hostfs');
+ }
+ );
+#endif
+
vector<string> parameters;
bool unpack_mode = false;
bool nosleep_mode = false;
diff --git a/icepll/icepll.cc b/icepll/icepll.cc
index 6b6cedb..82bf3e3 100644
--- a/icepll/icepll.cc
+++ b/icepll/icepll.cc
@@ -20,6 +20,10 @@
#include <string.h>
#include <math.h>
+#ifdef __EMSCRIPTEN__
+#include <emscripten.h>
+#endif
+
const char *binstr(int v, int n)
{
static char buffer[16];
@@ -52,6 +56,9 @@ void help(const char *cmd)
printf(" -m\n");
printf(" Save PLL configuration as Verilog module (use with -f)\n");
printf("\n");
+ printf(" -n <module name>\n");
+ printf(" Specify different Verilog module name than the default 'pll'\n");
+ printf("\n");
printf(" -q\n");
printf(" Do not print PLL configuration to stdout\n");
printf("\n");
@@ -60,15 +67,28 @@ void help(const char *cmd)
int main(int argc, char **argv)
{
+#ifdef __EMSCRIPTEN__
+ EM_ASM(
+ if (ENVIRONMENT_IS_NODE)
+ {
+ FS.mkdir('/hostcwd');
+ FS.mount(NODEFS, { root: '.' }, '/hostcwd');
+ FS.mkdir('/hostfs');
+ FS.mount(NODEFS, { root: '/' }, '/hostfs');
+ }
+ );
+#endif
+
double f_pllin = 12;
double f_pllout = 60;
bool simple_feedback = true;
char* filename = NULL;
+ char* module_name = NULL;
bool save_as_module = false;
bool quiet = false;
int opt;
- while ((opt = getopt(argc, argv, "i:o:Smf:q")) != -1)
+ while ((opt = getopt(argc, argv, "i:o:Smf:n:q")) != -1)
{
switch (opt)
{
@@ -87,6 +107,9 @@ int main(int argc, char **argv)
case 'f':
filename = optarg;
break;
+ case 'n':
+ module_name = optarg;
+ break;
case 'q':
quiet = true;
break;
@@ -238,11 +261,11 @@ int main(int argc, char **argv)
f_pllin, f_pllout, best_fout);
// generate Verilog module
- fprintf(f, "module pll(\n"
+ fprintf(f, "module %s(\n"
"\tinput clock_in,\n"
"\toutput clock_out,\n"
"\toutput locked\n"
- "\t);\n\n"
+ "\t);\n\n", (module_name ? module_name : "pll")
);
// save iCE40 PLL tile configuration
diff --git a/iceprog/iceprog.c b/iceprog/iceprog.c
index c19de9d..29d4c22 100644
--- a/iceprog/iceprog.c
+++ b/iceprog/iceprog.c
@@ -42,6 +42,120 @@ static bool verbose = false;
static bool ftdic_latency_set = false;
static unsigned char ftdi_latency;
+/* MPSSE engine command definitions */
+enum mpsse_cmd
+{
+ /* Mode commands */
+ MC_SETB_LOW = 0x80, /* Set Data bits LowByte */
+ MC_READB_LOW = 0x81, /* Read Data bits LowByte */
+ MC_SETB_HIGH = 0x82, /* Set Data bits HighByte */
+ MC_READB_HIGH = 0x83, /* Read data bits HighByte */
+ MC_LOOPBACK_EN = 0x84, /* Enable loopback */
+ MC_LOOPBACK_DIS = 0x85, /* Disable loopback */
+ MC_SET_CLK_DIV = 0x86, /* Set clock divisor */
+ MC_FLUSH = 0x87, /* Flush buffer fifos to the PC. */
+ MC_WAIT_H = 0x88, /* Wait on GPIOL1 to go high. */
+ MC_WAIT_L = 0x89, /* Wait on GPIOL1 to go low. */
+ MC_TCK_X5 = 0x8A, /* Disable /5 div, enables 60MHz master clock */
+ MC_TCK_D5 = 0x8B, /* Enable /5 div, backward compat to FT2232D */
+ MC_EN_3PH_CLK = 0x8C, /* Enable 3 phase clk, DDR I2C */
+ MC_DIS_3PH_CLK = 0x8D, /* Disable 3 phase clk */
+ MC_CLK_N = 0x8E, /* Clock every bit, used for JTAG */
+ MC_CLK_N8 = 0x8F, /* Clock every byte, used for JTAG */
+ MC_CLK_TO_H = 0x94, /* Clock until GPIOL1 goes high */
+ MC_CLK_TO_L = 0x95, /* Clock until GPIOL1 goes low */
+ MC_EN_ADPT_CLK = 0x96, /* Enable adaptive clocking */
+ MC_DIS_ADPT_CLK = 0x97, /* Disable adaptive clocking */
+ MC_CLK8_TO_H = 0x9C, /* Clock until GPIOL1 goes high, count bytes */
+ MC_CLK8_TO_L = 0x9D, /* Clock until GPIOL1 goes low, count bytes */
+ MC_TRI = 0x9E, /* Set IO to only drive on 0 and tristate on 1 */
+ /* CPU mode commands */
+ MC_CPU_RS = 0x90, /* CPUMode read short address */
+ MC_CPU_RE = 0x91, /* CPUMode read extended address */
+ MC_CPU_WS = 0x92, /* CPUMode write short address */
+ MC_CPU_WE = 0x93, /* CPUMode write extended address */
+};
+
+/* Transfer Command bits */
+
+/* All byte based commands consist of:
+ * - Command byte
+ * - Length lsb
+ * - Length msb
+ *
+ * If data out is enabled the data follows after the above command bytes,
+ * otherwise no additional data is needed.
+ * - Data * n
+ *
+ * All bit based commands consist of:
+ * - Command byte
+ * - Length
+ *
+ * If data out is enabled a byte containing bitst to transfer follows.
+ * Otherwise no additional data is needed. Only up to 8 bits can be transferred
+ * per transaction when in bit mode.
+ */
+
+/* b 0000 0000
+ * |||| |||`- Data out negative enable. Update DO on negative clock edge.
+ * |||| ||`-- Bit count enable. When reset count represents bytes.
+ * |||| |`--- Data in negative enable. Latch DI on negative clock edge.
+ * |||| `---- LSB enable. When set clock data out LSB first.
+ * ||||
+ * |||`------ Data out enable
+ * ||`------- Data in enable
+ * |`-------- TMS mode enable
+ * `--------- Special command mode enable. See mpsse_cmd enum.
+ */
+
+#define MC_DATA_TMS (0x40) /* When set use TMS mode */
+#define MC_DATA_IN (0x20) /* When set read data (Data IN) */
+#define MC_DATA_OUT (0x10) /* When set write data (Data OUT) */
+#define MC_DATA_LSB (0x08) /* When set input/output data LSB first. */
+#define MC_DATA_ICN (0x04) /* When set receive data on negative clock edge */
+#define MC_DATA_BITS (0x02) /* When set count bits not bytes */
+#define MC_DATA_OCN (0x01) /* When set update data on negative clock edge */
+
+/* Flash command definitions */
+/* This command list is based on the Winbond W25Q128JV Datasheet */
+enum flash_cmd {
+ FC_WE = 0x06, /* Write Enable */
+ FC_SRWE = 0x50, /* Volatile SR Write Enable */
+ FC_WD = 0x04, /* Write Disable */
+ FC_RPD = 0xAB, /* Release Power-Down, returns Device ID */
+ FC_MFGID = 0x90, /* Read Manufacturer/Device ID */
+ FC_JEDECID = 0x9F, /* Read JEDEC ID */
+ FC_UID = 0x4B, /* Read Unique ID */
+ FC_RD = 0x03, /* Read Data */
+ FC_FR = 0x0B, /* Fast Read */
+ FC_PP = 0x02, /* Page Program */
+ FC_SE = 0x20, /* Sector Erase 4kb */
+ FC_BE32 = 0x52, /* Block Erase 32kb */
+ FC_BE64 = 0xD8, /* Block Erase 64kb */
+ FC_CE = 0xC7, /* Chip Erase */
+ FC_RSR1 = 0x05, /* Read Status Register 1 */
+ FC_WSR1 = 0x01, /* Write Status Register 1 */
+ FC_RSR2 = 0x35, /* Read Status Register 2 */
+ FC_WSR2 = 0x31, /* Write Status Register 2 */
+ FC_RSR3 = 0x15, /* Read Status Register 3 */
+ FC_WSR3 = 0x11, /* Write Status Register 3 */
+ FC_RSFDP = 0x5A, /* Read SFDP Register */
+ FC_ESR = 0x44, /* Erase Security Register */
+ FC_PSR = 0x42, /* Program Security Register */
+ FC_RSR = 0x48, /* Read Security Register */
+ FC_GBL = 0x7E, /* Global Block Lock */
+ FC_GBU = 0x98, /* Global Block Unlock */
+ FC_RBL = 0x3D, /* Read Block Lock */
+ FC_IBL = 0x36, /* Individual Block Lock */
+ FC_IBU = 0x39, /* Individual Block Unlock */
+ FC_EPS = 0x75, /* Erase / Program Suspend */
+ FC_EPR = 0x7A, /* Erase / Program Resume */
+ FC_PD = 0xB9, /* Power-down */
+ FC_QPI = 0x38, /* Enter QPI mode */
+ FC_ERESET = 0x66, /* Enable Reset */
+ FC_RESET = 0x99, /* Reset Device */
+};
+
static void check_rx()
{
while (1) {
@@ -96,7 +210,8 @@ static void send_spi(uint8_t *data, int n)
if (n < 1)
return;
- send_byte(0x11);
+ /* Output only, update data on negative clock edge. */
+ send_byte(MC_DATA_OUT | MC_DATA_OCN);
send_byte(n - 1);
send_byte((n - 1) >> 8);
@@ -112,7 +227,8 @@ static void xfer_spi(uint8_t *data, int n)
if (n < 1)
return;
- send_byte(0x31);
+ /* Input and output, update data on negative edge read on positive. */
+ send_byte(MC_DATA_IN | MC_DATA_OUT | MC_DATA_OCN);
send_byte(n - 1);
send_byte((n - 1) >> 8);
@@ -140,15 +256,15 @@ static void set_gpio(int slavesel_b, int creset_b)
gpio |= 0x80;
}
- send_byte(0x80);
- send_byte(gpio);
- send_byte(0x93);
+ send_byte(MC_SETB_LOW);
+ send_byte(gpio); /* Value */
+ send_byte(0x93); /* Direction */
}
static int get_cdone()
{
uint8_t data;
- send_byte(0x81);
+ send_byte(MC_READB_LOW);
data = recv_byte();
// ADBUS6 (GPIOL2)
return (data & 0x40) != 0;
@@ -158,7 +274,7 @@ static void flash_read_id()
{
// fprintf(stderr, "read flash ID..\n");
- uint8_t data[21] = { 0x9F };
+ uint8_t data[21] = { FC_JEDECID };
set_gpio(0, 0);
xfer_spi(data, 21);
set_gpio(1, 0);
@@ -171,7 +287,7 @@ static void flash_read_id()
static void flash_power_up()
{
- uint8_t data[1] = { 0xAB };
+ uint8_t data[1] = { FC_RPD };
set_gpio(0, 0);
xfer_spi(data, 1);
set_gpio(1, 0);
@@ -179,7 +295,7 @@ static void flash_power_up()
static void flash_power_down()
{
- uint8_t data[1] = { 0xB9 };
+ uint8_t data[1] = { FC_PD };
set_gpio(0, 0);
xfer_spi(data, 1);
set_gpio(1, 0);
@@ -190,7 +306,7 @@ static void flash_write_enable()
if (verbose)
fprintf(stderr, "write enable..\n");
- uint8_t data[1] = { 0x06 };
+ uint8_t data[1] = { FC_WE };
set_gpio(0, 0);
xfer_spi(data, 1);
set_gpio(1, 0);
@@ -200,7 +316,7 @@ static void flash_bulk_erase()
{
fprintf(stderr, "bulk erase..\n");
- uint8_t data[1] = { 0xc7 };
+ uint8_t data[1] = { FC_CE };
set_gpio(0, 0);
xfer_spi(data, 1);
set_gpio(1, 0);
@@ -210,7 +326,7 @@ static void flash_64kB_sector_erase(int addr)
{
fprintf(stderr, "erase 64kB sector at 0x%06X..\n", addr);
- uint8_t command[4] = { 0xd8, (uint8_t)(addr >> 16), (uint8_t)(addr >> 8), (uint8_t)addr };
+ uint8_t command[4] = { FC_BE64, (uint8_t)(addr >> 16), (uint8_t)(addr >> 8), (uint8_t)addr };
set_gpio(0, 0);
send_spi(command, 4);
@@ -222,7 +338,7 @@ static void flash_prog(int addr, uint8_t *data, int n)
if (verbose)
fprintf(stderr, "prog 0x%06X +0x%03X..\n", addr, n);
- uint8_t command[4] = { 0x02, (uint8_t)(addr >> 16), (uint8_t)(addr >> 8), (uint8_t)addr };
+ uint8_t command[4] = { FC_PP, (uint8_t)(addr >> 16), (uint8_t)(addr >> 8), (uint8_t)addr };
set_gpio(0, 0);
send_spi(command, 4);
@@ -239,7 +355,7 @@ static void flash_read(int addr, uint8_t *data, int n)
if (verbose)
fprintf(stderr, "read 0x%06X +0x%03X..\n", addr, n);
- uint8_t command[4] = { 0x03, (uint8_t)(addr >> 16), (uint8_t)(addr >> 8), (uint8_t)addr };
+ uint8_t command[4] = { FC_RD, (uint8_t)(addr >> 16), (uint8_t)(addr >> 8), (uint8_t)addr };
set_gpio(0, 0);
send_spi(command, 4);
@@ -259,7 +375,7 @@ static void flash_wait()
while (1)
{
- uint8_t data[2] = { 0x05 };
+ uint8_t data[2] = { FC_RSR1 };
set_gpio(0, 0);
xfer_spi(data, 2);
@@ -678,16 +794,17 @@ int main(int argc, char **argv)
ftdic_latency_set = true;
+ /* Enter MPSSE (Multi-Protocol Synchronous Serial Engine) mode. Set all pins to output. */
if (ftdi_set_bitmode(&ftdic, 0xff, BITMODE_MPSSE) < 0) {
fprintf(stderr, "Failed to set BITMODE_MPSSE on iCE FTDI USB device.\n");
error(2);
}
// enable clock divide by 5
- send_byte(0x8b);
+ send_byte(MC_TCK_D5);
// set 6 MHz clock
- send_byte(0x86);
+ send_byte(MC_SET_CLK_DIV);
send_byte(0x00);
send_byte(0x00);
@@ -749,13 +866,13 @@ int main(int argc, char **argv)
send_spi(buffer, rc);
}
- // add 48 dummy bits
- send_byte(0x8f);
+ // add 48 dummy bits (aka 6 bytes)
+ send_byte(MC_CLK_N8);
send_byte(0x05);
send_byte(0x00);
// add 1 more dummy bit
- send_byte(0x8e);
+ send_byte(MC_CLK_N);
send_byte(0x00);
fprintf(stderr, "cdone: %s\n", get_cdone() ? "high" : "low");
diff --git a/icetime/icetime.cc b/icetime/icetime.cc
index cdec43e..f9e0994 100644
--- a/icetime/icetime.cc
+++ b/icetime/icetime.cc
@@ -33,6 +33,10 @@
#include <map>
#include <set>
+#ifdef __EMSCRIPTEN__
+#include <emscripten.h>
+#endif
+
// add this number of ns as estimate for clock distribution mismatch
#define GLOBAL_CLK_DIST_JITTER 0.1
@@ -1283,16 +1287,24 @@ std::string ecnetname_to_vlog(std::string ec_name)
std::string end = ec_name.substr(last_+1);
size_t nidx = 0;
- int num = std::stoi(end, &nidx, 10);
- if(nidx == end.length()) {
- return base + "[" + std::to_string(num) + "]";
- } else {
+ int num = 0;
+ try {
+ num = std::stoi(end, &nidx, 10);
+ if(nidx == end.length()) {
+ return base + "[" + std::to_string(num) + "]";
+ } else {
+ return ec_name;
+ }
+ } catch(std::invalid_argument e) { // Not numeric and stoi throws exception
return ec_name;
}
+
}
std::string make_dsp_ip(int x, int y, std::string net, std::string &primnet)
{
+ // Don't generate excessive warnings about unknown cells
+ static std::set<std::string> unsupported_cells;
std::tuple<int, int, std::string> ecnet(x, y, net);
std::tuple<std::string, int, int, int> key("", -1, -1, -1);
bool found = false;
@@ -1423,9 +1435,11 @@ std::string make_dsp_ip(int x, int y, std::string net, std::string &primnet)
return cell;
} else {
- netlist_cell_types[cell] = "SB_" + ectype;
- fprintf(stderr, "Warning: timing analysis not supported for cell type %s\n", ectype.c_str());
- return cell;
+ if (unsupported_cells.find(ectype) == unsupported_cells.end()) {
+ fprintf(stderr, "Warning: timing analysis not supported for cell type %s\n", ectype.c_str());
+ unsupported_cells.insert(ectype);
+ }
+ return "";
}
}
@@ -1567,8 +1581,8 @@ void make_seg_cell(int net, const net_segment_t &seg)
if(device_type == "up5k" && ((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);
- netlist_cell_ports[cell][primnet] = net_name(net);
if(cell != "") {
+ netlist_cell_ports[cell][primnet] = net_name(net);
make_inmux(seg.x, seg.y, net);
}
return;
@@ -2213,6 +2227,18 @@ void help(const char *cmd)
int main(int argc, char **argv)
{
+#ifdef __EMSCRIPTEN__
+ EM_ASM(
+ if (ENVIRONMENT_IS_NODE)
+ {
+ FS.mkdir('/hostcwd');
+ FS.mount(NODEFS, { root: '.' }, '/hostcwd');
+ FS.mkdir('/hostfs');
+ FS.mount(NODEFS, { root: '/' }, '/hostfs');
+ }
+ );
+#endif
+
bool listnets = false;
bool print_timing = false;
bool interior_timing = false;