Пример #1
0
    def init_llrf_settings(self):
	temp = get_map(os.path.join(base_dir, 'parameters/llrf_core_expand.json'))
	temp = temp['cryomodule']['regmap']
	self.app_reg_prefix = 'cryomodule_'

        self.wave_samp_per_name = get_reg_info(temp, [0], 'wave_samp_per')['name'].replace(self.app_reg_prefix, '')
        self.wave_shift_name = get_reg_info(temp, [0], 'wave_shift')['name'].replace(self.app_reg_prefix, '')
        self.chan_keep_name = get_reg_info(temp, [0], 'chan_keep')['name'].replace(self.app_reg_prefix, '')

        json_path = os.path.join(base_dir, 'parameters/llrf_core_expand.json')
        self.core_llrf = RegMapExpand(base=0, add_prefix=False, path=json_path)
        self.regmap.update(self.core_llrf.regmap)
        self.regmap_short.update(self.core_llrf.regmap_short)
        self.reg_addr_dict.update(self.core_llrf.reg_addr_dict)

        # see llrf_core.json
        self._cbuf_flip_name = 'DSP_CBUF_FLIP'
        self._slow_name = 'DSP_SLOW'
        self._cbuf_name = 'DSP_CBUF'
        self._cbuf_mode_channel_name = 'DSP_CBUF_MODE'
        self.config_rom_name = 'DSP_CONFIG_ROM'

        self.buf_dw = 16
        self.cbuf_width = 13
        self.adc_bits = 16
        self.shift_base = 1  # ccfilt.v
        self.wave_samp_per = 1
        self.wave_shift = 3
        self.num_dds = 7
        self.den_dds = 33
        self.clk_freq = 75e6
        self.chn_names = ['Field', 'Forward', 'Reflected', 'PhRef']
        self.chn_names.extend(['Null'] * 2)
        self.slow_buf_len = 2*len(self.chn_names) + 2
        self.cbuf_mode_list = ['default'] + ['Counter'] + self.chn_names[:3] + ['Drive']
        self.chn_sel = self.chn_names[:4]
        self.prng_data = {}
        # self.init_llrf_settings()
        self.to_fpga = PhysicsToFPGA(**{x['name']:x['value'] for x in physics_regs})
        self.cic_period = self.den_dds
        # channel FIR configurations may vary
        self.FIR_GAIN = 1.
        self.mon_gains, self.fir_gains = {}, {}

        for ch in self.chn_names:
            self.mon_gains[ch] = self.FIR_GAIN
            self.fir_gains[ch] = self.FIR_GAIN
        self.lo_gain = int((1 << 15) / self.CORDIC_GAIN)
        self.lo_dds_gain = self.lo_gain * 4 * self.CORDIC_GAIN / (1 << 17)
        self.adc_freq = 150e6
        self.time_step_adc = 1./self.adc_freq
        self.time_step_mon = self.wave_samp_per / self.clk_freq
        self.trace_len = (1 << 11)/len(self.chn_sel)
Пример #2
0
def RRRRR(name, regmap, value, station_index=None, mode_index=None, addr_offset=0):
    if station_index is not None:
	if mode_index is not None:
	    addr = get_reg_info(regmap_cryomodule, [station_index, mode_index], name)["base_addr"]
	else:
	    addr = get_reg_info(regmap_cryomodule, [station_index], name)["base_addr"]
    else:
	addr = get_reg_info(regmap_cryomodule, [], name)["base_addr"]
    if type(value) is list:
	for i, v in enumerate(value):
	    print addr_offset + addr + i, v, "#", name + "["+str(i)+"]"
    else:
	print addr_offset + addr, value, '#', name
Пример #3
0
def getFPGADict(simulation):
    """
    getFPGADict: Illustration of conversion of user-defined physics values
    (contained in the simulation object, which is obtained from the JSON parser)
    and the FPGA register values, contained in the output dictionary
    linac_reg_dict.  error_cnt is an error count reported from the
    floating-point to fix-point arithmetic conversions and scaling.
    """

    from read_regmap import get_map
    regmap = get_map(base_dir + "/../_autogen/regmap_cryomodule.json")
    c_reg_base = get_reg_info(regmap, [],
                              'llrf_' + str(0) + '_xxxx')['base_addr']

    # Initialize empty FPGA register objects
    simulation.Init_FPGA_Registers(regmap, [])

    # Compute FPGA register values based on configuration parameters
    flat_reg_dict, error_cnt = simulation.Compute_FPGA_Registers()

    # Replace computed values directly in register map
    for key, value in flat_reg_dict.iteritems():
        regmap[key] = value

    # Make sure all values are Register instances
    for key, value in regmap.iteritems():
        if not isinstance(value, Register):
            regmap[key] = Register(**value)

    return regmap, error_cnt, c_reg_base
Пример #4
0
def get_write_address(name):
    if type(name) is int:
        return name
    else:
        offset = 0
        if name.endswith(']'):
            x = re.search('^(\w+)\s*\[(\d+)\]', name)
            if x:
                name, offset = x.group(1), int(x.group(2))
        r = get_reg_info(reg_map, [0], name)
        return r['base_addr'] + offset
Пример #5
0
    def registers(self, regmap_json, cavity):

        # Read register map from JSON file
        from read_regmap import get_map, get_reg_info
        regmap = get_map(regmap_json)

        # Extract the registers of interest
        setmp = get_reg_info(regmap, [self.cavity], 'setmp')  # Set-points
        coeff = get_reg_info(regmap, [self.cavity],
                             'coeff')  # Feedback loop gains
        lim = get_reg_info(regmap, [self.cavity],
                           'lim')  # Controller upper and lower limits

        setmp_val, coeff_val, lim_val = self.integers()

        return {
            setmp['name']: setmp_val,
            coeff['name']: coeff_val,
            lim['name']: lim_val
        }
Пример #6
0
 def reg_read(self, name_list, hierarchy=[]):
     alist = []
     for name in name_list:
         x = get_reg_info(self.regmap, hierarchy, name)
         if x is not None:
             addr = x['base_addr']
         elif name in self.read_regmap:
             addr = self.read_regmap[name]
         elif name in list(self.read_regmap.values()):
             addr = name
         else:
             print(('unknown register:' + name + 'skipped'))
             addr = None
         if addr:
             alist.append(addr)
     return self.reg_read_alist(alist)
Пример #7
0
def gen_controller(controller_index, dds_phstep, dds_modulo):
    #set_ctl(addr, "ph_offset", -35800)
    # A change to offset the DDS phase, and match the signals between
    # cryomodule_tb and larger_tb
    wave_samp_per=1
    wave_shift=3
    # The LO amplitude in the FPGA is scaled by (32/33)^2, so that yscale
    # fits nicely within the 32768 limit for small values of wave_samp_per
    lo_cheat=(32/33.0)**2;
    yscale=lo_cheat*(33*wave_samp_per)**2*4**(8-wave_shift)/32
    RRRRR('wave_samp_per', ctl_regmap, wave_samp_per, addr_offset=controller_base)
    RRRRR('wave_shift', ctl_regmap, wave_shift, addr_offset=controller_base)
    RRRRR('sel_thresh', ctl_regmap, 5000, addr_offset=controller_base)
    RRRRR('ph_offset', ctl_regmap, -150800, addr_offset=controller_base)
    RRRRR('sel_en', ctl_regmap, 1, addr_offset=controller_base)
    RRRRR('lp1a_kx', ctl_regmap, 20486, addr_offset=controller_base)
    RRRRR('lp1a_ky', ctl_regmap, -20486, addr_offset=controller_base)
    RRRRR('chan_keep', ctl_regmap, 4080, addr_offset=controller_base)
    addr = get_reg_info(ctl_regmap,[],'lim')['base_addr']
    delay_pc=4096
    def delay_set_new(ticks,addr,data):
	delay_pc += 4
	print "%d %d # duration"  %(delay_pc-4, ticks)
	print "%d %d # dest addr (%s)" %(delay_pc-3, addr, addr)
	print "%d %d # value_msb" %(delay_pc-2, int(data)/65536)
	print "%d %d # value_lsb" %(delay_pc-1, int(data)%65536)

    if 0:  # FGEN
	print "3 300    # duration"
	print "4 5000   # amp_slope"
	print "7 22640  # amp_max"
	print "555 7600 # wait"
	print "10 36    # amp dest address (lim X hi)"
	print "12 38    # amp dest address (lim X lo)"
    else:  # TGEN
	# delay_set(0,    'lim_X_hi', 22640)
	# delay_set(6000, 'lim_X_lo', 22640)
	# delay_set(0,    'lim_X_hi', 0)
	# delay_set(0,    'lim_X_lo', 0)
	delay_set_new(0, addr, 22640)
	delay_set_new(6000, addr+2, 22640)
	delay_set_new(0, addr, 0)
	delay_set_new(0, addr+2, 0)

    if (error_cnt > 0):
	print "# %d scaling errors found"%error_cnt
	exit(1)
