IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> uvm_user_guide_1.2 -- ch2 TLM 通信 -> 正文阅读

[Java知识库]uvm_user_guide_1.2 -- ch2 TLM 通信

2.1 TLM-1的实现

2.1.1 Basics

2.1.1.1 Transactions

在UVM中,transaction是包含了两个组件之间传递的信息的类对象。例如,一个传输总线协议信息的transaction以如下方式建模:

class simple_trans extends uvm_sequence_item;
    rand data_t data;
    rand addr_t addr;
    rand enum {WRITE, READ} kind;
    constraint c1 { addr < 16'h2000; }
    ...
endclass

transaction对象包含变量、约束以及其他需要对transaction进行操作的域和方法。此外,上面的transaction可以被扩展到包含更多信息的transaction,也可以定义包含多个其他transaction的更高级别的transaction。

2.1.1.2 Transaction级通信

Transaction级的接口定义了一系列使用transaction对象作为参数的方法。一个TLM port 在特定的连接中定义了这些方法,TLM export 提供了这些方法的实现。将 port 连接到 export 后,在 port 中可以调用该方法进行执行。

2.1.1.3 基本TLM通信

最基本的transaction级操作允许一个组件将transaction put 到另一个组件。
在这里插入图片描述

producer的方块表示一个 port,consumer的圆圈表示一个 export。producer产生transaction然后通过其 put_port 发送:

class producer extends uvm_component;
    uvm_blocking_put_port #(simple_trans) put_port;
    ...
    put_port = new("put_port", this);  // instantiated in build phase
    ...
    virtual task run();
        simple_trans t;
        for(int i=0; i<N; i++) begin
            put_port.put(t);
        end
    endtask

:uvm_ * _port的参数是要传输的transaction类型

put() 方法由consumer实现:

class consumer extends uvm_component;
    uvm_blocking_put_imp #(simple_trans, consumer) put_export;
    ...
    task put(simple_trans t);
        ...
    endtask

:uvm_ * _imp的第一个参数是要传输的transaction类型,第二个参数是实现传输方法的对象类型

另一种与 put 操作相对应的操作是 get:
在这里插入图片描述

在这种情况下,consumer通过 get 端口向producer请求获取transaction。

class get_consumer extends uvm_component;
    uvm_blocking_get_port #(simple_trans) get_port;
    ...
    get_port = new("get_port", this);  // instantiated in build phase
    ...
    virtual task run();
        simple_trans t;
        for(int i=0; i<N; i++) begin
            get_port.get(t);
        end
    endtask

get()方法由producer实现

class get_producer extends uvm_component;
    uvm_blocking_get_imp #(simple_trans, get_producer) get_export;
    ...
    task get(output simple_trans t);
        ...
    endtask

上面两个例子中的put和get均为blocking操作。

2.1.1.4 进程间的通信

在上面的基本 put 例子中,只有在调用了 put() 方法之后 consumer 才被激活。在许多情况中,可能需要组件独立操作,producer 在创建 transaction 的同时,consumer 需要对这些 transaction 进行操作。UVM 提供了 uvm_tlm_fifo 通道来实现这种通信,uvm_tlm_fifo 实现了所有的 TLM 接口方法,所以 producer 将 transaction 放入 uvm_tlm_fifo,consumer 从 fifo 独立获取该 transaction:
在这里插入图片描述
在 producer 向 fifo 放入 transaction 时,如果 fifo 已满, 则会进行等待,否则会立即放入 fifo 并返回。如果 fifo 有 transaction 可获取,get 操作会立即从 fifo 中取出 transaction 并返回,否则会进入等待,直到有 transaction 可获取。因此,两次连续的 get 操作会为 consumer 取出两个不同的 transaction。peek() 方法会返回 transaction 的副本,并不从 fifo 中取出数据。两次连续的 peek 操作会返回同一个 transaction 的两个副本。

2.1.1.5 Blocking 与 Nonblocking

上述接口操作均为 blocking ---- 任务完成之前会阻塞。没有机制可以使 blocking 调用非正常终止或者改变控制流。blocking 在请求满足前一直等待。

相反地,nonblocking 调用立即返回,这种语义保证了在发起 nonblocking 调用的同一 delta cycle 完成返回,因而不消耗时间。UVM 中,nonblocking 调用建模为 function。

class consumer extends uvm_component;
    uvm_get_port #(simple_trans) get_port;
    task run;
        ...
        for(int i = 0; i < 10; i++)
            if(get_port.try_get(t))
            // Do something with t
        ...
    endtask
endclass

如果存在 transaction,该 transaction 会从函数参数中返回,且函数本身会返回 TRUE。如果不存在 transaction,函数会返回 FALSE。对于 try_peek() 与 try_put() 方法,情况与之类似。

2.1.1.6 连接 transaction 级组件

在组件中定义了 port 和 export 之后,实际的连接可以由上层组件或环境调用 connect() 方法来完成。在验证环境中,port 与 export 之间的 connect() 方法调用建立了点对点和层次性连接的网表,使得发起者的 port 连接到了目标的实现。

因此,当一个组件调用了:

put_port.put(t);

连接之后意味着实际上调用了:

target.put_export.put(t);

其中,target 是被连接的组件。

2.1.1.7 点到点的连接

当要连接的组件处于同一层次时,port 总是连接到 export。所有的 connect() 调用由上层组件完成。

class my_env extends uvm_env;
    ...
    virtual function void connect_phase(uvm_phase phase);
    // component.port.connect(target.export);
    producer.blocking_put_port.connect(fifo.put_export);
    get_consumer.get_port.connect(fifo.get_export);
    ...
    endfunction
endclass

2.1.1.8 Port/Export 匹配

要使连接有效,export 必须提供传输方法的实现。例如,一个 blocking_put_port 需要连接到的 blocking_put_export 或 put_export 实现 put() 方法。两个 export 都需要实现一个 put() 方法,put_export 还需要实现 try_put() 和 can_put() 方法。

2.1.2 封装和层次

TLM 接口的使用将验证环境中的每个组件独立出来,小的组件可能被封装到大的组件之中。通过使子类组件的接口在父类可见,能够实现对子类组件的访问。

2.1.2.1 层次性连接

在层次性的组件之间进行连接需要额外的操作:
在这里插入图片描述
上图中,producer 包含了三个组件,consumer 包含了两个组件。从 top 的角度看,producer 和 consumer 的连接关系与 Figure 4 一致,producer 的 put_port 连接到了 consumer 的 put_export。两个 fifo 是同一个 uvm_tlm_fifo 组件里的两个独立实例。

在上图中,连接A、B、D 和 F 是标准的点到点的连接。例如,连接 A 在 producer 的 connect() 方法中进行:

gen.put_port.connect(fifo.put_export);

连接 C 和 E 是一种不同类型的连接。连接 C 是 port-to-port 的连接,连接 E 是 export-to-export 的连接。这两种连接时层次性连接中所需要的。连接 C 从外面的组件向内部的组件 imports 了一个 port,连接 E 从内部的组件向外面的组件 exports 了一个 export。但是,port 和 export 的终点不一定是层次中相同的位置。使用 port-to-port 和 export-to-export 的连接来使层次边界的连接能够被更高层次访问。

对于连接 E,fifo 中实现的 export 被连接到了 consumer 的接口。在父类组件中的 export-to-export 连接以如下形式实现:

export.connect(subcomponent.export);

因此,连接 E 的代码为:

class consumer extends uvm_component;
    uvm_put_export #(trans) put_export;
    uvm_tlm_fifo #(trans) fifo;
    ...
    virtual function void connect_phase(uvm_phase phase);
        put_export.connect(fifo.put_export);  // E
        bfm.get_port.connect(fifo.get_export);  // F
    endfunction
    ...
endclass

port-to-port 的连接形式为:

subcomponent.port.connect(port);

连接 C 的代码为:

class producer extends uvm_component;
    uvm_put_port #(trans) put_port;
    conv c;
    ...
    virtual function void connect_phase(uvm_phase phase);
        c.put_port.connect(put_port);
        ...
    endfunction
    ...
endclass

2.1.2.2 连接类型

在这里插入图片描述
注: port.connect() 方法的参数可以为 port 或 export,但是 export.connect() 的参数总是子组件的 export。

2.1.3 Analysis 通信

put/get ports 通常需要对应的 export 来提供传输方法的实现。对于 Analysis 通信,一个组件如 monitor,可以产生一个 transaction 流,不管是否有目标实际进行连接。analysis 组件可以通过 analysis_port 进行连接,并独立接收 transaction 流。

2.1.3.1 Analysis Ports

在这里插入图片描述
uvm_analysis_port 是专用的 TLM 端口,其接口只包含一个函数 write()。analysis port 连接了一系列 analysis_export,当组件调用了 analysis_port.write(),analysis_port 调用所有连接的 export 的 write() 方法。如果没有连接任何 export,则 write() 函数可以直接返回。一个 analysis_port 可以连接到任意数量的 analysis_export,但是连接的数量不会影响 analysis_port 组件的 write 操作。因为 write() 是一个 void 函数,调用总是会在相同的 delta cycle 内完成。

class get_consumer_with_ap extends get_consumer;
    uvm_analysis_port #(trans) ap;
    ...
    virtual function void build_phase(uvm_phase phase);
        ap = new("analysis_port", this);
        ...
    endfunction
    task run_phase(uvm_phase phase);
        ...
        for(int i = 0; i < 10; i++)
            if(get_port.get(t)) begin
                // Do something with t
                ap.write(t);  // Write transaction
                ...
            end
    endtask
endclass

在上层组件中,将 analysis port 连接到 analysis export。

2.1.3.2 Analysis Exports

每个连接到 analysis port 的组件,都要为 analysis export 实现各自的 write() 方法。uvm_subscriber 类可以用于简化这个操作:

class sub1 #(type T = simple_trans) extends uvm_subscriber #(T);
    ...
    my_env env;
    function void write(T t);
        // Call desired functionality in parent
    endfunction
endclass

如果有多个 exports 连接到一个 analysis port,端口会调用每个 export 的 write() 方法。由于 write 方法为函数,因此 analysis port 的 write 方法调用立即完成,不管连接了多少个 export。

class my_env extends uvm_env;
    get_component_with_ap g;
    sub1 s1;
    sub2 s2;
    virtual function void build_phase(uvm_phase phase);
        s1 = new("s1");
        s1.env = this;
        s2 = new("s2");
        s2.env = this;
    endfunction
    virtual function void connect_phase(uvm_phase phase);
        g.ap.connect(s1.analysis_export);
        // to illustrate analysis port can be connected to multiple
        // subscribers; usually the subscribers are in separate components
        g.ap.connect(s2.analysis_export);
    endfunction
endclass

当调用了 write 方法之后,每个连接的 analysis export 都会收到指向同一个 transaction 的句柄。在 write 函数的实现中,必须对 transaction 进行 copy。

UVM 有一个 analysis_fifo,是一个含有 analysis export 的 uvm_tlm_fifo。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-03-31 23:49:43  更:2022-03-31 23:52:05 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 6:40:57-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码