From e6917688932208aa6f3da48f37fb105c770f03c6 Mon Sep 17 00:00:00 2001 From: dspitzba <daniel.spitzbart@cern.ch> Date: Fri, 9 Jun 2023 17:14:56 -0400 Subject: [PATCH 01/14] occupancy plot from L1A --- tamalero/FIFO.py | 3 +++ test_ETROC.py | 58 ++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/tamalero/FIFO.py b/tamalero/FIFO.py index 9d78d4f..346d8e7 100644 --- a/tamalero/FIFO.py +++ b/tamalero/FIFO.py @@ -172,6 +172,9 @@ class FIFO: print("uhal UDP error in FIFO.get_occupancy") raise + def is_full(self): + return self.rb.kcu.read_node(f"READOUT_BOARD_{self.rb.rb}.RX_FIFO_FULL").value() + def get_lost_word_count(self): return self.rb.kcu.read_node(f"READOUT_BOARD_{self.rb.rb}.RX_FIFO_LOST_WORD_CNT").value() diff --git a/test_ETROC.py b/test_ETROC.py index e71ae89..a384937 100644 --- a/test_ETROC.py +++ b/test_ETROC.py @@ -8,6 +8,7 @@ from tamalero.colors import red, green, yellow import numpy as np from scipy.optimize import curve_fit from matplotlib import pyplot as plt +from tqdm import tqdm import os import sys @@ -276,7 +277,7 @@ if __name__ == '__main__': #fifo.reset() etroc.wr_reg("selfTestOccupancy", 2, broadcast=True) - etroc.wr_reg("singlePort", 0x0) + #etroc.wr_reg("singlePort", 0x0) etroc.wr_reg("mergeTriggerData", 0x1) #etroc.wr_reg("") if not args.partial: @@ -359,7 +360,7 @@ if __name__ == '__main__': ax=ax, fontsize=15, ) - name = 'hit_matrix' + name = 'hit_matrix_internal_test_pattern' fig.savefig(os.path.join(plot_dir, "{}.pdf".format(name))) fig.savefig(os.path.join(plot_dir, "{}.png".format(name))) @@ -369,6 +370,59 @@ if __name__ == '__main__': for x in fifo.pretty_read(df): print(x) + ### Using noise hits for another occupancy map + i = 0 + occupancy = 0 + print("\n - Will send L1As until FIFO is full.") + occupancy = 0 + with tqdm(total=65536) as pbar: + while not fifo.is_full(): + fifo.send_l1a() + i +=1 + if i%100 == 0: + tmp = fifo.get_occupancy() + pbar.update(tmp-occupancy) + occupancy = tmp + + test_data = [] + while fifo.get_occupancy() > 0: + test_data += fifo.pretty_read(df) + + hits_total = np.zeros((16,16)) + hit_matrix = hist.Hist(col_axis,row_axis) + n_events_total = 0 + n_events_hit = 0 + for d in test_data: + if d[0] == 'trailer': + n_events_total += 1 + if d[1]['hits'] > 0: + n_events_hit += 1 + if d[0] == 'data': + hit_matrix.fill(row=d[1]['row_id'], col=d[1]['col_id']) + hits_total[d[1]['row_id']][d[1]['col_id']] += 1 + # NOTE could do some CRC check. + + print(f"Got number of total events {n_events_total=}") + print(f"Events with at least one hit {n_events_hit=}") + + fig, ax = plt.subplots(1,1,figsize=(7,7)) + hit_matrix.plot2d( + ax=ax, + ) + ax.set_ylabel(r'$Row$') + ax.set_xlabel(r'$Column$') + hep.cms.label( + "ETL Preliminary", + data=True, + lumi='0', + com=0, + loc=0, + ax=ax, + fontsize=15, + ) + name = 'hit_matrix_external_L1A' + fig.savefig(os.path.join(plot_dir, "{}.pdf".format(name))) + fig.savefig(os.path.join(plot_dir, "{}.png".format(name))) elif args.vth: -- GitLab From e5b765e187f95eccc698477f3215fcf48ca395f4 Mon Sep 17 00:00:00 2001 From: dspitzba <daniel.spitzbart@cern.ch> Date: Mon, 12 Jun 2023 10:20:13 -0400 Subject: [PATCH 02/14] add sanity check histograms --- test_ETROC.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test_ETROC.py b/test_ETROC.py index a384937..e9c09fb 100644 --- a/test_ETROC.py +++ b/test_ETROC.py @@ -425,6 +425,11 @@ if __name__ == '__main__': fig.savefig(os.path.join(plot_dir, "{}.png".format(name))) + print("\nOccupancy vs column:") + hit_matrix[{"row":sum}].show(columns=100) + print("\nOccupancy vs row:") + hit_matrix[{"col":sum}].show(columns=100) + elif args.vth: # ============================== # ======= Test Vth scan ======== -- GitLab From 61d909e9c7b027f949dc2bbcc9ee3c63e1af0989 Mon Sep 17 00:00:00 2001 From: jocain <jgocain@bu.edu> Date: Mon, 12 Jun 2023 14:26:22 -0400 Subject: [PATCH 03/14] Fix get_Qinj() typo --- tamalero/ETROC.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tamalero/ETROC.py b/tamalero/ETROC.py index 2480ffa..d9068d1 100644 --- a/tamalero/ETROC.py +++ b/tamalero/ETROC.py @@ -357,10 +357,10 @@ class ETROC(): def QInj_read(self, row=0, col=0, broadcast=True): if broadcast: - qinj = [[self.get_Qinj(row=y, col=x) for x in range(16)] for y in range(16)] + qinj = [[self.get_QInj(row=y, col=x) for x in range(16)] for y in range(16)] return qinj else: - return self.get_Qinj(row=row, col=col) + return self.get_QInj(row=row, col=col) def auto_threshold_scan(self): # FIXME not yet fully working -- GitLab From 947411c05f24adb6240aa8a62f143e6ad3b672ea Mon Sep 17 00:00:00 2001 From: dspitzba <daniel.spitzbart@cern.ch> Date: Tue, 13 Jun 2023 13:13:48 -0400 Subject: [PATCH 04/14] updates, still using internal test data --- tamalero/ETROC.py | 2 + tamalero/FIFO.py | 26 +++++++-- test_ETROC.py | 136 ++++++++++++++++++++++++++-------------------- 3 files changed, 98 insertions(+), 66 deletions(-) diff --git a/tamalero/ETROC.py b/tamalero/ETROC.py index 2480ffa..cc3af25 100644 --- a/tamalero/ETROC.py +++ b/tamalero/ETROC.py @@ -334,6 +334,7 @@ class ETROC(): # ======================= def QInj_set(self, charge, delay, row=0, col=0, broadcast=True, reset=True): + # FIXME this is a bad name, given that set_QInj also exists """ High-level function to set the charge injection in the ETROC; requires \'charge\' (in fC) and \'delay\' (in 781 ps steps). @@ -352,6 +353,7 @@ class ETROC(): """ if broadcast: self.set_ChargeInjReset(False) # Reset charge injection module + self.disable_QInj(broadcast=broadcast) # Only disable charge injection for specified pixel else: self.disable_QInj(row=row, col=col, broadcast=broadcast) # Only disable charge injection for specified pixel diff --git a/tamalero/FIFO.py b/tamalero/FIFO.py index 346d8e7..76e2aca 100644 --- a/tamalero/FIFO.py +++ b/tamalero/FIFO.py @@ -24,7 +24,10 @@ def merge_words(res): # offset is only needed when zero suppression is turned off, and packet boundaries are not defined # it relies on the fact that the second 32 bit word is half empty (8 bit ETROC data + 12 bits meta data) # if we ever add more meta data this has to be revisited - offset = 1 if (res[1] > res[0]) else 0 + #offset = 1 if (res[1] > res[0]) else 0 + offset = 0 + print(f"## Offset is {offset=}") + #offset = 0 res = res[offset:] #empty_frame_mask = np.array(res[0::2]) > (2**8) # masking empty fifo entries #print(res) @@ -105,12 +108,18 @@ class FIFO: def send_l1a(self, count=1): for i in range(count): - self.rb.kcu.write_node("SYSTEM.L1A_PULSE", 1) + try: + self.rb.kcu.write_node("SYSTEM.L1A_PULSE", 1) + except: + print("Couldn't send pulse.") def send_QInj(self, count=1, delay=0): self.rb.kcu.write_node("READOUT_BOARD_%s.L1A_INJ_DLY"%self.rb.rb, delay) for i in range(count): - self.rb.kcu.write_node("READOUT_BOARD_%s.L1A_QINJ_PULSE" % self.rb.rb, 0x01) + try: + self.rb.kcu.write_node("READOUT_BOARD_%s.L1A_QINJ_PULSE" % self.rb.rb, 0x01) + except: + print("Couldn't send pulse.") def reset(self): self.rb.kcu.write_node("READOUT_BOARD_%s.FIFO_RESET" % self.rb.rb, 0x01) @@ -169,11 +178,16 @@ class FIFO: try: return self.rb.kcu.read_node(f"READOUT_BOARD_{self.rb.rb}.RX_FIFO_OCCUPANCY").value() except uhal_exception: - print("uhal UDP error in FIFO.get_occupancy") - raise + print("uhal UDP error in FIFO.get_occupancy, trying again") + return self.rb.kcu.read_node(f"READOUT_BOARD_{self.rb.rb}.RX_FIFO_OCCUPANCY").value() + #raise def is_full(self): - return self.rb.kcu.read_node(f"READOUT_BOARD_{self.rb.rb}.RX_FIFO_FULL").value() + try: + return self.rb.kcu.read_node(f"READOUT_BOARD_{self.rb.rb}.RX_FIFO_FULL").value() + except uhal_exception: + print("uhal UDP error in FIFO.is_full, trying again") + return self.rb.kcu.read_node(f"READOUT_BOARD_{self.rb.rb}.RX_FIFO_FULL").value() def get_lost_word_count(self): return self.rb.kcu.read_node(f"READOUT_BOARD_{self.rb.rb}.RX_FIFO_LOST_WORD_CNT").value() diff --git a/test_ETROC.py b/test_ETROC.py index e9c09fb..f074e8f 100644 --- a/test_ETROC.py +++ b/test_ETROC.py @@ -13,6 +13,7 @@ from tqdm import tqdm import os import sys import json +import time from yaml import load, dump try: from yaml import CLoader as Loader, CDumper as Dumper @@ -284,7 +285,8 @@ if __name__ == '__main__': etroc.wr_reg("workMode", 0x1, broadcast=True) else: etroc.wr_reg("workMode", 0x0, broadcast=True) - # center pixels + ## center pixels + #etroc.wr_reg("workMode", 0x1, row=15, col=7) etroc.wr_reg("workMode", 0x1, row=7, col=7) etroc.wr_reg("workMode", 0x1, row=7, col=8) etroc.wr_reg("workMode", 0x1, row=8, col=7) @@ -370,65 +372,79 @@ if __name__ == '__main__': for x in fifo.pretty_read(df): print(x) - ### Using noise hits for another occupancy map - i = 0 - occupancy = 0 - print("\n - Will send L1As until FIFO is full.") - occupancy = 0 - with tqdm(total=65536) as pbar: - while not fifo.is_full(): - fifo.send_l1a() - i +=1 - if i%100 == 0: - tmp = fifo.get_occupancy() - pbar.update(tmp-occupancy) - occupancy = tmp - - test_data = [] - while fifo.get_occupancy() > 0: - test_data += fifo.pretty_read(df) - - hits_total = np.zeros((16,16)) - hit_matrix = hist.Hist(col_axis,row_axis) - n_events_total = 0 - n_events_hit = 0 - for d in test_data: - if d[0] == 'trailer': - n_events_total += 1 - if d[1]['hits'] > 0: - n_events_hit += 1 - if d[0] == 'data': - hit_matrix.fill(row=d[1]['row_id'], col=d[1]['col_id']) - hits_total[d[1]['row_id']][d[1]['col_id']] += 1 - # NOTE could do some CRC check. - - print(f"Got number of total events {n_events_total=}") - print(f"Events with at least one hit {n_events_hit=}") - - fig, ax = plt.subplots(1,1,figsize=(7,7)) - hit_matrix.plot2d( - ax=ax, - ) - ax.set_ylabel(r'$Row$') - ax.set_xlabel(r'$Column$') - hep.cms.label( - "ETL Preliminary", - data=True, - lumi='0', - com=0, - loc=0, - ax=ax, - fontsize=15, - ) - name = 'hit_matrix_external_L1A' - fig.savefig(os.path.join(plot_dir, "{}.pdf".format(name))) - fig.savefig(os.path.join(plot_dir, "{}.png".format(name))) - - - print("\nOccupancy vs column:") - hit_matrix[{"row":sum}].show(columns=100) - print("\nOccupancy vs row:") - hit_matrix[{"col":sum}].show(columns=100) + #etroc.QInj_unset(broadcast=True) + fifo.reset() + print("Will use workMode 1 to get some occupancy (no noise or charge injection)") + etroc.wr_reg("workMode", 0x1, broadcast=True) # this was missing + if not args.partial: + for j in range(5): + print(j) + ### Another occupancy map + i = 0 + occupancy = 0 + print("\n - Will send L1As until FIFO is full.") + + #etroc.QInj_set(30, 0, row=3, col=3, broadcast=False) + start_time = time.time() + with tqdm(total=65536) as pbar: + while not fifo.is_full(): + fifo.send_l1a() + #fifo.send_QInj(delay=j) + #fifo.send_QInj() + i +=1 + if i%100 == 0: + tmp = fifo.get_occupancy() + pbar.update(tmp-occupancy) + occupancy = tmp + #if time.time()-start_time>5: + # print("Time out") + # break + + test_data = [] + while fifo.get_occupancy() > 0: + test_data += fifo.pretty_read(df) + + hits_total = np.zeros((16,16)) + hit_matrix = hist.Hist(col_axis,row_axis) + n_events_total = 0 + n_events_hit = 0 + for d in test_data: + if d[0] == 'trailer': + n_events_total += 1 + if d[1]['hits'] > 0: + n_events_hit += 1 + if d[0] == 'data': + hit_matrix.fill(row=d[1]['row_id'], col=d[1]['col_id']) + hits_total[d[1]['row_id']][d[1]['col_id']] += 1 + # NOTE could do some CRC check. + + print(f"Got number of total events {n_events_total=}") + print(f"Events with at least one hit {n_events_hit=}") + + fig, ax = plt.subplots(1,1,figsize=(7,7)) + hit_matrix.plot2d( + ax=ax, + ) + ax.set_ylabel(r'$Row$') + ax.set_xlabel(r'$Column$') + hep.cms.label( + "ETL Preliminary", + data=True, + lumi='0', + com=0, + loc=0, + ax=ax, + fontsize=15, + ) + name = 'hit_matrix_external_L1A' + fig.savefig(os.path.join(plot_dir, "{}.pdf".format(name))) + fig.savefig(os.path.join(plot_dir, "{}.png".format(name))) + + + print("\nOccupancy vs column:") + hit_matrix[{"row":sum}].show(columns=100) + print("\nOccupancy vs row:") + hit_matrix[{"col":sum}].show(columns=100) elif args.vth: # ============================== -- GitLab From 367c63a924e162dc45aed468082d23aa59f7b9d3 Mon Sep 17 00:00:00 2001 From: jocain <jgocain@bu.edu> Date: Tue, 13 Jun 2023 13:34:29 -0400 Subject: [PATCH 05/14] Adding Single Pixel L1a Charge Injection Test --- test_ETROC.py | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/test_ETROC.py b/test_ETROC.py index f074e8f..26f63d5 100644 --- a/test_ETROC.py +++ b/test_ETROC.py @@ -446,6 +446,68 @@ if __name__ == '__main__': print("\nOccupancy vs row:") hit_matrix[{"col":sum}].show(columns=100) + fifo.reset() + q = 30 + delay = 6 + i = 4 + j = 3 + print(f"\n - Will send L1a/QInj pulse with delay of {delay} cycles and charge of {q} fC") + print(f"\n - to pixel at Row {i}, Col {j}.") + etroc.QInj_set(q, delay, row=row, col=col, broadcast = False) + with tqdm(total=65536) as pbar: + while not fifo.is_full(): + try: + kcu.write_node('READOUT_BOARD_0.L1A_QINJ_PULSE', 1) + except: + println('uhal._core.exception: Failed to pulse', file) + etroc.QInj_unset(broadcast = True) + test_data = [] + while fifo.get_occupancy() > 0: + test_data += fifo.pretty_read(df) + + hits_total = np.zeros((16,16)) + hit_matrix = hist.Hist(col_axis,row_axis) + n_events_total = 0 + n_events_hit = 0 + for d in test_data: + if d[0] == 'trailer': + n_events_total += 1 + if d[1]['hits'] > 0: + n_events_hit += 1 + if d[0] == 'data': + hit_matrix.fill(row=d[1]['row_id'], col=d[1]['col_id']) + hits_total[d[1]['row_id']][d[1]['col_id']] += 1 + # NOTE could do some CRC check. + + print(f"Got number of total events {n_events_total=}") + print(f"Events with at least one hit {n_events_hit=}") + + fig, ax = plt.subplots(1,1,figsize=(7,7)) + hit_matrix.plot2d( + ax=ax, + ) + ax.set_ylabel(r'$Row$') + ax.set_xlabel(r'$Column$') + hep.cms.label( + "ETL Preliminary", + data=True, + lumi='0', + com=0, + loc=0, + ax=ax, + fontsize=15, + ) + name = 'hit_matrix_external_L1A_QInj_Pulse' + fig.savefig(os.path.join(plot_dir, "{}.pdf".format(name))) + fig.savefig(os.path.join(plot_dir, "{}.png".format(name))) + + print("\nOccupancy vs column:") + hit_matrix[{"row":sum}].show(columns=100) + print("\nOccupancy vs row:") + hit_matrix[{"col":sum}].show(columns=100) + + + elif args.vth: # ============================== # ======= Test Vth scan ======== -- GitLab From 3afd7285dc61761e432e308ba45fc341dcd4e510 Mon Sep 17 00:00:00 2001 From: jocain <jgocain@bu.edu> Date: Tue, 13 Jun 2023 14:39:12 -0400 Subject: [PATCH 06/14] Fixed a couple of typos in last commit --- test_ETROC.py | 114 +++++++++++++++++++++++++------------------------- 1 file changed, 58 insertions(+), 56 deletions(-) diff --git a/test_ETROC.py b/test_ETROC.py index 26f63d5..3c97e1d 100644 --- a/test_ETROC.py +++ b/test_ETROC.py @@ -196,7 +196,7 @@ if __name__ == '__main__': etroc.set_singlePort("right") #etroc = ETROC(rb=rb_0, i2c_adr=96, i2c_channel=1, elinks={0:[0,2]}) - + print("\n - Checking peripheral configuration:") etroc.print_perif_conf() @@ -244,7 +244,7 @@ if __name__ == '__main__': else: print(f"Failed: {test0=}, {test1=}, {test2=}, {test3=}") - + etroc.wr_reg('serRateLeft', 0) etroc.wr_reg('serRateRight', 0) @@ -262,7 +262,7 @@ if __name__ == '__main__': #rb_0.SCA.set_gpio_direction('mod_d07', 1) #rb_0.SCA.set_gpio('mod_d07', 0) #rb_0.SCA.set_gpio('mod_d07', 1) - + print("\n - Checking elinks") locked = kcu.read_node(f"READOUT_BOARD_0.ETROC_LOCKED").value() if (locked & 0b101) == 5: @@ -275,12 +275,13 @@ if __name__ == '__main__': print(red('No elink is locked.')) print("\n - Getting internal test data") - + #fifo.reset() etroc.wr_reg("selfTestOccupancy", 2, broadcast=True) #etroc.wr_reg("singlePort", 0x0) etroc.wr_reg("mergeTriggerData", 0x1) #etroc.wr_reg("") + if not args.partial: etroc.wr_reg("workMode", 0x1, broadcast=True) else: @@ -445,66 +446,67 @@ if __name__ == '__main__': hit_matrix[{"row":sum}].show(columns=100) print("\nOccupancy vs row:") hit_matrix[{"col":sum}].show(columns=100) - + etroc.wr_reg("workMode", 0x0, broadcast=True) fifo.reset() q = 30 - delay = 6 + delay = 3 i = 4 j = 3 print(f"\n - Will send L1a/QInj pulse with delay of {delay} cycles and charge of {q} fC") print(f"\n - to pixel at Row {i}, Col {j}.") - etroc.QInj_set(q, delay, row=row, col=col, broadcast = False) - with tqdm(total=65536) as pbar: - while not fifo.is_full(): - try: - kcu.write_node('READOUT_BOARD_0.L1A_QINJ_PULSE', 1) - except: - println('uhal._core.exception: Failed to pulse', file) - etroc.QInj_unset(broadcast = True) - test_data = [] - while fifo.get_occupancy() > 0: - test_data += fifo.pretty_read(df) - - hits_total = np.zeros((16,16)) - hit_matrix = hist.Hist(col_axis,row_axis) - n_events_total = 0 - n_events_hit = 0 - for d in test_data: - if d[0] == 'trailer': - n_events_total += 1 - if d[1]['hits'] > 0: - n_events_hit += 1 - if d[0] == 'data': - hit_matrix.fill(row=d[1]['row_id'], col=d[1]['col_id']) - hits_total[d[1]['row_id']][d[1]['col_id']] += 1 - # NOTE could do some CRC check. - - print(f"Got number of total events {n_events_total=}") - print(f"Events with at least one hit {n_events_hit=}") - - fig, ax = plt.subplots(1,1,figsize=(7,7)) - hit_matrix.plot2d( - ax=ax, - ) - ax.set_ylabel(r'$Row$') - ax.set_xlabel(r'$Column$') - hep.cms.label( - "ETL Preliminary", - data=True, - lumi='0', - com=0, - loc=0, + for m in range(5): + etroc.QInj_set(q, delay, row=i, col=j, broadcast = False) + with tqdm(total=65536) as pbar: + while not fifo.is_full(): + try: + kcu.write_node('READOUT_BOARD_0.L1A_QINJ_PULSE', 1) + except: + print('uhal._core.exception: Failed to pulse', file) + etroc.QInj_unset(broadcast = True) + test_data = [] + while fifo.get_occupancy() > 0: + test_data += fifo.pretty_read(df) + + hits_total = np.zeros((16,16)) + hit_matrix = hist.Hist(col_axis,row_axis) + n_events_total = 0 + n_events_hit = 0 + for d in test_data: + if d[0] == 'trailer': + n_events_total += 1 + if d[1]['hits'] > 0: + n_events_hit += 1 + if d[0] == 'data': + hit_matrix.fill(row=d[1]['row_id'], col=d[1]['col_id']) + hits_total[d[1]['row_id']][d[1]['col_id']] += 1 + # NOTE could do some CRC check. + + print(f"Got number of total events {n_events_total=}") + print(f"Events with at least one hit {n_events_hit=}") + + fig, ax = plt.subplots(1,1,figsize=(7,7)) + hit_matrix.plot2d( ax=ax, - fontsize=15, ) - name = 'hit_matrix_external_L1A_QInj_Pulse' - fig.savefig(os.path.join(plot_dir, "{}.pdf".format(name))) - fig.savefig(os.path.join(plot_dir, "{}.png".format(name))) - - print("\nOccupancy vs column:") - hit_matrix[{"row":sum}].show(columns=100) - print("\nOccupancy vs row:") - hit_matrix[{"col":sum}].show(columns=100) + ax.set_ylabel(r'$Row$') + ax.set_xlabel(r'$Column$') + hep.cms.label( + "ETL Preliminary", + data=True, + lumi='0', + com=0, + loc=0, + ax=ax, + fontsize=15, + ) + name = f'hit_matrix_external_L1A_QInj_Pulse_'+str(m) + fig.savefig(os.path.join(plot_dir, "{}.pdf".format(name))) + fig.savefig(os.path.join(plot_dir, "{}.png".format(name))) + + print("\nOccupancy vs column:") + hit_matrix[{"row":sum}].show(columns=100) + print("\nOccupancy vs row:") + hit_matrix[{"col":sum}].show(columns=100) -- GitLab From aebab4855b83ce7a94a4485f267c9feed27128d1 Mon Sep 17 00:00:00 2001 From: dspitzba <daniel.spitzbart@cern.ch> Date: Wed, 21 Jun 2023 18:39:40 -0400 Subject: [PATCH 07/14] clean up --- test_ETROC.py | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/test_ETROC.py b/test_ETROC.py index f074e8f..d1c2d49 100644 --- a/test_ETROC.py +++ b/test_ETROC.py @@ -192,8 +192,8 @@ if __name__ == '__main__': modules[module-1].show_status() etroc = modules[module-1].ETROCs[0] - print(f"Setting the ETROC in single port mode ('right')") - etroc.set_singlePort("right") + #print(f"Setting the ETROC in single port mode ('right')") + #etroc.set_singlePort("right") #etroc = ETROC(rb=rb_0, i2c_adr=96, i2c_channel=1, elinks={0:[0,2]}) @@ -245,10 +245,6 @@ if __name__ == '__main__': print(f"Failed: {test0=}, {test1=}, {test2=}, {test3=}") - etroc.wr_reg('serRateLeft', 0) - etroc.wr_reg('serRateRight', 0) - - # NOTE below is WIP code for tests of the actual data readout from tamalero.FIFO import FIFO from tamalero.DataFrame import DataFrame @@ -258,11 +254,6 @@ if __name__ == '__main__': fifo.select_elink(2) fifo.ready() - ### this does in theory reset the ETROC, but not sure if it comes back up properly - #rb_0.SCA.set_gpio_direction('mod_d07', 1) - #rb_0.SCA.set_gpio('mod_d07', 0) - #rb_0.SCA.set_gpio('mod_d07', 1) - print("\n - Checking elinks") locked = kcu.read_node(f"READOUT_BOARD_0.ETROC_LOCKED").value() if (locked & 0b101) == 5: @@ -274,13 +265,13 @@ if __name__ == '__main__': else: print(red('No elink is locked.')) + fifo.send_l1a(10) + _ = fifo.pretty_read(df) + etroc.reset() + print("\n - Getting internal test data") - #fifo.reset() etroc.wr_reg("selfTestOccupancy", 2, broadcast=True) - #etroc.wr_reg("singlePort", 0x0) - etroc.wr_reg("mergeTriggerData", 0x1) - #etroc.wr_reg("") if not args.partial: etroc.wr_reg("workMode", 0x1, broadcast=True) else: @@ -374,9 +365,9 @@ if __name__ == '__main__': #etroc.QInj_unset(broadcast=True) fifo.reset() - print("Will use workMode 1 to get some occupancy (no noise or charge injection)") - etroc.wr_reg("workMode", 0x1, broadcast=True) # this was missing if not args.partial: + print("Will use workMode 1 to get some occupancy (no noise or charge injection)") + etroc.wr_reg("workMode", 0x1, broadcast=True) # this was missing for j in range(5): print(j) ### Another occupancy map -- GitLab From 68e02a6becdc26d02e27ac63f0acbd2cc19e393d Mon Sep 17 00:00:00 2001 From: dspitzba <daniel.spitzbart@cern.ch> Date: Wed, 21 Jun 2023 18:40:01 -0400 Subject: [PATCH 08/14] debugging features --- configs/dataformat.yaml | 4 ++-- tamalero/ETROC.py | 16 +++++++++++++++- tamalero/Module.py | 1 + 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/configs/dataformat.yaml b/configs/dataformat.yaml index 9ac80f3..4471c25 100644 --- a/configs/dataformat.yaml +++ b/configs/dataformat.yaml @@ -78,9 +78,9 @@ ETROC2: frame: 0x0000000000 mask: 0x8000000000 types: - 0: [ea, col_id, row_id, toa, cal, tot] + 0: [ea, col_id, row_id, toa, cal, tot, elink, full, any_full, global_full] 1: [ea, col_id, row_id, col_id2, row_id2, bcid, counter_a, elink, full, any_full, global_full] - 2: [ea, col_id, row_id, col_id2, row_id2, counter_b, test_pattern] + 2: [ea, col_id, row_id, col_id2, row_id2, counter_b, test_pattern, elink, full, any_full, global_full] data: header: # Define the different masks here? elink: diff --git a/tamalero/ETROC.py b/tamalero/ETROC.py index 372f2d8..7a88e3b 100644 --- a/tamalero/ETROC.py +++ b/tamalero/ETROC.py @@ -1,6 +1,7 @@ """ For ETROC control """ +import time from tamalero.utils import load_yaml, ffs, bit_count from tamalero.colors import red, green, yellow @@ -20,6 +21,7 @@ class ETROC(): elinks={0:[0]}, verbose=False, strict=True, + reset=None, ): self.isfake = False self.I2C_master = rb.DAQ_LPGBT if master.lower() == 'lpgbt' else rb.SCA @@ -29,6 +31,7 @@ class ETROC(): self.i2c_channel = i2c_channel self.i2c_adr = i2c_adr self.elinks = elinks + self.reset_pin = reset self.is_connected() if self.connected: self.ver = self.get_ver() @@ -237,6 +240,16 @@ class ETROC(): all_pass &= comp return all_pass + def reset(self, hard=False): + if hard: + self.rb.SCA.set_gpio(self.reset_pin, 0) + time.sleep(0.1) + self.rb.SCA.set_gpio(self.reset_pin, 1) + else: + self.wr_reg("asyResetGlobalReadout", 0) + time.sleep(0.1) + self.wr_reg("asyResetGlobalReadout", 1) + # ============================ # === MONITORING FUNCTIONS === # ============================ @@ -319,6 +332,7 @@ class ETROC(): def default_config(self): # FIXME should use higher level functions for better readability if self.connected: + self.reset() # soft reset of the global readout self.set_singlePort('both') self.set_mergeTriggerData('separate') self.disable_Scrambler() @@ -547,7 +561,7 @@ class ETROC(): def set_workMode(self, mode, row=0, col=0, broadcast=True): val = {'normal': 0b00, 'self test fixed': 0b01, 'self test random': 0b10} try: - self.wr_reg('workMode', val(mode), row=row, col=col, broadcast=broadcast) + self.wr_reg('workMode', val[mode], row=row, col=col, broadcast=broadcast) except KeyError: print('Choose between \'normal\', \'self test fixed\', \'self test random\'.') diff --git a/tamalero/Module.py b/tamalero/Module.py index af512bc..da8113a 100644 --- a/tamalero/Module.py +++ b/tamalero/Module.py @@ -38,6 +38,7 @@ class Module: #elinks = self.config['elinks'][j], i2c_adr = self.config['addresses'][j], strict = strict, + reset = self.config['reset'], )) #def configure(self): -- GitLab From 4eb86e126cd472f74602ba9c7c6e525cd8e22ddb Mon Sep 17 00:00:00 2001 From: dspitzba <daniel.spitzbart@cern.ch> Date: Wed, 21 Jun 2023 18:50:56 -0400 Subject: [PATCH 09/14] make qinj tests optional --- test_ETROC.py | 121 +++++++++++++++++++++++++------------------------- 1 file changed, 61 insertions(+), 60 deletions(-) diff --git a/test_ETROC.py b/test_ETROC.py index 84c0e2f..febd138 100644 --- a/test_ETROC.py +++ b/test_ETROC.py @@ -110,6 +110,7 @@ if __name__ == '__main__': argParser.add_argument('--module', action='store', default=0, choices=['1','2','3'], help="Module to test") argParser.add_argument('--host', action='store', default='localhost', help="Hostname for control hub") argParser.add_argument('--partial', action='store_true', default=False, help="Only read data from corners and edges") + argParser.add_argument('--qinj', action='store_true', default=False, help="Run some charge injection tests") args = argParser.parse_args() @@ -153,7 +154,6 @@ if __name__ == '__main__': print("Test passed.\n") elif args.test_chip: - # FIXME this is still hardcoded kcu = get_kcu(args.kcu, control_hub=True, host=args.host, verbose=False) if (kcu == 0): # if not basic connection was established the get_kcu function returns 0 @@ -436,67 +436,68 @@ if __name__ == '__main__': print("\nOccupancy vs row:") hit_matrix[{"col":sum}].show(columns=100) - etroc.wr_reg("workMode", 0x0, broadcast=True) - fifo.reset() - q = 30 - delay = 3 - i = 4 - j = 3 - print(f"\n - Will send L1a/QInj pulse with delay of {delay} cycles and charge of {q} fC") - print(f"\n - to pixel at Row {i}, Col {j}.") - for m in range(5): - etroc.QInj_set(q, delay, row=i, col=j, broadcast = False) - with tqdm(total=65536) as pbar: - while not fifo.is_full(): - try: - kcu.write_node('READOUT_BOARD_0.L1A_QINJ_PULSE', 1) - except: - print('uhal._core.exception: Failed to pulse', file) - etroc.QInj_unset(broadcast = True) - test_data = [] - while fifo.get_occupancy() > 0: - test_data += fifo.pretty_read(df) - - hits_total = np.zeros((16,16)) - hit_matrix = hist.Hist(col_axis,row_axis) - n_events_total = 0 - n_events_hit = 0 - for d in test_data: - if d[0] == 'trailer': - n_events_total += 1 - if d[1]['hits'] > 0: - n_events_hit += 1 - if d[0] == 'data': - hit_matrix.fill(row=d[1]['row_id'], col=d[1]['col_id']) - hits_total[d[1]['row_id']][d[1]['col_id']] += 1 - # NOTE could do some CRC check. - - print(f"Got number of total events {n_events_total=}") - print(f"Events with at least one hit {n_events_hit=}") - - fig, ax = plt.subplots(1,1,figsize=(7,7)) - hit_matrix.plot2d( - ax=ax, - ) - ax.set_ylabel(r'$Row$') - ax.set_xlabel(r'$Column$') - hep.cms.label( - "ETL Preliminary", - data=True, - lumi='0', - com=0, - loc=0, + if args.qinj: + etroc.wr_reg("workMode", 0x0, broadcast=True) + fifo.reset() + q = 30 + delay = 3 + i = 4 + j = 3 + print(f"\n - Will send L1a/QInj pulse with delay of {delay} cycles and charge of {q} fC") + print(f"\n - to pixel at Row {i}, Col {j}.") + for m in range(5): + etroc.QInj_set(q, delay, row=i, col=j, broadcast = False) + with tqdm(total=65536) as pbar: + while not fifo.is_full(): + try: + kcu.write_node('READOUT_BOARD_0.L1A_QINJ_PULSE', 1) + except: + print('uhal._core.exception: Failed to pulse', file) + etroc.QInj_unset(broadcast = True) + test_data = [] + while fifo.get_occupancy() > 0: + test_data += fifo.pretty_read(df) + + hits_total = np.zeros((16,16)) + hit_matrix = hist.Hist(col_axis,row_axis) + n_events_total = 0 + n_events_hit = 0 + for d in test_data: + if d[0] == 'trailer': + n_events_total += 1 + if d[1]['hits'] > 0: + n_events_hit += 1 + if d[0] == 'data': + hit_matrix.fill(row=d[1]['row_id'], col=d[1]['col_id']) + hits_total[d[1]['row_id']][d[1]['col_id']] += 1 + # NOTE could do some CRC check. + + print(f"Got number of total events {n_events_total=}") + print(f"Events with at least one hit {n_events_hit=}") + + fig, ax = plt.subplots(1,1,figsize=(7,7)) + hit_matrix.plot2d( ax=ax, - fontsize=15, ) - name = f'hit_matrix_external_L1A_QInj_Pulse_'+str(m) - fig.savefig(os.path.join(plot_dir, "{}.pdf".format(name))) - fig.savefig(os.path.join(plot_dir, "{}.png".format(name))) - - print("\nOccupancy vs column:") - hit_matrix[{"row":sum}].show(columns=100) - print("\nOccupancy vs row:") - hit_matrix[{"col":sum}].show(columns=100) + ax.set_ylabel(r'$Row$') + ax.set_xlabel(r'$Column$') + hep.cms.label( + "ETL Preliminary", + data=True, + lumi='0', + com=0, + loc=0, + ax=ax, + fontsize=15, + ) + name = f'hit_matrix_external_L1A_QInj_Pulse_'+str(m) + fig.savefig(os.path.join(plot_dir, "{}.pdf".format(name))) + fig.savefig(os.path.join(plot_dir, "{}.png".format(name))) + + print("\nOccupancy vs column:") + hit_matrix[{"row":sum}].show(columns=100) + print("\nOccupancy vs row:") + hit_matrix[{"col":sum}].show(columns=100) -- GitLab From a892423c8088e538f4a7b3584d96be15a99ec170 Mon Sep 17 00:00:00 2001 From: dspitzba <daniel.spitzbart@cern.ch> Date: Thu, 22 Jun 2023 08:36:36 -0400 Subject: [PATCH 10/14] reset option --- test_ETROC.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/test_ETROC.py b/test_ETROC.py index febd138..cf72207 100644 --- a/test_ETROC.py +++ b/test_ETROC.py @@ -111,6 +111,8 @@ if __name__ == '__main__': argParser.add_argument('--host', action='store', default='localhost', help="Hostname for control hub") argParser.add_argument('--partial', action='store_true', default=False, help="Only read data from corners and edges") argParser.add_argument('--qinj', action='store_true', default=False, help="Run some charge injection tests") + argParser.add_argument('--hard_reset', action='store_true', default=False, help="Hard reset of selected ETROC2 chip") + argParser.add_argument('--mode', action='store', default=['dual'], choices=['dual', 'single'] help="Port mode for ETROC2") args = argParser.parse_args() @@ -192,8 +194,14 @@ if __name__ == '__main__': modules[module-1].show_status() etroc = modules[module-1].ETROCs[0] - #print(f"Setting the ETROC in single port mode ('right')") - #etroc.set_singlePort("right") + if args.hard_reset: + etroc.reset(hard=True) + if args.mode == 'single': + print(f"Setting the ETROC in single port mode ('right')") + etroc.set_singlePort("right") + elif args.mode == 'dual': + print(f"Setting the ETROC in dual port mode ('both')") + etroc.set_singlePort("both") #etroc = ETROC(rb=rb_0, i2c_adr=96, i2c_channel=1, elinks={0:[0,2]}) -- GitLab From 1357534f832d9f9606a53e608ff976c312182b67 Mon Sep 17 00:00:00 2001 From: dspitzba <daniel.spitzbart@cern.ch> Date: Thu, 22 Jun 2023 11:13:00 -0400 Subject: [PATCH 11/14] temporary fix for reset pin for emulator --- configs/emulator_v2.yaml | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/configs/emulator_v2.yaml b/configs/emulator_v2.yaml index 71972d9..1d2ea92 100644 --- a/configs/emulator_v2.yaml +++ b/configs/emulator_v2.yaml @@ -65,6 +65,7 @@ modules: master: lpgbt channel: 1 status: mod_d01 + reset: None 2: elinks: [[[4],[4]], [[6],[6]], [[16],[16]], [[18],[18]]] addresses: [0x72, 0x72, 0x72, 0x72] @@ -72,10 +73,12 @@ modules: master: sca channel: 3 status: mod_d09 + reset: None 3: - elinks: [[[8],[8]], [[10],[10]], [[12],[12]], [[14],[14]]] - addresses: [0x72, 0x72, 0x72, 0x72] - i2c: - master: sca - channel: 0 - status: mod_d17 + elinks: [[[8],[8]], [[10],[10]], [[12],[12]], [[14],[14]]] + addresses: [0x72, 0x72, 0x72, 0x72] + i2c: + master: sca + channel: 0 + status: mod_d17 + reset: None -- GitLab From 3ec0811d8ebec996806558d9bbc9a6565f8e0428 Mon Sep 17 00:00:00 2001 From: dspitzba <daniel.spitzbart@cern.ch> Date: Thu, 22 Jun 2023 11:16:30 -0400 Subject: [PATCH 12/14] adding missing , in argParser --- test_ETROC.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_ETROC.py b/test_ETROC.py index cf72207..405db11 100644 --- a/test_ETROC.py +++ b/test_ETROC.py @@ -112,7 +112,7 @@ if __name__ == '__main__': argParser.add_argument('--partial', action='store_true', default=False, help="Only read data from corners and edges") argParser.add_argument('--qinj', action='store_true', default=False, help="Run some charge injection tests") argParser.add_argument('--hard_reset', action='store_true', default=False, help="Hard reset of selected ETROC2 chip") - argParser.add_argument('--mode', action='store', default=['dual'], choices=['dual', 'single'] help="Port mode for ETROC2") + argParser.add_argument('--mode', action='store', default=['dual'], choices=['dual', 'single'], help="Port mode for ETROC2") args = argParser.parse_args() -- GitLab From f3c9c6b56879619eb79a883da7e2ddf5719979ab Mon Sep 17 00:00:00 2001 From: dspitzba <daniel.spitzbart@cern.ch> Date: Thu, 22 Jun 2023 11:30:40 -0400 Subject: [PATCH 13/14] updating elink status --- tamalero/Module.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tamalero/Module.py b/tamalero/Module.py index da8113a..7efbb33 100644 --- a/tamalero/Module.py +++ b/tamalero/Module.py @@ -83,6 +83,7 @@ class Module: self.locked = {0:[], 1:[]} self.unlocked = {0:[], 1:[]} for etroc in self.ETROCs: + etroc.get_elink_status() for i in [0,1]: if i in etroc.links_locked: for j, link in enumerate(etroc.elinks[i]): -- GitLab From 279bdf6ae2d8609bd1b565f2d853654757ffc734 Mon Sep 17 00:00:00 2001 From: dspitzba <daniel.spitzbart@cern.ch> Date: Thu, 22 Jun 2023 11:41:43 -0400 Subject: [PATCH 14/14] reconfigure ETROC after hard reset --- test_ETROC.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test_ETROC.py b/test_ETROC.py index 405db11..205ec9e 100644 --- a/test_ETROC.py +++ b/test_ETROC.py @@ -196,6 +196,8 @@ if __name__ == '__main__': etroc = modules[module-1].ETROCs[0] if args.hard_reset: etroc.reset(hard=True) + etroc.default_config() + if args.mode == 'single': print(f"Setting the ETROC in single port mode ('right')") etroc.set_singlePort("right") -- GitLab