背景:https://help.aliyun.com/product/155039.html?spm=5176.10695662.852251.3.543d78dclwQb08
1.FPGA云服务器 > 最佳实践 > FPGA RTL开发流程最佳实践 > f3实例RTL开发最佳实践
1)compling.sh
rm cl_hello -rf
rm role_mem_if -rf
\cp ./sources/dcp/f3_shell_without_cl.dcp f3_shell_without_cl.dcp
//将参考设计中的shell的dcp取出,关于fpga云的shell可看://https://zhuanlan.zhihu.com/p/55805743
//关于dcp文件:
//http://design.eccn.com/design_2017051713346398.htm
vivado -mode batch -source ./run.tcl //以batch批处理模式启动vivado,执行run.tcl 转2)
//vivado -h
//vivado中采用TCL脚本语言来作为其命令解释语言。参考
//http://blog.chinaaet.com/luozhongpin1989/p/36014
//https://blog.csdn.net/rosa_zz/article/details/84818308if [
?
=
"
0
"
]
;
t
h
e
n
/
/
上
方
程
序
执
行
成
功
则
t
i
m
e
s
t
a
m
p
=
? = "0" ];then //上方程序执行成功则 timestamp=
?="0"];then//上方程序执行成功则timestamp=(date +"%y_%m_%d-%H%M%S") //生成时间戳
mkdir ./to_aliyun
cp ./sources/misc/xclbin.xml ./to_aliyun/
t
i
m
e
s
t
a
m
p
−
x
c
l
b
i
n
.
x
m
l
/
/
复
制
x
c
l
b
i
n
.
x
m
l
f
r
e
q
c
o
n
f
i
g
=
‘
c
a
t
.
f
a
a
s
f
r
e
q
c
o
n
f
i
g
‘
c
m
d
=
"
s
e
d
−
i
′
29
a
"
{timestamp}-xclbin.xml //复制xclbin.xml freq_config=`cat .faas_freq_config` cmd="sed -i '29a "
timestamp−xclbin.xml//复制xclbin.xmlfreqconfig=‘cat.faasfreqconfig‘cmd="sed−i′29a"{freq_config}"’ ./to_aliyun/${timestamp}-xclbin.xml"
//sed -i 就是直接对文本文件进行操作的
//插入频率配置信息到xclbin.xml
eval
c
m
d
/
/
s
h
e
l
l
也
提
供
了
e
v
a
l
命
令
,
如
同
熟
悉
的
其
他
脚
本
语
言
,
会
将
它
的
参
数
做
为
命
令
执
行
,
c
p
.
/
x
c
l
d
e
s
i
g
n
w
r
a
p
p
e
r
f
i
n
a
l
.
d
c
p
.
/
t
o
a
l
i
y
u
n
/
cmd //shell 也提供了 eval 命令,如同熟悉的其他脚本语言,会将它的参数做为命令执行, cp ./xcl_design_wrapper_final.dcp ./to_aliyun/
cmd//shell也提供了eval命令,如同熟悉的其他脚本语言,会将它的参数做为命令执行,cp./xcldesignwrapperfinal.dcp./toaliyun/{timestamp}_SH_CL_routed.dcp
//换个名字
tar -zcvf
t
i
m
e
s
t
a
m
p
S
D
A
c
c
e
l
K
e
r
n
e
l
.
t
a
r
.
g
z
t
o
a
l
i
y
u
n
/
{timestamp}_SDAccel_Kernel.tar.gz to_aliyun/
timestampSDAccelKernel.tar.gztoaliyun/{timestamp}_SH_CL_routed.dcp to_aliyun/KaTeX parse error: Undefined control sequence: \0 at position 41: …tar echo -e "\̲0̲33[32m{timestamp}_SDAccel_Kernel.tar.gz\033[0m has been generated"
/opt/Xilinx/SDx/2018.2/runtime/bin/xclbincat -bitstream xcl_design_wrapper_final_pblock_expanded_region_partial.bit -k mode:hw_pr -k featureRomTimestamp:1518077193 -k platformVBNV:xilinx:aliyun-vu9p-f3:4ddr-xpr:4.2 ./to_aliyun/${timestamp}-xclbin.xml bin_hw.xclbin
#rm -rf ./to_aliyun
Fi
2)run.tcl 顺序执行四个脚本
source create_design.tcl
source run_synth.tcl
source mem_design.tcl
source generate_dcp.tcl
3)create_design.tcl
Get current directory, used throughout script
#set launchDir [file dirname [file normalize [info script]]]
Create the project using the board local repo
set projName “cl_prj”
set projPart “xcvu9p-flgb2104-2l-e”
//设置变量名与值,类似宏定义 设置工程名与目标板
create_project
p
r
o
j
N
a
m
e
.
/
projName ./
projName./projName -part $projPart
//创建工程 以cl_prj为名,目标板是xcvu9p-flgb2104-2l-e
add_files -norecurse ./sources/hdl/usr_top.v
add_files -norecurse ./sources/hdl/usr_ddr_access.v
add_files -norecurse ./sources/hdl/ddr_test_hpi.v
#add_files -norecurse ./sources/hdl/axi4s_testing.v
add_files -norecurse ./sources/hdl/ddr_ex/ddr4_v2_2_axi_opcode_gen.sv
add_files -norecurse ./sources/hdl/ddr_ex/ddr4_v2_2_axi_tg_top.sv
add_files -norecurse ./sources/hdl/ddr_ex/ddr4_v2_2_boot_mode_gen.sv
add_files -norecurse ./sources/hdl/ddr_ex/ddr4_v2_2_custom_mode_gen.sv
add_files -norecurse ./sources/hdl/ddr_ex/ddr4_v2_2_data_chk.sv
add_files -norecurse ./sources/hdl/ddr_ex/ddr4_v2_2_data_gen.sv
add_files -norecurse ./sources/hdl/ddr_ex/ddr4_v2_2_prbs_mode_gen.sv
add_files -norecurse ./sources/hdl/ddr_ex/ddr4_v2_2_axi_wrapper.sv
add_files -norecurse ./sources/hdl/axi_data_top.v
add_files -norecurse ./sources/hdl/usr_dma/axi4s_prbs_test.v
add_files -norecurse ./sources/hdl/usr_dma/prbs31_gen.v
add_files -norecurse ./sources/hdl/usr_dma/prbs_gen.v
add_files -norecurse ./sources/hdl/usr_dma/prbs_chk.v
add_files -norecurse ./sources/hdl/usr_dma/prbs31_chk.v
add_files -norecurse ./sources/hdl/usr_dma/pcim_controller.v
add_files -norecurse ./sources/hdl/int_signal_converter.v
add_files ./sources/hdl/usr_lib/interconnect_data/interconnect_data.bd
//不递归的添加源文件
import_ip ./sources/hdl/usr_lib/axi_clock_converter_lite/axi_clock_converter_lite.xci
import_ip ./sources/hdl/usr_lib/axilite_crossbar_0/axilite_crossbar_0.xci
import_ip ./sources/hdl/usr_lib/axi_clock_converter_sport/axi_clock_converter_sport.xci
//添加ip
add_files -fileset constrs_1 -norecurse ./sources/constraints/usr_top.xdc
//指定的源文件应添加到的文件集。将约束文件xdc加入约束文件集 constrs_1
set_property used_in_implementation false [get_files usr_top.xdc]
//设置对象的属性 名-值-对象 在usr_top.xdc中将used_in_implementation设为否
set_property top usr_top [current_fileset]
//定义usr_top位顶层模块
update_compile_order -fileset sources_1
update_compile_order -fileset sim_1
//更新源码集合与仿真集合的编译顺序
4)run_synth.tcl
set_property -name {STEPS.SYNTH_DESIGN.ARGS.MORE OPTIONS} -value {-mode out_of_context} -objects [get_runs synth_1]
//ip以out_of_context的方式综合,关于ip综合的模式 global与out_of_context:
//https://blog.csdn.net/qq_26652069/article/details/90611519
launch_runs synth_1 -jobs 8
//8线程并行综合
wait_on_run synth_1
//阻塞其他tcl命令,直到综合完成
open_run synth_1 -name synth_1
//打开综合后生成的网表设计
write_checkpoint -force ./custom_logic.dcp
//强制将综合后的设计写入custom_logic.dcp
close_design
5)mem_design.tcl
Get current directory, used throughout script
#set launchDir [file dirname [file normalize [info script]]]
Create the project using the board local repo
set projName “role_mem_if”
//role的mem接口,关于shell的参考资料中有介绍
set projPart “xcvu9p-flgb2104-2l-e”
create_project
p
r
o
j
N
a
m
e
.
/
projName ./
projName./projName -part $projPart
add_files -norecurse ./sources/logic_if/mem_if/ddr4_wrapper.vp
add_files -norecurse ./sources/logic_if/mem_if/mem_rsv.vp
add_files -norecurse ./sources/logic_if/mem_if/ddr4_memc.vp
add_files -norecurse ./sources/logic_if/mem_if/role_mem_if.vp
//VP文件扩展名可以指被写入所谓的Verilog硬件描述语言的加密文件。这种语言是用于指定电子系统设
//计。它存储的Verilog源代码文件加密版本。它是用来保护保存在纯文本格式的源代码文件的知识产权。
//这个文件的扩展使开发人员能够以加密形式提供电子系统的模型。
import_files ./sources/config/config.v
//引入配置文件
set_property file_type {Verilog Header} [get_files config.v]
set_property top role_mem_if [current_fileset]
update_compile_order -fileset sources_1
update_compile_order -fileset sim_1
set_property -name {STEPS.SYNTH_DESIGN.ARGS.MORE OPTIONS} -value {-mode out_of_context} -objects [get_runs synth_1]
launch_runs synth_1 -jobs 8
wait_on_run synth_1
open_run synth_1 -name synth_1
write_checkpoint -force ./role_mem_if.dcp
close_design
open_checkpoint ./role_mem_if.dcp
//以role_mem_if.dcp为基础新开一个工程
read_checkpoint ./sources/logic_if/mem_if/ddr_wrapper.dcp
//将ddr_wrapper.dcp读入role_mem_if工程
write_checkpoint -force ./role_mem_if.dcp
close_design
6)generate_dcp.tcl
open_checkpoint ./f3_shell_without_cl.dcp
read_checkpoint -cell u_f3_role_top/u_usr_top ./custom_logic.dcp
read_checkpoint -cell u_f3_role_top/u_role_mem_if ./role_mem_if.dcp
//以f3_shell_without_cl.dcp为基础新建一个工程,读入综合好的custom_logic和role_mem_if
source ./sources/misc/faas_util.tcl
//见7)
source ./sources/config/config.tcl
faas_util::set_kernel_freq $kernel_clock $kernel2_clock
//上面三条命令,将内核频率设置为300与500m
read_xdc ./sources/constraints/false_path.xdc
read_xdc ./sources/constraints/ddr0_pin.xdc
read_xdc ./sources/constraints/ddr2_pin.xdc
read_xdc ./sources/constraints/ddr3_pin.xdc
read_xdc ./sources/constraints/ddr3_ip_ctrl.xdc
read_xdc ./sources/constraints/serdes_gt.xdc
//加入xdc文件
set_property DONT_TOUCH 0 [get_cells u_f3_role_top/u_role_mem_if]
set_property DONT_TOUCH 0 [get_cells u_f3_role_top/u_usr_top]
opt_design -directive Explore
//优化网表设计,全面优化
report_timing_summary -file opt_timing.rpt
//输出时序报告
place_design -fanout_opt
report_timing_summary -file place_timing.rpt
phys_opt_design -directive Explore
route_design -directive Explore
report_timing_summary -file route_timing.rpt
//布局布线,即实施
write_debug_probe -force xcl_design.ltx -quiet
//bit文件包含的内容是如何去配置FPGA里的资源来实现你的设计的逻辑,当然也包含debug core在里面
//ltx文件是在hardware manager里面如果去显示debug core所连接的带观测信号,比如信号名,位宽,是//否是bus,顺序等等
write_checkpoint -force xcl_design_wrapper_final.dcp
pr_verify ./sources/dcp/f3_shell_without_cl.dcp ./xcl_design_wrapper_final.dcp
//比较两个阶段的dcp
write_bitstream -force -file xcl_design_wrapper_final.bit //生成比特流
close_design
7)faas_util.tcl
package require math::bignum
//引入bignum包
// namespace,将命令和变量封装
namespace eval faas_util {
namespace export test set_kernel_freq
proc test { val } {
puts “test $val !”
};//测试程序,打印输出
proc set_kernel_freq { kerenl_freq kernel2_freq } { //函数作用,设置内核频率
write_user_impl_clock_constraint u_f3_role_top/u_usr_top kernel_clk_300m $kerenl_freq //自定义函数见下文
write_user_impl_clock_constraint u_f3_role_top/u_usr_top kernel2_clk_500m $kernel2_freq
set file “.faas_freq_config”
set fd [open $file w+]
seek $fd 0 start
puts $fd [format “<core name=“custom_logic” target=“bitstream” type=“clc_region” clockFreq=”%dMHz" numComputeUnits=“16”>" $kerenl_freq ]
puts $fd “”
puts $fd [format “<clock port=\“DATA_CLK\” frequency=\”%dMHz\"/>" $kerenl_freq ]
puts $fd [format “<clock port=\“KERNEL_CLK2\” frequency=\”%dMHz\"/>" $kernel2_freq ]
puts $fd “”
close $fd
};
proc write_user_impl_clock_constraint {inst clock_name clock_freq} {
set uninit_wiz true
set outpin_mmcm [get_pins [get_property SOURCE_PINS [get_clocks -of_objects [get_pins $inst/$clock_name]]]]
set gclock [get_clocks -of_objects [get_pins $outpin_mmcm]]
set gclock_name [get_property NAME $gclock]
set inpin_mmcm [get_property SOURCE $gclock]
set clock_period [get_property PERIOD [get_clocks -of_objects [get_pins $inpin_mmcm]]]
set clock_freq_orig [round_down [convert_period_to_freq $clock_period]]
if { $uninit_wiz } {
initialize_clkwiz_debug
set uninit_wiz false
}
set_clkwiz_prop $clock_freq_orig $clock_freq
set clkout0_divide [round_down [get_clkwiz_prop ChosenDiv0]]
set divclk_divide [round_down [get_clkwiz_prop ChosenD]]
set divide_by [expr {$clkout0_divide * $divclk_divide}]
set multiply_by [round_down [get_clkwiz_prop ChosenM]]
puts "internal step: create_generated_clock -name $gclock_name -divide_by $divide_by -multiply_by $multiply_by -source $inpin_mmcm $outpin_mmcm"
create_generated_clock -name $gclock_name -divide_by $divide_by -multiply_by $multiply_by -source $inpin_mmcm $outpin_mmcm
if { !$uninit_wiz } {
uninitialize_clkwiz_debug
}
};
proc initialize_clkwiz_debug {} {
load librdi_iptasks.so
set partinfo [get_property PART [current_project]]
Init_Clkwiz [current_project] test1 $partinfo
};
proc uninitialize_clkwiz_debug {} {
UnInit_Clkwiz [current_project] test1
};
proc get_clkwiz_prop {prop} {
set val [GetClkwizProperty [current_project] test1 $prop]
return $val
};
proc get_clkwiz_prop {prop} {
set val [GetClkwizProperty [current_project] test1 $prop]
return $val
};
proc round_down {val} {
set fl [expr {floor($val)}]
set retval [format “%.0f” $fl]
return $retval
};
proc convert_period_to_freq {period} {
return [expr {1000 / $period}]
};
proc set_clkwiz_prop {clock_freq_orig clock_freq} {
SetClkwizProperty [current_project] test1 UseFinePS true
# GetClosestSolution <project_name> <instance_name> <primitive (MMCM or PLL)>
GetClosestSolution [current_project] test1 $clock_freq 0 50 $clock_freq_orig 0 1 false false false false false false
};
};
8)config.tcl
#The maximum frequency on kernel_clock(kernel_clk_300m) is 300MHz. The steps are approximately 5 MHz apart.
set kernel_clock 300
#The maximum frequency on kernel_clock(kernel2_clk_500m) is 500MHz. The steps are approximately 5 MHz apart.
set kernel2_clock 500