Пример #8
0
def get_ctl_reg(name):
    r = get_reg_info(regmap_cryomodule, [0], name)
    return r
Пример #9
0
def gen_reg_list(mode1_foffset=5.0,
                 mode1_Q1=8.1e4,
                 mmode1_freq=30e3,
                 mmode1_Q=5.0,
                 net1_coupling=100,
                 net2_coupling=200,
                 net3_coupling=150,
                 sel_en=1,
                 set_X=0.0,
                 set_P=0.0,
                 k_PA=0,
                 k_PP=0,
                 maxq=0,
                 ph_offset=-35500,
                 amp_max=22640,
                 fwd_phase_shift=0,
                 rfl_phase_shift=0,
                 cav_phase_shift=0,
                 duration=300,
                 PRNG_en=1,
                 piezo_dc=0):
    regs = []
    error_cnt = 0

    #print 'mode1_foffset=%f,mode1_Q1=%f,mmode1_freq=%f,mmode1_Q=%f,net_coupling=%f'%(mode1_foffset,mode1_Q1,mmode1_freq,mmode1_Q,net_coupling)

    # Gang humbly requests that Q_1 be renamed Q_drive, and Q_2 as Q_probe.
    # Should apply here, physics.tex, elsewhere?

    # Note that Tstep is the ADC time step, also clocks the LLRF controller.
    # Divide by two for the cavity simulator (rtsim) clock time step.
    Tstep = 10e-9  # s
    f0 = 1300e6  # Hz
    nyquist_sign = -1  # -1 represents frequency inversion,
    # as with high-side LO or even-numbered Nyquist zones.

    VPmax = 48.0  # V piezo drive max

    # as we scale up, the following 10 parameters replicate per cavity:
    PAmax = 6e3  # W RF amplifier max
    PAbw = 1.5e6  # Hz bandwidth of power amplifier
    cav_adc_max = 1.2  # sqrt(W)
    rfl_adc_max = 180.0  # sqrt(W)
    fwd_adc_max = 160.0  # sqrt(W)
    phase_1 = fwd_phase_shift  # forward monitor phase shift
    phase_2 = rfl_phase_shift  # reflected monitor prompt phase shift
    cav_adc_off = 10
    rfl_adc_off = 20
    fwd_adc_off = 30

    mode1 = Emode(name="pi",
                  RoverQ=1036.0,
                  foffset=mode1_foffset,
                  peakV=1.5e6,
                  Q_0=1e10,
                  Q_1=mode1_Q1,
                  Q_2=2e9,
                  phase_1=rfl_phase_shift,
                  phase_2=cav_phase_shift,
                  mech_couplings=[net1_coupling, net2_coupling, net3_coupling])
    mode2 = Emode(name="8pi/9",
                  RoverQ=10.0,
                  foffset=-8e5,
                  peakV=0.15e6,
                  Q_0=1e10,
                  Q_1=8.1e4,
                  Q_2=2e9,
                  phase_1=10,
                  phase_2=-180,
                  mech_couplings=[0, 0, 0])

    mmode1 = Mmode('silly', mmode1_freq, mmode1_Q, 1.13, 40000, 1, 80000)
    mmode2 = Mmode('lowQ', 100000, 5.0, 1.5, 80000, 1, 20000)
    mmode3 = Mmode('other', 24500, 25.0, 1.5, 20000, 1, 10000)

    # DDS setup for simulator should be static
    # this construction is for 20 MHz / 94.286 MHz = 7/33
    dds_num = 7
    dds_den = 33

    # The following three parameters are set in the Verilog at compile-time,
    # not run-time.  Top-level setting in larger.v needs to be mirrored here.
    lp_shift = 9  # see lp_pair.v, a.k.a. mode_shift
    n_mech_modes = 7  # number of mechanical modes handled
    df_scale = 9  # see cav4_freq.v

    # ==== end of system configuration

    # ==== the following dictionaries should get pulled in from Verilog somehow
    sim_base = 0
    regmap_global = {
        'dds_phstep':
        get_reg_info(regmap_cryomodule, [cav_num],
                     "cav4_elec_phase_step")["base_addr"],
        'dds_modulo':
        get_reg_info(regmap_cryomodule, [cav_num],
                     "cav4_elec_modulo")["base_addr"],
        'amp_bw':
        get_reg_info(regmap_cryomodule, [cav_num], "amp_lp_bw")["base_addr"],
        'prompt':
        get_reg_info(regmap_cryomodule, [cav_num], "drive_couple_out_coupling")
        ["base_addr"],  # base address of 4 registers
        'cav_adc_off':
        get_reg_info(regmap_cryomodule, [cav_num],
                     "a_cav_offset")["base_addr"],
        'rfl_adc_off':
        get_reg_info(regmap_cryomodule, [cav_num],
                     "a_rfl_offset")["base_addr"],
        'fwd_adc_off':
        get_reg_info(regmap_cryomodule, [cav_num],
                     "a_for_offset")["base_addr"],
        'res_prop':
        get_reg_info(regmap_cryomodule, [cav_num],
                     "resonator_prop_const")["base_addr"],
        'dot_0_k':
        get_reg_info(regmap_cryomodule, [cav_num],
                     ["dot_0_k_out"])["base_addr"],
        'outer_0_k':
        get_reg_info(regmap_cryomodule, [cav_num],
                     ["outer_prod_0_k_out"])["base_addr"],
        'dot_1_k':
        get_reg_info(regmap_cryomodule, [cav_num],
                     ["dot_1_k_out"])["base_addr"],
        'outer_1_k':
        get_reg_info(regmap_cryomodule, [cav_num],
                     ["outer_prod_1_k_out"])["base_addr"],
        'dot_2_k':
        get_reg_info(regmap_cryomodule, [cav_num],
                     ["dot_2_k_out"])["base_addr"],
        'outer_2_k':
        get_reg_info(regmap_cryomodule, [cav_num],
                     ["outer_prod_2_k_out"])["base_addr"],
        'piezo_couple':
        get_reg_info(regmap_cryomodule, [cav_num],
                     "piezo_couple")["base_addr"],
        'noise_couple':
        get_reg_info(regmap_cryomodule, [cav_num], "noise_couple")["base_addr"]
    }  # base address of 1024 registers
    # base address for cavity n (zero-based) is 16+8*n
    regmap_emode = {
        'coarse_freq': 1,
        'drive_coupling': 2,
        'bw': 3,
        'out_couple': 4
    }  # base address of 4 registers

    # ==== end of hardware register dictionaries

    # send a register value "out"
    # looks address up in regmap[name]
    # finds value via name in python global namespace
    # value can be a scalar or a list
    # prefix and name are used to give a helpful comment
    # ==== now start the application-specific computations

    # Still may have bugs:
    #   Mechanical mode coupling
    # Needs a lot of work:
    #   LLRF controller

    omega0 = f0 * 2 * pi
    mech_tstep = Tstep * n_mech_modes
    interp_gain = n_mech_modes / 2**ceil(
        log(n_mech_modes) / log(2))  # interp0.v

    #print "# Globals"
    amp_bw = fix(Tstep * PAbw * 32, 18, "amp_bw")

    dds_phstep_h = int(dds_num * 2**20 / dds_den)
    dds_mult = int(4096 / dds_den)
    dds_phstep_l = (dds_num * 2**20) % dds_den * dds_mult
    dds_modulo = 4096 - dds_mult * dds_den
    dds_phstep = dds_phstep_h << 12 | dds_phstep_l
    #print "# dds",dds_mult,dds_phstep_h, dds_phstep_l, dds_modulo

    # four registers of pair_couple.v
    # neglect losses between directional coupler and cavity
    prompt = [
        fix(-sqrt(PAmax) / fwd_adc_max, 18, "out1", "cordic"),
        fix(-sqrt(PAmax) / rfl_adc_max, 18, "out2", "cordic"),
        fix(phase_1 / 180.0, 19, "out3"),
        fix(phase_2 / 180.0, 19, "out4")
    ]

    # Mechanical modes
    res_prop = []
    piezo_couple = []
    noise_couple = []
    dot_0_k = []
    outer_0_k = []
    dot_1_k = []
    outer_1_k = []
    dot_2_k = []
    outer_2_k = []
    mech_mode_list = [mmode1, mmode2, mmode3]
    for i, m in enumerate(mech_mode_list):
        #print "# Cavity mechanical mode %d: %s"%(i,m.name)
        w1 = mech_tstep * 2 * pi * m.freq
        # a1 + b1 * i represents the pole in the normalized s-plane
        a1 = w1 * (-1 / (2.0 * m.Q))
        b1 = w1 * sqrt(1 - 1 / (4.0 * m.Q**2))
        z_pole = cexp(a1 + b1 * 1j)
        #print "# z_pole = %7f + %7fi"%(z_pole.real,z_pole.imag)
        a1 = z_pole.real - 1.0
        b1 = z_pole.imag
        scale = int(-log(max(a1, b1)) / log(4))
        scale = max(min(scale, 9), 2)
        a2 = a1 * 4**scale
        b2 = b1 * 4**scale
        #print "# debug",w1,a1,b1,scale,a2,b2
        #c1 = -w1**2 / (k*b1)
        res_prop.append((fix(a2, 18, "a2") & (2**18 - 1)) +
                        ((9 - scale) << 18))
        res_prop.append((fix(b2, 18, "b2") & (2**18 - 1)) +
                        ((9 - scale) << 18))
        # the above is tested.  Onwards to the work-in-progress
        dc_gain = b2 / (a2**2 + b2**2)  # resonator.v
        m.dc_gain = dc_gain  # per-electical mode coupling computation will need this
        piezo_couple.append(m.piezo_hack)
        piezo_couple.append(0)
        noise_couple.append(m.vibration_hack)
        noise_couple.append(0)
        #dot_2_k.append(0)
        #dot_2_k.append(m.piezo_hack)

    for i, m in enumerate([mode1, mode2]):
        #print "# Cavity electrical mode %d: %s"%(i,m.name)
        Q_L = 1 / (1 / m.Q_0 + 1 / m.Q_1 + 1 / m.Q_2)
        # x is defined as sqrt(U)
        xmax = m.peakV / sqrt(m.RoverQ * omega0)
        # four registers of pair_couple.v
        out_coupling = [
            fix(
                sqrt(omega0 / m.Q_1) * xmax / rfl_adc_max, 18,
                m.name + ".out1", "cordic"),
            fix(
                sqrt(omega0 / m.Q_2) * xmax / cav_adc_max, 18,
                m.name + ".out2", "cordic"),
            fix(m.phase_1 / 180.0, 19, m.name + "out3"),
            fix(m.phase_2 / 180.0, 19, m.name + "out4")
        ]
        print out_coupling
        # see Pro tip in eav4_elec.v for better limit on foffset
        # XXX document using 33 for what's really a 28-bit register
        coarse_freq = fix(Tstep * nyquist_sign * m.foffset, 33,
                          m.name + "coarse_freq")
        V_achievable = 2 * sqrt(PAmax * m.Q_1 * m.RoverQ)
        drive_coupling = fix(V_achievable / m.peakV, 18,
                             m.name + "drive_coupling", "cordic")
        # bandwidth in Hz = f_clk/2/2^shift/(2*pi) * bw_register/2^17 = omega_0/(2*pi*2*Q_L)
        # XXX document origin of *2.0 better, compensates for shift right in lp_pair.v
        bw = fix(Tstep * omega0 / (2 * Q_L) * (2**lp_shift) * 2.0, 18,
                 m.name + ".bw")
        regmap_emode = {
            'coarse_freq':
            get_reg_info(regmap_cryomodule, [cav_num, i],
                         "coarse_freq")["base_addr"],
            'drive_coupling':
            get_reg_info(regmap_cryomodule, [cav_num, i],
                         "drive_coupling")["base_addr"],
            'bw':
            get_reg_info(regmap_cryomodule, [cav_num, i], "bw")["base_addr"],
            'out_coupling':
            get_reg_info(regmap_cryomodule, [cav_num, i],
                         "out_coupling")["base_addr"]
        }  # base address of 4 registers
        for n in regmap_emode:
            r = get_reg_info(regmap_cryomodule, [cav_num, i], n)
            regs.extend(
                set_reg(0, m.name + ".", n, regmap_emode, locals(), sim_base,
                        r['name']))
        for j, mech_couple in enumerate(m.mech_couplings):
            #print "# elec mode %d coupling index %d value %f"%(i,j,mech_couple)
            # Number of electrical modes implemented in the hardware is set by the
            # parameter mode_count in cav4_elec.v, frozen at the time of synthesis.
            # The address decode generator (newad.py) will embed mode index into a
            # text name, which is then given an address by addr_map.vh.  This explains
            # the funny-looking exec at the end of this stanze.
            mech_mode = mech_mode_list[j]
            Amn = sqrt(mech_couple / m.RoverQ) / omega0  # sqrt(J)/V^2
            Cmn = -sqrt(mech_couple * m.RoverQ) * omega0  # 1/s/sqrt(J)
            lorentz_en = 1
            outer = lorentz_en * Amn / mech_mode.mx * m.peakV**2 / mech_mode.dc_gain  # dimensionless
            inner = lorentz_en * Cmn * mech_mode.mx * Tstep / 2**df_scale / interp_gain  # dimensionless
            # note that inner*outer = net_coupling * mode1.peakV**2 * Tstep
            #print "# outer =",outer,"inner =",inner
            # additional scaling below comes from the 32-bit mech_phase_fine
            # accumulator, but only 18-bit d_result
            exec '''outer_%d_k.append(fix(outer/128,18,"outer")); outer_%d_k.append(0); dot_%d_k.append(0); dot_%d_k.append(fix(inner/128,18,"inner"))''' % (
                i, i, i, i)

    # Must be after electrical mode processing, to pick up outer_0_k etc.
    for n in regmap_global.keys():
        r_hg_0 = set_reg(0, "", n, regmap_global, locals(), sim_base, n)
        regs.extend(r_hg_0)

    # Pseudo-random generator initialization, see tt800v.v and prng.v
    prng_seed = "pushmi-pullyu"
    if prng_seed:
        #print "# PRNG subsystem seed is '%s'"%prng_seed
        hf = sha1()
        hf.update(prng_seed)
        r = get_reg_info(regmap_cryomodule, [cav_num], "prng_iva")
        r53 = push_seed(r["base_addr"], hf, r['name'])
        r = get_reg_info(regmap_cryomodule, [cav_num], "prng_ivb")
        r54 = push_seed(r["base_addr"], hf, r['name'])
        #print "%d 1  # turn on PRNG"%(52 + sim_base)
    regs.extend(r53)
    regs.extend(r54)
    regs.append(
        c_regs(
            'turn on PRNG',
            get_reg_info(regmap_cryomodule, [cav_num],
                         "prng_random_run")["base_addr"], PRNG_en))

    # Just hack in a few quick values for the controller
    # This should really be another construction as above, maybe in a separate Python module?
    # static DDS config, 7/33 as above
    # #print "17 %d  # phase_step"%dds_phstep
    # #print "18 %d  # modulo"%dds_modulo
    #print "phase_step %d  # phase_step"%dds_phstep
    #print "modulo %d  # modulo"%dds_modulo
    wave_samp_per = 1
    wave_shift = 3
    # The LO amplitude in the FPGA is scaled by (32/33)^2, so that yscale
    # fits nicely within the 32768 limit for small values of wave_samp_per
    lo_cheat = (32 / 33.0)**2
    yscale = lo_cheat * (33 * wave_samp_per)**2 * 4**(8 - wave_shift) / 32

    #regs.append(set_ctl('phase_step',dds_phstep))
    #regs.append(set_ctl('modulo',4))
    #regs.append(set_ctl('wave_samp_per',wave_samp_per))
    r = get_ctl_reg('phase_step')
    regs.append(c_regs('phase_step', r['base_addr'], dds_phstep, r['name']))
    r = get_ctl_reg('modulo')
    regs.append(c_regs('modulo', r['base_addr'], 4, r['name']))
    r = get_ctl_reg('wave_samp_per')
    regs.append(
        c_regs('wave_samp_per', r['base_addr'], wave_samp_per, r['name']))
    r = get_ctl_reg('wave_shift')
    regs.append(c_regs('wave_shift', r['base_addr'], wave_shift, r['name']))
    r = get_ctl_reg('piezo_dc')
    regs.append(c_regs('piezo_dc', r['base_addr'], piezo_dc, r['name']))
    r = get_ctl_reg('sel_thresh')
    regs.append(c_regs('sel_thresh', r['base_addr'], 5000, r['name']))
    r = get_ctl_reg('ph_offset')
    regs.append(c_regs('ph_offset', r['base_addr'], ph_offset, r['name']))
    r = get_ctl_reg('sel_en')
    regs.append(c_regs('sel_en', r['base_addr'], sel_en, r['name']))
    r = get_ctl_reg('lp1a_kx')
    regs.append(c_regs('lp1a_kx', r['base_addr'], 20486, r['name']))
    r = get_ctl_reg('lp1a_ky')
    regs.append(c_regs('lp1a_ky', r['base_addr'], -20486, r['name']))

    #regs.append(c_regs('wait',555,150-12))
    #regs.append(set_ctl('chan_keep',4080))
    r = get_ctl_reg('chan_keep')
    regs.append(c_regs('chan_keep', r['base_addr'], 4080, r['name']))

    #regs.append(set_ctl('lim',22640))
    #regs.append(set_ctl('lim',22640))
    #regs.append(set_ctl('set_X',int(set_X)))
    #regs.append(set_ctl('set_Y',int(set_P)))
    r = get_ctl_reg('setmp')
    regs.append(c_regs('set_X', r['base_addr'], int(set_X), r['name']))
    regs.append(c_regs('set_P', r['base_addr'] + 1, int(set_P), r['name']))

    # regs.append(set_ctl('coeff_X_I',-100))
    # regs.append(set_ctl('coeff_X_P',k_PA))
    # regs.append(set_ctl('coeff_Y_I',-100))
    # regs.append(set_ctl('coeff_Y_P',k_PP))
    r = get_ctl_reg('coeff')
    addr = r['base_addr']
    regs.append(c_regs('coeff_X_I', addr + 0, -100, r['name']))
    regs.append(c_regs('coeff_X_P', addr + 2, k_PA, r['name']))
    regs.append(c_regs('coeff_Y_I', addr + 1, -100, r['name']))
    regs.append(c_regs('coeff_Y_P', addr + 3, k_PP, r['name']))

    # regs.append(set_ctl('lim_X_hi',0))
    # regs.append(set_ctl('lim_Y_hi',0))
    # regs.append(set_ctl('lim_X_lo',0))
    # regs.append(set_ctl('lim_Y_lo',0))
    r = get_ctl_reg('lim')
    addr = r['base_addr']
    regs.append(c_regs('lim_X_hi', addr + 0, 0, r['name']))
    regs.append(c_regs('lim_Y_hi', addr + 1, 0, r['name']))
    regs.append(c_regs('lim_X_lo', addr + 2, 0, r['name']))
    regs.append(c_regs('lim_Y_lo', addr + 3, 0, r['name']))

    global delay_pc
    if 0:  # FGEN
        regs.append(c_regs('duration', 3, duration))
        regs.append(c_regs('amp_slope', 4, 5000))
        regs.append(c_regs('amp_max', 7, amp_max))
        regs.append(c_regs('amp_dest_addr', 10, 36))
        regs.append(c_regs('amp_dest_addr', 12, 38))
    elif 0:  # TGEN
        delay_pc = 4096
        # start the pulse in open loop (fixed drive amplitude) mode
        regs.extend(delay_set(0, 'lim_Y_hi', 0))
        regs.extend(delay_set(0, 'lim_Y_lo', 0))
        regs.extend(delay_set(0, 'lim_X_hi', 22640))
        regs.extend(delay_set(500 * 8, 'lim_X_lo', 22640))
        # allow the amplitude loop to run
        #regs.extend(delay_set(0, 52, 26000))
        regs.extend(delay_set(duration * 8, 'lim_X_lo', 16000))
        # allow the phase loop to run
        regs.extend(delay_set(0, 'lim_Y_hi', maxq))
        regs.extend(delay_set(5000 * 8, 'lim_Y_lo', -maxq))
        regs.extend(delay_set(0, 'lim_X_hi', 0))
        regs.extend(delay_set(0, 'lim_X_lo', 0))
    else:
        delay_pc = get_reg_info(regmap_cryomodule, [0], 'XXX')['base_addr']
        # regs.extend(delay_set(0, 'lim_X_hi', amp_max))
        # regs.extend(delay_set(duration*8, 'lim_X_lo', amp_max))
        # regs.extend(delay_set(0, 'lim_X_hi', 0))
        # regs.extend(delay_set(0, 'lim_X_lo', 0))
        regs.extend(delay_set(0, addr,
                              amp_max))  # 52 is the address of lim_X_hi
        regs.extend(delay_set(duration * 8, addr + 2,
                              amp_max))  # 54 is the address of lim_X_lo
        regs.extend(delay_set(0, addr, 0))  # 52 is the address of lim_X_hi
        regs.extend(delay_set(0, addr + 2, 0))  # 54 is the address of lim_X_lo
        for jx in range(6):
            regs.extend(delay_set(0, 0, 0))

        regs.append(c_regs('Mode Select', 65536 + 554, 0))
    if error_cnt > 0:
        print "# %d scaling errors found" % error_cnt
        #exit(1)
    global print_once
    if print_once == True:
        for r in regs:
            print r.print_regs()
        print_once = False
    return [regs, error_cnt]
