增加四通道生成器

This commit is contained in:
yangshenbo 2026-07-28 17:57:28 +08:00
parent d0352183e8
commit 4922a2f5d3
38 changed files with 4215 additions and 85 deletions

8
4ch-Z_Generator/.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
# 默认忽略的文件
/shelf/
/workspace.xml
# 基于编辑器的 HTTP 客户端请求
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View File

@ -0,0 +1 @@
FourChZCaseGenerator.ipynb

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="jdk" jdkName="Python 3.11" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@ -0,0 +1,17 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="PyPackageRequirementsInspection" enabled="false" level="WARNING" enabled_by_default="false">
<option name="ignoredPackages">
<value>
<list size="4">
<item index="0" class="java.lang.String" itemvalue="pyzmq" />
<item index="1" class="java.lang.String" itemvalue="matplotlib" />
<item index="2" class="java.lang.String" itemvalue="prometheus-client" />
<item index="3" class="java.lang.String" itemvalue="Pillow" />
</list>
</value>
</option>
</inspection_tool>
</profile>
</component>

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Black">
<option name="sdkName" value="Python 3.11" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.11" project-jdk-type="Python SDK" />
</project>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/4ch-Z_Generator.iml" filepath="$PROJECT_DIR$/.idea/4ch-Z_Generator.iml" />
</modules>
</component>
</project>

View File

@ -0,0 +1,300 @@
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)

View File

