【学习】symbiflow 构建 F4PGA excample 示例流程解析
前言
在执行新流程时,直接通过f4pga -vv build --flow ./flow.json
构建bitstream,通过不断调用封装好的模块实现bit流的生成,代码的可读性相对来说比较弱。
这篇文章主要阐述 F4PGA 依托 symbiflow 构建 bitstream.
修改 Makefile 文件
由于需要使用开源框架 symbiflow 进行构建,因此将 f4pga 注释掉
流程分析
参数准备
如上图所示, makefile 文件将读取命令行参数 target ,用来配置 XDC 路径 /home/f4pga/zhaoshuai/f4pga-examples/xc7/counter_test/arty.xdc ,之后加载common.mk。
在 common.mk 中(这里省略了参数解析等操作,只截了关键步骤),首先创建build目录,并执行symbiflow_synth -t ${TOP} ${SURELOG_OPT} -v ${SOURCES} -d ${BITSTREAM_DEVICE} -p ${PARTNAME} ${XDC_CMD}
语句
synth 阶段
- synth
首先进入 f4pga\wrappers\sh\__init__.py
模块中,执行 synth
模块
其输入参数为
[
'/opt/f4pga/xc7/conda/envs/xc7/bin/symbiflow_synth',
'-t',
'top',
'-v',
'/f4pga-examples/xc7/counter_test/counter.v',
'-d',
'artix7',
'-p',
'xc7a35tcsg324-1',
'-x',
'/f4pga-examples/xc7/counter_test/arty.xdc'
]
更新部分环境变量
{
"F4PGA_SHARE_DIR": "f4pga/xc7/share/f4pga",
"UTILS_PATH": "opt/f4pga/xc7/share/f4pga/scripts",
"TECHMAP_PATH": "opt/f4pga/xc7/share/f4pga/techmaps/xc7_vpr/techmap"
}
- p_run_sh_script
刷新输出缓冲区,将中间信息直接打印控制台,不等程序运行结束再输出。
之后通过 check_call 执行 synth.f4pga.sh ,该指令由 [str(script)] + sys_argv[1:]
拼接而成。
f4pga/wrappers/sh/xc7/synth.f4pga.sh -t top -v f4pga-examples/xc7/counter_test/counter.v -d artix7 -p xc7a35tcsg324-1 -x f4pga-examples/xc7/counter_test/arty.xdc'
- synth.f4pga.sh
这是一个 shell 文件,其主要作用解析传入参数,检查是否包含verilog文件,再执行yosys。(其中调用了f4pga/wrappers/tcl/__main__.py
得到 xc7.f4pga.tcl
的绝对路径)
其传入参数为:
-t top -v f4pga-examples/xc7/counter_test/counter.v -d artix7 -p xc7a35tcsg324-1 -x f4pga-examples/xc7/counter_test/arty.xdc
最终拼接为 yosys 命令
yosys -p ; tcl f4pga/wrappers/tcl/xc7.f4pga.tcl -l top_synth.log f4pga-examples/xc7/counter_test/counter.v
- yosys 阶段
通过上述命令后,执行 yosys。
该阶段共54个步骤,最后以54. Executing BLIF backend.
结束
最后将在 f4pga-examples/xc7/counter_test/build/arty_35/
路径生成 top.eblif
文件 .
pack 阶段
完成逻辑层级电路的描述后,执行pack阶段。
入口为 f4pga\wrappers\sh\__init__.py
的 pack
函数
首先通过 p_vpr_env_from_args
方法更新环境变量(仅列举部分,这期间调用了p_parse_vpr_args_quicklogic
,p_parse_vpr_args
等方法)
{
"CONDA_PROMPT_MODIFIER": "(xc7) ",
"XDG_SESSION_TYPE": "x11",
"SSH_AGENT_PID": "1675",
"TARGET": "arty_35",
"SHLVL": "0",
"CONDA_SHLVL": "2",
"MANAGERPID": "1504",
"LC_MONETARY": "zh_CN.UTF-8",
"DBUS_SESSION_BUS_ADDRESS": "unix:path=/run/user/1000/bus",
"MAKEFLAGS": "w",
"COLORTERM": "truecolor",
"TERM": "xterm-256color",
"GNOME_DESKTOP_SESSION_ID": "this-is-deprecated",
"GNOME_TERMINAL_SCREEN": "/org/gnome/Terminal/screen/3018b811_51f8_49ba_88f0_d519d9ff9139",
"LC_ADDRESS": "zh_CN.UTF-8",
"MAKELEVEL": "1",
"DISPLAY": ":0",
"LC_TELEPHONE": "zh_CN.UTF-8",
"LANG": "en_US.UTF-8",
"XAUTHORITY": "/run/user/1000/gdm/Xauthority",
"XMODIFIERS": "@im=ibus",
"GNOME_TERMINAL_SERVICE": ":1.118",
"QT_ACCESSIBILITY": "1",
"CONDA_DEFAULT_ENV": "xc7",
"LC_MEASUREMENT": "zh_CN.UTF-8",
"GPG_AGENT_INFO": "/run/user/1000/gnupg/S.gpg-agent:0:1",
"GJS_DEBUG_OUTPUT": "stderr",
"LC_IDENTIFICATION": "zh_CN.UTF-8",
"QT_IM_MODULE": "ibus",
"XDG_CONFIG_DIRS": "/etc/xdg/xdg-ubuntu:/etc/xdg",
"XDG_DATA_DIRS": "/usr/share/ubuntu:/usr/local/share/:/usr/share/:/var/lib/snapd/desktop",
"VTE_VERSION": "6003",
"DEVICE": "xc7a50t_test",
"DEVICE_NAME": "xc7a50t-test",
"EBLIF": "top.eblif",
"ARCH_DIR": "/home/f4pga/opt/f4pga/xc7/share/f4pga/arch/xc7a50t_test",
"ARCH_DEF": "/home/f4pga/opt/f4pga/xc7/share/f4pga/arch/xc7a50t_test/arch.timing.xml",
"RR_GRAPH": "/home/f4pga/opt/f4pga/xc7/share/f4pga/arch/xc7a50t_test/rr_graph_xc7a50t_test.rr_graph.real.bin",
"RR_GRAPH_XML": "/home/f4pga/opt/f4pga/xc7/share/f4pga/arch/xc7a50t_test/rr_graph_xc7a50t_test.rr_graph.real.xml",
"PLACE_DELAY": "/home/f4pga/opt/f4pga/xc7/share/f4pga/arch/xc7a50t_test/rr_graph_xc7a50t_test.place_delay.bin",
"LOOKAHEAD": "/home/f4pga/opt/f4pga/xc7/share/f4pga/arch/xc7a50t_test/rr_graph_xc7a50t_test.lookahead.bin",
"OUT_NOISY_WARNINGS": "noisy_warnings-xc7a50t_test_pack.log"
}
之后在 p_vpr_run
中进行必要参数的校验
利用 check_call 对指令进行拼接,通过vpr执行以下命令
opt/f4pga/xc7/conda/envs/xc7/bin/vpr opt/f4pga/xc7/share/f4pga/arch/xc7a50t_test/arch.timing.xml top.eblif --max_router_iterations 500 --routing_failure_predictor off --router_high_fanout_threshold -1 --constant_net_method route --route_chan_width 500 --router_heap bucket --clock_modeling route --place_delta_delay_matrix_calculation_method dijkstra --place_delay_model delta --router_lookahead extended_map --check_route quick --strict_checks off --allow_dangling_combinational_nodes on --disable_errors check_unbuffered_edges:check_route --congested_routing_iteration_threshold 0.8 --incremental_reroute_delay_ripup off --base_cost_type delay_normalized_length_bounded --bb_factor 10 --acc_fac 0.7 --astar_fac 1.8 --initial_pres_fac 2.828 --pres_fac_mult 1.2 --check_rr_graph off --suppress_warnings noisy_warnings-xc7a50t_test_pack.log,sum_pin_class:check_unbuffered_edges:load_rr_indexed_data_T_values:check_rr_node:trans_per_R:check_route:set_rr_graph_tool_comment:calculate_average_switch --device xc7a50t-test --read_rr_graph opt/f4pga/xc7/share/f4pga/arch/xc7a50t_test/rr_graph_xc7a50t_test.rr_graph.real.bin --read_router_lookahead opt/f4pga/xc7/share/f4pga/arch/xc7a50t_test/rr_graph_xc7a50t_test.lookahead.bin --read_placement_delay_lookup opt/f4pga/xc7/share/f4pga/arch/xc7a50t_test/rr_graph_xc7a50t_test.place_delay.bin --pack
- vpr
VPR(Versatile Packing, Placement and Routing for FPGAs)是由加拿大多伦多大学 Jonathan Rose、 Vaughn Betz 教授等可编程芯片领域著名研究人员开发的一款用于FPGA架构开发探索以及架构参数和性能评估的CAD工具(这里的CAD工具指的是将高层次的电路描述,如VHDL、原理图等编译成用于配置FPGA可编程开关状态的编程下载文件)。作为一款开源的FPGA架构评估软件,VPR获得了可编程领域学术界最广泛的认可,并为FPGA架构研究提供了便利手段。为了普及FPGA架构的开发流程知识,提高FPGA设计开发水平。
执行过程中,需要读取架构文件:arch.timing.xml.
最后将在 f4pga-examples/xc7/counter_test/build/arty_35/
路径生成 top.net
文件 .
place 阶段
同样的,先在mk文件中拼接 shell 指令
cd f4pga-examples/xc7/counter_test/build/arty_35 && symbiflow_place -e top.eblif -d xc7a50t_test -n top.net -P xc7a35tcsg324-1 2>&1 > /dev/null
之后进入 f4pga\wrappers\sh\__init__.py
的 place
函数
根据参数拼接cmd(只能拼)
if [ -z $NET ]; then echo "Please provide net file name"; exit 1; fi
echo "Generating constrains ..."
python3 -m f4pga.wrappers.sh.generate_constraints $EBLIF $NET $PART $DEVICE $ARCH_DEF $PCF
VPR_PLACE_FILE='constraints.place'
python3 -m f4pga.wrappers.sh.vpr_run --fix_clusters "${VPR_PLACE_FILE}" --place
然后执行p_vpr_env_from_args
更新系统变量(仅列举部分)
{
"CONDA_PROMPT_MODIFIER": "(xc7) ",
"XDG_SESSION_TYPE": "x11",
"SSH_AGENT_PID": "1675",
"TARGET": "arty_35",
"DBUS_SESSION_BUS_ADDRESS": "unix:path=/run/user/1000/bus",
"COLORTERM": "truecolor",
"MAKE_TERMERR": "/dev/pts/0",
"JOURNAL_STREAM": "8:52672",
"_": "/home/f4pga/opt/f4pga/xc7/conda/envs/xc7/bin/make",
"http_proxy": "http://192.168.11.32:7890",
"TERM": "xterm-256color",
"GNOME_DESKTOP_SESSION_ID": "this-is-deprecated",
"_CE_CONDA": "",
"WINDOWPATH": "2",
"SESSION_MANAGER": "local/ubuntu:@/tmp/.ICE-unix/1721,unix/ubuntu:/tmp/.ICE-unix/1721",
"INVOCATION_ID": "26428b967d644e5485c04881052bedb9",
"XDG_RUNTIME_DIR": "/run/user/1000",
"XDG_MENU_PREFIX": "gnome-",
"GNOME_TERMINAL_SCREEN": "/org/gnome/Terminal/screen/3018b811_51f8_49ba_88f0_d519d9ff9139",
"LC_ADDRESS": "zh_CN.UTF-8",
"MAKELEVEL": "1",
"DISPLAY": ":0",
"XAUTHORITY": "/run/user/1000/gdm/Xauthority",
"XMODIFIERS": "@im=ibus",
"GNOME_TERMINAL_SERVICE": ":1.118",
"SSH_AUTH_SOCK": "/run/user/1000/keyring/ssh",
"SHELL": "/bin/bash",
"LC_NAME": "zh_CN.UTF-8",
"F4PGA_INSTALL_DIR": "/home/f4pga/opt/f4pga",
"GDMSESSION": "ubuntu",
"QT_ACCESSIBILITY": "1",
"LESSCLOSE": "/usr/bin/lesspipe %s %s",
"CONDA_DEFAULT_ENV": "xc7",
"LC_MEASUREMENT": "zh_CN.UTF-8",
"GPG_AGENT_INFO": "/run/user/1000/gnupg/S.gpg-agent:0:1",
"GJS_DEBUG_OUTPUT": "stderr",
"LC_IDENTIFICATION": "zh_CN.UTF-8",
"QT_IM_MODULE": "ibus",
"XDG_CONFIG_DIRS": "/etc/xdg/xdg-ubuntu:/etc/xdg",
"FPGA_FAM": "xc7",
"MFLAGS": "-w",
"LC_PAPER": "zh_CN.UTF-8",
"VTE_VERSION": "6003",
"DEVICE": "xc7a50t_test",
"DEVICE_NAME": "xc7a50t-test",
"EBLIF": "top.eblif",
"VPR_OPTIONS": "--max_router_iterations 500 --routing_failure_predictor off --router_high_fanout_threshold -1 --constant_net_method route --route_chan_width 500 --router_heap bucket --clock_modeling route --place_delta_delay_matrix_calculation_method dijkstra --place_delay_model delta --router_lookahead extended_map --check_route quick --strict_checks off --allow_dangling_combinational_nodes on --disable_errors check_unbuffered_edges:check_route --congested_routing_iteration_threshold 0.8 --incremental_reroute_delay_ripup off --base_cost_type delay_normalized_length_bounded --bb_factor 10 --acc_fac 0.7 --astar_fac 1.8 --initial_pres_fac 2.828 --pres_fac_mult 1.2 --check_rr_graph off --suppress_warnings noisy_warnings-xc7a50t_test_place.log,sum_pin_class:check_unbuffered_edges:load_rr_indexed_data_T_values:check_rr_node:trans_per_R:check_route:set_rr_graph_tool_comment:calculate_average_switch",
"ARCH_DIR": "opt/f4pga/xc7/share/f4pga/arch/xc7a50t_test",
"ARCH_DEF": "opt/f4pga/xc7/share/f4pga/arch/xc7a50t_test/arch.timing.xml",
"RR_GRAPH": "opt/f4pga/xc7/share/f4pga/arch/xc7a50t_test/rr_graph_xc7a50t_test.rr_graph.real.bin",
"RR_GRAPH_XML": "opt/f4pga/xc7/share/f4pga/arch/xc7a50t_test/rr_graph_xc7a50t_test.rr_graph.real.xml",
"PLACE_DELAY": "opt/f4pga/xc7/share/f4pga/arch/xc7a50t_test/rr_graph_xc7a50t_test.place_delay.bin",
"LOOKAHEAD": "opt/f4pga/xc7/share/f4pga/arch/xc7a50t_test/rr_graph_xc7a50t_test.lookahead.bin",
"NET": "top.net",
"PART": "xc7a35tcsg324-1",
"OUT_NOISY_WARNINGS": "noisy_warnings-xc7a50t_test_place.log"
}
之后通过 p_run_bash_cmds
方法刷新缓冲区并执行cmd
p_run_bash_cmds(place_cmds, env=p_vpr_env_from_args("place"))
对于cmd而言,其实仍旧是在拼接vpr的命令,最终的cmd与pack阶段的vpr指令大同小异(这里只标出不一样之处)
- 错误日志名称
- noisy_warnings-xc7a50t_test_place.log
- 指令末尾新增
- --fix_clusters constraints.place --place
之后对若干 PlacerOpts 的属性进行了定义
PlacerOpts.place_freq: PLACE_ONCE
PlacerOpts.place_algorithm: CRITICALITY_TIMING_PLACE
PlacerOpts.pad_loc_type: FREE
PlacerOpts.constraints_file: Using constraints file 'constraints.place'
PlacerOpts.place_cost_exp: 1.000000
PlacerOpts.place_chan_width: 500
PlacerOpts.inner_loop_recompute_divider: 0
PlacerOpts.recompute_crit_iter: 1
PlacerOpts.timing_tradeoff: 0.500000
PlacerOpts.td_place_exp_first: 1.000000
PlacerOpts.td_place_exp_last: 8.000000
PlacerOpts.delay_offset: 0.000000
PlacerOpts.delay_ramp_delta_threshold: -1
PlacerOpts.delay_ramp_slope: 0.000000
PlacerOpts.tsu_rel_margin: 1.000000
PlacerOpts.tsu_abs_margin: 0.000000
PlacerOpts.post_place_timing_report_file:
PlacerOpts.allowed_tiles_for_delay_model:
PlacerOpts.delay_model_reducer: MIN
PlacerOpts.delay_model_type: DELTA
PlacerOpts.rlim_escape_fraction: 0.000000
PlacerOpts.move_stats_file:
PlacerOpts.placement_saves_per_temperature: 0
PlacerOpts.effort_scaling: CIRCUIT
PlacerOpts.place_delta_delay_matrix_calculation_method: DIJKSTRA_EXPANSION
PlaceOpts.seed: 0
AnnealSched.type: AUTO_SCHED
AnnealSched.inner_num: 0.500000
然后读取约束文件 constrains.place 并初始化时序裕量直方图(slack histogram)
Reading constraints.place.
Successfully read constraints file constraints.place.
There are 109 point to point connections in this circuit.
Completed placement consistency check successfully.
Initial placement cost: 1 bb_cost: 4.65204 td_cost: 3.23777e-08
Initial placement estimated Critical Path Delay (CPD): 9.05158 ns
Initial placement estimated setup Total Negative Slack (sTNS): 0 ns
Initial placement estimated setup Worst Negative Slack (sWNS): 0 ns
Initial placement estimated setup slack histogram:
[ 9.5e-10: 1.6e-09) 2 ( 7.7%) |********************
[ 1.6e-09: 2.2e-09) 4 ( 15.4%) |***************************************
[ 2.2e-09: 2.8e-09) 1 ( 3.8%) |**********
[ 2.8e-09: 3.5e-09) 2 ( 7.7%) |********************
[ 3.5e-09: 4.1e-09) 3 ( 11.5%) |*****************************
[ 4.1e-09: 4.7e-09) 1 ( 3.8%) |**********
[ 4.7e-09: 5.3e-09) 5 ( 19.2%) |*************************************************
[ 5.3e-09: 6e-09) 4 ( 15.4%) |***************************************
[ 6e-09: 6.6e-09) 0 ( 0.0%) |
[ 6.6e-09: 7.2e-09) 4 ( 15.4%) |***************************************
Placement contains 1 placement macros involving 7 blocks (average macro size 7.000000)
完成布局一致性检查 Completed placement consistency check successfully.
放置时序裕量直方图 Placement estimated setup slack histogram
最终执行完毕vpr,生成 top.place
route 阶段
在mk文件中拼接 shell 指令
cd f4pga-examples/xc7/counter_test/build/arty_35 && symbiflow_route -e top.eblif -d xc7a50t_test 2>&1 > /dev/null
之后进入 f4pga\wrappers\sh\__init__.py
的 route
函数
之后是同样的拼接vpr指令,这里不再赘述了
指令大致相同
结尾没有:--fix_clusters constraints.place
结尾为:--route
RouterOpts
RouterOpts.route_type: DETAILED
RouterOpts.router_algorithm: TIMING_DRIVEN
RouterOpts.base_cost_type: DELAY_NORMALIZED_LENGTH_BOUNDED
RouterOpts.fixed_channel_width: 500
RouterOpts.check_route: QUICK
RouterOpts.acc_fac: 0.700000
RouterOpts.bb_factor: 10
RouterOpts.bend_cost: 0.000000
RouterOpts.first_iter_pres_fac: 0.000000
RouterOpts.initial_pres_fac: 2.828000
RouterOpts.pres_fac_mult: 1.200000
RouterOpts.max_router_iterations: 500
RouterOpts.min_incremental_reroute_fanout: 16
RouterOpts.do_check_rr_graph: false
RouterOpts.verify_binary_search: false
RouterOpts.min_channel_width_hint: 0
RouterOpts.read_rr_edge_metadata: false
RouterOpts.exit_after_first_routing_iteration: false
RouterOpts.astar_fac: 1.800000
RouterOpts.router_profiler_astar_fac: 1.200000
RouterOpts.criticality_exp: 1.000000
RouterOpts.max_criticality: 0.990000
RouterOpts.init_wirelength_abort_threshold: 0.850000
RouterOpts.save_routing_per_iteration: false
RouterOpts.congested_routing_iteration_threshold_frac: 0.800000
RouterOpts.high_fanout_threshold: -1
RouterOpts.router_debug_net: -2
RouterOpts.router_debug_sink_rr: -2
RouterOpts.router_debug_iteration: -2
RouterOpts.max_convergence_count: 1
RouterOpts.reconvergence_cpd_threshold: 0.990000
RouterOpts.update_lower_bound_delays: true
RouterOpts.first_iteration_timing_report_file:
RouterOpts.incr_reroute_delay_ripup: OFF
RouterOpts.route_bb_update: DYNAMIC
RouterOpts.lookahead_type: EXTENDED_MAP
RouterOpts.initial_timing: LOOKAHEAD
RouterOpts.router_heap: BUCKET_HEAP_APPROXIMATION
RouterOpts.routing_failure_predictor = OFF
RouterOpts.routing_budgets_algorithm = DISABLE
AnalysisOpts.gen_post_synthesis_netlist: false
AnalysisOpts.timing_report_npaths: 100
AnalysisOpts.timing_report_skew: false
AnalysisOpts.echo_dot_timing_graph_node: -1
AnalysisOpts.timing_report_detail: NETLIST
AnalysisOpts.post_synth_netlist_unconn_input_handling: UNCONNECTED
AnalysisOpts.post_synth_netlist_unconn_output_handling: UNCONNECTED
加载 top.place
# Routing
RR Graph Nodes: 2934684
RR Graph Edges: 22357697
初始化路由 Initializing router criticalities
完成路由一致性检测 Completed routing consistency check successfully.
fasm 阶段
在mk文件中拼接 shell 指令
cd f4pga-examples/xc7/counter_test/build/arty_35 && symbiflow_write_fasm -e top.eblif -d xc7a50t_test
之后进入 f4pga\wrappers\sh\__init__.py
的 write_fasm
函数
拼接cmd
'/home/f4pga/opt/f4pga/xc7/conda/envs/xc7/bin/genfasm' ${ARCH_DEF} ${EBLIF} --device ${DEVICE_NAME} ${VPR_OPTIONS} --read_rr_graph ${RR_GRAPH}
TOP="${EBLIF%.*}"
FASM_EXTRA="${TOP}_fasm_extra.fasm"
if [ -f $FASM_EXTRA ]; then
echo "writing final fasm (extra: $FASM_EXTRA)"
cat $FASM_EXTRA >> ${TOP}.fasm
fi
之后是同样的拼接vpr指令,指令大致相同
执行主体不是vpr:opt/f4pga/xc7/conda/envs/xc7/bin/genfasm
结尾没有:--read_router_lookahead和--read_placement_delay_lookup
增加了: --device xc7a50t-test
在执行genfasm时,之前的流程与route相仿,之后加载了 Routing
并生成了 top.fasm
bit 阶段
在mk文件中拼接 shell 指令
cd f4pga-examples/xc7/counter_test/build/arty_35 && symbiflow_write_bitstream -d artix7 -f top.fasm -p xc7a35tcsg324-1 -b top.bit
之后进入 f4pga\wrappers\sh\__init__.py
的 write_bitstream
函数
拼接cmd
set -e
echo "Writing bitstream ..."
FRM2BIT=""
if [ ! -z ${FRAMES2BIT} ]; then FRM2BIT="--frm2bit ${FRAMES2BIT}"; fi
eval set -- $(
getopt --options=d:f:b:p: --longoptions=device:,fasm:,bit:,part: --name $0 -- -d artix7 -f top.fasm -p xc7a35tcsg324-1 -b top.bit
)
DEVICE=""
FASM=""
BIT=""
PART=xc7a35tcpg236-1
while true; do
case "$1" in
-d|--device) DEVICE=$2; shift 2; ;;
-p|--part) PART=$2; shift 2; ;;
-f|--fasm) FASM=$2; shift 2; ;;
-b|--bit) BIT=$2; shift 2; ;;
--) break ;;
esac
done
DATABASE_DIR=${DATABASE_DIR:-$(prjxray-config)}
if [ -z $DEVICE ]; then
# Try to find device name. Accept only when exactly one is found
PART_DIRS=(${DATABASE_DIR}/*/${PART})
if [ ${#PART_DIRS[@]} -eq 1 ]; then
DEVICE=$(basename $(dirname "${PART_DIRS[0]}"))
else
echo "Please provide device name"
exit 1
fi
fi
DBROOT=`realpath ${DATABASE_DIR}/${DEVICE}`
if [ -z $FASM ]; then echo "Please provide fasm file name"; exit 1; fi
if [ -z $BIT ]; then echo "Please provide bit file name"; exit 1; fi
xcfasm --db-root ${DBROOT} --part ${PART} --part_file ${DBROOT}/${PART}/part.yaml --sparse --emit_pudc_b_pullup --fn_in ${FASM} --bit_out ${BIT} ${FRM2BIT}
之后开始生成top.bit