Пример #10
0
def gen_cryomodule(station_count=2):
    emode_count = 2
    mmode_count = 2
    c_reg_base = []

    VPmax = 48.0  # V piezo drive max

    emode1 = Emode("pi", RoverQ = 1036.0, foffset = 5.0, peakV = 1.5e6,
		   Q_0 = 1e10, Q_1 = 8.1e4, Q_2 = 2e9, phase_1 = 0, phase_2 = 0)
    emode2 = Emode("8pi/9", RoverQ = 10.0, foffset = -8e5, peakV = 0.15e6,
		   Q_0 = 1e10, Q_1 = 8.1e4, Q_2 = 2e9, phase_1 = 10.0, phase_2 = -180.0)

    # This mode is silly, but lets the frequency change on the time scale of
    # software simulation = 40 us
    mmode1 = Mmode("silly", freq = 30000, Q = 5.0, mx = 1.13, piezo_hack = 0, lorentz_en = 1)
    mmode2 = Mmode("piezo", freq = 100000, Q = 5.0, mx = 0, piezo_hack = 80000, lorentz_en = 0)

    for si in range(station_count):
	c_reg_base.append(get_reg_info(regmap_cryomodule,[],'llrf_'+str(si)+'_xxxx')['base_addr'])

    # Mechanical modes
    # Still may have bugs:
    #   Mechanical mode coupling
    resonator_prop_const=[]
    piezo_couple=[]
    dot_0_k=[];  outer_prod_0_k=[]
    dot_1_k=[];  outer_prod_1_k=[]
    dot_2_k=[];  outer_prod_2_k=[]
    for i,m in enumerate([mmode1,mmode2]):
	print "# Cavity mechanical mode %d: %s"%(i,m.name)
	w1 = mech_tstep * 2*pi*m.freq
	# a1 + b1 * i represents the pole in the normalized s-plane
	a1 = w1 * (-1/(2.0*m.Q))
	b1 = w1 * sqrt(1-1/(4.0*m.Q**2))
	z_pole = exp(a1+b1*1j)
	print "# z_pole = %7f + %7fi"%(z_pole.real,z_pole.imag)
	a1 = z_pole.real-1.0
	b1 = z_pole.imag
	scale = int(-log(max(a1,b1))/log(4))
	scale = max(min(scale,9),2)
	a2 = a1 * 4**scale
	b2 = b1 * 4**scale
	print "# debug",w1,a1,b1,scale,a2,b2
	#c1 = -w1**2 / (k*b1)
	resonator_prop_const.append( (fix(a2,18,"a2")&(2**18-1)) + ((9-scale) << 18) )
	resonator_prop_const.append( (fix(b2,18,"b2")&(2**18-1)) + ((9-scale) << 18) )
	# the above is tested.  Onwards to the work-in-progress
	dc_gain = b2/(a2**2+b2**2)  # resonator.v
	net_coupling = 130.0 # Hz / V^2, negative is implicit
	Amn =   sqrt(net_coupling/emode1.RoverQ) / omega0  # sqrt(J)/V^2
	Cmn = - sqrt(net_coupling*emode1.RoverQ) * omega0  # 1/s/sqrt(J)
	outer = m.lorentz_en * Amn / mmode1.mx * emode1.peakV**2 / dc_gain # dimensionless
	inner = m.lorentz_en * Cmn * mmode1.mx * Tstep / 2**df_scale / interp_gain # dimensionless
	# note that inner*outer = net_coupling * emode1.peakV**2 * Tstep
	print "# outer =",outer,"inner =",inner
	# additional scaling below comes from the 32-bit mech_phase_fine
	# accumulator, but only 18-bit d_result
	outer_prod_0_k.append(fix(outer/128,18,"outer"))
	outer_prod_0_k.append(0)
	dot_0_k.append(0)
	dot_0_k.append(fix(inner/128,18,"inner"))
	# Use second resonance to test piezo subsystem
	# The scaling is still non-quantitative
	piezo_couple.append(m.piezo_hack)
	piezo_couple.append(0)
	dot_2_k.append(0)
	dot_2_k.append(m.piezo_hack)
    for si in range(station_count):
	gen_station(si, dds_modulo, dds_phstep, [emode1, emode2])
	RRRRR('dot_0_k', regmap_cryomodule, dot_0_k, si)
	RRRRR('dot_1_k', regmap_cryomodule, dot_1_k, si)
	RRRRR('dot_2_k', regmap_cryomodule, dot_2_k, si)
	RRRRR('outer_prod_0_k', regmap_cryomodule, outer_prod_0_k, si)
	RRRRR('outer_prod_1_k', regmap_cryomodule, outer_prod_1_k, si)
	RRRRR('outer_prod_2_k', regmap_cryomodule, outer_prod_2_k, si)
	RRRRR('piezo_couple', regmap_cryomodule, piezo_couple, si)
	#gen_controller(si, dds_modulo, dds_phstep)
    RRRRR('resonator_prop_const', regmap_cryomodule, resonator_prop_const)
    # TODO HACK:
    # Since the sole purpose of this file is to feed cryomodule_tb
    print "555 600    # Add delay of 600 cycles"
    print "14336 1    # Flip the circle buffer"
    print "14337 1    # Flip the circle buffer"