@ -0,0 +1,404 @@
{
"cells": [
{
"cell_type": "code",
"id": "initial_id",
"metadata": {
"collapsed": true,
"ExecuteTime": {
"end_time": "2026-07-28T09:50:05.947705Z",
"start_time": "2026-07-28T09:50:05.940378Z"
}
},
"source": [
"import sys\n",
"import os\n",
"import numpy as np\n",
"from make_case import *\n",
"from make_inst import *\n",
"from FourChZChipConfig import *\n",
"from FourChZAssemblyTemplateManager import *\n",
"from FourChZEnvelopeGenerator import *\n",
"from FourChZreg_define import *\n",
"from ParamsManager import ParamsManager\n",
"from copy import deepcopy\n",
"from itertools import product\n",
"from pathlib import Path\n",
"mk = make_case()\n",
"mk_instr = make_inst()\n",
"from pathlib import Path\n",
"def run_case(params, save_json=True, write_hw=False):\n",
" \"\"\"\n",
" 通用执行函数:自动判断模式并按需调用 configure_chip_output, env_config, instruction_config\n",
" :param output_dir: 可选,自定义输出文件和 JSON 保存的目录路径\n",
" \"\"\"\n",
" # 1. 确定最终输出目录\n",
" base_dir = Path('D:/MyDocument/工作/Z芯片的case生成器/4ch-Z_Generator/gen_cases') # 在这边选择case目录所在位置\n",
" folder_name = params.get('FolderName', 'General') #文件夹名不用在这边改在case参数里面改\n",
" out_dir = base_dir / folder_name\n",
" \n",
" case_name = params['CaseName'] #Case名不用在这边改在case参数里面改\n",
" config_file_path = out_dir / f\"{case_name}_HEX.txt\"\n",
" # 更新 params 中的路径信息\n",
" params['config_file'] = str(config_file_path)\n",
" \n",
" # 2. 自动创建目录并初始化保存器\n",
" pm = ParamsManager(out_dir)\n",
" if save_json:\n",
" pm.save(params, case_name)\n",
" \n",
" # 3. 基础芯片输出配置\n",
" config_chip_reg(mk, **params)\n",
" print(\"执行 config_chip_reg\")\n",
" \n",
" # 4. 自动识别并执行包络配置\n",
" if 'envelope_configs' in params or 'envelope_type' in params or 'amp' in params:\n",
" if 'env_config' in globals():\n",
" env_config(mk, **params)\n",
" print(\"执行了 env_config\")\n",
" \n",
" # 5. 自动识别并执行指令配置\n",
" if 'instr_type' in params:\n",
" instruction_config(mk, mk_instr, **params)\n",
" print(\"执行了 instruction_config\")\n",
" \n",
" \n",
" # 7. 基础硬件寄存器下发\n",
" if write_hw:\n",
" channel = params['channel']\n",
" envm_base =addr_base['ENVM0_BASE'] + channel* 0x600000\n",
" itcm_base = addr_base['ITCM0_BASE'] + channel* 0x600000\n",
" mk.rw_once('w',envm_base , 0, params['config_file'])\n",
" instr_type = params.get('instr_type', None)\n",
" if instr_type is None:\n",
" mk.rw_once('w', itcm_base, '0x2B', params['config_file'])\n",
"\n",
" print(f\"生成文件路径:{config_file_path.resolve()}\")\n",
" return None\n",
"\n"
],
"outputs": [],
"execution_count": 34
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2026-07-28T09:52:50.467599Z",
"start_time": "2026-07-28T09:52:50.435623Z"
}
},
"cell_type": "code",
"source": [
"#general_send_wait这个汇编模板的 SEND_WAIT效果示例。\n",
"#单通道 AWG通用模板\n",
"param_ch0 = {\n",
" 'channel' : 0,\n",
" 'chip_mode':'AWG', #分为AWG和RAMP模式\n",
" 'mode':'mod', #可选nco nco_fm env mod四种模式\n",
" 'tail_en': False, #拖尾矫正开关\n",
" 'tc_coef_set': 'coef3', #拖尾矫正打开生效\n",
" 'inner_sync': False, #内部触发,应该是软触发,写一个寄存器,就能触发\n",
" 'amp_mod_enable': True, #调幅的开关mod调制模式下起作用。\n",
" 'freq_mod_enable': True, #nco的开关\n",
" 'bias_enable': True, #必开的开关AWG模式下偏置必须打开否则AWG输出保持为0.\n",
" \n",
" 'fcw': [100, 200, 300, 400], # MHz\n",
" 'mcu_reg_clr': True,\n",
" 'pcw': [0, 30, 45, 90, 120, 135, 150, 180], # Deg \n",
" 'rz_ff_pha': 0,\n",
" 'rz_fm_pha': 45,\n",
" 'ff_amp': [32767, 32767, 32767, 32767],\n",
" 'fm_amp': [32767, 32767, 32767, 32767],\n",
" 'bias': [1, 2, 3, 4],\n",
" 'fm_en' :False, #nco_fm的开关在nco_fm模式时必须打开,不然nco_fm不工作就是一条直线. mod的模式下开启fm_en,同时打开nco就能看到两个正弦波叠加啊\n",
" 'instr_type': 'general_send_wait', #调用汇编搬移上面的数据到mcu_regfile,同时配合下面参数执行指令.AWG固定用这个模板不用改。\n",
" 'send_interval': [100, 150, 200, 250, 300, 350, 400,450,500],\n",
" 'cycle_num': 1, #0代表无限循环如果要想扫参那么这个波形序列就不能无限循环播放\n",
" 'codeword_configs': [\n",
" # {'wave_hold': 1, 'fcw_index': 0, 'pcw_index': 0, 'code_clr': 1, 'env_index': 0},\n",
" # {'wave_hold': 0, 'fcw_index': 0, 'pcw_index': 0, 'code_clr': 0, 'env_index': 1},\n",
" # {'wave_hold': 1, 'fcw_index': 0, 'pcw_index': 0, 'code_clr': 1, 'env_index': 2},\n",
" # {'wave_hold': 0, 'fcw_index': 0, 'pcw_index': 0, 'code_clr': 0, 'env_index': 3},\n",
" {'wave_hold': 0, 'fcw_index': 0, 'pcw_index': 0, 'code_clr': 1, 'env_index': 4},\n",
" {'wave_hold': 0, 'fcw_index': 0, 'pcw_index': 0, 'code_clr': 1, 'env_index': 5},\n",
" {'wave_hold': 0, 'fcw_index': 0, 'pcw_index': 0, 'code_clr': 1, 'env_index': 6},\n",
" {'wave_hold': 0, 'fcw_index': 0, 'pcw_index': 0, 'code_clr': 1, 'env_index': 7},\n",
" {'wave_hold': 0, 'fcw_index': 0, 'pcw_index': 0, 'code_clr': 1, 'env_index': 8},\n",
" ], \n",
" 'sweep_config': {\n",
" 'sweep_num': 0, # 外层循环如果是0则代表不扫参该部分无效只搬移一次的23个寄存器。如果是 1代表重载1次寄存器加上最初的那次共两次.\n",
" 'offsets': [0x78, 0x40], # 告诉硬件本次扫描要修改哪几个寄存器的偏移地址比如要重载2个寄存器0x78 = AMPR0 (幅度), 0x40 = CWFR0 (频率) \n",
" 'steps': [3000, int(100 / fs / 4 * 2 ** 32)] # 幅度每次 +3000频率每次 100MHz (支持负数Python会自动转32位补码给MCU) ,所以第一次载入是载入初始值,第二次就是原值+steps,第三次就是上一次的值+steps \n",
" },\n",
" 'envelope_configs': [ #包络配置\n",
" {'envelope_type': 'rect_hold', 'amp': 32767},\n",
" {'envelope_type': 'flattop_hold', 'amp': 32767, 'edge_time': 3.5, 'wave_time': 30},\n",
" {'envelope_type': 'acz', 'amp': 32767, 'wave_time': 12 * 4},\n",
" {'envelope_type': 'accz', 'wave_time': 12 * 4},\n",
" {'envelope_type': 'cosine', 'amp': 32767, 'wave_time': 12 * 25},\n",
" {'envelope_type': 'rect', 'amp': 32767, 'wave_time': 12},\n",
" {'envelope_type': 'flattop', 'amp': 32767, 'edge_time': 2, 'wave_time': 22},\n",
" ],\n",
" 'FolderName': 'General',\n",
" 'CaseName': 'env2',\n",
"}\n",
"run_case(param_ch0)\n",
"\n",
"#通道1\n",
"param_ch1 = param_ch0.copy()\n",
"param_ch1['channel'] = 1\n",
"param_ch1['fcw'] = [200, 200, 300, 400]\n",
"run_case(param_ch1)\n",
"\n",
"#通道2\n",
"param_ch2 = param_ch0.copy()\n",
"param_ch2['channel'] = 2\n",
"param_ch2['fcw'] = [300, 200, 300, 400]\n",
"run_case(param_ch2)\n",
"\n",
"#通道3\n",
"param_ch3 = param_ch0.copy()\n",
"param_ch3['channel'] = 3\n",
"param_ch3['fcw'] = [400, 200, 300, 400]\n",
"run_case(param_ch3)\n",
"\n",
"\n"
],
"id": "3e79e12a64f2769e",
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"执行 config_chip_reg\n",
"执行了 env_config\n",
"执行了 instruction_config\n",
"生成文件路径D:\\MyDocument\\工作\\Z芯片的case生成器\\4ch-Z_Generator\\gen_cases\\General\\env2_HEX.txt\n",
"执行 config_chip_reg\n",
"执行了 env_config\n",
"执行了 instruction_config\n",
"生成文件路径D:\\MyDocument\\工作\\Z芯片的case生成器\\4ch-Z_Generator\\gen_cases\\General\\env2_HEX.txt\n",
"执行 config_chip_reg\n",
"执行了 env_config\n",
"执行了 instruction_config\n",
"生成文件路径D:\\MyDocument\\工作\\Z芯片的case生成器\\4ch-Z_Generator\\gen_cases\\General\\env2_HEX.txt\n",
"执行 config_chip_reg\n",
"执行了 env_config\n",
"执行了 instruction_config\n",
"生成文件路径D:\\MyDocument\\工作\\Z芯片的case生成器\\4ch-Z_Generator\\gen_cases\\General\\env2_HEX.txt\n"
]
}
],
"execution_count": 40
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2026-07-28T09:50:35.917889Z",
"start_time": "2026-07-28T09:50:35.900732Z"
}
},
"cell_type": "code",
"source": [
"# RAMP 通用模板1\n",
"#RAMP SPI控制\n",
"param_ch0 = {\n",
" 'channel' : 0,\n",
" 'chip_mode': 'RAMP',\n",
" 'ramp_ctrl':'SPI',\n",
" 'fixed_enable': True, #是固定值还是斜坡模式\n",
" 'fixed_value': 22767, #固定值模式生效\n",
" 'height': 512, 'step_time': 34 , #斜坡模式生效 step_time就是台阶宽度\n",
" \n",
" 'FolderName': 'RAMP',\n",
" 'CaseName': f\"RAMP_SPI\"\n",
"}\n",
"run_case(param_ch0,write_hw = True)\n",
"\n",
"#通道1\n",
"param_ch1 = param_ch0.copy()\n",
"param_ch1['channel'] = 1\n",
"run_case(param_ch1,write_hw = True)\n",
"\n",
"#通道2\n",
"param_ch2 = param_ch0.copy()\n",
"param_ch2['channel'] = 2\n",
"run_case(param_ch2,write_hw = True)\n",
"\n",
"#通道3\n",
"param_ch3 = param_ch0.copy()\n",
"param_ch3['channel'] = 3\n",
"run_case(param_ch3,write_hw = True)\n"
],
"id": "1f6f70a26d5da7f8",
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"执行 config_chip_reg\n",
"生成文件路径D:\\MyDocument\\工作\\Z芯片的case生成器\\4ch-Z_Generator\\gen_cases\\RAMP\\RAMP_SPI_HEX.txt\n",
"执行 config_chip_reg\n",
"生成文件路径D:\\MyDocument\\工作\\Z芯片的case生成器\\4ch-Z_Generator\\gen_cases\\RAMP\\RAMP_SPI_HEX.txt\n",
"执行 config_chip_reg\n",
"生成文件路径D:\\MyDocument\\工作\\Z芯片的case生成器\\4ch-Z_Generator\\gen_cases\\RAMP\\RAMP_SPI_HEX.txt\n",
"执行 config_chip_reg\n",
"生成文件路径D:\\MyDocument\\工作\\Z芯片的case生成器\\4ch-Z_Generator\\gen_cases\\RAMP\\RAMP_SPI_HEX.txt\n"
]
}
],
"execution_count": 36
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2026-07-28T09:26:33.012700Z",
"start_time": "2026-07-28T09:26:32.989301Z"
}
},
"cell_type": "code",
"source": [
"#RAMP MCU控制时,斜坡模式\n",
"param_ch0 = {\n",
" 'channel' : 0 ,\n",
" 'chip_mode': 'RAMP',\n",
" 'ramp_ctrl':'MCU',\n",
" #是固定值还是斜坡模式如过是斜坡模式则要指令选ramp_step\n",
" 'instr_type': 'ramp_step', #可选ramp_step或ramp_fixed. mcu执行不同指令操作模板实现台阶或斜坡这两种模式\n",
" 'ensemble_num' : 2, #大循环次数\n",
" 'param_num' :2, # 循环中参数个数,和列表个数一致\n",
" 'height': [128,256], \n",
" 'step_time': [50,50], \n",
" \n",
" 'FolderName': 'RAMP',\n",
" 'CaseName': f\"RAMP_MCU_STEP\"\n",
"}\n",
"\n",
"run_case(param_ch0,write_hw = True)\n",
"\n",
"#通道1\n",
"param_ch1 = param_ch0.copy()\n",
"param_ch1['channel'] = 1\n",
"run_case(param_ch1,write_hw = True)\n",
"\n",
"#通道2\n",
"param_ch2 = param_ch0.copy()\n",
"param_ch2['channel'] = 2\n",
"run_case(param_ch2,write_hw = True)\n",
"\n",
"#通道3\n",
"param_ch3 = param_ch0.copy()\n",
"param_ch3['channel'] = 3\n",
"run_case(param_ch3,write_hw = True)"
],
"id": "84e2c612b0a8f7ab",
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"执行 config_chip_reg\n",
"执行了 instruction_config\n",
"生成文件路径D:\\MyDocument\\工作\\Z芯片的case生成器\\4ch-Z_Generator\\gen_cases\\General\\RAMP_MCU_STEP_HEX.txt\n",
"执行 config_chip_reg\n",
"执行了 instruction_config\n",
"生成文件路径D:\\MyDocument\\工作\\Z芯片的case生成器\\4ch-Z_Generator\\gen_cases\\General\\RAMP_MCU_STEP_HEX.txt\n",
"执行 config_chip_reg\n",
"执行了 instruction_config\n",
"生成文件路径D:\\MyDocument\\工作\\Z芯片的case生成器\\4ch-Z_Generator\\gen_cases\\General\\RAMP_MCU_STEP_HEX.txt\n",
"执行 config_chip_reg\n",
"执行了 instruction_config\n",
"生成文件路径D:\\MyDocument\\工作\\Z芯片的case生成器\\4ch-Z_Generator\\gen_cases\\General\\RAMP_MCU_STEP_HEX.txt\n"
]
}
],
"execution_count": 26
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2026-07-28T09:51:30.781841Z",
"start_time": "2026-07-28T09:51:30.762192Z"
}
},
"cell_type": "code",
"source": [
"#RAMP MCU控制时,固定值模式\n",
"param_ch0 ={\n",
" 'channel' : 0,\n",
" 'chip_mode': 'RAMP',\n",
" 'ramp_ctrl':'MCU',\n",
" #是固定值还是斜坡模式如果是固定值模式则指令选ramp_fixed\n",
" 'instr_type': 'ramp_fixed', #可选ramp_step或ramp_fixed. mcu执行不同指令操作模板实现台阶或斜坡这两种模式\n",
" 'fixed_value': [1<<15] + [1<<15 | 1<<i for i in range(0,15)] + [0], \n",
" 'wait_clk': [1000]*17,\n",
" 'config_param_num': 17, \n",
" 'ensemble_num': 0, \n",
" \n",
" 'FolderName': 'RAMP',\n",
" 'CaseName': f\"RAMP_MCU_FIXED\"\n",
"}\n",
"\n",
"run_case(param_ch0,write_hw = True)\n",
"\n",
"#通道1\n",
"param_ch1 = param_ch0.copy()\n",
"param_ch1['channel'] = 1\n",
"run_case(param_ch1,write_hw = True)\n",
"\n",
"#通道2\n",
"param_ch2 = param_ch0.copy()\n",
"param_ch2['channel'] = 2\n",
"run_case(param_ch2,write_hw = True)\n",
"\n",
"#通道3\n",
"param_ch3 = param_ch0.copy()\n",
"param_ch3['channel'] = 3\n",
"run_case(param_ch3,write_hw = True)"
],
"id": "e2743613b0b64ea7",
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"执行 config_chip_reg\n",
"执行了 instruction_config\n",
"生成文件路径D:\\MyDocument\\工作\\Z芯片的case生成器\\4ch-Z_Generator\\gen_cases\\RAMP\\RAMP_MCU_FIXED_HEX.txt\n",
"执行 config_chip_reg\n",
"执行了 instruction_config\n",
"生成文件路径D:\\MyDocument\\工作\\Z芯片的case生成器\\4ch-Z_Generator\\gen_cases\\RAMP\\RAMP_MCU_FIXED_HEX.txt\n",
"执行 config_chip_reg\n",
"执行了 instruction_config\n",
"生成文件路径D:\\MyDocument\\工作\\Z芯片的case生成器\\4ch-Z_Generator\\gen_cases\\RAMP\\RAMP_MCU_FIXED_HEX.txt\n",
"执行 config_chip_reg\n",
"执行了 instruction_config\n",
"生成文件路径D:\\MyDocument\\工作\\Z芯片的case生成器\\4ch-Z_Generator\\gen_cases\\RAMP\\RAMP_MCU_FIXED_HEX.txt\n"
]
}
],
"execution_count": 38
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.6"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@ -0,0 +1,189 @@
import numpy as np
import os
import copy
from FourChZreg_define import *
class FourChZChipConfig(object):
CHANNEL_OFFSET = 0x00600000
SCALE_FACTOR = 2 ** 31
def __init__(self, mk_instance, **kwargs):
self.mk = mk_instance
self.FolderName = kwargs.get('FolderName')
self.config_file = kwargs.get('config_file')
self._setup_environment()
def _setup_environment(self):
if self.FolderName:
os.makedirs(self.FolderName, exist_ok=True)
def write_registers_batch(self, register_values):
"""批量写入寄存器"""
if isinstance(register_values, dict):
register_values = register_values.items()
for address, value in register_values:
self.mk.rw_once('w', address, value, self.config_file)
def write_register(self, address, value):
self.mk.rw_once('w', address, value, self.config_file)
def _calculate_tc_coefficients(self, **kwargs):
tc_coef_set = kwargs.get('tc_coef_set')
coef_set = TC_COEFFICIENT_SETS[tc_coef_set]
amp_real = coef_set['amp_real']
amp_imag = coef_set['amp_imag']
time_real = coef_set['time_real']
time_imag = coef_set['time_imag']
sampling_rate = 3e9
coef1, coef2 = [], []
for ar, ai, tr, ti in zip(amp_real, amp_imag, time_real, time_imag):
amp_coef = ar + 1j * ai
time_coef = tr + 1j * ti
coef1.append(amp_coef * np.exp(1e9 / sampling_rate / 2 / (1 - amp_coef) * time_coef) / (1 - amp_coef))
coef2.append(np.exp(1e9 / sampling_rate / (1 - amp_coef) * time_coef))
return {
'alpha_re': [int(c.real * self.SCALE_FACTOR) for c in coef1],
'alpha_im': [int(c.imag * self.SCALE_FACTOR) for c in coef1],
'beta_re': [int(c.real * self.SCALE_FACTOR) for c in coef2],
'beta_im': [int(c.imag * self.SCALE_FACTOR) for c in coef2]
}
def _general_reg_config(self, **kwargs):
# 深拷贝 kwargs 保护原始字典
kwargs = copy.deepcopy(kwargs)
# 自定义寄存器配置支持
if 'custom_registers' in kwargs:
custom_registers = kwargs.pop('custom_registers')
first_item = custom_registers[0]
if isinstance(first_item, tuple):
self.write_registers_batch(custom_registers)
elif isinstance(first_item, dict):
for item in custom_registers:
self.write_register(item['addr'], item['values'])
elif isinstance(first_item, list):
for item in custom_registers:
self.write_register(item[0], item[1])
# 芯片工作模式配置
if 'chip_mode' in kwargs:
chip_mode = kwargs.pop('chip_mode')
if chip_mode == 'RAMP':
self._ramp_config(**kwargs)
elif chip_mode == 'AWG':
self._awg_config(**kwargs)
def _ramp_config(self, **kwargs):
# 统一使用相对基地址(动态适配当前 Channel
channel = kwargs.get('channel')
ctrl_base = addr_base['CTRL0_BASE'] + channel * 0x600000
self.write_register(ctrl_base + FourChZreg_define['ctrl_reg']['MODDOTR'], 8) # 切换到RAMP输出
ramp_ctrl = kwargs.get('ramp_ctrl')
if ramp_ctrl == 'MCU': # RAMP连到 mcu_regfile
self.write_register(ctrl_base + FourChZreg_define['ctrl_reg']['SPI_RAMPENR'], 1 << 30)
elif ramp_ctrl == 'SPI': # RAMP连到 ctrl_regfile
ramp_spi_registers = []
fixed_enable = kwargs.get('fixed_enable', False)
if fixed_enable: # 固定值模式
fixed_value = kwargs.get('fixed_value', 0)
ramp_spi_registers += [1 << 15 | fixed_value << 16]
# 写寄存器函数自带了通道偏移
self.write_register(ctrl_base + FourChZreg_define['ctrl_reg']['SPI_RAMPFIXR'], ramp_spi_registers)
else: # 斜坡模式
height = kwargs.get('height', 0)
length = kwargs.get('step_time', 0)
ramp_spi_registers += [0 << 15]
ramp_spi_registers += [height << 16]
ramp_spi_registers += [length]
self.write_register(ctrl_base + FourChZreg_define['ctrl_reg']['SPI_RAMPFIXR'], ramp_spi_registers)
# 配置使能
self.write_register(ctrl_base + FourChZreg_define['ctrl_reg']['SPI_RAMPENR'], 1 << 31 | 0 << 30)
def _awg_config(self, **kwargs):
channel = kwargs.get('channel', 0)
ctrl_base = addr_base['CTRL0_BASE'] + channel*0x600000
tcco_base = addr_base['TCCO0_BASE'] + channel*0x600000
dtcm_base = addr_base['DTCM0_BASE'] + channel*0x600000
mode_map = {'nco': 6, 'nco_fm': 7, 'env': 4, 'mod': 5}
mode = kwargs.get('mode', None)
moddotr_val = mode_map.get(mode, 0)
# 1. DSP (拖尾矫正) 配置
tail_en = kwargs.get('tail_en', False)
if tail_en:
coefficients = self._calculate_tc_coefficients(**kwargs)
tc_coef_registers = (
coefficients['alpha_re'] +
coefficients['alpha_im'] +
coefficients['beta_re'] +
coefficients['beta_im']
)
self.write_register(tcco_base + FourChZreg_define['tc_reg']['TCPARR0'], tc_coef_registers)
tccdr_addr = tcco_base + FourChZreg_define['tc_reg']['TCCDR']
for i in range(8):
self.write_register(tccdr_addr, 1 << i)
moddotr_val &= ~4 # 把[2]清零
# 2. 数据选择寄存器 MODDOTR 配置
self.write_register(ctrl_base + FourChZreg_define['ctrl_reg']['MODDOTR'], moddotr_val)
# 3. 调制使能寄存器 MODENR 配置
amp_mod_enable = kwargs.get('amp_mod_enable', False)
freq_mod_enable = kwargs.get('freq_mod_enable', False)
bias_enable = kwargs.get('bias_enable', False)
mod_enable = (
(int(not bias_enable) << 0)
| (int(not freq_mod_enable) << 1)
| (int(not amp_mod_enable) << 2)
)
self.write_register(ctrl_base + FourChZreg_define['ctrl_reg']['MODENR'], mod_enable)
# 4. mcu_regfile 配置
mcu_registers = []
fcw_list = kwargs.get('fcw', [0])
mcu_reg_clr = kwargs.get('mcu_reg_clr', False)
pcw_list = kwargs.get('pcw', [0])
for fcw in fcw_list:
mcu_registers.append(int(fcw / fs / 4 * 2 ** 32))
mcu_registers.append(1 << 31 if mcu_reg_clr else 0 << 31)
for pcw in pcw_list:
mcu_registers.append(int(pcw / 360 * (2 ** 16 - 1)) << 16)
rz_pha = kwargs.get('rz_pha', 0)
mcu_registers.append(int(rz_pha / 360 * (2 ** 16 - 1)))
ff_amp_list = kwargs.get('ff_amp', [0])
fm_amp_list = kwargs.get('fm_amp', [0])
for ff, fm in zip(ff_amp_list, fm_amp_list):
mcu_registers.append(((ff & 0xFFFF) << 16) | (fm & 0xFFFF))
bias_list = kwargs.get('bias', [0])
for bias in bias_list:
mcu_registers.append(bias << 16)
self.write_register(dtcm_base + FourChZreg_define['mcu_reg']['CWFR0'], mcu_registers)
# 5. FMER 配置
fm_en = kwargs.get('fm_en', False)
self.write_register(dtcm_base + FourChZreg_define['mcu_reg']['FMER'], 1 << 31 if fm_en else 0)
return None
def config_chip_reg(mk_instance, **kwargs):
config = FourChZChipConfig(mk_instance, **kwargs)
config._general_reg_config(**kwargs)

