Chip_Case_Generator/4ch-Z_Generator/FourChZAssemblyTemplateMana...

300 lines
10 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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)