目录
用tcl,通过telnet连接openocd,与JTAG_DPI连接,JTAG_DPI的verilog model 例化在testbench中,DUT是riscv的core,具有JTAG的调试接口,遵循riscv-debug-spec
这个文章的介绍只是我操作过程中的一些理解和整理,也有很多不涉及的或者有偏差的地方,如果大家又发现问题,可以随时私信沟通交流,多谢。
我是用的下边的JTAG_DPI
GitHub - yaozhaosh/e200_opensource: The Ultra-Low Power RISC Core
配置target.cfg 文件
##配置interface,bitbang和jtag_dpi相连,telnet_port是telnet和openocd相连
interface remote_bitbang
##注意,bitbang的host和port要和jtag_dpi设置为相同的配置
remote_bitbang_port 44853
remote_bitbang_host t01n70
tcl_port 6667 #自行更改
telnet_port 44441 #自行更改,如果是window界面,可以在windows打开telnet服务
##以下是配置chipname和tap_ID
if { [info exists CHIPNAME] } {
set _CHIPNAME $CHIPNAME
} else {
set _CHIPNAME riscv
}
if { [info exists CPUTAPID ] } {
set _CPUTAPID $CPUTAPID
} else {
## 以下设置jtag tap的IDCODE
set _CPUTAPID 0x****
}
## 设置jtag的new_tap
jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id $_CPUTAPID
set _TARGETNAME $_CHIPNAME.cpu
## 根据该core的harts的情况配置target,认为每一个hart 都是一个target
## 为何除了hart5,其他都是defer-examine,因为本方案每次调试只会启动一个hart,其他的都是sleep状态,所以不需要其他core 做examine;
target create $_TARGETNAME.hart0 riscv -chain-position $_TARGETNAME -coreid 0 -rtos hwthread -defer-examine
target create $_TARGETNAME.hart1 riscv -chain-position $_TARGETNAME -coreid 1 -rtos hwthread -defer-examine
target create $_TARGETNAME.hart2 riscv -chain-position $_TARGETNAME -coreid 2 -rtos hwthread -defer-examine
target create $_TARGETNAME.hart3 riscv -chain-position $_TARGETNAME -coreid 3 -rtos hwthread -defer-examine
target create $_TARGETNAME.hart4 riscv -chain-position $_TARGETNAME -coreid 4 -rtos hwthread -defer-examine
target create $_TARGETNAME.hart5 riscv -chain-position $_TARGETNAME -coreid 5 -rtos hwthread -defer-examine
target create $_TARGETNAME.hart6 riscv -chain-position $_TARGETNAME -coreid 6 -rtos hwthread -defer-examine
target create $_TARGETNAME.hart7 riscv -chain-position $_TARGETNAME -coreid 7 -rtos hwthread -defer-examine
## 一些其他配置
gdb_report_data_abort enable
gdb_report_register_access_error enable
riscv set_command_timeout_sec 120
## 当hart5 examine结束之后,立刻halt该hart
$_TARGETNAME.hart5 configure -event examine-end {
halt
}
############ target.cfg 配置完成。
跑起vcs仿真,(仿真截止时间一定要长,应为jtag 输入实在太慢了)
## -d 可以打出很多debug的信息,感觉非常有用,打出log文件,可以不用trace屏幕了
openocd -f target.cfg -d -l my.log
## 用telnet连接
telnet host port_number
## 连接成功之后,可以在命令行调试;
我做的调试命令是
##打印出当前的targets都有哪些
targets
##选中要调试的hart,不然会处于hart7
targets riscv.cpu.hart5
##可以看到current target是不是hart5,如果是可以做后续调试
target current
##查看hart5是不是处于halted状态,或者,当前是处于什么状态;
riscv.cpu.hart5 curstate
## 可以做hartreset,这个需要根据自己的需求自定义
## 这个proc是设置起始地址和hartreset,haltreq,hartreset之后会进入到debug mode ## 该proc完成后,可以做step,或者是设置硬件断点 proc halted_hartreset_halt {target data0 data1 dmcontrol} { set CurS [$target curstate] if { $CurS eq "halted" } { set dmctrl_ori [riscv dmi_read 0x10] set dmctrl_new [ expr $dmctrl_ori | $dmcontrol ] riscv dmi_write 0x05 $data1 riscv dmi_write 0x04 $data0 riscv dmi_write 0x10 $dmctrl_new riscv dmi_read 0x11 riscv dmi_read 0x10 } } |
##hartreset之后
## 设置单步执行,该命令会设置dcsr的step位域,然后resume,执行一条指令,理论上会再次进入debug mode
step
## 查看该hart 的状态,一般是halted
riscv.cpu.hart5 curstate
## reg 可以通过abstract command的register access的方式读取hart内部的寄存器
## 读取dcsr
reg dcsr
## 给x1 写入0x20 (一般不会这么用)我的工程主要是read
reg x1 0x20
## 设置硬件断点,地址,asid,字节数,hw,4个option
bp 0x000000000010001c 0 4 hw
## 断点设置成功之后,resume,然后再断点进入debug mode
resume
## 如果想要设置第二个断点,先要remove所有的断点,然后再设置
## remove bp,不会对tdata2 清零,要注意;
rbp all
## exit,调试结束
exit
调试之前会做target examine,只有完成target examine之后,后续的调试命令才能被识别,否则openocd会报告当前的target还没有被examine
通常target的examine主要做的流程是:(假如只启动某一个调试hart的examine)
Step这个操作会
bp 这个命令
通过访问tselect,tdata1和tdata2 做相关的trigger的配置
我的方案是支持1个硬件指令断点,tdata1的type位域是2;
resume
该操作会清除dcsr的step位域,解除单步的设置,直到响应了断点,或者haltreq
rbp all
清除所有的trigger设置,对tdata1 清零,但不会改变tdata2的值