对UVM添加超时前的打印信息+AXI低功耗接口+process的await语句+对象当成参数+sv的单例模式+关联数组的初始化+VIM的正则表达式+grep的或操作+uvm event的电平触发+二维队列降维到平铺状态
对UVM添加超时前的打印信息
首先获取到UVM的超时值,然后手动设定\$time的比较和while延时循环,当超出时间后,打印特殊的debug信息。
$time < set_time,则进行循环。
uvm_cmdline_processor clp;
clp = uvm_cmdline_processor::get_inst();
string timeout_settings[$];
string timeout;
time timeout_int;
string override_spec;
clp.get_arg_values("+UVM_TIMEOUT=", timeout_settings);
timeout = timeout_settings[0];
void'($sscanf(timeout,"%d,%s",timeout_int,override_spec));
AXI低功耗接口
AXI低功耗接口_csysreq-CSDN博客
CSYSREQ
系统时钟控制器通过拉低 CSYSREQ 来请求设备进入低功耗状态;
系统时钟控制器通过拉高 CSYSREQ 来请求设备退出低功耗状态。
CSYSACK
设备通过拉低 CSYSACK 来响应系统时钟控制器请求进入低功耗状态的请求;
设备通过拉高 CSYSACK 来响应系统时钟控制器请求退出低功耗状态的请求。
CACTIVATE
CACTIVATE 用于指示设备是否需要时钟信号。
process的await语句
手册语句
task do_n_way( int N );
process job[1:N];
for ( int j = 1; j <= N; j++ )
fork
automatic int k = j;
begin job[k] = process::self(); ... ; end
join_none
// wait for all processes to start
for( int j = 1; j <= N; j++ )
wait( job[j] != null );
job[1].await(); // wait for first process to finish
for ( int k = 1; k <= N; k++ ) begin
if ( job[k].status != process::FINISHED )
job[k].kill();
end
endtask
对象当成参数
传递的内容为对象,不管是output,还是task、function,其都转换为了ref类型。
class MyClass;
int value;
endclass
module test;
// Task that takes a class object by reference
task modify_class(output MyClass obj);
obj.value = 42;
endtask
initial begin
MyClass my_obj = new();
my_obj.value = 10;
$display("Before modify: %0d", my_obj.value);
// Call the task, passing the object by reference
modify_class(my_obj);
$display("After modify: %0d", my_obj.value);
end
endmodule
sv的单例模式
使用protected类型,禁止使用new方法,随后定义一个新的类似new的方法,在每次使用实例之前调用。
在实际用的时候,虽然不可以使用静态的class,但是可以使用静态的方法和变量,因此可以通过定义静态的方法,实现直接调用。
使用class_inst::function_name()调用函数,使用class_inst::value_name = x;赋值变量。
class Singleton;
// 单例的静态变量
static Singleton instance;
// 私有的构造函数
protected function new();
$display("Singleton instance created.");
endfunction
// 获取单例实例的方法
static function Singleton getInstance();
if (instance == null) begin
instance = new();
end
return instance;
endfunction
// 示例方法
function void display();
$display("This is the singleton instance.");
endfunction
endclass
module testbench;
initial begin
// 获取单例实例
Singleton s1;
Singleton s2;
s1 = Singleton::getInstance();
s1.display();
// 尝试获取另一个实例
s2 = Singleton::getInstance();
s2.display();
// 比较两个实例的地址
if (s1 == s2) begin
$display("s1 and s2 are the same instance.");
end
else begin
$display("s1 and s2 are different instances.");
end
end
endmodule
关联数组的初始化、元素查找、索引打印
初始化过程和队列不同,队列初始化使用{},等同于即delete();而关联数组使用'{}
program test_find;
int arr[int];
int result[$];
int idx;
// 查找所有大于5的元素
initial begin
int i;
// 初始化
arr = '{};
for(i=3;i<10;i++) begin
arr[i] = i+10;
end
result = arr.find_index() with (item > 14);
$display("Elements greater than : %p", result);
// 使用 first() 获取第一个索引
if (arr.first(idx)) begin
// 遍历并打印所有索引
do begin
$display("Index: %d, Value: %0d", idx, arr[idx]);
end while (arr.next(idx)); // 使用 next() 获取下一个索引
end
$display("Elements: %p", idx);
end
endprogram
vim正则表达式和普通表达式
不同的地方在于vim的正则需要额外加上斜杠转义
https://blog.csdn.net/gsjthxy/article/details/99696704
#元字符 说明
* #匹配0-任意个
\+ #匹配1-任意个
\? #匹配0-1个
\{n,m} #匹配n-m个
\{n} #匹配n个
\{n,} #匹配n-任意个
\{,m} #匹配0-m个
\_. #匹配包含换行在内的所有字符
\{-} #表示前一个字符可出现零次或多次,但在整个正则表达式可以匹配成功的前提下,匹配的字符数越少越好
\= #匹配一个可有可无的项
\_s #匹配空格或断行
\_[]
#元字符 说明
\* #匹配 * 字符。
\. #匹配 . 字符。
\/ #匹配 / 字符。
\\ #匹配 \ 字符。
\[ #匹配 [ 字符。
grep的或操作
使用正则表达式即可,正则表达式中的|表示或的意思
https://blog.csdn.net/stalin_/article/details/81450633
grep 'pattern1\|pattern2' filename
grep -E 'pattern1|pattern2' filename
uvm event的电平触发
https://blog.csdn.net/hh199203/article/details/127652972
使用trigger和wait_trigger实现脉冲的触发和等待
使用trigger+reset和wait_on+wait_off实现电平的触发和等待,trigger函数一方面会形成脉冲,另一方面也会将状态转换为on。
module testbench();
class my_test extends uvm_test;
`uvm_component_utils(my_test)
uvm_event my_event;
function new(string name = "my_test", uvm_component parent = null);
super.new(name, parent);
my_event = uvm_event_pool::get_global("my_event");
endfunction
task run_phase(uvm_phase phase);
phase.raise_objection(this);
// Fork a process to trigger the event after some time
fork begin
#10ns;
my_event.trigger();
#5ns;
my_event.reset();
end join_none
// Wait on the event
uvm_report_info("WAIT_ON", "Waiting for the event to trigger", UVM_LOW);
my_event.wait_on();
uvm_report_info("WAIT_ON", "Event has been triggered", UVM_LOW);
#10ns;
my_event.wait_off();
uvm_report_info("WAIT_OFF", "Event has been off triggered", UVM_LOW);
phase.drop_objection(this);
endtask
endclass
initial begin
run_test("my_test");
end
endmodule
二维队列降维到平铺状态
module two_dim_queue_flatten_stream;
bit[31:0] d_queue[$][$] = '{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
bit [511:0] flattened_queue;
initial begin
// 打印二维队列
$display("Original 2D Queue:");
for (int i = 0; i < d_queue.size(); i++) begin
$display("%p", d_queue[i]);
end
// 使用流操作降维
flattened_queue = {>> {d_queue}};
// 打印降维后的队列
$display("Flattened Queue:");
$display("%0h", flattened_queue);
end
endmodule
输出
Original 2D Queue:
'{'h1, 'h2, 'h3}
'{'h4, 'h5, 'h6}
'{'h7, 'h8, 'h9}
Flattened Queue:
1000000020000000300000004000000050000000600000007000000080000000900000000000000000000000000000000000000000000000000000000
Le vent se lève! . . . il faut tenter de vivre!
Le vent se lève! . . . il faut tenter de vivre!