RISCV C开发调试笔记

hello.c

1
2
3
4
5
6
7
8
#include <stdio.h>
int main(){
long a = 0x876543210 ;
float pi = 3.1415926 ;
printf("Hello %s!\n","World");
a = a*pi;
return a ;
}

RISCV 汇编指令调试

RISCV汇编指令调试,立即数使用分析

新建文件 test.s

1
2
3
4
5
6
.global main

.text
main:
li a5, 0x12345678
ret

riscv.....gcc test.s 编译成汇编代码
riscv.....gdb test.s 用调试器运行

SBT 版本问题

QA

    1. sbt 指向 “java -Dsbt.ivy.home=/nishome/jijing/ivy2 -jar /DATA/jijing/rocket-chip/sbt-launch.jar”

现象
ivy2 也是最新的,包含 org.scala-lang#scala-library;2.11.12 正确的版本号

依然会报错!!

1
2
3
4
5
[warn] 	::::::::::::::::::::::::::::::::::::::::::::::
[warn] :: UNRESOLVED DEPENDENCIES ::
[warn] ::::::::::::::::::::::::::::::::::::::::::::::
[warn] :: org.scala-lang#scala-library;2.11.12: public: unable to get resource for org/scala-lang#scala-library;2.11.12: res=https://repo1.maven.org/maven2/org/scala-lang/scala-library/2.11.12/scala-library-2.11.12.pom: java.net.UnknownHostException: repo1.maven.org: Temporary failure in name resolution
[warn] ::::::::::::::::::::::::::::::::::::::::::::::

原因

~/.sbt 目录可能存在旧的版本,导致问题,

解决

删除 ~/.sbt 目录,如果联网,直接重新sbt run ,会自动下载更新,否则copy 别的机子上正确的 .sbt 到home 目录下。

    1. IDEA,rochi-chip:sync failed ,但在terminal下正常编译 ,也是~/.sbt导致的
    1. C 程序编译好的.out文件不能再 rocket-chip/emulator 目录下运行,而 run-asm-isa-test 则会没有问题

这是由于直接用rvgcc 编译的文件,并没有按照处理器的格式做link,因此想要正确的在处理器上运行,需要正确的link

可以参见 bootrom/link.lds 文件 :

1
2
3
4
5
6
7
8
9
10
11
 1 SECTIONS 
2 {
3 ROM_BASE = 0x10000; /* ... but actually position independent */
4
5 . = ROM_BASE;
6 .text.start : { *(.text.start) }
7 . = ROM_BASE + 0x40;
8 .text.hang : { *(.text.hang) }
9 . = ROM_BASE + 0x80;
10 .rodata.dtb : { *(.rodata.dtb) }
11 }

rvgcc -T link.ld bootrom.S -nostdlib -static -wl,--no-gc-section -o bootrom.img

同理C代码编译的时候也需要使用正确的linkfile 文件 。

如何编译指定CPU的可执行文件

