TLM2通信

一、概述

  • TLM是一种为了构建更高级抽象模型的传输方式。虽然SV语言本身没有原生的TLM传输方式,但是TLM在UVM很好地集成进来,并且在组件传输中得到了充分运用。
  • 伴随着SystemC模型的广泛引用,SystemC通信机制TLM2.0业发展起来,成为SystemC模型之间的核心传输方式。
  • TLM协议本身并不依赖于某一种语言,而是可以跨语言来实现其传输标准。
  • 与TLM1.0相比,TLM2.0提供了更丰富更强大的传输特性,主要包括:双向的阻塞或者非阻塞接口时间标记统一的数据包。通过这些特性,TLM2.0使得接口之间的通信更趋于标准化,更容易为系统构建抽象模型。
  • 虽然TLM2.0一开始作为SystemC标准库的一部分(由C++实现),但是由于RTL与SystemC模型的混合仿真趋势,要求SV也能够有与之匹配的接口便于日后的互相嵌套。

二、接口实现

  • TLM2.0的传输是双向的,意味着在一次完整传输中有request和response类型。这与TLM1.0的transport端口传输方式是类似的。
  • TLM2.0支持blockingnonblocking两种transport方式。blocking的传输方式要求在一次传输过程中,完成request和response的传输。nonblocking的传输方式则将request和response的传输分为了两个独立的单向传输,而两次传输整体视为完成一次握手传输。

两种传输方式对应的UVM方法如下

task b_transport(T t, uvm_tlm_time delay);
function uvm_tlm_sync_e nb_transport_fw(T t, ref P p, input uvm_tlm_time delay);
function uvm_tlm_sync_e nb_transport_bw(T t, ref P p, input uvm_tlm_time delay);

这里T代表着统一的传输数据类uvm_tlm_generic_payload,而P代表着nonblocking传输方式中用来做状态同步的类型。

在定义TLM2.0的过程中,仍然有initiator和target的概念,也有port、export、imp端口类型。对于port类型,它是用来发起请求并调用target一端的传输方法,export用来传导这一要求,最后由imp端口所在组件来实现数据传输方法。

UVM将TLM2.0端口类型称之为socket,它们是由port、export、imp组合而成。一个socket首先是双向传输的,例如TLM1.0的双向传输端口transport可以用来做单次完成的双向传输,master和slave端口用来完成多次的单向传输。

socket则按照blocking和nonblocking的传输方式,组合initiator或者target的发起端区别,可以分为下面这些端口类型:

uvm_tlm_b_initiator_socket
uvm_tlm_b_target_socket
uvm_tlm_nb_initiator_socket
uvm_tlm_nb_target_socket
uvm_tlm_b_passthrough_initiator_socket
uvm_tlm_b_passthrough_target_socket
uvm_tlm_nb_passthrough_initiator_socket
uvm_tlm_nb_passthrough_target_socket

socket类型都继承于uvm_port_base,具有同TLM1.0端口一样的基础函数,而在这些socket内部,它们是通过例化port、export、imp最终实现数据双向传输的。TLM2.0的port、export、imp类型不同于TLM1.0。首先这些相关的端口类型是新引入的类,例如uvm_tlm_b_transport_portuvm_tlm_b_transport_exportuvm_tlm_b_transport_imp。这里没有改变的概念是不同端口类型之间的连接关系,改变的只是新的端口类型名所匹配的方法不再是put()get()peek()而是变成了b_transport()nb_transport_fw()nb_transport_bw()。这些socket通过内置这些端口,最终可以实现数据的双向传输。

三、传送数据

  • TLM1.0传送的数据类型是由用户自己定义的,这就对组件之间的数据传输做出了更多限制,例如如果端口传输数据类型不同,则端口无法连接,同时针对传输不同数据类型的TLM端口,相应的传送方法也要做出调整,因此这种方式不利于组件之间的快速连接和整个平台的搭建。
  • TLM2.0对于传送数据类型提出了一致化要求,这里统一的数据类型由uvm_tlm_generic_payload表示,即传输方法中使用的数据类型都应该为uvm_tlm_generic_payload。为了保持TLM2.0端口的良好连接性,最好不要在uvm_tlm_generic_payload类的基础上做出更多扩展。