Пример #11
0
def gen_station(station_index, cav4_elec_phase_step, cav4_elec_modulo, emodes):
    # as we scale up, the following 10 parameters replicate per cavity:
    PAmax = 6e3   # W RF amplifier max
    PAbw = 1.5e6  # Hz bandwidth of power amplifier
    cav_adc_max = 1.2 # sqrt(W)
    rfl_adc_max = 180.0 # sqrt(W)
    fwd_adc_max = 160.0 # sqrt(W)
    phase_1 = 0  # forward monitor phase shift
    phase_2 = 0  # reflected monitor prompt phase shift
    a_cav_offset = 10
    a_rfl_offset = 30
    a_for_offset = 20

    amp_lp_bw = fix(Tstep*PAbw*32, 18, "amp_lp_bw")

    cav4_elec_phase_step = cav4_elec_phase_step
    cav4_elec_modulo = cav4_elec_modulo

    drive_couple_out_coupling = [fix(-sqrt(PAmax) / fwd_adc_max, 18, "out1", "cordic"),
				 fix(-sqrt(PAmax) / rfl_adc_max, 18, "out2", "cordic"),
				 fix(phase_1 / 180.0, 19, "out3"),
				 fix(phase_2 / 180.0, 19, "out4")]

    for i, m in enumerate(emodes):
	print "# Cavity electrical mode %d: %s"%(i, m.name)
	Q_L = 1 / (1/m.Q_0 + 1/m.Q_1 + 1/m.Q_2)
	# x is defined as sqrt(U)
	xmax = m.peakV / sqrt(m.RoverQ*omega0)
	# four registers of pair_couple.v
	out_couple_out_coupling = [
	    fix(sqrt(omega0/m.Q_1) * xmax / rfl_adc_max, 18, m.name+".out1", "cordic"),
	    fix(sqrt(omega0/m.Q_2) * xmax / cav_adc_max, 18, m.name+".out2", "cordic"),
	    fix(m.phase_1 / 180.0, 19, m.name+"out3"),
	    fix(m.phase_2 / 180.0, 19, m.name+"out4")]
	# see Pro tip in eav4_elec.v for better limit on foffset
	# XXX document using 33 for what's really a 28-bit register
	coarse_freq = fix(Tstep*nyquist_sign*m.foffset, 33, m.name+"coarse_freq")
	V_achievable = 2*sqrt(PAmax*m.Q_1*m.RoverQ)
	drive_coupling = fix( V_achievable / m.peakV, 18, m.name+"drive_coupling", "cordic")
	# bandwidth in Hz = f_clk/2/2^shift/(2*pi) * bw_register/2^17 = omega_0/(2*pi*2*Q_L)
	# XXX document origin of *2.0 better, compensates for shift right in lp_pair.v
	bw = fix(Tstep*omega0/(2*Q_L)*(2**lp_shift)*2.0, 18, m.name+".bw")
	RRRRR('coarse_freq', regmap_cryomodule, coarse_freq, station_index, i)
	RRRRR('drive_coupling', regmap_cryomodule, drive_coupling, station_index, i)
	RRRRR('bw', regmap_cryomodule, bw, station_index, i)
	RRRRR('out_couple_out_coupling', regmap_cryomodule, out_couple_out_coupling, station_index, i)

    RRRRR('cav4_elec_phase_step', regmap_cryomodule, cav4_elec_phase_step, station_index)
    RRRRR('cav4_elec_modulo', regmap_cryomodule, cav4_elec_modulo, station_index)
    RRRRR('amp_lp_bw', regmap_cryomodule, amp_lp_bw, station_index)
    RRRRR('drive_couple_out_coupling', regmap_cryomodule, drive_couple_out_coupling, station_index)
    RRRRR('a_cav_offset', regmap_cryomodule, a_cav_offset, station_index)
    RRRRR('a_rfl_offset', regmap_cryomodule, a_rfl_offset, station_index)
    RRRRR('a_for_offset', regmap_cryomodule, a_for_offset, station_index)

    if prng_seed is not None:
	print "# PRNG subsystem seed is '%s'"%prng_seed
	hf = sha1()
	hf.update(prng_seed)
	push_seed(get_reg_info(regmap_cryomodule,[station_index],"prng_iva")["base_addr"],hf)
	push_seed(get_reg_info(regmap_cryomodule,[station_index],"prng_ivb")["base_addr"],hf)
	print "%d 1  # turn on PRNG"%(get_reg_info(regmap_cryomodule,[station_index],"prng_random_run")["base_addr"])
