import numpy as np import copy from typing import List from FourChZreg_define import * class AssemblyTemplateManager: """汇编指令模板管理器""" def __init__(self, mk_instance, mk_instr, **kwargs): self.mk = mk_instance self.mk_instr = mk_instr self.config_file = kwargs.get('config_file') self.templates = { 'general_send_wait': self._generic_awg_control_template, 'ramp_fixed': self._ramp_mcu_fixed_template, 'ramp_step': self._ramp_mcu_template } def create_instructions(self, **kwargs): template_type = kwargs.get('instr_type', str) params = copy.deepcopy(kwargs) return self.templates[template_type](**params) def _codeword_encode(self, **kwargs): sendc = kwargs.pop('sendc', 0) wave_hold = kwargs.pop('wave_hold', 0) ff_amp_index = kwargs.pop('ff_amp_index', 0) fm_amp_index = kwargs.pop('fm_amp_index', 0) bias_index = kwargs.pop('bias_index', 0) fcw_index = kwargs.pop('fcw_index', 0) pcw_index = kwargs.pop('pcw_index', 0) code_clr = kwargs.pop('code_clr', 0) env_index = kwargs.pop('env_index', 0) codeword = 0 codeword |= sendc << 31 codeword |= wave_hold << 30 codeword |= ff_amp_index << 28 codeword |= fm_amp_index << 26 codeword |= bias_index << 24 codeword |= fcw_index << 22 codeword |= pcw_index << 19 codeword |= code_clr << 18 codeword |= env_index << 12 return codeword def _codeword_gen(self, **kwargs): codeword_configs = kwargs.pop('codeword_configs', []) codeword_list = [] for config in codeword_configs: codeword = self._codeword_encode(**config) codeword_list.append(codeword) return codeword_list def write_register(self, address, value): self.mk.rw_once('w', address, value, self.config_file) def _generic_awg_control_template(self, **kwargs): """ 通用 AWG汇编控制模版 (支持扫参) """ channel = kwargs.get('channel', 0) codeword_list = self._codeword_gen(**kwargs) send_interval_list = kwargs.get('send_interval', [100]) cycle_num = kwargs.get('cycle_num', 1) sweep_config = kwargs.get('sweep_config', {}) sweep_num = sweep_config.get('sweep_num', 1) sweep_offsets = sweep_config.get('offsets', []) sweep_steps = sweep_config.get('steps', []) sweep_reg_num = len(sweep_offsets) dtcm_payload = [sweep_num, cycle_num, len(codeword_list), sweep_reg_num] for cw, wait_clk in zip(codeword_list, send_interval_list): dtcm_payload.append(cw) dtcm_payload.append(wait_clk) if sweep_reg_num > 0: dtcm_payload.extend(sweep_offsets) dtcm_payload.extend([s & 0xFFFFFFFF for s in sweep_steps]) dtcm_base = addr_base['DTCM0_BASE'] + channel * 0x600000 target_addr = dtcm_base + FourChZreg_define['mcu_reg']['DTFR'] + 4 self.write_register(target_addr, dtcm_payload) return f""" start: lui x1 , 0x100 lui x2 , 0x200 addi x3 , x0 , 4 addi x4 , x0 , 22 addi x5 , x1 , 0x40 addi x6 , x2 , 0x40 load_nco_params_loop: addi x4 , x4 , -1 lw x31, 0x00(x5) sw x31, 0x00(x6) add x5 , x5 , x3 add x6 , x6 , x3 bne x4 , x0 , load_nco_params_loop lw x31, 0xb4(x1) sw x31, 0xb4(x2) lw x10, 0xdc(x1) lw x11, 0xe0(x1) lw x12, 0xe4(x1) lw x17, 0xe8(x1) addi x13, x1 , 0xec slli x14, x12, 3 add x18, x13, x14 slli x14, x17, 2 add x20, x18, x14 run_sweep_iteration: addi x28, x11, 0 middle_ensemble_loop: addi x28, x28, -1 addi x26, x12, 0 addi x25, x13, 0 inner_wave_send_loop: addi x26, x26, -1 lw x31, 0x00(x25) lw x30, 0x04(x25) addi x25, x25, 8 send x0 , x31, 0 bne x26, x0 , inner_wait_branch beq x0 , x0 , outer_wait_branch inner_wait_branch: wait x0 , x30, -24 bne x26, x0 , inner_wave_send_loop outer_wait_branch: wait x0 , x30, -36 bne x28, x0 , middle_ensemble_loop beq x10, x0 , mcu_exit addi x10, x10, -1 wait x0 , x0 , 100 beq x17, x0 , run_sweep_iteration addi x4 , x17, 0 addi x21, x18, 0 addi x23, x20, 0 update_param_loop: addi x4 , x4 , -1 lw x29, 0(x21) lw x24, 0(x23) add x5 , x1 , x29 lw x31, 0(x5) add x31, x31, x24 sw x31, 0(x5) add x6 , x2 , x29 sw x31, 0(x6) addi x21, x21, 4 addi x23, x23, 4 bne x4 , x0 , update_param_loop beq x0 , x0 , run_sweep_iteration mcu_exit: exit x0 , x0 , 0 """ def _ramp_mcu_template(self, **kwargs): channel = kwargs.pop('channel') ramp_mcu_registers = [] ramp_mcu_registers.append(0 << 16) ramp_mcu_registers += [1 << 31] param_num = kwargs.pop('param_num') ensemble_num = kwargs.pop('ensemble_num') ramp_mcu_registers.append(param_num) ramp_mcu_registers.append(ensemble_num) height_list = kwargs.pop('height', 0) length_list = kwargs.pop('step_time', 0) for height, length in zip(height_list, length_list): ramp_mcu_registers += [height << 16] ramp_mcu_registers += [length] wait = 65536 / height * length ramp_mcu_registers += [wait] dtcm_base = addr_base['DTCM0_BASE'] + channel * 0x600000 target_addr = dtcm_base + FourChZreg_define['mcu_reg']['DTFR'] + 4 self.write_register(target_addr, ramp_mcu_registers) return f""" start: lui x1 , 0x100 lui x2 , 0x200 lw x31, 0xdc(x1) sw x31, 0xb8(x2) lw x28, 0xe0(x1) addi x6 , x0, 12 lw x7 , 0xe8(x1) ensemble_loop: addi x7 , x7, -1 addi x8 , x1, 0 lw x5 , 0xe4(x1) ramp_loop: addi x5, x5, -1 lw x31, 0xec(x8) lw x30, 0xf0(x8) lw x29, 0xf4(x8) add x8 , x8 , x6 sw x30, 0xc0(x2) sw x31, 0xbc(x2) sw x28, 0xc4(x2) wait x0 , x29, -30 bne x5 , x0 , ramp_loop bne x7 , x0 , ensemble_loop sw x0, 0xc4(x2) exit x0, x0, 0 """ def _ramp_mcu_fixed_template(self, **kwargs): channel = kwargs.pop('channel') ramp_mcu_registers = [] ramp_mcu_registers += [1 << 31] ensemble_num = kwargs.pop('ensemble_num') config_param_num = kwargs.pop('config_param_num') ramp_mcu_registers.append(ensemble_num) ramp_mcu_registers.append(config_param_num) fixed_value_list = kwargs.pop('fixed_value') wait_list = kwargs.pop('wait_clk') for fixed_value, wait_clk in zip(fixed_value_list, wait_list): ramp_mcu_registers += [fixed_value << 16 | 1 << 15] ramp_mcu_registers += [wait_clk] dtcm_base = addr_base['DTCM0_BASE'] + channel * 0x600000 target_addr = dtcm_base + FourChZreg_define['mcu_reg']['DTFR'] + 4 self.write_register(target_addr, ramp_mcu_registers) return f""" start: lui x1 , 0x100 lui x2 , 0x200 lw x31, 0xdc(x1) sw x31, 0xc4(x2) addi x3 , x0, 8 lw x4 , 0xe0(x1) ensemble_loop: addi x4 , x4, -1 addi x6 , x1, 0 lw x5 , 0xe4(x1) ramp_loop: addi x5, x5, -1 lw x31, 0xe8(x6) lw x30, 0xec(x6) sw x31, 0xb8(x2) add x6 , x6 , x3 bne x5 , x0 , ramp_loop_wait jal x0 , ensemble_loop_wait ramp_loop_wait: wait x0 , x30, -24 jal x0 , ramp_loop ensemble_loop_wait: wait x0 , x30, -36 bne x4 , x0 , ensemble_loop exit: wait x0 , x0, 15 sw x0, 0xb8(x2) sw x0, 0xc4(x2) exit x0, x0, 0 """ def _write_machine_codes_to_chip(self, machine_codes: str, **kwargs): # 修正:同时把通道号传给 make_inst 的 channel_id 字段 channel = kwargs.pop('channel') self.mk_instr.write( machine_codes, self.config_file, channel_id=channel, show=kwargs.pop('instr_show', False) ) if 'inner_sync' in kwargs: inner_sync = kwargs.pop('inner_sync') if inner_sync: self.write_register(addr_base['SYST_BASE'] + FourChZreg_define['sys_reg']['SYNCR'], 15 << 28 | 1 << 17) self.mk.rw_once('r', addr_base['SYST_BASE'] + FourChZreg_define['pll_reg']['INTPLL_CLKRXPD'], [0] * 20, self.config_file) self.mk.rw_once('r', addr_base['DBGM_BASE'], [0] * 2048, self.config_file) def instruction_config(mk_instance, mk_instr, **kwargs): # 直接将 **kwargs 传入,__init__ 会自动匹配字典里的 'channel_id',彻底避免重复传参报错 asm_templates = AssemblyTemplateManager(mk_instance, mk_instr, **kwargs) machine_codes = asm_templates.create_instructions(**kwargs) asm_templates._write_machine_codes_to_chip(machine_codes, **kwargs)