View File

@ -0,0 +1,194 @@
import numpy as np
import os
import logging
import copy
import matplotlib.pyplot as plt
import sys
from typing import Any, Dict, List, Optional, Union, Callable
from enum import Enum
from env_gen.flattop import flattop
from env_gen.acz import aczwave
from env_gen.accz_gen import accz_wave
from matplotlib import gridspec
from FourChZreg_define import *
class EnvelopeGenerator:
_axes_list: List[tuple] = []
PLOT_STYLES = [
'ggplot', 'bmh', 'fivethirtyeight', 'Solarize_Light2',
'fast', 'tableau-colorblind10', 'seaborn-poster', 'seaborn-bright'
]
PLOT_COLORS = ['C0', 'C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7']
SINGLE_PLOT_CONFIG = {
'figsize': (8, 6),
'dpi': 220,
'style': 'seaborn-v0_8-poster',
'linewidth': 3,
'fontsize': {'xlabel': 22, 'ylabel': 22, 'title': 20, 'legend': 18, 'tick': 18}
}
MULTI_PLOT_CONFIG = {
'dpi': 200,
'fontsize': {'xlabel': 18, 'ylabel': 18, 'title': 16, 'tick': 16},
'grid_alpha': 0.3
}
def __init__(self, mk_instance, **kwargs):
self.mk = mk_instance
self.config_file = kwargs.get('config_file')
def write_register(self, address, value):
self.mk.rw_once('w', address, value, self.config_file)
def _generate_rect_envelope(self, **kwargs):
amp = kwargs.pop('amp')
wave_time = kwargs.pop('wave_time')
rect_wave = [amp] * wave_time
return rect_wave
def _generate_rect_hold_envelope(self, **kwargs):
amp = kwargs.pop('amp')
rect_rising_edge = [amp] * 4
rect_falling_edge = [0] * 4
return rect_rising_edge, rect_falling_edge
def _generate_flattop_envelope(self, **kwargs):
amp = kwargs.pop('amp')
edge_time = kwargs.pop('edge_time')
wave_time = kwargs.pop('wave_time')
flattop_wave = flattop(float(amp), float(edge_time), float(wave_time), 1.0)
return flattop_wave
def _generate_flattop_hold_envelope(self, **kwargs):
amp = kwargs.pop('amp')
edge_time = kwargs.pop('edge_time')
wave_time = kwargs.pop('wave_time')
flattop_wave = flattop(float(amp), float(edge_time), float(wave_time), 1.0)
hold_value = flattop_wave.max()
hold_idx = np.where(flattop_wave == hold_value)[0]
rising_edge_end_idx = hold_idx[0]
falling_edge_start_idx = hold_idx[-1]
flattop_rising_edge = flattop_wave[:rising_edge_end_idx + 1]
flattop_falling_edge = flattop_wave[falling_edge_start_idx:-2]
return flattop_rising_edge, flattop_falling_edge
def _generate_acz_envelope(self, **kwargs):
amp = kwargs.pop('amp')
wave_time = kwargs.pop('wave_time')
acz_wave = aczwave(amp, wave_time, 0.0, 0.0, 0.0, 0.864, 0.05, -0.18, 0.04)
acz_wave_real = [val.real for val in acz_wave]
return acz_wave_real
def _generate_accz_envelope(self, **kwargs):
wave_time = kwargs.pop('wave_time')
env_accz = accz_wave(T=wave_time, A=0.8, plot=False)
return env_accz
def _cosine_envelope(self, **kwargs):
alpha = kwargs.pop('alpha', 1)
phi = kwargs.pop('phi', np.pi)
amp = kwargs.pop('amp')
wave_time = kwargs.pop('wave_time')
t_norm = np.arange(wave_time) / wave_time
cosine_wave = amp * (1 + alpha * np.cos(2 * np.pi * t_norm + phi)) / 2
return cosine_wave
def _generate_envelope_data(self, envelope_type, **kwargs):
if envelope_type == 'rect':
env_data = self._generate_rect_envelope(**kwargs)
elif envelope_type == 'rect_hold':
env_data = self._generate_rect_hold_envelope(**kwargs)
elif envelope_type == 'flattop':
env_data = self._generate_flattop_envelope(**kwargs)
elif envelope_type == 'flattop_hold':
env_data = self._generate_flattop_hold_envelope(**kwargs)
elif envelope_type == 'acz':
env_data = self._generate_acz_envelope(**kwargs)
elif envelope_type == 'accz':
env_data = self._generate_accz_envelope(**kwargs)
elif envelope_type == 'cosine':
env_data = self._cosine_envelope(**kwargs)
elif envelope_type == 'file_read_direct':
env_data = kwargs.get('external_envelope_data', [])
elif envelope_type == 'file_read_txt':
file_path = kwargs.get('file_path')
if file_path is None:
raise ValueError("Missing 'file_path'")
txt_data = np.loadtxt(file_path)
env_data = np.asarray(txt_data, dtype=float).reshape(-1).tolist()
return env_data
def _next_env_idx(self, idx_num, env_idx_mem, envelope_length):
if idx_num == 0:
return envelope_length
else:
last_env_idx = env_idx_mem[-1]
env_base_addr = (last_env_idx >> 16) + ((last_env_idx & 0xFFFF) << 1)
return env_base_addr << 16 | envelope_length
def _env_data_pack(self, float_data_array):
data_int = np.round(float_data_array).astype(int)
data_int[data_int < 0] += 65536
hex_pairs = []
for data0, data1 in zip(data_int[::2], data_int[1::2]):
hex_pairs.append((data1 << 16) | data0)
return hex_pairs
def _generate_envelope_batch(self, **kwargs):
kwargs_copy = copy.deepcopy(kwargs)
channel = kwargs_copy.pop('channel')
envelope_configs = kwargs_copy.pop('envelope_configs', [])
env_data_mem = []
env_idx_mem = []
idx_num = 0
for envelope_config in envelope_configs:
envelope_type = envelope_config.pop('envelope_type')
env_data = self._generate_envelope_data(envelope_type, **envelope_config)
if isinstance(env_data, tuple):
retun_param_count = len(env_data)
else:
retun_param_count = 1
if retun_param_count == 1:
envelope = env_data
envelope_arr = np.asarray(envelope, dtype=float).reshape(-1)
if envelope_arr.size % 4 != 0:
raise ValueError("Envelope length must be multiple of 4")
env_data_mem += envelope_arr.astype(int).tolist()
envelope_length = int(envelope_arr.size)
current_env_idx = self._next_env_idx(idx_num, env_idx_mem, envelope_length)
env_idx_mem.append(current_env_idx)
idx_num += 1
elif retun_param_count == 2:
rising_edge, falling_edge = env_data
rising_edge_arr = np.asarray(rising_edge, dtype=float).reshape(-1)
falling_edge_arr = np.asarray(falling_edge, dtype=float).reshape(-1)
if rising_edge_arr.size % 4 != 0:
raise ValueError("Envelope length must be multiple of 4")
env_data_mem += rising_edge_arr.astype(int).tolist()
rising_edge_length = int(rising_edge_arr.size)
rising_edge_idx = self._next_env_idx(idx_num, env_idx_mem, rising_edge_length)
env_idx_mem.append(rising_edge_idx)
idx_num += 1
env_data_mem += falling_edge_arr.astype(int).tolist()
falling_edge_length = int(falling_edge_arr.size)
falling_edge_idx = self._next_env_idx(idx_num, env_idx_mem, falling_edge_length)
env_idx_mem.append(falling_edge_idx)
idx_num += 1
env2mem_format = self._env_data_pack(env_data_mem)
ENVI_BASE = addr_base['ENVI0_BASE'] + channel*0x600000
ENVM_BASE = addr_base['ENVM0_BASE'] + channel*0x600000
self.write_register(ENVI_BASE, env_idx_mem)
self.write_register(ENVM_BASE, env2mem_format)
def env_config(mk_instance, **kwargs):
env_gen = EnvelopeGenerator(mk_instance, **kwargs)
env_gen._generate_envelope_batch(**kwargs)