Пример #12
0
def printFPGADict():
    """printFPGADict: Replication of the old param.py program for illustration purposes.
    Run this program in order to call JSON parser, user-defined physics settings to FPGA register space conversion,
    and prints used by Verilog test-bench for configuration parsing.
    """

    from readjson.readjson_accelerator import push_seed

    # Get the simulation and accelerator objects from the JSON parser
    file_list = [
        "readjson/configfiles/LCLS-II/default_accelerator.json",
        "readjson/configfiles/LCLS-II/LCLS-II_accelerator.json",
        "readjson/configfiles/LCLS-II/LCLS-II_append.json"
    ]

    simulation = parseSim.ParseSimulation(file_list)

    # ==== the following dictionaries should get pulled in from Verilog somehow
    sim_base = 16384  # base address for vmod1, see larger.v line 33

    # regmap_global and regmap_emode dictionaries will be automatically created from a JSON file
    # regmap_mode: base address for cavity n (zero-based) is 16+8*n
    regmap_file = "readjson/configfiles/LCLS-II/register_map.json"
    regmap_global, regmap_emode = parseRegMap.ParseRegisterMap(regmap_file)

    from read_regmap import get_map, get_reg_info
    regmap = get_map("./_autogen/regmap_cryomodule.json")

    print "# Globals"
    # Convert user input into FPGA registers
    error_cnt = getFPGADict(simulation)

    # Grab the variables of interest from the dictionary
    ## First go down the hierarchy and get handles to dictionaries
    linac_obj = simulation.linac_list[0]
    cryomodule_obj = linac_obj.cryomodule_list[0]
    station_obj = cryomodule_obj.station_list[0]

    linac_reg_dict = linac_obj.reg_dict
    station0_reg_dict = station_obj.reg_dict
    cm_reg_dict = cryomodule_obj.reg_dict
    mechMode0_reg_dict = cryomodule_obj.mechanical_mode_list[0].reg_dict
    mechMode1_reg_dict = cryomodule_obj.mechanical_mode_list[1].reg_dict
    mechMode2_reg_dict = cryomodule_obj.mechanical_mode_list[2].reg_dict
    elecMode0_reg_dict = station_obj.cavity.elec_modes[0].reg_dict
    elecMode1_reg_dict = station_obj.cavity.elec_modes[1].reg_dict
    # Quick hack to add name field
    elecMode0_reg_dict['name'] = station_obj.cavity.elec_modes[0].name
    elecMode1_reg_dict['name'] = station_obj.cavity.elec_modes[1].name

    piezo0_reg_dict = station_obj.piezo_list[0].reg_dict

    reg_dict = {}
    ## Linac variables
    reg_dict['dds_phstep'] = linac_reg_dict['dds_phstep']
    reg_dict['dds_modulo'] = linac_reg_dict['dds_modulo']
    ## Station variables
    reg_dict['amp_bw'] = station0_reg_dict['amp_bw']

    # Manually construct prompt for now
    reg_dict['prompt'] = station0_reg_dict['prompt']

    for e in [elecMode0_reg_dict, elecMode1_reg_dict]:
        reg_dict['prompt'].value.append(e["prompt_rfl"].value)
        reg_dict['prompt'].value.append(e["prompt_fwd"].value)

    reg_dict['cav_adc_off'] = station0_reg_dict['cav_adc_off']
    reg_dict['rev_adc_off'] = station0_reg_dict['rev_adc_off']
    reg_dict['fwd_adc_off'] = station0_reg_dict['fwd_adc_off']

    reg_dict['res_prop'] = cm_reg_dict['res_prop']
    reg_dict['res_prop'].set_value([
        mechMode0_reg_dict['a2'].value, mechMode0_reg_dict['b2'].value,
        mechMode1_reg_dict['a2'].value, mechMode1_reg_dict['b2'].value,
        mechMode2_reg_dict['a2'].value, mechMode2_reg_dict['b2'].value
    ])

    reg_dict['dot_0_k'] = elecMode0_reg_dict['dot_list']
    reg_dict['outer_0_k'] = elecMode0_reg_dict['outer_list']
    reg_dict['dot_1_k'] = elecMode1_reg_dict['dot_list']
    reg_dict['outer_1_k'] = elecMode1_reg_dict['outer_list']
    reg_dict['dot_2_k'] = [
        piezo0_reg_dict['piezo_couple'].value[0],
        piezo0_reg_dict['piezo_couple'].value[1],
        piezo0_reg_dict['piezo_couple'].value[3],
        piezo0_reg_dict['piezo_couple'].value[2]
    ]
    reg_dict['outer_2_k'] = []
    reg_dict['piezo_couple'] = piezo0_reg_dict['piezo_couple']

    # Added to generate the vibration_hack values
    reg_dict['noise_couple'] = cm_reg_dict['noise_couple']
    reg_dict['noise_couple'].set_value([
        mechMode0_reg_dict['vibration_hack'].value[0],
        mechMode0_reg_dict['vibration_hack'].value[1],
        mechMode1_reg_dict['vibration_hack'].value[0],
        mechMode1_reg_dict['vibration_hack'].value[1],
        mechMode2_reg_dict['vibration_hack'].value[0],
        mechMode2_reg_dict['vibration_hack'].value[1]
    ])

    # Pop some elements to match paramhg.py
    del reg_dict['prompt'].value[4:]
    del reg_dict['dot_2_k'][0:]

    for n in regmap_global.keys():
        set_reg(0, "", n, regmap_global, reg_dict, sim_base)

    for i, emode in enumerate([elecMode0_reg_dict, elecMode1_reg_dict]):
        reg_dict['coarse_freq'] = emode['coarse_freq']
        reg_dict['drive_coupling'] = emode['drive_coupling']
        reg_dict['bw'] = emode['bw']
        reg_dict['out_coupling'] = emode['out_coupling']
        reg_dict['out_phase_offset'] = emode['out_phase_offset']
        regmap_emode.pop('out_couple', None)
        regmap_emode['out_coupling'] = None
        regmap_emode['out_phase_offset'] = None
        print "# Cavity electrical mode %d: %s" % (i, emode['name'])
        for n in regmap_emode:
            set_reg(16 + 8 * i, emode['name'] + ".", n, regmap_emode, reg_dict,
                    sim_base)

    # Pseudo-random generator initialization, see tt800v.v and prng.v
    prng_seed = "pushmi-pullyu"
    prng_iva = get_reg_info(regmap, [], "prng_iva")
    prng_ivb = get_reg_info(regmap, [], "prng_ivb")
    prng_random_run = get_reg_info(regmap, [], "prng_random_run")
    if (prng_seed is not None):
        from hashlib import sha1
        print "# PRNG subsystem seed is '%s'" % prng_seed
        hf = sha1()
        hf.update(prng_seed)
        push_seed(prng_iva['base_addr'] + sim_base, hf)
        push_seed(prng_ivb['base_addr'] + sim_base, hf)
        print "%d 1  # turn on PRNG" % (prng_random_run['base_addr'] +
                                        sim_base)

    # Just hack in a few quick values for the controller
    # This should really be another construction as above, maybe in a separate Python module?
    # static DDS config, 7/33 as above
    wave_samp_per = 1
    wave_shift = 3
    # The LO amplitude in the FPGA is scaled by (32/33)^2, so that yscale
    # fits nicely within the 32768 limit for small values of wave_samp_per
    lo_cheat = (32 / 33.0)**2
    yscale = lo_cheat * (33 * wave_samp_per)**2 * 4**(8 - wave_shift) / 32

    reg_list = []

    # Variables defined to print out the registers value
    piezo_dc = 0
    ph_offset = -35800
    sel_en = 0
    set_X = 0.0
    set_P = 0.0
    k_PA = 0
    k_PP = 0

    from read_regmap import get_map, get_reg_info
    ctl_regmap = get_map("./_autogen/regmap_llrf_shell.json")
    # Maybe the following lines should be removed in the future
    #reg_list.append(c_regs('phase_step', 17+18, reg_dict['dds_phstep'].value))
    #reg_list.append(c_regs('modulo', 18+18, reg_dict['dds_modulo'].value))
    addr = get_reg_info(ctl_regmap, [], 'wave_samp_per')['base_addr']
    reg_list.append(c_regs('wave_samp_per', addr, wave_samp_per))
    addr = get_reg_info(ctl_regmap, [], 'wave_shift')['base_addr']
    reg_list.append(c_regs('wave_shift', addr, wave_shift))
    addr = get_reg_info(ctl_regmap, [], 'piezo_dc')['base_addr']
    reg_list.append(c_regs('piezo_dc', addr, piezo_dc))
    addr = get_reg_info(ctl_regmap, [], 'sel_thresh')['base_addr']
    reg_list.append(c_regs('sel_thresh', addr, 5000))
    addr = get_reg_info(ctl_regmap, [], 'ph_offset')['base_addr']
    reg_list.append(c_regs('ph_offset', addr, ph_offset))
    addr = get_reg_info(ctl_regmap, [], 'sel_en')['base_addr']
    reg_list.append(c_regs('sel_en', addr, sel_en))
    addr = get_reg_info(ctl_regmap, [], 'lp1a_kx')['base_addr']
    reg_list.append(c_regs('lp1a', addr, 20486))
    addr = get_reg_info(ctl_regmap, [], 'lp1a_ky')['base_addr']
    reg_list.append(c_regs('lp1a', addr, -20486))
    reg_list.append(c_regs('wait', 555, 150 - 12))
    addr = get_reg_info(ctl_regmap, [], 'chan_keep')['base_addr']
    reg_list.append(c_regs('ch_keep', addr, 4080))
    addr = get_reg_info(ctl_regmap, [], 'setmp')['base_addr']
    reg_list.append(c_regs('set_X', addr, int(set_X)))
    reg_list.append(c_regs('set_P', addr + 1, int(set_P)))
    addr = get_reg_info(ctl_regmap, [], 'coeff')['base_addr']
    reg_list.append(c_regs('coeff_X_I', addr + 0, -100))
    reg_list.append(c_regs('coeff_X_P', addr + 2, k_PA))
    reg_list.append(c_regs('coeff_Y_I', addr + 1, -100))
    reg_list.append(c_regs('coeff_Y_P', addr + 3, k_PP))
    addr = get_reg_info(ctl_regmap, [], 'lim')['base_addr']
    reg_list.append(c_regs('lim_X_hi', addr + 0, 0))
    reg_list.append(c_regs('lim_Y_hi', addr + 1, 0))
    reg_list.append(c_regs('lim_X_lo', addr + 2, 0))
    reg_list.append(c_regs('lim_Y_lo', addr + 3, 0))

    # Variables needed
    amp_max = 22640

    reg_list.extend(delay_set(0, addr,
                              amp_max))  # 52 is the address of lim_X_hi
    reg_list.extend(delay_set(duration * 8, addr + 2,
                              amp_max))  # 54 is the address of lim_X_lo
    reg_list.extend(delay_set(0, addr, 0))  # 52 is the address of lim_X_hi
    reg_list.extend(delay_set(0, addr + 2, 0))  # 54 is the address of lim_X_lo

    for jx in range(6):
        reg_list.extend(delay_set(0, 0, 0))

    for reg in reg_list:
        print str(reg.addr) + " " + str(reg.value)

    if (error_cnt > 0):
        print "# %d scaling errors found" % error_cnt
        exit(1)
