aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Shah <davey1576@gmail.com>2017-11-13 16:51:28 +0000
committerDavid Shah <davey1576@gmail.com>2017-11-17 15:09:17 +0000
commit2f962ac92e018370793b9db3635fabd5b599afef (patch)
tree39f28c1dc8cdb9d154ac1384855084727dc21562
parent64e3c1a9cd81e61d9a3b163c9e9f9390fa4c5c21 (diff)
downloadicestorm-2f962ac92e018370793b9db3635fabd5b599afef.tar.gz
icestorm-2f962ac92e018370793b9db3635fabd5b599afef.tar.bz2
icestorm-2f962ac92e018370793b9db3635fabd5b599afef.zip
Fix 5k corner routing, and reverse engineer SPRAM
-rw-r--r--docs/ultraplus.html24
-rw-r--r--icebox/icebox.py113
-rw-r--r--icefuzz/tests/spram/.gitignore1
-rwxr-xr-xicefuzz/tests/spram/fuzz_spram.py173
-rw-r--r--icefuzz/tests/spram/up5k_spram_data.txt232
5 files changed, 523 insertions, 20 deletions
diff --git a/docs/ultraplus.html b/docs/ultraplus.html
index 4220cad..1074862 100644
--- a/docs/ultraplus.html
+++ b/docs/ultraplus.html
@@ -193,4 +193,28 @@ The <span style="font-family:monospace">CLKLF</span> output of SB_LFOSC is conne
<p>SB_LFOSC has no configuration bits.</p>
+<h2>SPRAM</h2>
+<p>The UltraPlus devices have 1Mbit of extra single-ported RAM, split into 4 256kbit blocks. The full list of connections for each SPRAM block in the 5k device is shown below,
+ as well as the location of the 1 configuration bit which is set to enable use of that SPRAM block.</p>
+
+ <table class="ctab">
+ <tr><th>Signal</th><th>SPRAM (0, 0, 1)</th><th>SPRAM (0, 0, 2)</th><th>SPRAM (25, 0, 3)</th><th>SPRAM (25, 0, 4)</th></tr>
+ <tr><td>ADDRESS[1:0]</td><td>(0, 2, lutff_[1:0]/in_1)</td><td>(0, 2, lutff_[7:6]/in_0)</td><td>(25, 2, lutff_[1:0]/in_1)</td><td>(25, 2, lutff_[7:6]/in_0)</td></tr>
+ <tr><td>ADDRESS[7:2]</td><td>(0, 2, lutff_[7:2]/in_1)</td><td>(0, 3, lutff_[5:0]/in_3)</td><td>(25, 2, lutff_[7:2]/in_1)</td><td>(25, 3, lutff_[5:0]/in_3)</td></tr>
+ <tr><td>ADDRESS[9:8]</td><td>(0, 2, lutff_[1:0]/in_0)</td><td>(0, 3, lutff_[7:6]/in_3)</td><td>(25, 2, lutff_[1:0]/in_0)</td><td>(25, 3, lutff_[7:6]/in_3)</td></tr>
+ <tr><td>ADDRESS[13:10]</td><td>(0, 2, lutff_[5:2]/in_0)</td><td>(0, 3, lutff_[3:0]/in_1)</td><td>(25, 2, lutff_[5:2]/in_0)</td><td>(25, 3, lutff_[3:0]/in_1)</td></tr>
+ <tr><td>DATAIN[7:0]</td><td>(0, 1, lutff_[7:0]/in_3)</td><td>(0, 1, lutff_[7:0]/in_0)</td><td>(25, 1, lutff_[7:0]/in_3)</td><td>(25, 1, lutff_[7:0]/in_0)</td></tr>
+ <tr><td>DATAIN[15:8]</td><td>(0, 1, lutff_[7:0]/in_1)</td><td>(0, 2, lutff_[7:0]/in_3)</td><td>(25, 1, lutff_[7:0]/in_1)</td><td>(25, 2, lutff_[7:0]/in_3)</td></tr>
+ <tr><td>MASKWREN[3:0]</td><td>(0, 3, lutff_[3:0]/in_0)</td><td>(0, 3, lutff_[7:4]/in_0)</td><td>(25, 3, lutff_[3:0]/in_0)</td><td>(25, 3, lutff_[7:4]/in_0)</td></tr>
+ <tr><td>WREN</td><td>(0, 3, lutff_4/in_1)</td><td>(0, 3, lutff_5/in_1)</td><td>(25, 3, lutff_4/in_1)</td><td>(25, 3, lutff_5/in_1)</td></tr>
+ <tr><td>CHIPSELECT</td><td>(0, 3, lutff_6/in_1)</td><td>(0, 3, lutff_7/in_1)</td><td>(25, 3, lutff_6/in_1)</td><td>(25, 3, lutff_7/in_1)</td></tr>
+ <tr><td>CLOCK</td><td>(0, 1, clk)</td><td>(0, 2, clk)</td><td>(25, 1, clk)</td><td>(25, 2, clk)</td></tr>
+ <tr><td>STANDBY</td><td>(0, 4, lutff_0/in_3)</td><td>(0, 4, lutff_1/in_3)</td><td>(25, 4, lutff_0/in_3)</td><td>(25, 4, lutff_1/in_3)</td></tr>
+ <tr><td>SLEEP</td><td>(0, 4, lutff_2/in_3)</td><td>(0, 4, lutff_3/in_3)</td><td>(25, 4, lutff_2/in_3)</td><td>(25, 4, lutff_3/in_3)</td></tr>
+ <tr><td>POWEROFF</td><td>(0, 4, lutff_4/in_3)</td><td>(0, 4, lutff_5/in_3)</td><td>(25, 4, lutff_4/in_3)</td><td>(25, 4, lutff_5/in_3)</td></tr>
+ <tr><td>DATAOUT[7:0]</td><td>(0, 1, slf_op_[7:0])</td><td>(0, 3, slf_op_[7:0])</td><td>(25, 1, slf_op_[7:0])</td><td>(25, 3, slf_op_[7:0])</td></tr>
+ <tr><td>DATAOUT[15:8]</td><td>(0, 2, slf_op_[7:0])</td><td>(0, 4, slf_op_[7:0])</td><td>(25, 2, slf_op_[7:0])</td><td>(25, 4, slf_op_[7:0])</td></tr>
+ <tr><td><em>SPRAM_ENABLE</em></td><td><em>(0, 1, CBIT_0)</em></td><td><em>(0, 1, CBIT_1)</em></td><td><em>(25, 1, CBIT_0)</em></td><td><em>(25, 1, CBIT_1)</em></td></tr>
+ </table>
+
</body></html>
diff --git a/icebox/icebox.py b/icebox/icebox.py
index a6d7155..9b3e35f 100644
--- a/icebox/icebox.py
+++ b/icebox/icebox.py
@@ -313,25 +313,25 @@ class iceconfig:
if netname.startswith("logic_op_bot_"):
if y == self.max_y and 0 < x < self.max_x: return True
if netname.startswith("logic_op_bnl_"):
- if x == self.max_x and 1 < y < self.max_y: return True
+ if x == self.max_x and 1 < y < self.max_y and (self.device != "5k"): return True
if y == self.max_y and 1 < x < self.max_x: return True
if netname.startswith("logic_op_bnr_"):
- if x == 0 and 1 < y < self.max_y: return True
+ if x == 0 and 1 < y < self.max_y and (self.device != "5k"): return True
if y == self.max_y and 0 < x < self.max_x-1: return True
if netname.startswith("logic_op_top_"):
if y == 0 and 0 < x < self.max_x: return True
if netname.startswith("logic_op_tnl_"):
- if x == self.max_x and 0 < y < self.max_y-1: return True
+ if x == self.max_x and 0 < y < self.max_y-1 and (self.device != "5k"): return True
if y == 0 and 1 < x < self.max_x: return True
if netname.startswith("logic_op_tnr_"):
- if x == 0 and 0 < y < self.max_y-1: return True
+ if x == 0 and 0 < y < self.max_y-1 and (self.device != "5k"): return True
if y == 0 and 0 < x < self.max_x-1: return True
if netname.startswith("logic_op_lft_"):
- if x == self.max_x: return True
+ if x == self.max_x and (self.device != "5k"): return True
if netname.startswith("logic_op_rgt_"):
- if x == 0: return True
+ if x == 0 and (self.device != "5k"): return True
return False
@@ -355,7 +355,7 @@ class iceconfig:
def follow_funcnet(self, x, y, func):
neighbours = set()
def do_direction(name, nx, ny):
- if 0 < nx < self.max_x and 0 < ny < self.max_y:
+ if (0 < nx < self.max_x or self.device == "5k") and 0 < ny < self.max_y:
neighbours.add((nx, ny, "neigh_op_%s_%d" % (name, func)))
if nx in (0, self.max_x) and 0 < ny < self.max_y and nx != x:
neighbours.add((nx, ny, "logic_op_%s_%d" % (name, func)))
@@ -444,7 +444,52 @@ class iceconfig:
assert False
return funcnets
-
+
+ #UltraPlus corner routing: given the corner name and net index,
+ #return a tuple containing H and V indexes, or none if NA
+ def ultraplus_trace_corner(self, corner, idx):
+ h_idx = None
+ v_idx = None
+ if corner == "bl":
+ if idx >= 4:
+ v_idx = idx + 28
+ if idx >= 32 and idx < 48:
+ h_idx = idx - 28
+ elif corner == "tl":
+ #TODO: bounds check for v_idx case?
+ v_idx = (idx + 8) ^ 1
+ if idx >= 8 and idx < 32:
+ h_idx = (idx ^ 1) - 8
+ elif corner == "tr":
+ #TODO: bounds check for v_idx case?
+ if idx <= 24:
+ v_idx = (idx + 12) ^ 1
+ if idx >= 12 and idx < 36:
+ h_idx = (idx ^ 1) - 12
+ elif corner == "br":
+ #TODO: bounds check for v_idx case?
+ if idx <= 16:
+ v_idx = idx + 32
+ if idx >= 32 and idx < 48: #check
+ h_idx = idx - 32
+ return (h_idx, v_idx)
+
+ def get_corner(self, x, y):
+ corner = ""
+ if y == 0:
+ corner += "b"
+ elif y == self.max_y:
+ corner += "t"
+ else:
+ corner += "x"
+ if x == 0:
+ corner += "l"
+ elif x == self.max_x:
+ corner += "r"
+ else:
+ corner += "x"
+ return corner
+
def follow_net(self, netspec):
x, y, netname = netspec
neighbours = self.rlookup_funcnet(x, y, netname)
@@ -465,7 +510,7 @@ class iceconfig:
neighbours.add((nx, ny, netname))
match = re.match(r"sp4_r_v_b_(\d+)", netname)
- if match and ((0 < x < self.max_x-1) or (self.device == "5k")):
+ if match and ((0 < x < self.max_x-1) or (self.device == "5k" and (x < self.max_x))):
neighbours.add((x+1, y, sp4v_normalize("sp4_v_b_" + match.group(1))))
#print('\tafter r_v_b', neighbours)
@@ -501,23 +546,39 @@ class iceconfig:
if s[0] in (0, self.max_x) and s[1] in (0, self.max_y):
if re.match("span4_(vert|horz)_[lrtb]_\d+$", n):
-
+ m = re.match("span4_(vert|horz)_([lrtb])_\d+$", n)
+ if self.device == "5k" and (m.group(2) == "l" or m.group(2) == "t"):
+ continue
vert_net = n.replace("_l_", "_t_").replace("_r_", "_b_").replace("_horz_", "_vert_")
horz_net = n.replace("_t_", "_l_").replace("_b_", "_r_").replace("_vert_", "_horz_")
if self.device == "5k":
m = re.match("span4_vert_([lrtb])_(\d+)$", vert_net)
assert m
- vert_net = "sp4_v_%s_%d" % (m.group(1), int(m.group(2)) + 28)
+ idx = int(m.group(2))
+ h_idx, v_idx = self.ultraplus_trace_corner(self.get_corner(s[0], s[1]), idx)
+ if v_idx is None:
+ if (s[0] == 0 and s[1] == 0 and direction == "l") or (s[0] == self.max_x and s[1] == self.max_y and direction == "r"):
+ continue
+ else:
+ vert_net = "sp4_v_%s_%d" % (m.group(1), v_idx)
m = re.match("span4_horz_([lrtb])_(\d+)$", horz_net)
assert m
- horz_net = "span4_horz_%s_%d" % (m.group(1), int(m.group(2)) - 28)
+ idx = int(m.group(2))
+ h_idx, v_idx = self.ultraplus_trace_corner(self.get_corner(s[0], s[1]), idx)
+ if h_idx is None:
+ if (s[0] == 0 and s[1] == 0 and direction == "b") or (s[0] == self.max_x and s[1] == self.max_y and direction == "t"):
+ continue
+ else:
+ horz_net = "span4_horz_%s_%d" % (m.group(1), h_idx)
+
+
if s[0] == 0 and s[1] == 0:
if direction == "l": s = (0, 1, vert_net)
if direction == "b": s = (1, 0, horz_net)
-
+
if s[0] == self.max_x and s[1] == self.max_y:
if direction == "r": s = (self.max_x, self.max_y-1, vert_net)
if direction == "t": s = (self.max_x-1, self.max_y, horz_net)
@@ -525,23 +586,35 @@ class iceconfig:
vert_net = netname.replace("_l_", "_t_").replace("_r_", "_b_").replace("_horz_", "_vert_").replace("_h_", "_v_")
horz_net = netname.replace("_t_", "_l_").replace("_b_", "_r_").replace("_vert_", "_horz_").replace("_v_", "_h_")
- if self.device == "5k":
+ if self.device == "5k":
m = re.match("(span4_vert|sp4_v)_([lrtb])_(\d+)$", vert_net)
assert m
- vert_net = "sp4_v_%s_%d" % (m.group(2), int(m.group(3)) + 28)
+ idx = int(m.group(3))
+ h_idx, v_idx = self.ultraplus_trace_corner(self.get_corner(s[0], s[1]), idx)
+ if v_idx is None:
+ if (s[0] == 0 and s[1] == self.max_y and direction == "l") or (s[0] == self.max_x and s[1] == 0 and direction == "r"):
+ continue
+ else:
+ vert_net = "sp4_v_%s_%d" % (m.group(2), v_idx)
m = re.match("(span4_horz|sp4_h)_([lrtb])_(\d+)$", horz_net)
assert m
- horz_net = "span4_horz_%s_%d" % (m.group(2), int(m.group(3)) - 28)
+ idx = int(m.group(3))
+ h_idx, v_idx = self.ultraplus_trace_corner(self.get_corner(s[0], s[1]), idx)
+ if h_idx is None:
+ if (s[0] == 0 and s[1] == self.max_y and direction == "t") or (s[0] == self.max_x and s[1] == 0 and direction == "b"):
+ continue
+ else:
+ horz_net = "span4_horz_%s_%d" % (m.group(2), h_idx)
if s[0] == 0 and s[1] == self.max_y:
if direction == "l": s = (0, self.max_y-1, vert_net)
if direction == "t": s = (1, self.max_y, horz_net)
-
+
if s[0] == self.max_x and s[1] == 0:
if direction == "r": s = (self.max_x, 1, vert_net)
if direction == "b": s = (self.max_x-1, 0, horz_net)
-
+
if self.tile_has_net(s[0], s[1], s[2]):
neighbours.add((s[0], s[1], s[2]))
@@ -1097,13 +1170,13 @@ def pos_follow_net(pos, direction, netname, device):
if case == "rr" and idx >= 12:
return "span4_horz_l_%d" % idx
- if pos == "l" and direction == "r":
+ if pos == "l" and direction == "r" and (device != "5k"):
m = re.match("span4_horz_(\d+)$", netname)
if m: return sp4h_normalize("sp4_h_l_%s" % m.group(1))
m = re.match("span12_horz_(\d+)$", netname)
if m: return sp12h_normalize("sp12_h_l_%s" % m.group(1))
- if pos == "r" and direction == "l":
+ if pos == "r" and direction == "l" and (device != "5k"):
m = re.match("span4_horz_(\d+)$", netname)
if m: return sp4h_normalize("sp4_h_r_%s" % m.group(1))
m = re.match("span12_horz_(\d+)$", netname)
diff --git a/icefuzz/tests/spram/.gitignore b/icefuzz/tests/spram/.gitignore
new file mode 100644
index 0000000..c6ebe02
--- /dev/null
+++ b/icefuzz/tests/spram/.gitignore
@@ -0,0 +1 @@
+work_spram/ \ No newline at end of file
diff --git a/icefuzz/tests/spram/fuzz_spram.py b/icefuzz/tests/spram/fuzz_spram.py
new file mode 100755
index 0000000..33e62cb
--- /dev/null
+++ b/icefuzz/tests/spram/fuzz_spram.py
@@ -0,0 +1,173 @@
+#!/usr/bin/env python3
+
+import os, sys, re
+
+device = "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 script is designed to determine the routing of 5k SPRAM signals,
+# and the location of the enable config bits
+
+spram_locs = [(0, 0, 1), (0, 0, 2), (25, 0, 3), (25, 0, 4)]
+#spram_locs = [(0, 0, 1)]
+spram_data = { }
+
+spram_signals = ["WREN", "CHIPSELECT", "CLOCK", "STANDBY", "SLEEP", "POWEROFF"]
+
+for i in range(14):
+ spram_signals.append("ADDRESS[%d]" % i)
+
+for i in range(16):
+ spram_signals.append("DATAIN[%d]" % i)
+
+for i in range(16):
+ spram_signals.append("DATAOUT[%d]" % i)
+
+for i in range(4):
+ spram_signals.append("MASKWREN[%d]" % i)
+
+fuzz_options = ["ADDRESS", "DATAIN", "MASKWREN", "DATAOUT"]
+
+#Parse the output of an icebox vlog file to determine connectivity
+def parse_vlog(f, pin2net, net_map):
+ current_net = None
+
+ for line in f:
+ 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
+ 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":
+ if splitline[1][:5] == "CBIT_":
+ bitidx = int(splitline[1][5:])
+ bits.add((current_x, current_y, splitline[1].strip()))
+ return bits
+
+if not os.path.exists("./work_spram"):
+ os.mkdir("./work_spram")
+
+for loc in spram_locs:
+ x, y, z = loc
+ net_map = {}
+ for sig in spram_signals:
+ net_map[sig] = set()
+ net_map["C_SPRAM_EN"] = set() # actually a CBIT not a net
+
+ for n in fuzz_options:
+ with open("./work_spram/spram.v","w") as f:
+ print("""
+ module top(
+ input WREN,
+ input CHIPSELECT,
+ input CLOCK,
+ input STANDBY,
+ input SLEEP,
+ input POWEROFF,
+ """, file=f)
+ if n == "ADDRESS":
+ print("\t\t\tinput [13:0] ADDRESS,", file=f)
+ if n == "DATAIN":
+ print("\t\t\tinput [15:0] DATAIN,", file=f)
+ if n == "MASKWREN":
+ print("\t\t\tinput [3:0] MASKWREN,", file=f)
+ if n == "DATAOUT":
+ print("\t\t\toutput [15:0] DATAOUT);", file=f)
+ else:
+ print("\t\t\toutput [0:0] DATAOUT);", file=f) #some dataout is always required to prevent optimisation away
+
+ addr_net = "ADDRESS" if n == "ADDRESS" else ""
+ din_net = "DATAIN" if n == "DATAIN" else ""
+ mwren_net = "MASKWREN" if n == "MASKWREN" else ""
+
+ print("""
+ SB_SPRAM256KA spram_i
+ (
+ .ADDRESS(%s),
+ .DATAIN(%s),
+ .MASKWREN(%s),
+ .WREN(WREN),
+ .CHIPSELECT(CHIPSELECT),
+ .CLOCK(CLOCK),
+ .STANDBY(STANDBY),
+ .SLEEP(SLEEP),
+ .POWEROFF(POWEROFF),
+ .DATAOUT(DATAOUT)
+ );
+ """ % (addr_net, din_net, mwren_net), file=f)
+ print("endmodule",file=f)
+ pin2net = {}
+ with open("./work_spram/spram.pcf","w") as f:
+ temp_pins = list(pins)
+ for sig in spram_signals:
+ if sig.startswith("ADDRESS") and n != "ADDRESS":
+ continue
+ if sig.startswith("DATAIN") and n != "DATAIN":
+ continue
+ if sig.startswith("MASKWREN") and n != "MASKWREN":
+ continue
+ if sig.startswith("DATAOUT") and n != "DATAOUT" and sig != "DATAOUT[0]":
+ continue
+
+ 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 spram_i %d %d %d" % loc, file=f)
+ retval = os.system("bash ../../icecube.sh -" + device + " ./work_spram/spram.v > ./work_spram/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_spram/spram.asc > ./work_spram/spram.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_spram/spram.asc > ./work_spram/spram.vlog")
+ if retval != 0:
+ sys.stderr.write('ERROR: icebox_vlog returned non-zero error code\n')
+ sys.exit(1)
+ with open("./work_spram/spram.vlog", "r") as f:
+ parse_vlog(f, pin2net, net_map)
+ bits = []
+ with open("./work_spram/spram.exp", "r") as f:
+ bits = parse_exp(f)
+ net_map["C_SPRAM_EN"].update(bits)
+ spram_data[loc] = net_map
+
+with open(device + "_spram_data.txt", "w") as f:
+ for loc in spram_data:
+ print("SPRAM %d %d %d" % loc, file=f)
+ data = spram_data[loc]
+ for net in sorted(data):
+ cnets = []
+ for cnet in data[net]:
+ cnets.append("(%d, %d, %s)" % cnet)
+ print("\t%s: %s" % (net, " ".join(cnets)), file=f) \ No newline at end of file
diff --git a/icefuzz/tests/spram/up5k_spram_data.txt b/icefuzz/tests/spram/up5k_spram_data.txt
new file mode 100644
index 0000000..c824e73
--- /dev/null
+++ b/icefuzz/tests/spram/up5k_spram_data.txt
@@ -0,0 +1,232 @@
+SPRAM 0 0 1
+ ADDRESS[0]: (0, 2, lutff_0/in_1)
+ ADDRESS[10]: (0, 2, lutff_2/in_0)
+ ADDRESS[11]: (0, 2, lutff_3/in_0)
+ ADDRESS[12]: (0, 2, lutff_4/in_0)
+ ADDRESS[13]: (0, 2, lutff_5/in_0)
+ ADDRESS[1]: (0, 2, lutff_1/in_1)
+ ADDRESS[2]: (0, 2, lutff_2/in_1)
+ ADDRESS[3]: (0, 2, lutff_3/in_1)
+ ADDRESS[4]: (0, 2, lutff_4/in_1)
+ ADDRESS[5]: (0, 2, lutff_5/in_1)
+ ADDRESS[6]: (0, 2, lutff_6/in_1)
+ ADDRESS[7]: (0, 2, lutff_7/in_1)
+ ADDRESS[8]: (0, 2, lutff_0/in_0)
+ ADDRESS[9]: (0, 2, lutff_1/in_0)
+ CHIPSELECT: (0, 3, lutff_6/in_1)
+ CLOCK: (0, 1, clk)
+ C_SPRAM_EN: (0, 1, CBIT_0)
+ DATAIN[0]: (0, 1, lutff_0/in_3)
+ DATAIN[10]: (0, 1, lutff_2/in_1)
+ DATAIN[11]: (0, 1, lutff_3/in_1)
+ DATAIN[12]: (0, 1, lutff_4/in_1)
+ DATAIN[13]: (0, 1, lutff_5/in_1)
+ DATAIN[14]: (0, 1, lutff_6/in_1)
+ DATAIN[15]: (0, 1, lutff_7/in_1)
+ DATAIN[1]: (0, 1, lutff_1/in_3)
+ DATAIN[2]: (0, 1, lutff_2/in_3)
+ DATAIN[3]: (0, 1, lutff_3/in_3)
+ DATAIN[4]: (0, 1, lutff_4/in_3)
+ DATAIN[5]: (0, 1, lutff_5/in_3)
+ DATAIN[6]: (0, 1, lutff_6/in_3)
+ DATAIN[7]: (0, 1, lutff_7/in_3)
+ DATAIN[8]: (0, 1, lutff_0/in_1)
+ DATAIN[9]: (0, 1, lutff_1/in_1)
+ DATAOUT[0]: (0, 1, slf_op_0)
+ DATAOUT[10]: (0, 2, slf_op_2)
+ DATAOUT[11]: (0, 2, slf_op_3)
+ DATAOUT[12]: (0, 2, slf_op_4)
+ DATAOUT[13]: (0, 2, slf_op_5)
+ DATAOUT[14]: (0, 2, slf_op_6)
+ DATAOUT[15]: (0, 2, slf_op_7)
+ DATAOUT[1]: (0, 1, slf_op_1)
+ DATAOUT[2]: (0, 1, slf_op_2)
+ DATAOUT[3]: (0, 1, slf_op_3)
+ DATAOUT[4]: (0, 1, slf_op_4)
+ DATAOUT[5]: (0, 1, slf_op_5)
+ DATAOUT[6]: (0, 1, slf_op_6)
+ DATAOUT[7]: (0, 1, slf_op_7)
+ DATAOUT[8]: (0, 2, slf_op_0)
+ DATAOUT[9]: (0, 2, slf_op_1)
+ MASKWREN[0]: (0, 3, lutff_0/in_0)
+ MASKWREN[1]: (0, 3, lutff_1/in_0)
+ MASKWREN[2]: (0, 3, lutff_2/in_0)
+ MASKWREN[3]: (0, 3, lutff_3/in_0)
+ POWEROFF: (0, 4, lutff_4/in_3)
+ SLEEP: (0, 4, lutff_2/in_3)
+ STANDBY: (0, 4, lutff_0/in_3)
+ WREN: (0, 3, lutff_4/in_1)
+SPRAM 0 0 2
+ ADDRESS[0]: (0, 2, lutff_6/in_0)
+ ADDRESS[10]: (0, 3, lutff_0/in_1)
+ ADDRESS[11]: (0, 3, lutff_1/in_1)
+ ADDRESS[12]: (0, 3, lutff_2/in_1)
+ ADDRESS[13]: (0, 3, lutff_3/in_1)
+ ADDRESS[1]: (0, 2, lutff_7/in_0)
+ ADDRESS[2]: (0, 3, lutff_0/in_3)
+ ADDRESS[3]: (0, 3, lutff_1/in_3)
+ ADDRESS[4]: (0, 3, lutff_2/in_3)
+ ADDRESS[5]: (0, 3, lutff_3/in_3)
+ ADDRESS[6]: (0, 3, lutff_4/in_3)
+ ADDRESS[7]: (0, 3, lutff_5/in_3)
+ ADDRESS[8]: (0, 3, lutff_6/in_3)
+ ADDRESS[9]: (0, 3, lutff_7/in_3)
+ CHIPSELECT: (0, 3, lutff_7/in_1)
+ CLOCK: (0, 2, clk)
+ C_SPRAM_EN: (0, 1, CBIT_1)
+ DATAIN[0]: (0, 1, lutff_0/in_0)
+ DATAIN[10]: (0, 2, lutff_2/in_3)
+ DATAIN[11]: (0, 2, lutff_3/in_3)
+ DATAIN[12]: (0, 2, lutff_4/in_3)
+ DATAIN[13]: (0, 2, lutff_5/in_3)
+ DATAIN[14]: (0, 2, lutff_6/in_3)
+ DATAIN[15]: (0, 2, lutff_7/in_3)
+ DATAIN[1]: (0, 1, lutff_1/in_0)
+ DATAIN[2]: (0, 1, lutff_2/in_0)
+ DATAIN[3]: (0, 1, lutff_3/in_0)
+ DATAIN[4]: (0, 1, lutff_4/in_0)
+ DATAIN[5]: (0, 1, lutff_5/in_0)
+ DATAIN[6]: (0, 1, lutff_6/in_0)
+ DATAIN[7]: (0, 1, lutff_7/in_0)
+ DATAIN[8]: (0, 2, lutff_0/in_3)
+ DATAIN[9]: (0, 2, lutff_1/in_3)
+ DATAOUT[0]: (0, 3, slf_op_0)
+ DATAOUT[10]: (0, 4, slf_op_2)
+ DATAOUT[11]: (0, 4, slf_op_3)
+ DATAOUT[12]: (0, 4, slf_op_4)
+ DATAOUT[13]: (0, 4, slf_op_5)
+ DATAOUT[14]: (0, 4, slf_op_6)
+ DATAOUT[15]: (0, 4, slf_op_7)
+ DATAOUT[1]: (0, 3, slf_op_1)
+ DATAOUT[2]: (0, 3, slf_op_2)
+ DATAOUT[3]: (0, 3, slf_op_3)
+ DATAOUT[4]: (0, 3, slf_op_4)
+ DATAOUT[5]: (0, 3, slf_op_5)
+ DATAOUT[6]: (0, 3, slf_op_6)
+ DATAOUT[7]: (0, 3, slf_op_7)
+ DATAOUT[8]: (0, 4, slf_op_0)
+ DATAOUT[9]: (0, 4, slf_op_1)
+ MASKWREN[0]: (0, 3, lutff_4/in_0)
+ MASKWREN[1]: (0, 3, lutff_5/in_0)
+ MASKWREN[2]: (0, 3, lutff_6/in_0)
+ MASKWREN[3]: (0, 3, lutff_7/in_0)
+ POWEROFF: (0, 4, lutff_5/in_3)
+ SLEEP: (0, 4, lutff_3/in_3)
+ STANDBY: (0, 4, lutff_1/in_3)
+ WREN: (0, 3, lutff_5/in_1)
+SPRAM 25 0 3
+ ADDRESS[0]: (25, 2, lutff_0/in_1)
+ ADDRESS[10]: (25, 2, lutff_2/in_0)
+ ADDRESS[11]: (25, 2, lutff_3/in_0)
+ ADDRESS[12]: (25, 2, lutff_4/in_0)
+ ADDRESS[13]: (25, 2, lutff_5/in_0)
+ ADDRESS[1]: (25, 2, lutff_1/in_1)
+ ADDRESS[2]: (25, 2, lutff_2/in_1)
+ ADDRESS[3]: (25, 2, lutff_3/in_1)
+ ADDRESS[4]: (25, 2, lutff_4/in_1)
+ ADDRESS[5]: (25, 2, lutff_5/in_1)
+ ADDRESS[6]: (25, 2, lutff_6/in_1)
+ ADDRESS[7]: (25, 2, lutff_7/in_1)
+ ADDRESS[8]: (25, 2, lutff_0/in_0)
+ ADDRESS[9]: (25, 2, lutff_1/in_0)
+ CHIPSELECT: (25, 3, lutff_6/in_1)
+ CLOCK: (25, 1, clk)
+ C_SPRAM_EN: (25, 1, CBIT_0)
+ DATAIN[0]: (25, 1, lutff_0/in_3)
+ DATAIN[10]: (25, 1, lutff_2/in_1)
+ DATAIN[11]: (25, 1, lutff_3/in_1)
+ DATAIN[12]: (25, 1, lutff_4/in_1)
+ DATAIN[13]: (25, 1, lutff_5/in_1)
+ DATAIN[14]: (25, 1, lutff_6/in_1)
+ DATAIN[15]: (25, 1, lutff_7/in_1)
+ DATAIN[1]: (25, 1, lutff_1/in_3)
+ DATAIN[2]: (25, 1, lutff_2/in_3)
+ DATAIN[3]: (25, 1, lutff_3/in_3)
+ DATAIN[4]: (25, 1, lutff_4/in_3)
+ DATAIN[5]: (25, 1, lutff_5/in_3)
+ DATAIN[6]: (25, 1, lutff_6/in_3)
+ DATAIN[7]: (25, 1, lutff_7/in_3)
+ DATAIN[8]: (25, 1, lutff_0/in_1)
+ DATAIN[9]: (25, 1, lutff_1/in_1)
+ DATAOUT[0]: (25, 1, slf_op_0)
+ DATAOUT[10]: (25, 2, slf_op_2)
+ DATAOUT[11]: (25, 2, slf_op_3)
+ DATAOUT[12]: (25, 2, slf_op_4)
+ DATAOUT[13]: (25, 2, slf_op_5)
+ DATAOUT[14]: (25, 2, slf_op_6)
+ DATAOUT[15]: (25, 2, slf_op_7)
+ DATAOUT[1]: (25, 1, slf_op_1)
+ DATAOUT[2]: (25, 1, slf_op_2)
+ DATAOUT[3]: (25, 1, slf_op_3)
+ DATAOUT[4]: (25, 1, slf_op_4)
+ DATAOUT[5]: (25, 1, slf_op_5)
+ DATAOUT[6]: (25, 1, slf_op_6)
+ DATAOUT[7]: (25, 1, slf_op_7)
+ DATAOUT[8]: (25, 2, slf_op_0)
+ DATAOUT[9]: (25, 2, slf_op_1)
+ MASKWREN[0]: (25, 3, lutff_0/in_0)
+ MASKWREN[1]: (25, 3, lutff_1/in_0)
+ MASKWREN[2]: (25, 3, lutff_2/in_0)
+ MASKWREN[3]: (25, 3, lutff_3/in_0)
+ POWEROFF: (25, 4, lutff_4/in_3)
+ SLEEP: (25, 4, lutff_2/in_3)
+ STANDBY: (25, 4, lutff_0/in_3)
+ WREN: (25, 3, lutff_4/in_1)
+SPRAM 25 0 4
+ ADDRESS[0]: (25, 2, lutff_6/in_0)
+ ADDRESS[10]: (25, 3, lutff_0/in_1)
+ ADDRESS[11]: (25, 3, lutff_1/in_1)
+ ADDRESS[12]: (25, 3, lutff_2/in_1)
+ ADDRESS[13]: (25, 3, lutff_3/in_1)
+ ADDRESS[1]: (25, 2, lutff_7/in_0)
+ ADDRESS[2]: (25, 3, lutff_0/in_3)
+ ADDRESS[3]: (25, 3, lutff_1/in_3)
+ ADDRESS[4]: (25, 3, lutff_2/in_3)
+ ADDRESS[5]: (25, 3, lutff_3/in_3)
+ ADDRESS[6]: (25, 3, lutff_4/in_3)
+ ADDRESS[7]: (25, 3, lutff_5/in_3)
+ ADDRESS[8]: (25, 3, lutff_6/in_3)
+ ADDRESS[9]: (25, 3, lutff_7/in_3)
+ CHIPSELECT: (25, 3, lutff_7/in_1)
+ CLOCK: (25, 2, clk)
+ C_SPRAM_EN: (25, 1, CBIT_1)
+ DATAIN[0]: (25, 1, lutff_0/in_0)
+ DATAIN[10]: (25, 2, lutff_2/in_3)
+ DATAIN[11]: (25, 2, lutff_3/in_3)
+ DATAIN[12]: (25, 2, lutff_4/in_3)
+ DATAIN[13]: (25, 2, lutff_5/in_3)
+ DATAIN[14]: (25, 2, lutff_6/in_3)
+ DATAIN[15]: (25, 2, lutff_7/in_3)
+ DATAIN[1]: (25, 1, lutff_1/in_0)
+ DATAIN[2]: (25, 1, lutff_2/in_0)
+ DATAIN[3]: (25, 1, lutff_3/in_0)
+ DATAIN[4]: (25, 1, lutff_4/in_0)
+ DATAIN[5]: (25, 1, lutff_5/in_0)
+ DATAIN[6]: (25, 1, lutff_6/in_0)
+ DATAIN[7]: (25, 1, lutff_7/in_0)
+ DATAIN[8]: (25, 2, lutff_0/in_3)
+ DATAIN[9]: (25, 2, lutff_1/in_3)
+ DATAOUT[0]: (25, 3, slf_op_0)
+ DATAOUT[10]: (25, 4, slf_op_2)
+ DATAOUT[11]: (25, 4, slf_op_3)
+ DATAOUT[12]: (25, 4, slf_op_4)
+ DATAOUT[13]: (25, 4, slf_op_5)
+ DATAOUT[14]: (25, 4, slf_op_6)
+ DATAOUT[15]: (25, 4, slf_op_7)
+ DATAOUT[1]: (25, 3, slf_op_1)
+ DATAOUT[2]: (25, 3, slf_op_2)
+ DATAOUT[3]: (25, 3, slf_op_3)
+ DATAOUT[4]: (25, 3, slf_op_4)
+ DATAOUT[5]: (25, 3, slf_op_5)
+ DATAOUT[6]: (25, 3, slf_op_6)
+ DATAOUT[7]: (25, 3, slf_op_7)
+ DATAOUT[8]: (25, 4, slf_op_0)
+ DATAOUT[9]: (25, 4, slf_op_1)
+ MASKWREN[0]: (25, 3, lutff_4/in_0)
+ MASKWREN[1]: (25, 3, lutff_5/in_0)
+ MASKWREN[2]: (25, 3, lutff_6/in_0)
+ MASKWREN[3]: (25, 3, lutff_7/in_0)
+ POWEROFF: (25, 4, lutff_5/in_3)
+ SLEEP: (25, 4, lutff_3/in_3)
+ STANDBY: (25, 4, lutff_1/in_3)
+ WREN: (25, 3, lutff_5/in_1)