【学习】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__.pypack 函数

首先通过 p_vpr_env_from_args 方法更新环境变量(仅列举部分,这期间调用了p_parse_vpr_args_quicklogicp_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__.pyplace 函数

根据参数拼接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__.pyroute 函数

之后是同样的拼接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__.pywrite_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__.pywrite_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

posted @ 2023-05-05 17:04  小拳头呀  阅读(273)  评论(0编辑  收藏  举报