Пример #13
0
def run_test_bench(setmp_val,
                   coeff_val,
                   lim_val,
                   test_type,
                   in_file,
                   out_file,
                   setmp_step_time=0,
                   setmp_step_val=0,
                   lim_step_time=0,
                   lim_step_val=0,
                   in_i=0,
                   in_q=0):
    """
    Generates an input file for fdbk_core_tb with the appropriate register settings,
    and runs test-bench using Icarus Verilog.
    """

    # Get register map from JSON
    from read_regmap import get_map, get_reg_info
    regmap_fdbk_core = get_map("./_autogen/regmap_fdbk_core_tb.json")

    # Extract the registers of interest
    setmp = get_reg_info(regmap_fdbk_core, [], 'setmp')  # Set-points
    coeff = get_reg_info(regmap_fdbk_core, [], 'coeff')  # Feedback loop gains
    lim = get_reg_info(regmap_fdbk_core, [],
                       'lim')  # Controller upper and lower limits

    setmp['value'] = setmp_val  # set X, set Y
    coeff['value'] = coeff_val  # coeff X I, coeff Y I, coeff X P, coeff Y P
    lim['value'] = lim_val  # lim X hi, lim Y hi, lim X lo, lim Y lo

    # Write the configuration file (register writes) for the test-bench
    write_reg_file([setmp, coeff, lim], regmap_fdbk_core, in_file)

    # Start with empty command to handle exception
    command = ''

    if ((test_type == 2) or (test_type == 3) or (test_type == 4)):
        # Write configuration file for set-point step
        setmp_file = 'setmp_step_file_in.dat'
        # index selects either amplitude or phase step on the set-point
        if (test_type == 2 or test_type == 4):  # Amplitude modulation
            index = 0
        elif (test_type == 3):  # Phase modulation
            index = 1

        # Apply step to set-point to amplitude or phase depending on the test
        setmp['value'][
            index] = setmp['value'][index] + setmp_step_val  # set X, set Y
        write_reg_file([setmp], regmap_fdbk_core, setmp_file)

        # Write configuration file for limits step
        lim_file = 'lim_step_file_in.dat'
        lim['value'] = lim_step_val
        write_reg_file([lim], regmap_fdbk_core, lim_file)

        # Command line to run Verilog simulation
        # Arguments depend on the type of test-bench being run (test_type)
        command = 'vvp -n fdbk_core_tb +vcd +test=' + \
            str(test_type) + ' +in_file=' + in_file + ' +out_file=' + out_file + \
            ' +sp_step_time=' + str(setmp_step_time) + ' +sp_step_file=' + setmp_file +\
            ' +lim_step_time=' + str(lim_step_time) + ' +lim_step_file=' + lim_file

        if test_type == 3:
            command = command + ' +in_i=' + str(in_i) + ' +in_q=' + str(in_q)

    elif (test_type == 0 or test_type == 4):
        command = 'vvp -n fdbk_core_tb +vcd +test=' + str(
            test_type) + ' +in_file=' + in_file + ' +out_file=' + out_file
    elif (test_type == 1):
        command = 'vvp -n fdbk_core_tb +vcd +test=' + str(
            test_type
        ) + ' +in_file=' + in_file + ' +out_file=' + out_file + ' +in_i=' + str(
            in_i) + ' +in_q=' + str(in_q)

    # Run the Verilog test-bench
    print 'Running Verilog test-bench from Python...\n\n' + command + '\n'

    if command == '':
        print 'test_type not defined with a valid code'
        print 'test_type value supplied is ' + str(test_type)
    else:
        return_code = call(command, shell=True)
