Skip to content

Optimize I2C parameter mapping

Artur Lobanov requested to merge reorg_roc_i2c into HGCROCv2

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

See in git

    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

See in git

    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

Merge request reports