必要信息:

  • $(CC) 需要默认的target (例如intel x86, AMD64, MIPS 等等, 如果RISCV, 需要支持的指定指令集 (例如 rv32imc rv64g,rv32imdfc 等等)
  • link 脚本,如果不指定,会有导入默认的脚本,否则需要显示指定,尤其是自己设计的处理器,需要显式的指定堆栈起始地址,程序默认存放地址,这些信息响应的也会体现在CPU硬件设计当中。需要正确match
1
2


综合时序分析回顾

时序分析

静态时序分析工具STA,在分析时序的时候会统一从一个点出发开始计算分析(这样才有可行性),往往是从时钟PLL出来以后开始计算

一般情况下都会设一个clock network delay 表示从PLL 到寄存器段clk的群延迟 ,理想情况下,到每个寄存器的群延迟都是一样的(时钟balance)
寄存器

路径计算

看一个timing报告:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
****************************************

Startpoint: U_xx/_ram_sp1024x8/srsp_1024x8
(rising edge-triggered flip-flop clocked by clk)
Endpoint: U_xx/nS_bit_reg_1_
(rising edge-triggered flip-flop clocked by clk)
Path Group: clk
Path Type: max

Des/Clust/Port Wire Load Model Library
------------------------------------------------
xx_top ZeroWireload tef40ulp128x8hd_ph_ssg0p99v2p25vm40c

Point Incr Path
--------------------------------------------------------------------------
clock clk (rise edge) 0.0000 0.0000
clock network delay (ideal) 2.0000 2.0000 #时钟群延迟设为2ns
xx/srsp_1024x8/CLK (sadr41p1024x8m4b1) 0.0000 2.0000 r #arrival + 2ns
xx/srsp_1024x8/Q[0] (sadr41p1024x8m4b) 2.2361 4.2361 f
xx/U37/X (SVN_ND2_T_2) 0.0290 4.2651 r
xx/U47/X (SVN_ND2_2) 0.0323 4.2974 f
....
..
xx/U188/X (SVN_EN2_F_1) 0.0956 4.8690 f
xx/nS_bit_reg_1_/D (SVN_FSDPRBQ_D_4) 0.0000 4.8690 f
data arrival time 4.8690


clock clk (rise edge) 3.3300 3.3300 #300Mhz = 3.33ns
clock network delay (ideal) 2.0000 5.3300 #required + 2 =5.33ns
clock uncertainty 0.3000 5.0300 #恶化抖动
xxx/nS_bit_reg_1_/CK (SVN_FSDPRBQ_D_4) 0.0000 5.0300 r
library setup time 0.3303 4.6997 #- setup time
data required time 4.6997
--------------------------------------------------------------------------
data required time 4.6997 # = clk_arvl_time - Setuptime - skew
data arrival time -4.8690 #
--------------------------------------------------------------------------
slack (VIOLATED) -0.1693

****************************************

Clock Setup Slack = Data Required Time – Data Arrival Time

Clock Arrival Time = Latch Edge + Clock Network Delay to Destination Register

Data Required = Clock Arrival Time – μtSU – Setup Uncertainty

Data Arrival Time = Launch Edge + Clock Network Delay Source Register + μtCO + Register-to-Register Delay

综合时序分析回顾

关于计算机大小端

一般计算机所讲的大小端指的是字节序的大小端,比特序一般默认都是小端无论字节序为大端还是小端

字节序大小端

HSB(大端格式):
按字节从大到小排布

1
2
3
byte0,byte1,byte2,byte3
byte4,byte5,byte6,byte7
...

LSB(小端格式):
按字节从小到大排布

1
2
3
byte3,byte2,byte1,byte0
byte7,byte6,byte5,byte4
...

比特序大小端

bit大端 =[01234567]
bit小端 =[76543210]
一般常见的都是bit小端

Terminal配置常见问题

Teriminal 配置常见问题

    1. ls后文件名包含引号,例如 'Program file'

      在 ~/.zshrc 里面配置

    1. MACOS ls 目录后没有颜色显示,

      'alias ls =/bin/ls -G' , 一定要指到/bin/ls

    1. 其他

VCS仿真option

VCS、verdi的命令的配置

该Makefile可作为仿真工作脚本,参考了开源处理器蜂鸟e200的仿真环境

https://github.com/SI-RISCV/e200_opensource/blob/master/vsim/bin/run.makefile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
RUN_DIR      := ${PWD}

TESTCASE := 00
DUMPWAVE := 1

VSRC_DIR := ${RUN_DIR}/../rtl
VTB_DIR := ${RUN_DIR}/../tb
INC_DIR := ${RUN_DIR}/../rtl/dir_inc_defines1
INC_DIR += ${RUN_DIR}/../rtl/dir_inc_defines2
# TESTNAME := $(notdir $(patsubst %.dump,%,${TESTCASE}.dump))
TESTNAME := case${TESTNAME}
TEST_RUNDIR := ${TESTNAME}

RTL_V_FILES := $(wildcard ${VSRC_DIR}/*/*.v)
TB_V_FILES := $(wildcard ${VTB_DIR}/*.v)

# The following portion is depending on the EDA tools you are using, Please add them by yourself according to your EDA vendors
SIM_TOOL := vcs # this is a free solution here to use iverilog to compile the code
SIM_OPTIONS := -sverilog -debug_all +incdir+${INC_DIR} -timescale=1ns/100ps +notimingcheck +nospecify +v2k +memcbk -fsdb -l com.log
SIM_EXEC := ${RUN_DIR}/simv -l sim.log +notimingcheck +nospecify +loopreport +memcbk +novopt

WAV_TOOL := verdi #To-ADD: to add the waveform tool
WAV_OPTIONS := -timescale=1ns/100ps +notimingcheck +nospecify #To-ADD: to add the waveform tool options
WAV_PFIX := #To-ADD: to add the waveform file postfix

all: run

compile.flg: ${RTL_V_FILES} ${TB_V_FILES}
@-rm -rf compile.flg
${SIM_TOOL} ${SIM_OPTIONS} ${RTL_V_FILES} ${TB_V_FILES} ;
touch compile.flg

compile: compile.flg

wave:
# gvim -p ${TESTCASE}.spike.log ${TESTCASE}.dump &
${WAV_TOOL} ${WAV_OPTIONS} ${RTL_V_FILES} ${TB_V_FILES} &

run: compile
rm -rf ${TEST_RUNDIR}
mkdir ${TEST_RUNDIR}
cd ${TEST_RUNDIR}; ${SIM_EXEC} +DUMPWAVE=${DUMPWAVE} +TESTCASE=${TESTCASE} |& tee ${TESTNAME}.log; cd ${RUN_DIR};

.PHONY: run clean all

晶振,PLL, VCO介绍

晶振,vco区别

晶振分有源晶振和无源晶振,一般会产生1~200Mhz时钟频率
vco亚控振荡器,可以产生比较高的频率比如2Ghz,但是不稳定

为什么既要晶振还要vco?

就是为了能够产生稳定的高频时钟信号,就需要用到PLL, PLL内部会有
一个VCO 产生高频时钟,通过分频器假设得到10分频的时钟2,再拿这个时钟2
和晶振产生的100mhz基用鉴相器做比较,输出一个比较的波形后经过低通滤波,
用输出电压控制VCO的输出, 那么就能是vco输出的高频时钟得到稳定的频率,达到了
倍频的效果。

20Mhz一下的晶振基本上都是基频的器件,稳定度好,20mhz以上的晶振大多是谐波(如3次,5次谐波)
稳定度差,因此强烈建议使用低频的器件,毕竟倍频器用的pll电路需要的周边配置主要是电容,
电阻,电感,其稳定度和价格方面要远远浩宇晶体晶振器件。

如果只需要一个20mhz以内的时钟频率,完全可以不用pll,直接接晶振就够了

晶振一般有哪些参数

晶振有几个重要参数:

1,晶体元件规格书中所指定的频率,也是工程师在电路设计和元件选购时首要关注的参数。晶振常用标称频率在1~200MHz之间,比如32768Hz、8MHz、12MHz、24MHz、125MHz等,更高的输出频率也常用PLL(锁相环)将低频进行倍频至1GHz以上。我们称之为标称频率。

2,输出信号的频率不可避免会有一定的偏差,我们用频率误差(Frequency Tolerance)或频率稳定度(Frequency Stability),用单位ppm来表示,即百万分之一(parts per million)(1/106),是相对标称频率的变化量,此值越小表示精度越高。比如,12MHz晶振偏差为±20ppm,表示它的频率偏差为12×20Hz=±240Hz,即频率范围是(11999760~12000240Hz)

3,还有一个温度频差(Frequency Stability vs Temp)表示在特定温度范围内,工作频率相对于基准温度时工作频率的允许偏离,它的单位也是ppm。

4,另外,负载电容CL(Load capacitance),它是电路中跨接晶体两端的总的有效电容(不是晶振外接的匹配电容),主要影响负载谐振频率和等效负载谐振电阻,与晶体一起决定振荡器电路的工作频率,通过调整负载电容,就可以将振荡器的工作频率微调到标称值。更准确而言,无源晶体的负载电容是一项非常重要的参数,因为无源晶体属于被动元器件,所谓的被动元器件即是自身不能工作,需要外部元器件协助工作,无源晶体即是!

其中:

CS为晶体两个管脚之间的寄生电容(又名晶振静态电容或Shunt Capacitance),在晶体的规格书上可以找到具体值,一般0.2pF~8pF不等。如图二是某32.768KHz的电气参数,其寄生电容典型值是0.85pF(在表格中采用的是Co)。

CG指的是晶体振荡电路输入管脚到GND的总电容,其容值为以下三个部分的和。

  • 需加外晶振主芯片管脚芯到GND的寄生电容 Ci
  • 晶体震荡电路PCB走线到到GND的寄生电容CPCB
  • 电路上外增加的并联到GND的外匹配电容 CL1
    CD指的是晶体振荡电路输入管脚到GND的总电容。容值为以下三个部分的和。
  • 需加外晶振主芯片管脚芯到GND的寄生电容, Co
  • 晶体震荡电路PCB走线到到gnd的寄生电容,CPCB
  • 电路上外增加的并联到GND的外匹配电容, CL2

既然晶振的负载电容是一个非常重要的参数,如果此项参数与外部电容匹配不正确会导致什么样的现象?晶振两端的等效电容与晶振标称的负载电容匹配不正确,晶振输出的谐振频率将与标称工作的工作频率会产生一定偏差(又称之为频偏),负载电容(load capacitance)主要影响负载谐振频率和等效负载谐振电阻,它与石英谐振器一起决定振荡器的工作频率,通过调整负载电容,一般可以将振荡器的工作频率调到标称值。应用时我们一般外接电容,便是为了使晶振两端的等效电容等于或接近负载电容,对于要求高的场合还要考虑ic输入端的对地电容,这样便可以使得晶振工作的频率达到标称频率。所以合理匹配合适的外加电容使晶振两端的等效电容等于或接近负载电容显得十分重要。

负载电容常用的标准值有12.5 pF,16 pF,20 pF,30pF,负载电容和谐振频率之间的关系不是线性的,负载电容变小时,频率偏差量变大;负载电容提高时,频率偏差减小。图3是一个晶体的负载电容和频率的误差的关系图。

例外情况:

现在有很多芯片内部已经增加了补偿电容(internal capacitance),所以在设计的时候,只需要选按照芯片datasheet推荐的负载电容值的选择晶体即可,不需要额外再加电容。但是因为实际设计的寄生电路的不确定性,最好还是预留CL1/CL2的位置。

Verilog仿真不打拍分析

现象

例如:
1
出现:
2

原因

这是由于采样的时钟tx_gen_symbol_clk 和数据信号subframe_start之间存在竞争关系导致的。
我们的设计意图是时钟tx_gen_symbol_clk应该采到subframe_start信号的后沿
3
有人可能会说在代码中加入延迟#1来解决,实际上不推荐这样做,还会存在两个#1的信号同样还会存在竞争。

仿真模型原理分析

要搞清楚产生这种问题的原因首先要了解仿真器对于时序仿真的模型。
4
第4级的时钟不能正常采到第3级输出的数据,但是第2级的时钟能采到第二级时钟打出来的数据(D3),
原因就是,仿真器会在寄存器输出的时候添加一个虚拟的延迟δ,虽然这个虚拟延迟我们是看不到的,
在仿真器上都是0,但是对于仿真器工作的时候,到遇到always采样事件时先要判断这个δ延迟,决定触发器的采样输出。
(当延迟相等时,clk延迟的优先级会比data延迟的优先级高,即clk1能采到D1的前沿, 也就是我们看到的数据不打拍,这跟我们的预期是不一致的,
而clk1能采不到D2的前沿,但能采到D2的后沿,这跟我们的预期一样的。这些讨论仅限于前仿,
实际器件上我们必须有时序约束来保证建立保持时间,也不会存在这样的问题。
但是硬件设计就是要保证仿真和物理器件一致。因此我们要注意这个现象。
5

如何解决

在你的TB里时钟都由一个单独的模块产生送给DUT,不管产生多少个时钟,这些时钟保证都经历了n级分频下来的然后送入DUT,这样数据就不会出现不delay的现象。