Пример #14
0
def get_cryo_reg(h, name):
    r = get_reg_info(regmap_cryomodule, h, name)
    return r
Пример #15
0
def gen_reg_list(verbose=False):
    """
    gen_reg_list: Replication of the old param.py program for illustration
    purposes.  Run this program in order to call JSON parser, user-defined
    physics settings to FPGA register space conversion, and prints used by
    Verilog test-bench for configuration parsing.
    """
    # Get the simulation and accelerator objects from the JSON parser
    file_list = [
        base_dir + "/configfiles/LCLS-II/default_accelerator.json",
        base_dir + "/configfiles/LCLS-II/LCLS-II_accelerator.json",
        base_dir + "/configfiles/LCLS-II/LCLS-II_append.json"
    ]

    simulation = parseSim.ParseSimulation(file_list, verbose)

    sim_base = 0  # base address for vmod1, see larger.v line 33

    # Convert user input into FPGA registers
    regmap, error_cnt, c_reg_base = getFPGADict(simulation)

    # Pseudo-random generator initialization, see tt800v.v and prng.v
    prng_seed = "pushmi-pullyu"

    prng_iva = regmap["cavity_0_prng_iva"]
    prng_ivb = regmap["cavity_0_prng_ivb"]
    prng_random_run = regmap["cavity_0_prng_random_run"]

    if (prng_seed is not None):
        from readjson_accelerator import push_seed
        from hashlib import sha1
        # print "# PRNG subsystem seed is '%s'"%prng_seed
        hf = sha1()
        hf.update(prng_seed)
        push_seed(prng_iva.address + sim_base, hf)
        push_seed(prng_ivb.address + sim_base, hf)
        # print "%d 1  # turn on PRNG"%(prng_random_run.address+sim_base)

    # Just hack in a few quick values for the controller
    # This should really be another construction as above, maybe in a separate Python module?
    # static DDS config, 7/33 as above
    wave_samp_per = 1
    wave_shift = 3

    reg_list = []

    # Variables defined by hand, should really come from JSON controller configuration
    piezo_dc = 0
    ph_offset = -150800
    sel_en = 1
    sel_thresh = 5000
    lp1a_kx = 20486
    lp1a_ky = -20486
    chan_keep = 4080

    ctl_regmap = get_map(base_dir + "/../_autogen/regmap_llrf_shell.json")

    reg = Register(**get_reg_info(ctl_regmap, [], 'wave_samp_per'))
    reg.value = wave_samp_per
    reg_list.append(reg)

    reg = Register(**get_reg_info(ctl_regmap, [], 'wave_shift'))
    reg.value = wave_shift
    reg_list.append(reg)

    reg = Register(**get_reg_info(ctl_regmap, [], 'piezo_dc'))
    reg.value = piezo_dc
    reg_list.append(reg)

    reg = Register(**get_reg_info(ctl_regmap, [], 'sel_thresh'))
    reg.value = sel_thresh
    reg_list.append(reg)

    reg = Register(**get_reg_info(ctl_regmap, [], 'ph_offset'))
    reg.value = ph_offset
    reg_list.append(reg)

    reg = Register(**get_reg_info(ctl_regmap, [], 'sel_en'))
    reg.value = sel_en
    reg_list.append(reg)

    reg = Register(**get_reg_info(ctl_regmap, [], 'lp1a_kx'))
    reg.value = lp1a_kx
    reg_list.append(reg)

    reg = Register(**get_reg_info(ctl_regmap, [], 'lp1a_ky'))
    reg.value = lp1a_ky
    reg_list.append(reg)

    reg = Register(**get_reg_info(ctl_regmap, [], 'chan_keep'))
    reg.value = chan_keep
    reg_list.append(reg)

    # reg = Register(**get_reg_info(ctl_regmap,[],'setmp'))
    # reg.name = 'set_X'
    # reg.address = reg.address + 0
    # reg.value = int(set_X)
    # reg_list.append(reg)

    # reg = Register(**get_reg_info(ctl_regmap,[],'setmp'))
    # reg.name = 'set_P'
    # reg.address = reg.address + 1
    # reg.value = int(set_P)
    # reg_list.append(reg)

    # reg = Register(**get_reg_info(ctl_regmap,[],'coeff'))
    # reg.name = 'coeff_X_I'
    # reg.address = reg.address + 0
    # reg.value = coeff_X_I
    # reg_list.append(reg)

    # reg = Register(**get_reg_info(ctl_regmap,[],'coeff'))
    # reg.name = 'coeff_X_P'
    # reg.address = reg.address + 1
    # reg.value = coeff_X_P
    # reg_list.append(reg)

    # reg = Register(**get_reg_info(ctl_regmap,[],'coeff'))
    # reg.name = 'coeff_Y_I'
    # reg.address = reg.address + 2
    # reg.value = coeff_Y_I
    # reg_list.append(reg)

    # reg = Register(**get_reg_info(ctl_regmap,[],'coeff'))
    # reg.name = 'coeff_Y_P'
    # reg.address = reg.address + 3
    # reg.value = coeff_Y_P
    # reg_list.append(reg)

    # reg = Register(**get_reg_info(ctl_regmap,[],'lim'))
    # reg.name = 'lim_X_hi'
    # reg.address = reg.address + 0
    # reg.value = lim_X_hi
    # reg_list.append(reg)

    # reg = Register(**get_reg_info(ctl_regmap,[],'lim'))
    # reg.name = 'lim_Y_hi'
    # reg.address = reg.address + 1
    # reg.value = lim_Y_hi
    # reg_list.append(reg)

    # reg = Register(**get_reg_info(ctl_regmap,[],'lim'))
    # reg.name = 'lim_X_lo'
    # reg.address = reg.address + 2
    # reg.value = lim_X_lo
    # reg_list.append(reg)

    # reg = Register(**get_reg_info(ctl_regmap,[],'lim'))
    # reg.name = 'lim_Y_lo'
    # reg.address = reg.address + 3
    # reg.value = lim_Y_lo
    # reg_list.append(reg)

    addr = get_reg_info(ctl_regmap, [], 'lim')['base_addr']
    # Variables needed

    # reg_list.extend(delay_set(0, addr, amp_max))            # 52 is the address of lim_X_hi
    # reg_list.extend(delay_set(duration*8, addr+2, amp_max))   # 54 is the address of lim_X_lo
    # reg_list.extend(delay_set(0, addr, 0))                  # 52 is the address of lim_X_hi
    # reg_list.extend(delay_set(0, addr+2, 0))                  # 54 is the address of lim_X_lo

    # for jx in range(6):
    #    reg_list.extend(delay_set(0,0,0))

    for item in reg_list:
        if item.name != '':
            regmap[item.name] = item

    if (error_cnt > 0):
        print "# %d scaling errors found" % error_cnt
        exit(1)

    return regmap
