Optimize I2C parameter mapping
This MR implements an update of the HGCROC I2C parameter mapping, going from bit-wise to register-wise mapping. A description was presented in this DAQ&FW meeting and below. The change is transparent with regards to the usage of the ROC config class.
HGCROCv2 bit-mask to reg-mask
What was there before:
HGCROC I2C address-space stored at bit-level (dataframe stored in CSV)
- Pro: taking HGCROC files from omega as is
- Con: need to perform on-the-fly computations for register-level infromation (masks)
Parameter READ code
df_par = df.loc[(block, blockid, name)]
# compute number of bits
nbits = len(df_par)
## check value is within range:
max_val = 2**nbits
if value > max_val:
print("Warning: value %i out of range %i" %(value, max_val))
return None
## group by SubAddress and register
gb = df_par.groupby(["SubAddress","Register"])
# parameter bit blockides
param_bits = gb.param_bit.apply(lambda x: x.values).to_dict()
# bit locations in register
bit_locations = gb.reg_bit.apply(lambda x: x.values).to_dict()
reg_adds = param_bits.keys()
param_parts = {}
val_enabled_bits = np.array([1*((value & (1 << i)) != 0) for i in range(nbits)])
## Split value in registers
for reg_add in reg_adds:
param_bit_positions = param_bits[reg_add]
reg_bit_positions = bit_locations[reg_add]
i2c_reg = get_I2C_reg_val(reg_add[0],reg_add[1])
reg_on_bits = val_enabled_bits[param_bit_positions]
reg_mask = np.sum(2**(reg_bit_positions))
reg_data = np.sum(reg_on_bits * (2**(reg_bit_positions)))
param_parts[i2c_reg] = reg_data
set_I2C_parameter_masked(i2c_reg[0], i2c_reg[1], reg_data, reg_mask)
New approach:
-
Convert bit-level map to parameter-level map with masks
-
Store map in nested dict instead of dataframe:
-
map["ch"][35]["Adc_pedestal"]
inseadt of `df.iloc[("ch",35,"Adc_pedestal")] --> ~100x faster
-
-
Pro: remove the computation from the I2C code
-
Con: needs another conversion step from old CSV (done once and stored instead of CSV)
A corresponding CSV like this:
Parameter READ code
Much shorter and faster
par_regs = d_map[block][blockid][name]
param_parts = {}
for reg_id,reg in par_regs.iteritems():
# apply mask to parameter
reg_data = value & reg["param_mask"]
reg_data >>= get_lsb_id(reg["param_mask"])
reg_data <<= get_lsb_id(reg["reg_mask"])
param_parts[reg_id] = hex(reg_data)
# dummy set
#set_dummy_I2C(reg['R0'],reg['R1'], reg_data)
# real I2C setting
set_I2C_parameter_masked(reg['R0'],reg['R1'], reg_data, reg["reg_mask"])
Edited by Artur Lobanov