Fix 5k corner routing, and reverse engineer SPRAM

This commit is contained in:
David Shah 2017-11-13 16:51:28 +00:00
parent 64e3c1a9cd
commit 2f962ac92e
5 changed files with 523 additions and 20 deletions

View File

@ -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>

View File

@ -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)

1
icefuzz/tests/spram/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
work_spram/

173
icefuzz/tests/spram/fuzz_spram.py Executable file
View File

@ -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)

View File

@ -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)