From f8e119d1ea51e0f3d8718ff966f1b1fa6acd8c63 Mon Sep 17 00:00:00 2001 From: dspitzba <daniel.spitzbart@cern.ch> Date: Fri, 1 Dec 2023 19:57:39 -0500 Subject: [PATCH 1/5] always enable all elinks for readout --- test_tamalero.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test_tamalero.py b/test_tamalero.py index c1f8675..e8d321c 100644 --- a/test_tamalero.py +++ b/test_tamalero.py @@ -284,6 +284,9 @@ if __name__ == '__main__': # Module Status #------------------------------------------------------------------------------- + rb.enable_etroc_readout() + rb.enable_etroc_readout(slave=True) + modules = [] pb_channel = [] if args.configuration == 'emulator' or args.configuration.count('modulev0'): -- GitLab From 4417a8871c806428de33553e74f83b299fd3a563 Mon Sep 17 00:00:00 2001 From: dspitzba <daniel.spitzbart@cern.ch> Date: Fri, 1 Dec 2023 19:58:05 -0500 Subject: [PATCH 2/5] retry SCA I2C reads because they do fail sometimes --- tamalero/SCA.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tamalero/SCA.py b/tamalero/SCA.py index 0fdcc3b..fda4cec 100644 --- a/tamalero/SCA.py +++ b/tamalero/SCA.py @@ -582,7 +582,16 @@ class SCA: def I2C_read(self, reg=0x0, master=3, slave_addr=0x48, nbytes=1, adr_nbytes=2, freq=2): # wrapper function to have similar interface as lpGBT I2C_read if nbytes > 1 or adr_nbytes>1: - return self.I2C_read_multi(channel=master, servant=slave_addr, reg=reg, nbytes=nbytes, adr_nbytes=adr_nbytes, freq=freq) + start_time = time.time() + while True: + try: + return self.I2C_read_multi(channel=master, servant=slave_addr, reg=reg, nbytes=nbytes, adr_nbytes=adr_nbytes, freq=freq) + except: + if (time.time() - start_time) < 2: + pass + else: + #print("I2C_read in SCA timed out.") # not printing this. SCA will time out e.g. if we're trying to see if a module/ETROC is connected on an empty slot! + raise RuntimeError("SCA timed out") else: return self.I2C_read_single_byte(channel=master, servant=slave_addr, reg=reg, freq=freq) -- GitLab From 28c8f7d88cf55ec150ff5fb7c919c3b6d8d842d7 Mon Sep 17 00:00:00 2001 From: dspitzba <daniel.spitzbart@cern.ch> Date: Fri, 1 Dec 2023 19:59:56 -0500 Subject: [PATCH 3/5] using a proper chip ID, WIP --- tamalero/ETROC.py | 12 +++++++++++- tamalero/Module.py | 4 +++- test_ETROC.py | 26 +++++++++++++++++++++++--- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/tamalero/ETROC.py b/tamalero/ETROC.py index 36ffab1..06d64f4 100644 --- a/tamalero/ETROC.py +++ b/tamalero/ETROC.py @@ -27,6 +27,7 @@ class ETROC(): vref=None, vref_pd=False, vtemp = None, + chip_id = 0, ): self.QINJ_delay = 504 # this is a fixed value for the default settings of ETROC2 self.isfake = False @@ -47,8 +48,17 @@ class ETROC(): else: self.ver = "X-X-X" + self.chip_id = chip_id self.regs = load_yaml(os.path.join(here, '../address_table/ETROC2_example.yaml')) + # NOTE: some ETROCs need to be hard reset, otherwise the I2C target does not come alive. + # This actually solves this issue, so please don't take it out (Chesterton's Fence, anyone?) + for i in range(2): + if self.is_connected(): + break + self.reset(hard=True) + time.sleep(0.1) + if self.is_connected(): if vref_pd: self.power_down_VRef() @@ -436,7 +446,7 @@ class ETROC(): self.invalid_FC_counter = self.get_invalidFCCount() # give some number to the ETROC - self.wr_reg("EFuse_Prog", 1234) # gives a chip ID of 308. + self.wr_reg("EFuse_Prog", (self.chip_id)<<2) # gives the correct chip ID # configuration as per discussion with ETROC2 developers self.wr_reg("onChipL1AConf", 0) # this should be default anyway diff --git a/tamalero/Module.py b/tamalero/Module.py index 3a96cc5..bf8a74d 100644 --- a/tamalero/Module.py +++ b/tamalero/Module.py @@ -7,7 +7,7 @@ from tamalero.Monitoring import Lock from time import sleep class Module: - def __init__(self, rb, i=1, strict=False, enable_power_board=False): + def __init__(self, rb, i=1, strict=False, enable_power_board=False, moduleid=0): # don't like that this also needs a RB # think about a better solution self.config = rb.configuration['modules'][i] @@ -17,6 +17,7 @@ class Module: #self.regs_em = ['disScrambler', 'singlePort', 'mergeTriggerData', 'triggerGranularity'] self.i = i self.rb = rb + self.id = moduleid if enable_power_board: self.enable_power_board() @@ -50,6 +51,7 @@ class Module: vref = self.config['vref'][j], vref_pd = self.config['disable_vref_gen'][j], vtemp = self.config['vtemp'][j], + chip_id = (self.id << 2) | j # this gives every ETROC a unique ID, based on module ID and ETROC number on the module )) #def configure(self): diff --git a/test_ETROC.py b/test_ETROC.py index f424c82..3d49240 100644 --- a/test_ETROC.py +++ b/test_ETROC.py @@ -254,7 +254,8 @@ if __name__ == '__main__': connected_modules = [] for i in [1,2,3]: # FIXME we might want to hard reset all ETROCs at this point? - m_tmp = Module(rb=rb_0, i=i, enable_power_board=args.enable_power_board) + moduleid = int(args.moduleid) if i==int(args.module) else (i+200) # NOTE: at some point we should also include the RB number, e.g. (rb << 4) | (module) + m_tmp = Module(rb=rb_0, i=i, enable_power_board=args.enable_power_board, moduleid = moduleid) modules.append(m_tmp) if m_tmp.ETROCs[0].is_connected(): # NOTE assume that module is connected if first ETROC is connected connected_modules.append(i) @@ -344,11 +345,30 @@ if __name__ == '__main__': # FIXME the below code is still pretty stupid modules = [] connected_modules = [] + for i in [1,2,3]: - m_tmp = Module(rb=rb_0, i=i, enable_power_board=args.enable_power_board) + # FIXME we might want to hard reset all ETROCs at this point? + moduleid = int(args.moduleid) if i==int(args.module) else (i+200) + m_tmp = Module(rb=rb_0, i=i, enable_power_board=args.enable_power_board, moduleid = moduleid) modules.append(m_tmp) - if m_tmp.ETROCs[0].connected: # NOTE assume that module is connected if first ETROC is connected + if m_tmp.ETROCs[0].is_connected(): # NOTE assume that module is connected if first ETROC is connected connected_modules.append(i) + for e_tmp in m_tmp.ETROCs: + if args.hard_reset: + print(f"Running hard reset and default config on module {i}") + e_tmp.reset(hard=True) + e_tmp.default_config() + time.sleep(1.1) + #e_tmp.default_config() + # + print("Setting ETROCs into workMode 0") + e_tmp.wr_reg("workMode", 0, broadcast=True) + + #for i in [1,2,3]: + # m_tmp = Module(rb=rb_0, i=i, enable_power_board=args.enable_power_board) + # modules.append(m_tmp) + # if m_tmp.ETROCs[0].connected: # NOTE assume that module is connected if first ETROC is connected + # connected_modules.append(i) print(f"Found {len(connected_modules)} connected modules") if int(args.module) > 0: -- GitLab From e285c175a4bf62104947406d556fac008a100458 Mon Sep 17 00:00:00 2001 From: dspitzba <daniel.spitzbart@cern.ch> Date: Fri, 1 Dec 2023 20:00:41 -0500 Subject: [PATCH 4/5] proper init for any ETROC, including hard resets and PLL/FC resets --- tamalero/ETROC.py | 21 +++++++++-- test_ETROC.py | 92 +++++++++++++++++++++++++---------------------- 2 files changed, 68 insertions(+), 45 deletions(-) diff --git a/tamalero/ETROC.py b/tamalero/ETROC.py index 06d64f4..b2fc2e1 100644 --- a/tamalero/ETROC.py +++ b/tamalero/ETROC.py @@ -338,7 +338,7 @@ class ETROC(): self.reset_PLL() self.reset_fast_command() self.reset() - self.default_config() + self.default_config(no_reset=True) self.rb.kcu.write_node("READOUT_BOARD_%s.BITSLIP_AUTO_EN"%self.rb.rb, 0x1) time.sleep(0.1) self.rb.kcu.write_node("READOUT_BOARD_%s.BITSLIP_AUTO_EN"%self.rb.rb, 0x0) @@ -432,7 +432,7 @@ class ETROC(): # === CONTROL FUNCTIONS === # ========================= - def default_config(self): + def default_config(self, no_reset=False): # FIXME should use higher level functions for better readability if self.is_connected(): self.reset() # soft reset of the global readout @@ -474,6 +474,23 @@ class ETROC(): self.wr_reg("lowerCalTrig", 0, broadcast=True) self.reset() # soft reset of the global readout, 2nd reset needed for some ETROCs + # + # FIXME this is where the module_reset should happen if links are not locked?? + if not no_reset: + elink_status = self.get_elink_status() + #print(elink_status) + stat = True + for elinks in elink_status: + #print(elink_status[elinks]) + for elink in elink_status[elinks]: + if elink == False: + stat &= False + + if not stat: + print("elinks not locked, resetting PLL and FC modules") + self.reset_modules() + + #print(self.get_elink_status()) def is_good(self): good = True diff --git a/test_ETROC.py b/test_ETROC.py index 3d49240..de31c5a 100644 --- a/test_ETROC.py +++ b/test_ETROC.py @@ -241,6 +241,8 @@ if __name__ == '__main__': sys.exit(1) fifo = FIFO(rb=rb_0) + fifo.send_l1a(1) + fifo.reset() is_configured = rb_0.DAQ_LPGBT.is_configured() if not is_configured: @@ -266,6 +268,9 @@ if __name__ == '__main__': e_tmp.default_config() time.sleep(1.1) #e_tmp.default_config() + # + print("Setting ETROCs into workMode 0") + e_tmp.wr_reg("workMode", 0, broadcast=True) time.sleep(0.1) @@ -473,49 +478,50 @@ if __name__ == '__main__': print("\n - Checking elinks") - print("Disabling readout for all elinks but the ETROC under test") - rb_0.disable_etroc_readout(all=True) - rb_0.reset_data_error_count() - #rb_0.enable_etroc_readout() - for lpgbt in etroc.elinks: - if lpgbt == 0: - slave = False - else: - slave = True - for link in etroc.elinks[lpgbt]: - print(f"Enabling elink {link}, slave is {slave}") - rb_0.enable_etroc_readout(link, slave=slave) - #time.sleep(0.5) - #rb_0.reset_data_error_count() - #fifo.select_elink(link, slave) - #fifo.ready() - rb_0.rerun_bitslip() - time.sleep(1.5) - rb_0.reset_data_error_count() - stat = rb_0.get_link_status(link, slave=slave, verbose=False) - if stat: - rb_0.get_link_status(link, slave=slave) - start_time = time.time() - while not stat: - #rb_0.disable_etroc_readout(link, slave=slave) - rb_0.enable_etroc_readout(link, slave=slave) - #time.sleep(0.5) - #time.sleep(0.1) - #rb_0.reset_data_error_count() - #fifo.select_elink(link, slave) - #fifo.ready() - rb_0.rerun_bitslip() - time.sleep(1.5) - rb_0.reset_data_error_count() - stat = rb_0.get_link_status(link, slave=slave, verbose=False - ) - if stat: - rb_0.get_link_status(link, slave=slave) - break - if time.time() - start_time > 2: - print('Link not good, but continuing') - rb_0.get_link_status(link, slave=slave) - break + #print("Disabling readout for all elinks but the ETROC under test") + ## FIXME this is still problematic... + #rb_0.disable_etroc_readout(all=True) + #rb_0.reset_data_error_count() + ##rb_0.enable_etroc_readout() + #for lpgbt in etroc.elinks: + # if lpgbt == 0: + # slave = False + # else: + # slave = True + # for link in etroc.elinks[lpgbt]: + # print(f"Enabling elink {link}, slave is {slave}") + # rb_0.enable_etroc_readout(link, slave=slave) + # #time.sleep(0.5) + # #rb_0.reset_data_error_count() + # #fifo.select_elink(link, slave) + # #fifo.ready() + # rb_0.rerun_bitslip() + # time.sleep(1.5) + # rb_0.reset_data_error_count() + # stat = rb_0.get_link_status(link, slave=slave, verbose=False) + # if stat: + # rb_0.get_link_status(link, slave=slave) + # start_time = time.time() + # while not stat: + # #rb_0.disable_etroc_readout(link, slave=slave) + # rb_0.enable_etroc_readout(link, slave=slave) + # #time.sleep(0.5) + # #time.sleep(0.1) + # #rb_0.reset_data_error_count() + # #fifo.select_elink(link, slave) + # #fifo.ready() + # rb_0.rerun_bitslip() + # time.sleep(1.5) + # rb_0.reset_data_error_count() + # stat = rb_0.get_link_status(link, slave=slave, verbose=False + # ) + # if stat: + # rb_0.get_link_status(link, slave=slave) + # break + # if time.time() - start_time > 2: + # print('Link not good, but continuing') + # rb_0.get_link_status(link, slave=slave) + # break ## Bloc below to be retired ## Keeping it for one more iteration -- GitLab From e1efe67da491ae567a7c8f88cf57fdaf3a938322 Mon Sep 17 00:00:00 2001 From: dspitzba <daniel.spitzbart@cern.ch> Date: Fri, 1 Dec 2023 20:11:49 -0500 Subject: [PATCH 5/5] fixing reset for emulators --- tamalero/ETROC.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/tamalero/ETROC.py b/tamalero/ETROC.py index b2fc2e1..a2da9ad 100644 --- a/tamalero/ETROC.py +++ b/tamalero/ETROC.py @@ -321,14 +321,16 @@ class ETROC(): 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) + if self.breed not in ['software', 'emulator']: + # the emulators are not going to be reset at all + 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) if not self.isfake: self.rb.rerun_bitslip() # NOTE this is necessary to get the links to lock again -- GitLab