View File

@ -0,0 +1,279 @@
# TODO: 寄存器统一由excel表格维护
# TODO: 寄存由excel表格生成
FourChZreg_define = {
'sys_reg': {
'IDR': 0x00,
'VIDR': 0x04,
'DATER': 0x08,
'VERR': 0x0C,
'TESTR': 0x10,
'IMR': 0x14,
'ISR': 0x18,
'SFRTR': 0x1C,
'SFRR': 0x20,
'CH0RSTR': 0x24,
'CH1RSTR': 0x28,
'CH2RSTR': 0x2C,
'CH3RSTR': 0x30,
'DBGCFGR': 0x34,
'MISR': 0x40,
'SYNCR': 0x44,
'MSDENR': 0x48,
'MSDPCNTR': 0x4C,
},
'ctrl_reg': {
'MCUPARAR0': 0x00,
'MCUPARAR1': 0x04,
'MCUPARAR2': 0x08,
'MCUPARAR3': 0x0C,
'MCURESR0': 0x10,
'MCURESR1': 0x14,
'MCURESR2': 0x18,
'MCURESR3': 0x1C,
'RTIMR': 0x98,
'ICNTR': 0x9C,
'FSIR': 0xA0,
'MODMR': 0x100,
'MODENR': 0x104,
'MODDOTR': 0x108,
'MIXODFR': 0x10C,
'STR': 0x110,
'NCOAOR': 0x114,
'SPI_RAMPFIXR': 0x118,
'SPI_RAMPSR': 0x11C,
'SPI_RAMPIFSR': 0x120,
'SPI_RAMPENR': 0x124,
'TSTIMER': 0x130,
'TSITVLR': 0x134,
'TSENR': 0x138,
'TSVALR': 0x13C,
},
'mcu_reg': {
'CWFR0': 0x40,
'CWFR1': 0x44,
'CWFR2': 0x48,
'CWFR3': 0x4C,
'CWPRR': 0x50,
'GAPR0': 0x54,
'GAPR1': 0x58,
'GAPR2': 0x5C,
'GAPR3': 0x60,
'GAPR4': 0x64,
'GAPR5': 0x68,
'GAPR6': 0x6C,
'GAPR7': 0x70,
'LCPR': 0x74,
'AMPR0': 0x78,
'AMPR1': 0x7C,
'AMPR2': 0x80,
'AMPR3': 0x84,
'BIASR0': 0x88,
'BIASR1': 0x8C,
'BIASR2': 0x90,
'BIASR3': 0x94,
'RTIMR': 0x98, # Note: Same as in ctrl_reg
'ICNTR': 0x9C, # Note: Same as in ctrl_reg
'FSIR': 0xA0, # Note: Same as in ctrl_reg
'DCBVR': 0xA4,
'FMER': 0xB4,
'MCU_RAMPFIXR': 0xB8,
'MCU_RAMPSR': 0xBC,
'MCU_RAMPIFSR': 0xC0,
'MCU_RAMPENR': 0xC4,
'PRNGSDR': 0xC8,
'PRNGRESR': 0xCC,
'MULTR0': 0xD0,
'MULTR1': 0xD4,
'DTFR': 0xD8,
},
'tc_reg': {
'TCPARR0': 0x000,
'TCPARR1': 0x004,
'TCPARR2': 0x008,
'TCPARR3': 0x00C,
'TCPARR4': 0x010,
'TCPARR5': 0x014,
'TCPARR6': 0x018,
'TCPARR7': 0x01C,
'TCPAIR0': 0x020,
'TCPAIR1': 0x024,
'TCPAIR2': 0x028,
'TCPAIR3': 0x02C,
'TCPAIR4': 0x030,
'TCPAIR5': 0x034,
'TCPAIR6': 0x038,
'TCPAIR7': 0x03C,
'TCPBRR0': 0x040,
'TCPBRR1': 0x044,
'TCPBRR2': 0x048,
'TCPBRR3': 0x04C,
'TCPBRR4': 0x050,
'TCPBRR5': 0x054,
'TCPBRR6': 0x058,
'TCPBRR7': 0x05C,
'TCPBIR0': 0x060,
'TCPBIR1': 0x064,
'TCPBIR2': 0x068,
'TCPBIR3': 0x06C,
'TCPBIR4': 0x070,
'TCPBIR5': 0x074,
'TCPBIR6': 0x078,
'TCPBIR7': 0x07C,
'TCBPR': 0x080,
'TCCER': 0x084,
'TCOVR': 0x088,
'TCCDR': 0x08C,
},
'pll_reg': {
'INTPLL_REFCTRL' : 0x00,
'INTPLL_PCNT' : 0x04,
'INTPLL_PFDCTRL' : 0x08,
'INTPLL_SPDCTRL' : 0x0C,
'INTPLL_PTATCTRL' : 0x10,
'INTPLL_SELCTRL' : 0x14,
'INTPLL_VCOCTRL' : 0x18,
'INTPLL_TCCTRL' : 0x1C,
'INTPLL_AFCCTRL' : 0x20,
'INTPLL_AFCFBCTRL': 0x24,
'INTPLL_AFCLDCNT' : 0x28,
'INTPLL_DIVRSTSEL': 0x2C,
'INTPLL_TESTCLK' : 0x30,
'INTPLL_DIGCLKSEL': 0x34,
'INTPLL_STATUS' : 0x38,
'INTPLL_SYNC' : 0x3C,
'INTPLL_UPDATE' : 0x40,
'INTPLL_CLKRXPD' : 0x44,
'INTPLL_RESV' : 0x48,
'CCALRSTR' : 0x4C,
'CCALATENR' : 0x50,
'CCALSELALNR' : 0x54,
'CCALDCCQECR' : 0x58,
'CCALQECCT0R' : 0x5C,
'CCALQECCT1R' : 0x60,
'CCALDCCCT0R' : 0x64,
'CCALDCCCT1R' : 0x68,
'DIVSYNCDCR' : 0x6C,
'SYNCCLRENR' : 0x70,
'CCALDCCCT2R' : 0x74,
'CCALSTR' : 0x78,
}
}
# Usage example:
# value = reg_define['sys_reg']['DATER'] # Gets 0x00
# print(f"IDR value: {value}")
# import reg_define
# 预定义的TC系数组
TC_COEFFICIENT_SETS = {
'default': {
'amp_real': [0.025, 0.015, 0.0002, 0.2, 0, 0, 0, 0],
'amp_imag': [0, 0, 0, 0, 0, 0, 0, 0],
'time_real': [-1/250, -1/650, -1/1600, -1/20, 0, 0, 0, 0],
'time_imag': [0, 0, 0, 0, 0, 0, 0, 0],
'description': '默认TC系数组'
},
'coef1': {
'amp_real': [0.025, 0.015, 0.0002, 0.2, 0, 0, 0, 0],
'amp_imag': [0, 0, 0, 0, 0, 0, 0, 0],
'time_real': [-1/250, -1/650, -1/1600, -1/20, 0, 0, 0, 0],
'time_imag': [0, 0, 0, 0, 0, 0, 0, 0],
'description': 'lsw - coef1'
},
'coef2': {
'amp_real': [0.025, 0.015, 0.0002, 0.2, 0, 0, 0, 0],
'amp_imag': [0, 0, 0, 0, 0, 0, 0, 0],
'time_real': [-1/250, -1/650, -1/1600, -1/20, 0, 0, 0, 0],
'time_imag': [0, -1/300, -1/500, 0, 0, 0, 0, 0],
'description': 'lsw - coef2'
},
'coef3': {
'amp_real': [0.025, 0.009, 0.0002, 0.2, 0, 0, 0, 0],
'amp_imag': [0, 0.012, 0, 0, 0, 0, 0, 0],
'time_real': [-1/250, -1/650, -1/1600, -1/20, 0, 0, 0, 0],
'time_imag': [0, -1/300, -1/500, 0, 0, 0, 0, 0],
'description': 'lsw - coef3'
},
'coef4': {
'amp_real': [0.025, 0.015, 0.0002, 0.2, 0, 0, 0, 0],
'amp_imag': [0, 0, 0, 0, 0, 0, 0, 0],
'time_real': [-1/250, -1/2000, -1/1600, -1/20, 0, 0, 0, 0],
'time_imag': [0, -1/15, -1/50, 0, 0, 0, 0, 0],
'description': 'lsw - coef4'
},
'coef5': {
'amp_real': [0.0281, 0.0024, 0.0021, 0.0011, 0, 0, 0, 0],
'amp_imag': [0, 0, 0, 0, 0, 0, 0, 0],
'time_real': [-0.0033, -0.0027, -0.0027, -0.0002, 0, 0, 0, 0],
'time_imag': [0, 0, 0, 0, 0, 0, 0, 0],
'description': 'czy - coef5'
},
'coef6': {
'amp_real': [0.0314, 0.0132, 0.0055, 0.0017, 0, 0, 0, 0],
'amp_imag': [0, 0, 0, 0, 0, 0, 0, 0],
'time_real': [-0.0096, -0.0021, -0.0009, -0.0002, 0, 0, 0, 0],
'time_imag': [0, 0, 0, 0, 0, 0, 0, 0],
'description': 'czy - coef6'
},
'coef7': {
'amp_real': [0, 0.0282, 0, 0.0130, 0, 0, 0, 0],
'amp_imag': [0, 0, 0, 0, 0, 0, 0, 0],
'time_real': [-0.0193, -0.0051, -0.0012, -0.0020, 0, 0, 0, 0],
'time_imag': [0, 0, 0, 0, 0, 0, 0, 0],
'description': 'czy - coef7'
},
'coef8': {
'amp_real': [0.0314*1, 0.0132*1, 0.0055*1, 0.0017*1, 0.0282*1, 0.0130*1, 0.0024*1, 0.0021*1],
'amp_imag': [0, 0, 0, 0, 0, 0, 0, 0],
'time_real': [-0.0096, -0.0021, -0.0009, -0.0002, -0.0051, -0.0020, -0.0027, -0.0027],
'time_imag': [0, 0, 0, 0, 0, 0, 0, 0],
'description': 'thfu - coef8'
},
'coef9': {
'amp_real': [0.0314*1, 0.0132*1, 0.0055*1, 0.0017*1, 0.0282*1, 0.0130*1, 0.0024*1, 0.0021*1],
'amp_imag': [0.012, 0.012, 0.012, 0.012, 0.012, 0.012, 0.012, 0.012],
'time_real': [-0.0096, -0.0021, -0.0009, -0.0011, -0.0051, -0.0020, -0.0027, -0.0027],
'time_imag': [-1/300, -1/500, -1/15, -1/20, -1/100, -1/200, -1/400, -1/800],
'description': 'thfu - coef9'
},
'custom': {
'amp_real': [0, 0, 0, 0, 0, 0, 0, 0],
'amp_imag': [0, 0, 0, 0, 0, 0, 0, 0],
'time_real': [0, 0, 0, 0, 0, 0, 0, 0],
'time_imag': [0, 0, 0, 0, 0, 0, 0, 0],
'description': '自定义系数组 - 需要手动设置'
}
}
#### regfile base address ####
addr_base = {
'SYST_BASE': 0x00000000,
'DBGM_BASE': 0x01900000,
'ITCM0_BASE': 0x00100000,
'DTCM0_BASE': 0x00200000,
'CTRL0_BASE': 0x00300000,
'TCCO0_BASE': 0x00301000,
'ENVI0_BASE': 0x00400000,
'ENVM0_BASE': 0x00500000,
'CLK0_BASE': 0x01F00000,
'DAC0_BASE': 0x01F01000,
'ITCM1_BASE': 0x00700000,
'DTCM1_BASE': 0x00800000,
'CTRL1_BASE': 0x00900000,
'TCCO1_BASE': 0x00901000,
'ENVI1_BASE': 0x00A00000,
'ENVM1_BASE': 0x00B00000,
'CLK1_BASE': 0x01F02000,
'DAC1_BASE': 0x01F03000,
}
# 共用是SYST_BASE 基地址前5个地址其实就是偏移地址夹600000后面两个其实是加1000
fs = 750 #MHz

