对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
posted @ 2024-10-08 21:16  大浪淘沙、  阅读(33)  评论(0编辑  收藏  举报