-
Notifications
You must be signed in to change notification settings - Fork 0
/
hydra_chain.py
394 lines (325 loc) · 19.7 KB
/
hydra_chain.py
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
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
import sys
import time
import argparse
from base import graphs
import larpix
import larpix.io
import larpix.logger
from base import generate_config
from base import pacman_base
from tqdm import tqdm
import numpy as np
import json
from base import v2a_base
from base.v2a_base import *
arr = graphs.NumberedArrangement()
def string_to_chips_list(string):
chiplist = string.split(',')
return [int(chip) for chip in chiplist]
def convert_voltage_for_pacman(voltage):
max_voltage, max_scale = 1.8, 46020
v = voltage
if v > max_voltage: v=max_voltage
return int( (v/max_voltage)*max_scale )
def get_temp_key(io_group, io_channel):
return larpix.key.Key(io_group, io_channel, 1)
def get_good_roots(c, io_group, io_channels):
#root chips with external connections to pacman
root_chips = [11, 41, 71, 101]
print('getting good roots...')
good_tile_channel_indices = []
for n, io_channel in enumerate(io_channels):
#writing initial config
key = larpix.key.Key(io_group, io_channel, 1)
c.add_chip(key)
c[key].config.chip_id = root_chips[n]
c.write_configuration(key, 'chip_id')
c.remove_chip(key)
key = larpix.key.Key(io_group, io_channel, root_chips[n])
c.add_chip(key)
c[key].config.chip_id = key.chip_id
c[key].config.enable_miso_downstream = [1,0,0,0]
c[key].config.enable_miso_differential = [1,1,1,1]
c.write_configuration(key, 'enable_miso_downstream')
###############################################################################
#resetting clocks
c[key].config.enable_miso_downstream=[0]*4
c[key].config.enable_miso_upstream=[0]*4
c.write_configuration(key, 'enable_miso_downstream')
c.write_configuration(key, 'enable_miso_upstream')
c[key].config.clk_ctrl = v2a_base._default_clk_ctrl
c.write_configuration(key, 'clk_ctrl')
c.io.set_uart_clock_ratio(io_channel, clk_ctrl_2_clk_ratio_map[v2a_base._default_clk_ctrl], io_group=io_group)
print("setting uart clock ratio to:",clk_ctrl_2_clk_ratio_map[v2a_base._default_clk_ctrl])
################################################################################
#rewriting config
c[key].config.enable_miso_downstream = [1,0,0,0]
c[key].config.enable_miso_differential = [1,1,1,1]
c.write_configuration(key, 'enable_miso_differential')
c.write_configuration(key, 'enable_miso_downstream')
#enforcing configuration on chip
ok,diff = c.enforce_registers([(key,122), (key, 125)], timeout=0.1, n=5, n_verify=5)
if ok:
good_tile_channel_indices.append(n)
print('verified root chip ' + str(root_chips[n]))
else:
print('unable to verify root chip ' + str(root_chips[n]))
#checking each connection for every chip
good_roots = [root_chips[n] for n in good_tile_channel_indices]
good_channels = [io_channels[n] for n in good_tile_channel_indices]
print('Found working root chips: ', good_roots)
return good_roots, good_channels
def get_initial_controller(io_group, io_channels, vdda=0, pacman_version='v1rev3b'):
#creating controller with pacman io
c = larpix.Controller()
c.io = larpix.io.PACMAN_IO(relaxed=True)
c.io.double_send_packets = True
print('getting initial controller')
#if pacman_version == 'v1rev3b':
#print('setting power,', vdda)
#vddd_voltage = 1.6
#vddd = convert_voltage_for_pacman(vddd_voltage)
#vddd=37800
#vdda = convert_voltage_for_pacman(vdda)
#reg_pairs = get_reg_pairs(io_channels)
#for pair in reg_pairs:
# c.io.set_reg(pair[0], vdda, io_group=io_group)
# c.io.set_reg(pair[1], vddd, io_group=io_group)
#tiles = get_all_tiles(io_channels)
#bit_string = list('100000000') # prepended '1' to enable the clock
#for tile in tiles: bit_string[-1*tile] = '1'
#c.io.set_reg(0x00000014, 1, io_group=io_group) # enable global larpix power
#print(bit_string)
#print(int("".join(bit_string),2))
#c.io.set_reg(0x00000010, int("".join(bit_string), 2), io_group=io_group) # enable tiles to be powered
#c.io.set_reg(0x101C, 4, io_group=io_group)
#c.io.set_reg(0x18, 0xffffffff, io_group=io_group) # enable uarts (for all tiles?)
#power = power_registers()
#adc_read = 0x00024001
#for i in power.keys():
# val_vdda = c.io.get_reg(adc_read+power[i][0], io_group=io_group)
# val_idda = c.io.get_reg(adc_read+power[i][1], io_group=io_group)
# val_vddd = c.io.get_reg(adc_read+power[i][2], io_group=io_group)
# val_iddd = c.io.get_reg(adc_read+power[i][3], io_group=io_group)
# print('TILE',i,
# '\tVDDA:',(((val_vdda>>16)>>3)*4),
# '\tIDDA:',(((val_idda>>16)-(val_idda>>31)*65535)*500*0.01),
# '\tVDDD:',(((val_vddd>>16)>>3)*4),
# '\tIDDD:',(((val_iddd>>16)-(val_iddd>>31)*65535)*500*0.01))
#adding pacman!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
for io_channel in io_channels:
c.add_network_node(io_group, io_channel, c.network_names, 'ext', root=True)
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
#resetting larpix
c.io.reset_larpix(length=10240, io_group=io_group)
for io_channel in io_channels:
c.io.set_uart_clock_ratio(io_channel, clk_ctrl_2_clk_ratio_map[0], io_group=io_group)
print("setting uart clock ratio to:",clk_ctrl_2_clk_ratio_map[0])
##################################################################################
#pacman_base.enable_pacman_uart_from_tile(c.io, io_group, [tile] )
#pacman_base.enable_pacman_uart_from_io_channels(c.io, io_group, io_channels )
return c
def reset_board_get_controller(c, io_group, io_channels):
#resetting larpix
c.io.reset_larpix(length=10240)
for io_channel in io_channels:
c.io.set_uart_clock_ratio(io_channel, clk_ctrl_2_clk_ratio_map[0], io_group=io_group)
print("setting uart clock ratio to:",clk_ctrl_2_clk_ratio_map[0])
c.chips.clear()
###################################################################################
return c
def init_initial_network(c, io_group, io_channels, paths):
root_chips = [path[0] for path in paths]
still_stepping = [True for root in root_chips]
ordered_chips_by_channel = [ [] for io_channel in io_channels ]
for ipath, path in enumerate(paths):
step = 0
while step < len(path)-1:
step += 1
next_key = larpix.key.Key(io_group, io_channels[ipath], path[step])
prev_key = larpix.key.Key(io_group, io_channels[ipath], path[step-1])
if prev_key.chip_id in root_chips:
#this is the first step. need to re-add root chip
temp_key = get_temp_key(io_group, io_channels[ipath])
c.add_chip(temp_key)
c[temp_key].config.chip_id = prev_key.chip_id
c.write_configuration(temp_key, 'chip_id')
c.remove_chip(temp_key)
c.add_chip(prev_key)
c[prev_key].config.chip_id = prev_key.chip_id
c[prev_key].config.enable_miso_downstream = arr.get_uart_enable_list(prev_key.chip_id)
c[prev_key].config.enable_miso_differential = [1,1,1,1]
c.write_configuration(prev_key, 'enable_miso_downstream')
c.write_configuration(prev_key, 'enable_miso_differential')
ordered_chips_by_channel[ipath].append(prev_key.chip_id)
c[prev_key].config.enable_miso_upstream = arr.get_uart_enable_list(prev_key.chip_id, next_key.chip_id)
c.write_configuration(prev_key, 'enable_miso_upstream')
temp_key = get_temp_key(io_group, io_channels[ipath])
c.add_chip(temp_key)
c[temp_key].config.chip_id = next_key.chip_id
c.write_configuration(temp_key, 'chip_id')
c.remove_chip(temp_key)
c.add_chip(next_key)
c[next_key].config.chip_id = next_key.chip_id
c[next_key].config.enable_miso_downstream = arr.get_uart_enable_list(next_key.chip_id, prev_key.chip_id)
c[next_key].config.enable_miso_differential =[1,1,1,1]
c.write_configuration(next_key, 'enable_miso_downstream')
ordered_chips_by_channel[ipath].append(next_key.chip_id)
for chip_ids in ordered_chips_by_channel[ipath][::-1]:
key = larpix.key.Key(io_group, io_channels[ipath], chip_ids)
c[key].config.enable_miso_downstream=[0]*4
c[key].config.enable_miso_upstream=[0]*4
c.write_configuration(key, 'enable_miso_downstream')
c.write_configuration(key, 'enable_miso_upstream')
c[key].config.clk_ctrl = v2a_base._default_clk_ctrl
c.write_configuration(key, 'clk_ctrl')
c.io.set_uart_clock_ratio(io_channels[ipath], clk_ctrl_2_clk_ratio_map[v2a_base._default_clk_ctrl], io_group=io_group)
print("setting uart clock ratio to:",clk_ctrl_2_clk_ratio_map[v2a_base._default_clk_ctrl])
return True
def test_network(c, io_group, io_channels, paths):
print('Testing io-group {} io_channels'.format(io_group), io_channels)
root_chips = [path[0] for path in paths]
step = 0
still_stepping = [True for path in paths]
valid = [True for path in paths]
pbar=tqdm(total=np.sum([len(p) for p in paths]))
while any(still_stepping):
step += 1
#tqdm(c.chips,desc='configuring chips...',ncols=80,smoothing=0)
for ipath, path in enumerate(paths):
if not still_stepping[ipath] or not valid[ipath]:
continue
if step > len(path)-1:
still_stepping[ipath] = False
continue
next_key = larpix.key.Key(io_group, io_channels[ipath], path[step])
prev_key = larpix.key.Key(io_group, io_channels[ipath], path[step-1])
#print('trying to enable {} from {}'.format(str(next_key), str(prev_key)))
broadcast ='{}-{}-255'.format(io_group, prev_key.io_channel)
c.add_chip(broadcast)
if prev_key.chip_id in root_chips:
c[prev_key].config.chip_id = prev_key.chip_id
c[prev_key].config.enable_miso_downstream = arr.get_uart_enable_list(prev_key.chip_id)
c[prev_key].config.enable_miso_differential = [1,1,1,1]
c.write_configuration(broadcast, 'test_mode_uart0')
c.write_configuration(broadcast, 'test_mode_uart1')
c.write_configuration(broadcast, 'test_mode_uart2')
c.write_configuration(broadcast, 'test_mode_uart3')
c.write_configuration(prev_key, 'enable_miso_downstream')
c[prev_key].config.enable_miso_differential = [1,1,1,1]
c.write_configuration(broadcast, 'test_mode_uart0')
c.write_configuration(broadcast, 'test_mode_uart1')
c.write_configuration(broadcast, 'test_mode_uart2')
c.write_configuration(broadcast, 'test_mode_uart3')
c.remove_chip(broadcast)
c[prev_key].config.enable_miso_upstream = arr.get_uart_enable_list(prev_key.chip_id, next_key.chip_id)
c.write_configuration(prev_key, 'enable_miso_upstream')
c[next_key].config.chip_id = next_key.chip_id
c[next_key].config.enable_miso_downstream = arr.get_uart_enable_list(next_key.chip_id, prev_key.chip_id)
c[next_key].config.enable_miso_differential =[1,1,1,1]
c.write_configuration(next_key, 'enable_miso_downstream')
#if (path[step-1], path[step]) in arr.good_connections:
# #already verified links
# #print(next_key, 'already verified')
# pbar.update(1)
# continue
ok, diff = c.enforce_registers([(next_key, reg) for reg in range(5,225)], timeout=0.4, n=5, n_verify=5)
#ok, diff = c.enforce_configuration(next_key)
pbar.update(1)
if ok:
arr.add_good_connection((path[step-1], path[step]))
continue
else:
#planned path to traverse has been interrupted... restart with adding excluded link
arr.add_onesided_excluded_link((prev_key.chip_id, next_key.chip_id))
still_stepping[ipath] = False
valid[ipath] = False
print(ok, diff)
return False
pbar.close()
print('returning:', all(valid))
return all(valid)
def main(pacman_tile, io_group, pacman_version, vdda=0, config_name=None, exclude=None):
d = {'_config_type' : 'controller', '_include':[]}
if isinstance(pacman_tile, list):
if exclude is None: exclude = {t : None for t in pacman_tile}
for tile in pacman_tile:
if not tile in exclude.keys(): exclude[tile]=None
d['_include'].append(hydra_chain(io_group, tile, pacman_version, vdda, exclude[tile], first=True))
if isinstance(pacman_tile, int):
d['_include'].append(hydra_chain(io_group, pacman_tile, pacman_version, vdda, exclude, first=True))
fname=config_name
if config_name is None: #no input file to incluce
fname='config-{}.json'.format(time.strftime("%Y_%m_%d_%H_%M_%Z"))
with open(fname, 'w') as f: json.dump(d, f)
return fname
else:
ed = {}
try:
with open(config_name, 'r') as f: ed = json.load(f)
for file in ed['_include']:
d['_include'].append(file)
with open(fname, 'w') as f: json.dump(d, f)
print('writing', fname)
except:
with open(fname, 'w') as f: json.dump(d, f)
print('writing', fname)
return fname
#c = larpix.Controller()
#c.io = larpix.io.PACMAN_IO(relaxed=True)
#if isinstance(pacman_tile, list): pacman_base.enable_pacman_uart_from_tile(c.io, io_group, pacman_tile )
#else: pacman_base.enable_pacman_uart_from_tile(c.io, io_group, [pacman_tile] )
#c = v2a_base.main(controller_config=config_name, enforce=True)
#c = v2a_base.reset(c, config_name, enforce=True)
#c.io.set_reg(0x00000010, 0, io_group=io_group)
return fname
def hydra_chain(io_group, pacman_tile, pacman_version, vdda, exclude=None, first=False):
if first: arr.clear()
if not exclude is None:
if type(exclude)==int: arr.add_excluded_chip(exclude)
else:
for chip in exclude: arr.add_excluded_chip(chip)
io_channels = [ 1 + 4*(pacman_tile - 1) + n for n in range(4)]
print("--------------------------------------------")
print("get_initial_controller(",io_group,",",io_channels,",",vdda,",",pacman_version,")")
c = get_initial_controller(io_group, io_channels, vdda, pacman_version)
root_chips, io_channels = get_good_roots(c, io_group, io_channels)
print('found root chips:', root_chips)
c = reset_board_get_controller(c, io_group, io_channels)
#need to init whole network first and write clock frequency, then we can step through and test
existing_paths = [ [chip] for chip in root_chips ]
#initial network
paths = arr.get_path(existing_paths)
print('path including', sum( [len(path) for path in paths] ), 'chips' )
#bring up initial network and set clock frequency
init_initial_network(c, io_group, io_channels, paths)
#test network to make sure all chips were brought up correctly
ok = test_network(c, io_group, io_channels, paths)
while not ok:
c = reset_board_get_controller(c, io_group, io_channels)
existing_paths = [ [chip] for chip in root_chips ]
#initial network
paths = arr.get_path(existing_paths)
print('path inlcuding', sum( [len(path) for path in paths] ), 'chips' )
#bring up initial network and set clock frequency
init_initial_network(c, io_group, io_channels, paths)
#test network to make sure all chips were brought up correctly
ok = test_network(c, io_group, io_channels, paths)
#existing network is full initialized, start tests
######
##generating config file
_name = "iog-{}-".format(io_group)+"pacman-tile-"+str(pacman_tile)+"-hydra-network.json"
if True:
print('writing configuration', _name + ', including', sum( [len(path) for path in paths] ), 'chips' )
generate_config.write_existing_path(_name, io_group, root_chips, io_channels, paths, ['no test performed'], arr.excluded_chips, asic_version=2, script_version=v2a_base.LARPIX_10X10_SCRIPTS_VERSION)
return _name
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--pacman_tile', default=1, type=int, help='''Pacman software tile number; 1-8 for Pacman v1rev3; 1 for Pacman v1rev2''')
parser.add_argument('--pacman_version', default='v1rev3b', type=str, help='''Pacman version; v1rev2 for SingleCube; otherwise, v1rev3''')
parser.add_argument('--vdda', default=0, type=float, help='''VDDA setting during test [V]''')
parser.add_argument('--io_group', default=1, type=int, help='''IO group to perform test on''')
parser.add_argument('--exclude', default=None, type=int, help='''Chips to exclude chip from test and networks, formatted chip_id_1,chip_id_2,...''')
args = parser.parse_args()
c = main(**vars(args))
###### disable tile power