1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
#!/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["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["SPRAM_EN"].update(bits)
spram_data[loc] = net_map
with open(device + "_spram_data.txt", "w") as f:
for loc in spram_data:
print("\t(%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\t%s %s, " % (("\"" + net.replace("[","_").replace("]","") + "\":").ljust(24), " ".join(cnets)), file=f)
print("\t},", file=f)
|