View File

@ -0,0 +1,56 @@
import json
import os
from pathlib import Path
class ParamsManager:
def __init__(self, params_dir='params'):
self.params_dir = params_dir
self._ensure_dir_exists()
def _ensure_dir_exists(self):
Path(self.params_dir).mkdir(parents=True, exist_ok=True)
def save(self, params, filename):
if not filename.endswith('.json'):
filename = filename + '.json'
filepath = os.path.join(self.params_dir, filename)
with open(filepath, 'w', encoding='utf-8') as f:
json.dump(params, f, indent=2, ensure_ascii=False)
def load(self, filename):
if not filename.endswith('.json'):
filename = filename + '.json'
filepath = os.path.join(self.params_dir, filename)
with open(filepath, 'r', encoding='utf-8') as f:
params = json.load(f)
return params
def save_multiple(self, params_dict):
filepaths = []
for filename, params in params_dict.items():
filepath = self.save(params, filename)
filepaths.append(filepath)
return filepaths
def load_multiple(self, filenames):
result = {}
for filename in filenames:
result[filename] = self.load(filename)
return result
# from ParamsManager import ParamsManager
# # 创建参数管理器实例
# pm = ParamsManager('params') # 参数保存在 params 文件夹中
# # 保存单个参数
# pm.save(params, 'AWG_NCO') # 自动添加 .json 后缀
# # 加载单个参数
# params = pm.load('AWG_NCO')

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,28 @@
import numpy as np
import matplotlib.pyplot as plt
# accz
T = 100 # ns
A = 0.8 # 归一化幅度
P = 0.16
omega_d = 100e6 # Hz
theta = 0
a2 = 0.1
phi = 0
sample_rate = 1e9 # Hz
N = int(100 / (1/sample_rate * 1e9)) # 采样点个数
A = A * 2**15
# 包络函数
t = np.linspace(0, N, N+1)
env = A/(np.sqrt(1 + P**2)) * (np.sin(np.pi * t / N) + P * np.sin(3*np.pi * t / N))
# 载波调制
f = env * (np.cos(omega_d * t + theta) + a2 * np.cos(2*omega_d*t + 2*theta + phi))
fint16 = np.int16(f)
#np.savetxt(r'D:\SynologyDrive\SynologyDrive\Work\SQC2.1\gene_wave_on_board\code\acczdata.txt',fint16,'%d')
plt.figure()
plt.plot(t,fint16)
plt.show()

View File

@ -0,0 +1,19 @@
import numpy as np
import matplotlib.pyplot as plt
def accz_wave(T=100, A=0.8, P=0.16, omega_d=100e6, theta=0, a2=0.1, phi=0, sample_rate=1e9, plot=False):
N = int(T / (1/sample_rate * 1e9))
A_scaled = A * 2**15
t = np.linspace(0, N, N)
env = A_scaled/(np.sqrt(1 + P**2)) * (np.sin(np.pi * t / N) + P * np.sin(3*np.pi * t / N))
f = env * (np.cos(omega_d * t + theta) + a2 * np.cos(2*omega_d*t + 2*theta + phi))
fint16 = np.int16(f)
if plot:
plt.figure()
plt.plot(t, env)
plt.show()
return env
# 示例:外部调用
# env = accz_wave(T=200, A=1.0, plot=True)
# print(env)

View File

