EDA工具使用+GIT操作+python编程+C语言编程+Riscv相关+TCL操作
EDA工具使用
Verdi覆盖率转网页
urg -full64 -dir simv.vdb
Verdi加载session
verdi -ssr sessionFile
Vcs分部编译
- 额外选项
-partcomp:自动分块编译。
-fastpartcomp:使用多核计算系统并行部分编译。
-pcmakeprof:查看每部分编译占用的时间,方便对时间更久的进行拆分。
-partcomp -top mytop /path/to/mytop.v -fastpartcomp=j8
- 更改top文件
config mytop
design my_tb_top;
partition instance my_tb_top.my_design;
partition package my_package;
partition package vip_package;
default liblist DEFAULT;
endconfig
license管理
- 添加lic并启动
./lmgrd -c ../lib/xxx.lic
- lmgrd的其它操作
down status all up
- 其它服务器级联
如果host服务器的地址是111.111.11.11,在新的服务器设置下述环境变量的导入。
export LM_LICENSE_FILE=27001@111.111.11.11
export SNPSLMD_LICENSE_FILE=27001@111.111.11.11
export XXX_LICENSE_FILE=27001@111.111.11.11
重置编译器指示
`resetall,重置已经启动的所有编译器指示到默认值。
GIT操作
# 在进行重定向stat的内容到文件中,当文件名过长,则送到文件中的内容被截断
git diff --stat=10000
# ----------------------------------------------------------------------------------------------------
# 生成patch
git diff > test.patch
# ----------------------------------------------------------------------------------------------------
# 生成patch(没必要使用format-patch生成,和am恢复)
# 生成patch是在做变更以后生成。
# 其他人使用旧的代码和patch以后,apply,则获取到新的变更结果。
git diff > test.patch
# 应用patch
git apply --stat test.patch #查看应用统计
git apply --check test.patch #查看是否可以应用,不能应用的部分
git apply xxx.patch # 应用patch。
# ----------------------------------------------------------------------------------------------------
git fetch #将某个远程主机的更新,全部取回本地:
git remote prune origin #在本地删除远程已经删除过的分支
# ----------------------------------------------------------------------------------------------------
# cherry-pick,本质上是一个merge,更灵活的将不同分支内不同的commit进行合并
git cherry-pick C3 C5 C7
https://blog.csdn.net/GBS20200720/article/details/123840359
# ----------------------------------------------------------------------------------------------------
# 获取远程分支
git fetch origin master
# 比较远程分支和本地分支的文件变化量
git diff --stat master..origin/master
# 远程分支合入本地
git merge origin/master
# ----------------------------------------------------------------------------------------------------
# git查看树形结构
git log --oneline --graph --decorate --all
# ----------------------------------------------------------------------------------------------------
git clean -n
# 是一次 clean 的演习, 告诉你哪些文件会被删除,不会真的删除
git clean -f
# 删除当前目录下所有没有 track 过的文件
git clean -f <path>
# 删除指定路径下的没有被 track 过的文件
git clean -df
# 删除当前目录下没有被 track 过的文件和文件夹
git reset --hard
git clean -df
git status
# 运行后, 工作目录和缓存区回到最近一次 commit 时候一摸一样的状态。
# ----------------------------------------------------------------------------------------------------
# git reflog显示时间
git reflog --date=iso
# ----------------------------------------------------------------------------------------------------
# git只显示修改的文件细节
git diff --diff-filter=M
# ----------------------------------------------------------------------------------------------------
# git revert版本回退
git revert -n xxxx # 执行版本回退
git revert --continue # 执行完后,执行本命令创建新的提交
# ----------------------------------------------------------------------------------------------------
# gitmodules删除子模块
rm -rf module_dir # 删除子模块目录及源码
vi .gitmodules # 删除项目目录下.gitmodules文件中子模块相关条目
vi .git/config # 删除配置项中子模块相关条目
rm .git/module/module_dir # 删除模块下的子模块目录,每个子模块对应一个目录
# ----------------------------------------------------------------------------------------------------
# git 查看是哪个文件导致目标文件被忽略
git check-ignore -v
git check-ignore -v .idea
git status --ignored来查看被忽略的文件
python编程
# 字符串切分,相比于split,更好用
re.findall(r"[0-9a-zA-Z]{1,200}", str_content)
# python创建defaultdict的函数
def constant_factory(value):
return lambda: value
d = defaultdict(constant_factory('<missing>'))
# python实时刷新打印
print("something。。。", flush=True)
# Python for循环并行运行
from multiprocessing.dummy import Pool as ThreadPool
def fun():
#功能处理函数
return 0
#待处理的目标对象
items = ['apple', 'bananan', 'cake', 'dumpling']
pool = ThreadPool()
pool.map(fun, items)
pool.close()
pool.join()
# os.popen为并行执行,没有前后依赖,串行化使用subprocess替代
#,并添加communicate机制。
#● shell=True 不添加,则无法正常执行
#● stdout=subprocess.PIPE不添加,则没有返回值
#● communicate() 控制串行执行
#● 返回的结果如output1,为bytes类型,需要使用output1.decode()方法,转换为字符串。
import subprocess
# 执行第一个命令
cmd1 = "echo hello world"
process1 = subprocess.Popen(cmd1, shell=True, stdout=subprocess.PIPE)
output1, error1 = process1.communicate()
# 执行第二个命令
cmd2 = "ls -l"
process2 = subprocess.Popen(cmd2, shell=True, stdout=subprocess.PIPE)
output2, error2 = process2.communicate()
# 执行第三个命令
cmd3 = "pwd"
process3 = subprocess.Popen(cmd3, shell=True, stdout=subprocess.PIPE)
output3, error3 = process3.communicate()
# 输出所有命令的输出
print(output1)
print(output2)
print(output3)
# 16进制显示并前面补0
# 对于16进制,使用%x,而不是%h
#前面补零,宽度16,则使用%016x
C语言编程
C内嵌汇编
- 输入变量
asm volitate("ld t0, 0(%0)"::"r"(value))
- 伪汇编操作
绝对地址:使用li,对应到lui addi
相对地址:使用la,对应到auipc,addi。对于la的addi部分,因为是相对地址,需要使用1b对应到上个指令的地址:
1:
auipc t0, %pcrel_hi(mtvec)
addi t0, t0, %pcrel(1b)
Assembler Notation | Description |
---|---|
%hi(symbol) | Absolute(HI20) |
%lo(symbol) | Absolute(LO12) |
%pcrel_hi(symbol) | PC-relative (HI20) |
%pcrel_lo(label) | PC-relative (LO12) |
nm软件
nm软件可以列出目标文件中的符号。直接nm加上文件名,不使用交叉编译工具链。
T:全局文本符号。
t:本地文本符号。
elf文件中获取机器码
# 从elf文件中获取机器码
objcopy -O binary -S source.elf target.bin
读取elf文件
readelf -S test.elf
gcc编译选项
# 编译的时候把中间文件:.i文件、.o文件,分别生成在对应的目录下
-save-temps=obj
# 代码优化选项,省去fp指针的使用,在-O1以上才有效
-fomit-frame-pointer
全局偏移表
位置无关代码是指代码无论被加载到哪个地址上都可以正常执行。gcc选项中添加-fPIC会产生相关代码。X86上数据引用通过全局偏移表global offset table(GOT)实现。GOT是一张在data中保存的一张表,里面记录了很多地址字段 (entry)。GOT的entry包含了变量的绝对地址。
注:PIC:position-independent code地址无关代码
段空间分配
https://blog.csdn.net/feelabclihu/article/details/108289461
Segment | 作 用 |
---|---|
STACK | 应用程序的栈空间,用于函数调用执行、返回的上下文,自动变量的分配空间,由高地址向低地址生长 |
动态映射区 | 主要用于mmap()系统调用映射文件I/O,加载动态库,匿名映射等 |
HEAP | 用于动态分配的内存,如malloc()申请的空间,由低地址向高地址生长 |
BSS | 未初始化的或初值为0的全局变量和静态局部变量存放的空间 |
DATA | 已初始化的且初值不为0的全局变量和静态局部变量存放的空间 |
TEXT | 可执行代码、字符串字面值 |
SBSS | 小的BSS段,用于存放“近”数据,即使用短指针(near)寻址的数据。有利于小的对象组合到单个可以直接寻址的区域。 |
common | 弱符号保存在common段中。bss段中的符号为强符号。当遇到重名,在多个目标文件进行链接过程中,弱符号被强符号覆盖。-fno-common选项来禁止将未初始化的全局变量放入到common段。 |
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#include<sys/mman.h>
#include<sys/types.h>
#include<fcntl.h>
#include<unistd.h>
int bss_var;
int data_var = 200;
void text_var(void){
printf("Test Func! n");
}
int main (int argc, char *argv[])
{
int stack_var;
int fd;
int heap_var;
void *mmap_var;
fd = open ( "1.tst" , O_CREAT|O_RDWR,0777) ;
mmap_var = mmap(NULL, 4096,PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0) ;
munmap ( mmap_var,4096);
heap_var =malloc ( 16) ;
printf ( "stack_var: %p\n" ,&stack_var) ;
printf ( "mmap_var : %p\n", mmap_var) ;
printf ( "heap_var : %p\n", heap_var) ;
printf("bss_var : %p\n",&bss_var) ;
printf ( "data_var : %p\n",&data_var);
printf ( "text_var : %p\n",&text_var) ;
return 0;
}
C编译指示
替代ifndef define endif指示
#pragma once
https://blog.csdn.net/weixin_39640298/article/details/84503428
替代void __attribute__((weak)) weak0();的指示
#pragma weak weak0
https://rancho333.gitee.io/2020/03/03/C%E8%AF%AD%E8%A8%80%E5%BC%B1%E7%AC%A6%E5%8F%B7weak/
对特定地址的调用
(*(void(*) ())0)();
https://zhuanlan.zhihu.com/p/317301422
在-O1的时候,使用关键字volatile,则防止被优化,一定有存储操作。当去掉volatile,则被优化为一条ret指令。
int square() {
volatile int a = 12;
}
在-O1的时候,以上c程序生成以下代码
addi sp,sp,-16
li a5,12
sw a5,12(sp)
addi sp,sp,16
jr ra
# C语言调用汇编
extern int sub(int i, int j);
Sub = sub(0x10,0x20);
.globl sub
sub:
add a0, a0, a1
ret
# 汇编调用C语言
.globl add
li a0, 0x11
li a1, 0x22 #a0,a1为add传入参数,返回值存入a0
call add
add t3, x0, a0
int add(int a, int b)
{
return a+b;
}
Riscv相关
伪操作
# 连续存储区域分配
# 以汇编的形式,使用space。
a: .space 8,0x1
# 以C语言形式
char a[8]={0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1};
# 以汇编的形式,使用skip。
.skip 4096
# ----------------------------------------------------------------------------------------------
# macro使用并携带变量。
.macro enable_rvc inst_str="nop"
.option push
.option rvc
\inst_str
.option pop
.endm
异常和中断处理的差异
中断处理和异常处理的一个差异在于csr被更新的值。
在mepc方面。对于异常处理,mepc指向当前发生异常的指令PC值;对于中断处理,mepc指向下一条指令的PC值。
在mtval方面。对于异常处理,mtval根据异常类型进行更新(如出错的取值地址,存储加载的指令码等);对于中断处理,mtval更新为0。
异常处理还需要:
1.对mstatus的MIE保存到MPIE,然后MIE清零,禁止响应中断。
2.将之前的权限保存到MPP中,切换到M模式
3.根据mtval,得到异常服务程序的入口地址。执行完毕以后,调用mret,返回mepc指向的地址。
浮点编码
ABI相关
RISCV的参数超过8个:ABI中定义了int reg的用途,其中的x10-x17可以为参数寄存器,当参数超过8个,则约定额外的参数放在fp指针的上方,位于内存中,使用fp指针寻址。
gp:全局指针是指向静态数据区
TCL操作
# 设置环境变量。在save和restore仿真中间状态时,之前的环境变量也会保存
# 此时可以通过以下方式覆盖环境变量
set ::env(ENV_VAL) env_value
Le vent se lève! . . . il faut tenter de vivre!
Le vent se lève! . . . il faut tenter de vivre!