总结一些面试题集
verilog
边沿检测
写出上升沿检测,下降沿检测,边沿检测代码
1 | @always @(posedge clk, negedge rstn) |
System verilog
interface和virtual interface区别
interface是个硬件块,等价于module概念。virtual interface是个软件块,可以理解为指向硬件块的指针。
硬件块和软件块的区别
module静态对象,compile time construct
class动态对象,run time construct
virtual function和pure virtual function
virtual function,函数重载,子类可重载父类的函数
pure virtual function,纯虚函数,不可实例化,必须继承并重载该函数
coverage种类
function coverage功能覆盖率
code coverage代码覆盖率,line,fsm,condition,toggle
UVM
phase有哪些,哪些消耗仿真时间
build_phase
connect_phase
end_of_elaboration_phase
start_of_simulation_phase
reset_phase(pre/post),耗时
configure_phase(pre/post),耗时
main_phase(pre/post),耗时
shutdown_phase(pre/post),耗时
extract_phase
check_phase
report_phase
final_phase
run_phase,耗时
执行顺序
build_phase:自上而下。需要上层先将下层类实例化,才能调用下层类的build_phase。同一层次以字典顺序执行。深度优先。
例如:
aa bb
/ \ / \
cc dd ee ff
aa->cc->dd->bb->ee->ff
除build_phase之外的function phase:自下而上,先下层类的,后上层类的。
task phase:自下而上启动,同时运行。
uvm采用深度优先原则build
new和create区别
new是直接实例化类。
create是利用factory机制创建类,会将类注册到factory中。
env::type_id::create("env",this);
factory有什么用
通过字符串创建一个类。
关键:参数化类,静态变量,静态函数,联合数组
override功能。用一个子类替换掉父类。
将所有override信息记录下来,在创建时替换掉,所以不能用new的方式创建类,需要调用特定函数。
C语言
strlen和sizeof
strlen是函数,sizeof是运算符
sizeof可用类型做参数,strlen只能用char*做参数,切必须以\0结尾
数组做sizeof不退化,传递给strlen就退化成指针
strlen的结果在运行时计算出来,是计算字符串的实际长度;而sizeof是类型占用内存的大小,在编译时就得到的。
将一个地址某一bit清零
*(volatile unsigned int * 0x8000) =(*(volatile unsigned int * 0x8000)) & 0xfffffffe;
指针
指向指针的指针:int **a;
一个有10个指针的数组:int * a[10];
一个指向有10个整型数组的指针:int (*a)[10];
一个指向函数的指针:int (*a)(int)
一个有10个指针的数组,指针指向一个函数:int (*a[10])(int)
函数指针:void (*f)()
函数返回指针:void * f()
const指针:const int * p
或者int const *p
,*p是const的,p可变
指向const的指针:int * const p
,p是const的,*p可变
static作用
退出一块后仍然存在的局部变量
不能被其他文件访问的全局变量,函数
const作用
只读
为读代码的人传递有用信息
为保护那些不希望被改变的参数,防止被无意修改
volatile作用
可能会被意想不到改变,编译器每次都小心地重新读取这个变量的值,而不取寄存器的备份(告诉编译器取消优化)
并行设备的硬件寄存器
中断子程序中会访问的非自动变量(全局变量)
多线程应用中被几个任务共享的值
大端小端
大端:数据高字节存放在低地址,低字节存放在高地址,与阅读习惯一致。
小端:数据高字节放在高地址,低字节放在低地址。
int value = 0x12345678;
小端 | 大端 | |
---|---|---|
高地址 | 12 | 78 |
34 | 56 | |
56 | 34 | |
低地址 | 78 | 12 |
1 | int is_little_endian(){ |
宏定义
定义宏取两个值里面小的值
1 | #define MIN(A,B) ((A)<=(B)?(A):(B)) |
定义宏交换两个值
1 | #define SWAP(X,Y) (X) = (X) ^ (Y); \ |
判断float是否等于零
1 | const float EPSINON = 0.00001; |
假设有一个没有头指针的单链表,一个指针指向此链表中间的一个节点(非头,非尾),请将该节点删除
假设该节点是B,下一个节点是C,那将B节点的内容替换为C节点内容,再删掉C节点就可以了。