TLM2.0标准制定的北京就是为了解决总线级别的抽象问题,所以它的统一数据格式也是按照总线数据的内容来定义的。

  • bit[63:0] m_address:数据的读写地址。
  • uvm_tlm_command_e m_command:数据的读写命令。
  • byte unsigned data[]:写入的数据或者读出的数据,由byte unsigned类型构成动态数组,这是按照总线传输的最小粒度进行划分,便于target一侧进行数据整合。
  • int unsigned length:data数组的长度,该数值应该与data数组的实际容量保持一致。
  • uvm_tlm_response_status_e m_response_status:由target返回的状态值,表示数据传输是否完成和有效。
  • byte unsigned m_byte_enable[]:用来标记写入数据的有效性,标记哪个byte应该写入。
  • byte unsigned m_byte_enable_length:该数值应该等于m_byte_enable数组的容量值。
  • m_stream_width:用来表示连续传输时的数据传输长度。
  • uvm_tlm_extension_base m_extensions[uvm_tlm_extension_base]:如果一些数据域不在上面的部分,那么可以在这个数据延伸域中添加。

从各个数据域可以看出,对于一般总线传输而言,这里包含的数据信息已经足够,那么如果该传输还包括其他数据内容,可以将其合并作为数据成员data数据中的一部分,或者是创建新的uvm_tlm_extension类,将额外的数据成员装入到该数据延伸对象中,通过uvm_tlm_generic_payload::set_extension(uvm_tlm_extension_base ext)来添加这一部分的数据,对于一个数据类而言,拷贝、比较、和打印等功能是必不可少的,而uvm_tlm_extension类也提供了do_copy()do_compare()do_print()等回调函数。

四、时间标记

  • 不同的时间标记间隔是SystemC可以构建不同时间精确度模型的重要手段。尽管SystemC原则上也可以通过自建时钟源利用时钟事件来驱动内部逻辑,但为了提高模型的运行效率,将数据传输和处理的时间通过标记时间来反映,可以很大程度上避免时钟依赖。
  • 在TLM2传输中,由于可以标定延迟时间,这使得target端可以模拟延迟,并且在准确的延迟时刻做出响应。
  • 为了便于标记延迟时间,例如实数范围的延迟1.1ns(SV继承于Verilog的时间精度方式,只能使用整数的延迟方式),UVM新建了一个时间类uvm_tlm_time,这个时间类的便携之处在于可以随时设置它的时间单位(默认为1ps),并且进行时间的增减操作。同时这个类的存在,也是为了解决在不同模块或者数据包之间出现的不同时间单位和精度单位的问题。有了这个灵活的时间类,target一侧要进行时间等待这些操作就容易得多了,也不会出现时间单位或精度单位错误的问题。

五、示例

class comp1 extends uvm_component;
	uvm_tlm_b_initiator_socket b_ini_skt;
	`uvm_component_utils(comp1)
	...
	task run_phase(uvm_phase phase);
		byte unsigned data[] = {1, 2, 3, 4, 5, 6, 7, 8};
		uvm_tlm_generic_payload p1 = new("p1");
		uvm_tlm_time delay = new("delay");
		p1.set_address('h0000F000);
		p1.set_data_length(8);
		p1.set_data(data);
		p1.set_byte_enable_length(8);
		p1.set_write();
		delay.incr(0.3ns, 1ps);
		`uvm_info("INITRSP", $sformatf("initiated a trans at %0d ps", $realtime()), UVM_LOW);
		b_ini_skt.b_transport(p1, delay);
	endtask
endclass

class comp2 extends uvm_component;
	uvm_tlm_b_target_socket #(comp2) b_tgt_skt;
	`uvm_component_utils(comp2)
	...
	
	
	task b_transport(uvm_tlm_generic_payload p1, uvm_tlm_time delay);
		`uvm_info("TGTTRSP", $sformatf("received a trans at %0d ps", $realtime()), UVM_LOW)
		p1.print();
		#(delay.get_realtime(1ps));
		p1.set_response_status(UVM_TLM_OK_RESPONSE);
		`uvm_info("TGTTRSP", $sformatf("complete a trans at %0d ps", $realtime()), UVM_LOW)
		p1.print();
	endtask
endclass

class env1 extends uvm_env;
	comp1 c1;
	comp2 c2;
	`uvm_component_utils(env1)
	...
	
	
	function void build_phase(uvm_phase phase);
		super.build_phase(phase);
		c1 = comp1::type_id::create("c1", this);
		c2 = comp2::type_id::create("c2", this);
	endfunction
	function void connect_phase(uvm_phase phase);
		super.connect_phase(phase);
		c1.b_ini_skt.connect(c2.b_tgt_skt);
	endfunction
endclass

从这个示例可以看出,有了标准的传输数据包和准确的延迟时间,方便了模块还在建的复用和建立更高层次的模型,从实用角度来看,TLM2.0在UVM的实现,是为了可以同SystemC的TLM2.0接口无缝衔接。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值