@ -0,0 +1,208 @@
import numpy as np
import math
from typing import List
import os
import matplotlib.pyplot as plt
class Interp1d:
def __init__(self, xs : List[float], ys : List[float]):
xs, ys = np.array(xs), np.array(ys)
# ascending order
inds = np.argsort(xs)
self.xs, self.ys = xs[inds], ys[inds]
self.len = len(self.xs)
def __call__(self, x):
lowerboundp = 0
# optain the lowerbound
for i, xi in enumerate(self.xs):
if x >= xi:
lowerboundp = i
else:
break
if lowerboundp < self.len - 1:
upperboundp = lowerboundp + 1
else:
lowerboundp, upperboundp = self.len - 2, self.len - 1
x0, y0, x1, y1 = self.xs[lowerboundp], self.ys[lowerboundp], self.xs[upperboundp], self.ys[upperboundp]
if x1 == x0:
return (y0 + y1) / 2.0
return y0 + (x-x0)/(x1-x0)*(y1-y0)
def linspace(start : float, end : float, n : int):
samples = []
step = (end - start) / (n-1)
for i in range(n):
samples.append(start + float(i)*step)
return samples
def zeros(n : int):
return [0] * n
def aczwave(amplitude : float, length : int,
carrierFreq : float, carrierPhase : float, dragAlpha : float,
thf : float, thi : float, lam2 : float, lam3 : float):
t = linspace(0, 1, length)
han2 = []
for k, x in enumerate(t):
han2.append(
(1-lam3)*(1-math.cos(2.0*math.pi*x)) +
lam2*(1-math.cos(4*math.pi*x)) +
lam3*(1-math.cos(6*math.pi*x))
)
maxHan2 = max(han2)
ths1 = []
for k in range(length):
ths1.append(
thi + (thf-thi)*han2[k]/maxHan2
)
t1u = zeros(length)
for k, v in enumerate(t1u):
if k < (length - 1):
t1u[k+1] = v + math.sin(ths1[k])/float(length-1)
for k, v in enumerate(t):
t[k] = v * t1u[length-1]
th = Interp1d(t1u, ths1)
th0 = 1.0 / math.tan(th(t[0]))
thval = []
for k in range(length):
thval.append(
1.0/math.tan(th(t[k])) - th0
)
thmin = min(thval)
samples = []
for k in range(length):
env = thval[k] * amplitude / thmin
samples.append(complex(env, 0))
return samples
def test():
amplitude = 26214
length = 30
carrierFreq = 0
carrierPhase = 0.000000
dragAlpha = 0.000000
thf = 0.864
thi = 0.05
lam2 = -0.18
lam3 = 0.04
data = aczwave(
amplitude, length, carrierFreq,
carrierPhase, dragAlpha,
thf, thi, lam2, lam3,
)
for c in data:
print(c.real, c.imag)
return data
class Benchmark:
def __init__(self, num_samplings : int):
self.data_dir = "data"
self.num_samplings = num_samplings
self.params_dict = {}
self.gt_dict = {}
self.load_params()
self.load_gt()
def load_params(self):
for i in range(self.num_samplings):
file = os.path.join(self.data_dir, "aczgo_param_{}.log".format(i))
with open(file, 'r') as f:
lines = f.readlines()
params = {}
for line in lines:
key, value = line.split(", ")
if key=="length":
value = int(value)
else:
value = float(value)
params[key] = value
self.params_dict[i] = params
def eval(self, idx):
params = self.params_dict[idx]
amplitude = params["amplitude"]
length = params["length"]
carrierFreq = params["carrierFreq"]
carrierPhase = params["carrierPhase"]
dragAlpha = params["dragAlpha"]
thf = params["thf"]
thi = params["thi"]
lam2 = params["lam2"]
lam3 = params["lam3"]
data = aczwave(
amplitude, length, carrierFreq,
carrierPhase, dragAlpha,
thf, thi, lam2, lam3,
)
xs, ys = [], []
for c in data:
xs.append(c.real)
ys.append(c.imag)
return (xs, ys)
def load_gt(self):
for i in range(self.num_samplings):
file = os.path.join(self.data_dir, "aczgo_result_{}.log".format(i))
xs, ys = [], []
with open(file, 'r') as f:
lines = f.readlines()
for line in lines:
x, y = line.split(", ")
x, y = float(x), float(y)
xs.append(x)
ys.append(y)
self.gt_dict[i] = (xs, ys)
def test(self, idx):
def check_valid(vs):
return all(map(lambda x:not np.isnan(x) and not np.isinf(x), vs))
def max_ab_dis(xs, bxs):
return np.abs(np.array(bxs) - np.array(xs)).max()
(bxs, bys) = self.gt_dict[idx]
if check_valid(bxs) and check_valid(bys):
xs, ys = self.eval(idx)
return (max_ab_dis(xs, bxs), max_ab_dis(ys, bys))
else:
return "not valid"
def test_all(self):
for i in range(self.num_samplings):
print(self.test(i))
if __name__ == "__main__":
b = Benchmark(11)
print(b.test_all())
# data = test()
#
# np.savetxt('D:/Work/TailCorr/acz_750.csv', data, delimiter=' ')
# plt.figure()
# plt.plot(data)
# plt.show()

View File

@ -0,0 +1,75 @@
import numpy as np
from scipy.special import erf
def flattop(A, edge, length, fsn):
'''
生成平顶包络函数 (Python版本)
Parameters:
-----------
A : float
幅度
edge : float
边沿时间参数
length : int
长度采样点数
fsn : float
采样频率
Returns:
--------
numpy.ndarray
平顶包络波形
'''
Ts = 0
r_sigma = 0.21230
T = length / fsn
t = np.arange(0, length + 2) / fsn
mu = 0.5 * edge
sigma = r_sigma * (edge - 1)
p = T - 1 - edge
x1 = (t - mu - Ts) / (np.sqrt(2) * sigma)
x2 = (t - mu - p + Ts) / (np.sqrt(2) * sigma)
f = A / 2 * (erf(x1) - erf(x2))
# f_padded = np.pad(f, (1, 1), mode='constant', constant_values=0)
return f
"""
# 使用示例
if __name__ == "__main__":
# 测试参数
A = 1.0 # 幅度
edge = 0.1 # 边沿时间
length = 1000 # 长度
fsn = 10000 # 采样频率
# 生成平顶包络
envelope = flattop(A, edge, length, fsn)
print(f"生成的包络长度: {len(envelope)}")
print(f"最大值: {np.max(envelope):.6f}")
print(f"最小值: {np.min(envelope):.6f}")
# 可选:绘图显示
try:
import matplotlib.pyplot as plt
plt.figure(figsize=(10, 6))
time_axis = np.arange(len(envelope)) / fsn
plt.plot(time_axis, envelope, 'b-', linewidth=2)
plt.xlabel('时间 (s)')
plt.ylabel('幅度')
plt.title('平顶包络波形')
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
except ImportError:
print("matplotlib 未安装,跳过绘图")
"""

View File