Пример #16
0
                return
        else:
            # print "# Key not found: %s"%(name)
            return
    addr = regmap[name]['base_addr']
    if type(val) is list:
        for i, v in enumerate(val):
            print('{} {} # {}'.format(addr + i, v,
                                      prefix + name + "[" + str(i) + "]"))
    else:
        print('{} {} # {}'.format(addr, val, prefix + name))


regmap_global = {
    'beam_phase_step':
    get_reg_info(regmap, [], "beam_phase_step")["base_addr"],
    'beam_modulo':
    get_reg_info(regmap, [], "beam_modulo")["base_addr"],
    'drive_couple_out_coupling':
    get_reg_info(regmap, [], "drive_couple_out_coupling")
    ["base_addr"],  # base address of 4 registers
    'amp_lp_bw':
    get_reg_info(regmap, [], "amp_lp_bw")["base_addr"],
    'a_cav_offset':
    get_reg_info(regmap, [], "a_cav_offset")["base_addr"],
    'a_rfl_offset':
    get_reg_info(regmap, [], "a_rfl_offset")["base_addr"],
    'a_for_offset':
    get_reg_info(regmap, [], "a_for_offset")["base_addr"],
    'resonator_prop_const':
    get_reg_info(regmap, [], "resonator_prop_const")["base_addr"],
Пример #17
0
def get_ctl_reg_and_set(name, value):
    addr = get_reg_info(regmap_cryomodule, [0], name)['base_addr']
    set_ctl(addr, name, value)
Пример #18
0
# this construction is for 20 MHz / 94.286 MHz = 7/33
dds_num = 7
dds_den = 33

# The following three parameters are set in the Verilog at compile-time,
# not run-time.  Top-level setting in larger.v needs to be mirrored here.
lp_shift = 9  # see lp_pair.v, a.k.a. mode_shift
n_mech_modes = 7  # number of mechanical modes handled
df_scale = 9  # see cav4_freq.v

# ==== end of system configuration

# ==== the following dictionaries should get pulled in from Verilog somehow
regmap_global = {
    'dds_phstep':
    get_reg_info(regmap_cryomodule, [cav_num],
                 "cav4_elec_phase_step")["base_addr"],
    'dds_modulo':
    get_reg_info(regmap_cryomodule, [cav_num],
                 "cav4_elec_modulo")["base_addr"],
    'amp_bw':
    get_reg_info(regmap_cryomodule, [cav_num], "amp_lp_bw")["base_addr"],
    'prompt':
    get_reg_info(regmap_cryomodule, [cav_num], "drive_couple_out_coupling")
    ["base_addr"],  # base address of 4 registers
    'cav_adc_off':
    get_reg_info(regmap_cryomodule, [cav_num], "a_cav_offset")["base_addr"],
    'rfl_adc_off':
    get_reg_info(regmap_cryomodule, [cav_num], "a_rfl_offset")["base_addr"],
    'fwd_adc_off':
    get_reg_info(regmap_cryomodule, [cav_num], "a_for_offset")["base_addr"],
    'res_prop':