@ -0,0 +1,150 @@
{
"channel": 3,
"chip_mode": "AWG",
"mode": "nco",
"tail_en": false,
"tc_coef_set": "coef3",
"inner_sync": false,
"amp_mod_enable": true,
"freq_mod_enable": true,
"bias_enable": true,
"fcw": [
400,
200,
300,
400
],
"mcu_reg_clr": true,
"pcw": [
0,
30,
45,
90,
120,
135,
150,
180
],
"rz_ff_pha": 0,
"rz_fm_pha": 45,
"ff_amp": [
32767,
32767,
32767,
32767
],
"fm_amp": [
32767,
32767,
32767,
32767
],
"bias": [
1,
2,
3,
4
],
"fm_en": false,
"instr_type": "general_send_wait",
"send_interval": [
100,
150,
200,
250,
300,
350,
400,
450,
500
],
"cycle_num": 1,
"codeword_configs": [
{
"wave_hold": 0,
"fcw_index": 0,
"pcw_index": 0,
"code_clr": 1,
"env_index": 4
},
{
"wave_hold": 0,
"fcw_index": 0,
"pcw_index": 0,
"code_clr": 1,
"env_index": 5
},
{
"wave_hold": 0,
"fcw_index": 0,
"pcw_index": 0,
"code_clr": 1,
"env_index": 6
},
{
"wave_hold": 0,
"fcw_index": 0,
"pcw_index": 0,
"code_clr": 1,
"env_index": 7
},
{
"wave_hold": 0,
"fcw_index": 0,
"pcw_index": 0,
"code_clr": 1,
"env_index": 8
}
],
"sweep_config": {
"sweep_num": 0,
"offsets": [
120,
64
],
"steps": [
3000,
143165576
]
},
"envelope_configs": [
{
"envelope_type": "rect_hold",
"amp": 32767
},
{
"envelope_type": "flattop_hold",
"amp": 32767,
"edge_time": 3.5,
"wave_time": 30
},
{
"envelope_type": "acz",
"amp": 32767,
"wave_time": 48
},
{
"envelope_type": "accz",
"wave_time": 48
},
{
"envelope_type": "cosine",
"amp": 32767,
"wave_time": 300
},
{
"envelope_type": "rect",
"amp": 32767,
"wave_time": 12
},
{
"envelope_type": "flattop",
"amp": 32767,
"edge_time": 2,
"wave_time": 22
}
],
"FolderName": "General",
"CaseName": "env2",
"config_file": "D:\\MyDocument\\工作\\Z芯片的case生成器\\4ch-Z_Generator\\gen_cases\\General\\env2_HEX.txt"
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,49 @@
{
"channel": 3,
"chip_mode": "RAMP",
"ramp_ctrl": "MCU",
"instr_type": "ramp_fixed",
"fixed_value": [
32768,
32769,
32770,
32772,
32776,
32784,
32800,
32832,
32896,
33024,
33280,
33792,
34816,
36864,
40960,
49152,
0
],
"wait_clk": [
1000,
1000,
1000,
1000,
1000,
1000,
1000,
1000,
1000,
1000,
1000,
1000,
1000,
1000,
1000,
1000,
1000
],
"config_param_num": 17,
"ensemble_num": 0,
"FolderName": "RAMP",
"CaseName": "RAMP_MCU_FIXED",
"config_file": "D:\\MyDocument\\工作\\Z芯片的case生成器\\4ch-Z_Generator\\gen_cases\\RAMP\\RAMP_MCU_FIXED_HEX.txt"
}

View File

@ -0,0 +1,316 @@
00300108
00100004
00000008
00300124
00100004
40000000
002000dc
00100094
80000000
00000000
00000011
80008000
000003e8
80018000
000003e8
80028000
000003e8
80048000
000003e8
80088000
000003e8
80108000
000003e8
80208000
000003e8
80408000
000003e8
80808000
000003e8
81008000
000003e8
82008000
000003e8
84008000
000003e8
88008000
000003e8
90008000
000003e8
a0008000
000003e8
c0008000
000003e8
00008000
000003e8
00100000
00100060
001000b7
00200137
0dc0af83
0df12223
00800193
0e00a203
fff20213
00008313
0e40a283
fff28293
0e832f83
0ec32f03
0bf12c23
00330333
00029463
00c0006f
fe8f000b
fe1ff06f
fdcf000b
fc0216e3
00f0000b
0a012c23
0c012223
0000002b
00500000
00100004
00000000
00900108
00100004
00000008
00900124
00100004
40000000
008000dc
00100094
80000000
00000000
00000011
80008000
000003e8
80018000
000003e8
80028000
000003e8
80048000
000003e8
80088000
000003e8
80108000
000003e8
80208000
000003e8
80408000
000003e8
80808000
000003e8
81008000
000003e8
82008000
000003e8
84008000
000003e8
88008000
000003e8
90008000
000003e8
a0008000
000003e8
c0008000
000003e8
00008000
000003e8
00700000
00100060
001000b7
00200137
0dc0af83
0df12223
00800193
0e00a203
fff20213
00008313
0e40a283
fff28293
0e832f83
0ec32f03
0bf12c23
00330333
00029463
00c0006f
fe8f000b
fe1ff06f
fdcf000b
fc0216e3
00f0000b
0a012c23
0c012223
0000002b
00b00000
00100004
00000000
00f00108
00100004
00000008
00f00124
00100004
40000000
00e000dc
00100094
80000000
00000000
00000011
80008000
000003e8
80018000
000003e8
80028000
000003e8
80048000
000003e8
80088000
000003e8
80108000
000003e8
80208000
000003e8
80408000
000003e8
80808000
000003e8
81008000
000003e8
82008000
000003e8
84008000
000003e8
88008000
000003e8
90008000
000003e8
a0008000
000003e8
c0008000
000003e8
00008000
000003e8
00d00000
00100060
001000b7
00200137
0dc0af83
0df12223
00800193
0e00a203
fff20213
00008313
0e40a283
fff28293
0e832f83
0ec32f03
0bf12c23
00330333
00029463
00c0006f
fe8f000b
fe1ff06f
fdcf000b
fc0216e3
00f0000b
0a012c23
0c012223
0000002b
01100000
00100004
00000000
01500108
00100004
00000008
01500124
00100004
40000000
014000dc
00100094
80000000
00000000
00000011
80008000
000003e8
80018000
000003e8
80028000
000003e8
80048000
000003e8
80088000
000003e8
80108000
000003e8
80208000
000003e8
80408000
000003e8
80808000
000003e8
81008000
000003e8
82008000
000003e8
84008000
000003e8
88008000
000003e8
90008000
000003e8
a0008000
000003e8
c0008000
000003e8
00008000
000003e8
01300000
00100060
001000b7
00200137
0dc0af83
0df12223
00800193
0e00a203
fff20213
00008313
0e40a283
fff28293
0e832f83
0ec32f03
0bf12c23
00330333
00029463
00c0006f
fe8f000b
fe1ff06f
fdcf000b
fc0216e3
00f0000b
0a012c23
0c012223
0000002b
01700000
00100004
00000000

View File

@ -0,0 +1,93 @@
from ctypes import Union
import numpy as np
import random
class make_case(object):
def __init__(
self
):
self = 0
def data_gen(
self,
mode = 'random',
length = 1,
params = {}
):
match mode:
case 'random':
data = [random.randint(0,2**32) for _ in range(length)]
case 'ones':
data = (2**32-1)*np.ones(length)
case 'amp':
amp = params['amp']
amp = int(amp,0) if isinstance(amp, str) else int(amp)
data = amp*np.ones(length)
case 'zeros':
data = np.zeros(length)
case 'value':
value = params['value']
if np.size(value) != length:
print("Warnning: Length Mismatch")
elif length ==1:
data = int(value,0) if isinstance(value, str) else int(value)
else:
data = np.zeros(length)
for i in range(0,length):
data[i] = int(value[i],0) if isinstance(value[i], str) else int(value[i])
case 'acc':
ini_data = params['ini_data']
ini_data = int(ini_data,0) if isinstance(ini_data, str) else int(ini_data)
step_size = params['step_size']
step_size = int(step_size,0) if isinstance(step_size, str) else int(step_size)
data = np.zeros(length)
for i in range(0,length):
data[i] = ini_data + i*step_size
case 'rd_file':
file_name = params['file_name']
with open(file_name, "r") as f:
data_bin = f.read()
data_bin = data_bin.split('\n')
data = []
for d in data_bin:
data.append((int(d,2)))
return data
def rw_once(
self,
op = 'w',
addr = 0x1F00044,
data = [0],
file_name = 'case.txt',
chip_id = 0,
exaddr = 1,
ard_flag = 0
):
with open(file_name, "a") as f:
cmd = 1 if (op=='r') or (op==1) else 0
if isinstance(addr, str):
addr = int(addr,0)
else:
addr = int(addr)
f.write(f"{((int(cmd)<<31) | (int(ard_flag)<<30) | (int(chip_id)<<25) | (addr)):08x}\n")
f.write(f"{((int(exaddr)<<20) | (int(np.size(data)*4))):08x}\n")
if op == 'w':
if np.size(data) == 1:
if isinstance(data, str):
dt = int(data,0)
else:
dt = int(np.round(data))
f.write(f"{(dt if dt>=0 else 2**32+dt):08x}\n")
else:
for i in range(0,np.size(data)):
if isinstance(data[i], str):
dt = int(data[i],0)
else:
dt = int(np.round(data[i]))
f.write(f"{(dt if dt>=0 else 2**32+dt):08x}\n")
f.write('\n')

View File

@ -0,0 +1,319 @@
import numpy as np
class make_inst(object):
def parse_instruction(self, instruction, labels, pc):
# 去掉所有逗号
instruction = instruction.replace(',', ' ')
parts = instruction.split()
opcode = parts[0].upper().strip()
if opcode.endswith(':'):
# 处理标签
label_name = opcode[:-1]
labels[label_name] = pc
return None
operands = [op.strip() for op in parts[1:]]
def parse_immediate(imm_str):
try:
if imm_str.startswith('0x') or imm_str.startswith('0X'):
return int(imm_str, 16)
elif imm_str.startswith('0b') or imm_str.startswith('0B'):
return int(imm_str, 2)
elif imm_str.startswith('-0x') or imm_str.startswith('-0X'):
return -int(imm_str[1:], 16)
elif imm_str.startswith('-0b') or imm_str.startswith('-0B'):
return -int(imm_str[1:], 2)
elif imm_str.startswith('-'):
return -int(imm_str[1:], 10)
else:
return int(imm_str, 10)
except ValueError:
raise ValueError(f"Invalid immediate value: {imm_str}")
if opcode == 'LUI':
rd, imm = operands
rd = int(rd[1:]) # 去掉寄存器名称前的 'x'
imm = parse_immediate(imm)
return format((self.opcode_map[opcode]) | (imm & 0xFFFFF) << 12 | (rd << 7), '032b')
elif opcode == 'AUIPC':
rd, imm = operands
rd = int(rd[1:]) # 去掉寄存器名称前的 'x'
imm = parse_immediate(imm)
return format((self.opcode_map[opcode]) | (imm & 0xFFFFF) << 12 | (rd << 7), '032b')
elif opcode == 'JAL':
rd, label_or_imm = operands
rd = int(rd[1:]) # 去掉寄存器名称前的 'x'
if label_or_imm.lstrip('-').isdigit() or label_or_imm.startswith(('0x', '0X', '0b', '0B', '-0x', '-0X', '-0b', '-0B')):
imm = parse_immediate(label_or_imm)
else:
imm = labels.get(label_or_imm.upper().strip(), 0) - pc
imm_bits = (((imm >> 20) & 0x1) << 19) | (((imm >> 1) & 0x3FF) << 9) | (((imm >> 11) & 0x1) << 8) | ((imm >> 12) & 0xFF)
return format((self.opcode_map[opcode]) | (imm_bits) << 12 | (rd << 7), '032b')
elif opcode == 'JALR':
rd = operands[0]
operands[1] = operands[1].rstrip(')')
imm, rs1 = operands[1].split('(')
rd = int(rd[1:]) # 去掉寄存器名称前的 'x'
rs1 = int(rs1[1:]) # 去掉寄存器名称前的 'x'
imm = parse_immediate(imm)
funct3 = self.opcode_funct3_map[opcode]
return format((self.opcode_map[opcode]) | (imm & 0xFFF) << 20 | (rs1 << 15) | (funct3 << 12) | (rd << 7), '032b')
elif opcode in ['BEQ', 'BNE', 'BLT', 'BGE', 'BLTU', 'BGEU']:
rs1, rs2, label_or_imm = operands
rs1 = int(rs1[1:]) # 去掉寄存器名称前的 'x'
rs2 = int(rs2[1:]) # 去掉寄存器名称前的 'x'
if label_or_imm.lstrip('-').isdigit() or label_or_imm.startswith(('0x', '0X', '0b', '0B', '-0x', '-0X', '-0b', '-0B')):
imm = parse_immediate(label_or_imm)
else:
imm = labels.get(label_or_imm.upper().strip(), 0) - pc
imm_high_bits = (((imm >> 12) & 0x1) << 6) | (((imm >> 5 ) & 0x3F))
imm_low_bits = (((imm >> 1 ) & 0xF) << 1) | (((imm >> 11) & 0x1 ))
funct3 = self.opcode_funct3_map[opcode]
return format((self.opcode_map[opcode]) | (imm_high_bits << 25) | (rs2 << 20) | (rs1 << 15) | (funct3 << 12) | (imm_low_bits << 7), '032b')
elif opcode in ['LB', 'LH', 'LW', 'LBU', 'LHU']:
rd = operands[0]
operands[1] = operands[1].rstrip(')')
imm, rs1 = operands[1].split('(')
rd = int(rd[1:]) # 去掉寄存器名称前的 'x'
rs1 = int(rs1[1:]) # 去掉寄存器名称前的 'x'
imm = parse_immediate(imm)
funct3 = self.opcode_funct3_map[opcode]
return format((self.opcode_map[opcode]) | ((imm & 0xFFF) << 20) | (rs1 << 15) | (funct3 << 12) | (rd << 7), '032b')
elif opcode in ['SB', 'SH', 'SW']:
rs2 = operands[0]
operands[1] = operands[1].rstrip(')')
imm, rs1 = operands[1].split('(')
rs2 = int(rs2[1:]) # 去掉寄存器名称前的 'x'
rs1 = int(rs1[1:]) # 去掉寄存器名称前的 'x'
imm = parse_immediate(imm)
funct3 = self.opcode_funct3_map[opcode]
return format((self.opcode_map[opcode]) | (((imm >> 5) & 0x7F) << 25) | (rs2 << 20) | (rs1 << 15) | (funct3 << 12) | ((imm & 0x1F) << 7), '032b')
elif opcode in ['ADDI', 'SLTI', 'SLTIU', 'XORI', 'ORI', 'ANDI']:
rd, rs1, imm = operands
rd = int(rd[1:]) # 去掉寄存器名称前的 'x'
rs1 = int(rs1[1:]) # 去掉寄存器名称前的 'x'
imm = parse_immediate(imm)
funct3 = self.opcode_funct3_map[opcode]
return format((self.opcode_map[opcode]) | ((imm & 0xFFF) << 20) | (rs1 << 15) | (funct3 << 12) | (rd << 7), '032b')
elif opcode in ['SLLI', 'SRLI', 'SRAI']:
rd, rs1, shamt = operands
rd = int(rd[1:]) # 去掉寄存器名称前的 'x'
rs1 = int(rs1[1:]) # 去掉寄存器名称前的 'x'
shamt = parse_immediate(shamt)
funct3 = self.opcode_funct3_map[opcode]
funct7 = self.opcode_funct7_map[opcode]
return format((self.opcode_map[opcode]) | (funct7 << 25) | ((shamt & 0x1F) << 20) | (rs1 << 15) | (funct3 << 12) | (rd << 7), '032b')
elif opcode in ['ADD', 'SUB', 'SLL', 'SLT', 'SLTU', 'XOR', 'SRL', 'SRA', 'OR', 'AND']:
rd, rs1, rs2 = operands
rd = int(rd[1:]) # 去掉寄存器名称前的 'x'
rs1 = int(rs1[1:]) # 去掉寄存器名称前的 'x'
rs2 = int(rs2[1:]) # 去掉寄存器名称前的 'x'
funct3 = self.opcode_funct3_map[opcode]
funct7 = self.opcode_funct7_map[opcode]
return format((self.opcode_map[opcode]) | (funct7 << 25) | (rs2 << 20) | (rs1 << 15) | (funct3 << 12) | (rd << 7), '032b')
elif opcode in ['WAIT', 'SEND', 'SENDC']:
rd, rs1, imm = operands
rd = int(rd[1:]) # 去掉寄存器名称前的 'x'
rs1 = int(rs1[1:]) # 去掉寄存器名称前的 'x'
imm = parse_immediate(imm)
funct3 = self.opcode_funct3_map[opcode]
return format((self.opcode_map[opcode]) | ((imm & 0xFFF) << 20) | (rs1 << 15) | (funct3 << 12) | (rd << 7), '032b')
elif opcode in ['EXIT']:
return format((self.opcode_map[opcode]), '032b')
elif opcode in ['EXIT_IR']:
return '00000000000000000001000000101011'
else:
raise ValueError(f"Unsupported opcode: {opcode}")
def write(self, instructions, file_name, exaddr = 1, chip_id = 0, channel_id = 0, pc_start = 0, ard_flag = 0, show = False):
if instructions == "":
pass
else:
labels = {}
binary_instructions = []
# 将整段汇编代码拆成多条指令组成的字符串数组
inst_list = instructions.split('\n')
instructions = []
for this_inst in inst_list:
this_inst = this_inst.split('#')
if this_inst[0].strip() != '':
instructions.append(this_inst[0].strip())
# 第一遍扫描:记录标签位置
pc = pc_start
for instr in instructions:
binary = self.parse_instruction(instr, labels, pc)
if binary is not None:
binary_instructions.append(binary)
pc += 4
else:
# 如果是标签不增加pc
pass
# 第二遍扫描:生成最终的二进制代码
pc = pc_start
final_binary_instructions = []
for instr in instructions:
binary = self.parse_instruction(instr, labels, pc)
if binary is not None:
final_binary_instructions.append(binary)
if show:
print(f"{instr}: {binary}")
pc += 4
else:
# 如果是标签不增加pc
pass
with open(file_name, "a") as f:
base_addr = 0x010_0000 + pc_start + channel_id * 0x060_0000
length = np.size(final_binary_instructions)
f.write(f"{((ard_flag << 30) | (chip_id << 25) | (base_addr)):08x}\n")
f.write(f"{((exaddr << 20) | (length<<2)):08x}\n")
for binary_instr in final_binary_instructions:
f.write(f"{int(binary_instr,2):08x}\n")
f.write("\n")
return final_binary_instructions
opcode_map = {
'LUI': 0x37,
'AUIPC': 0x17,
'JAL': 0x6F,
'JALR': 0x67,
'BEQ': 0x63,
'BNE': 0x63,
'BLT': 0x63,
'BGE': 0x63,
'BLTU': 0x63,
'BGEU': 0x63,
'LB': 0x03,
'LH': 0x03,
'LW': 0x03,
'LBU': 0x03,
'LHU': 0x03,
'SB': 0x23,
'SH': 0x23,
'SW': 0x23,
'ADDI': 0x13,
'SLTI': 0x13,
'SLTIU': 0x13,
'XORI': 0x13,
'ORI': 0x13,
'ANDI': 0x13,
'SLLI': 0x13,
'SRLI': 0x13,
'SRAI': 0x13,
'ADD': 0x33,
'SUB': 0x33,
'SLL': 0x33,
'SLT': 0x33,
'SLTU': 0x33,
'XOR': 0x33,
'SRL': 0x33,
'SRA': 0x33,
'OR': 0x33,
'AND': 0x33,
'WAIT': 0x0B,
'SEND': 0x0B,
'SENDC': 0x0B,
'EXIT': 0x2B,
}
opcode_funct3_map = {
'JALR': 0x0,
'BEQ': 0x0,
'BNE': 0x1,
'BLT': 0x4,
'BGE': 0x5,
'BLTU': 0x6,
'BGEU': 0x7,
'LB': 0x0,
'LH': 0x1,
'LW': 0x2,
'LBU': 0x4,
'LHU': 0x5,
'SB': 0x0,
'SH': 0x1,
'SW': 0x2,
'ADDI': 0x0,
'SLTI': 0x2,
'SLTIU': 0x3,
'XORI': 0x4,
'ORI': 0x6,
'ANDI': 0x7,
'SLLI': 0x1,
'SRLI': 0x5,
'SRAI': 0x5,
'ADD': 0x0,
'SUB': 0x0,
'SLL': 0x1,
'SLT': 0x2,
'SLTU': 0x3,
'XOR': 0x4,
'SRL': 0x5,
'SRA': 0x5,
'OR': 0x6,
'AND': 0x7,
'WAIT': 0x0,
'SEND': 0x2,
'SENDC': 0x3,
'EXIT': 0x0,
}
opcode_funct7_map = {
'JALR': 0x00,
'BEQ': 0x00,
'BNE': 0x00,
'BLT': 0x00,
'BGE': 0x00,
'BLTU': 0x00,
'BGEU': 0x00,
'LB': 0x00,
'LH': 0x00,
'LW': 0x00,
'LBU': 0x00,
'LHU': 0x00,
'SB': 0x00,
'SH': 0x00,
'SW': 0x00,
'ADDI': 0x00,
'SLTI': 0x00,
'SLTIU': 0x00,
'XORI': 0x00,
'ORI': 0x00,
'ANDI': 0x00,
'SLLI': 0x00,
'SRLI': 0x00,
'SRAI': 0x20,
'ADD': 0x00,
'SUB': 0x20,
'SLL': 0x00,
'SLT': 0x00,
'SLTU': 0x00,
'XOR': 0x00,
'SRL': 0x00,
'SRA': 0x20,
'OR': 0x00,
'AND': 0x00,
'WAIT': 0x00,
'SEND': 0x00,
'SENDC': 0x00,
'EXIT': 0x00,
}

View File

@ -314,7 +314,7 @@ class ZChipConfig(object):
self.write_register(moddotr_addr, moddotr_val)
#调制使能寄存器300104配置开始
amp_mod_enable = kwargs.pop('amp_mod_enSable', False)
amp_mod_enable = kwargs.pop('amp_mod_enable', False)
freq_mod_enable = kwargs.pop('freq_mod_enable', False)
bias_enable = kwargs.pop('bias_enable', False)
# 低电平使能逻辑True(开启) -> 0False(关闭) -> 1

View File

@ -1,7 +1,7 @@
{
"chip_mode": "AWG",
"mode": "env",
"tail_en": true,
"mode": "nco",
"tail_en": false,
"tc_coef_set": "coef3",
"inner_sync": true,
"amp_mod_enable": true,

View File

@ -1,77 +1,10 @@
00301000
00100080
0347a17d
0124e4fe
00068de1
1fab1c0c
00000000
00000000
00000000
00000000
00000000
019010e7
ffffff71
00000000
00000000
00000000
00000000
00000000
7fd3383d
7fef7953
7ff92a57
7d5c6533
80000000
80000000
80000000
80000000
00000000
ffdb1444
ffea27a5
00000000
00000000
00000000
00000000
00000000
0030108c
00100004
00000001
0030108c
00100004
00000002
0030108c
00100004
00000004
0030108c
00100004
00000008
0030108c
00100004
00000010
0030108c
00100004
00000020
0030108c
00100004
00000040
0030108c
00100004
00000080
00300108
00100004
00000000
00000006
00300104
00100004
00000004
00000000
00200040
00100058

View File

@ -6,8 +6,8 @@
"metadata": {
"collapsed": true,
"ExecuteTime": {
"end_time": "2026-07-27T07:02:43.526779Z",
"start_time": "2026-07-27T07:02:40.289259Z"
"end_time": "2026-07-28T01:22:28.958603Z",
"start_time": "2026-07-28T01:22:28.252034Z"
}
},
"source": [
@ -134,15 +134,15 @@
{
"metadata": {
"ExecuteTime": {
"end_time": "2026-07-20T07:18:13.898053Z",
"start_time": "2026-07-20T07:18:13.810352Z"
"end_time": "2026-07-27T07:06:09.129502Z",
"start_time": "2026-07-27T07:06:08.999951Z"
}
},
"cell_type": "code",
"source": [
"# load params\n",
"# 1. 指定要加载的 JSON 文件完整路径\n",
"json_file_path = r'D:\\MyDocument\\工作\\Z芯片的case生成器\\四通道\\4ChannelZ_case_Generator\\gen_cases\\General\\env.json'\n",
"json_file_path = r'D:\\MyDocument\\工作\\Z芯片的case生成器\\Chip_Case_Generator\\Z_case_Generator_V2.0\\gen_cases\\General\\env.json'\n",
"\n",
"json_path = Path(json_file_path)\n",
"load_dir = json_path.parent # 获取目录\n",
@ -153,20 +153,31 @@
"params = pm_load.load(case_name)\n",
"\n",
"# 3. 自定义你的新输出路径 \n",
"custom_output_dir = r'D:\\MyDocument\\工作\\Z芯片的case生成器\\四通道\\4ChannelZ_case_Generator\\gen_cases\\General\\Custom_Output'\n",
"custom_output_dir = r'D:\\MyDocument\\工作\\Z芯片的case生成器\\Chip_Case_Generator\\Z_case_Generator_V2.0\\gen_cases\\General\\Custom_Output'\n",
"\n",
"# 4. 运行 run_case传入自定义输出路径\n",
"run_case(params, output_dir=custom_output_dir, save_json=True)"
],
"id": "dd0c2d05a0afc9b6",
"outputs": [],
"execution_count": 103
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"执行 config_chip_reg\n",
"执行了 env_config\n",
"执行了 instruction_config\n",
"生成文件路径D:\\MyDocument\\工作\\Z芯片的case生成器\\Chip_Case_Generator\\Z_case_Generator_V2.0\\gen_cases\\General\\Custom_Output\\env_HEX.txt\n"
]
}
],
"execution_count": 3
},
{
"metadata": {
"ExecuteTime": {
"end_time": "2026-07-27T07:03:03.234232Z",
"start_time": "2026-07-27T07:03:03.117436Z"
"end_time": "2026-07-28T02:13:35.712324Z",
"start_time": "2026-07-28T02:13:35.563143Z"
}
},
"cell_type": "code",
@ -175,8 +186,8 @@
"# AWG通用模板\n",
"run_case({\n",
" 'chip_mode':'AWG', #分为AWG和RAMP模式\n",
" 'mode':'env', #可选nco nco_fm env mod四种模式\n",
" 'tail_en': True, #拖尾矫正开关\n",
" 'mode':'nco', #可选nco nco_fm env mod四种模式\n",
" 'tail_en': False, #拖尾矫正开关\n",
" 'tc_coef_set': 'coef3', #拖尾矫正打开生效\n",
" 'inner_sync': True, #内部触发,应该是软触发,写一个寄存器,就能触发\n",
" 'amp_mod_enable': True, #调幅的开关mod调制模式下起作用。\n",
@ -237,7 +248,7 @@
]
}
],
"execution_count": 2
"execution_count": 3
},
{
"metadata": {