SystemC事务级建模03之DMI
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SystemC事务级建模03之DMI相关的知识,希望对你有一定的参考价值。
参考技术A 现在我们对以下情形进行事务级建模:GPU往显存(DDR)写一个32位的数据。按照前面文章介绍的做法,我们可以在CPU发起一个事务,然后DDR接收并处理。但是,写显存的操作通常具有频繁和数据量大的特点,频繁的发起事务会降低仿真的执行效率。这里介绍一个比较高效的方法,
DMI,Direct Memory Interface,直接存储访问接口,即一个模块可以拥有另一个模块的存储的指针。
下面开始建模,
GPU是事务发起者,所有他有一个initiator socket;DDR是事务接收者,所以他有一个target socket,
给target socket注册一个获取存储指针的方法,
该方法返回存储指针,
注册一个访问DDR的进程方法,
在该方法中访问DDR,
在上面的方法中,往显存的0xf开始的地址写入了一个32位的数据:0x12345678
Hello TLM
前言
目标
了解TLM程序的基本过程。TLM的英文全称是Transaction Level Modeling,中文翻译为事务级建模。它是在SystemC基础上的一个扩展库。
功能描述
模块A向模块B发送一个“Hello”字符串
任务拆解
- 创建模块A和B
- 连接模块A和B
- 模块A发送“Hello”到B
创建模块A和B
包含头文件systemc.h
#include "systemc.h"
模块A
class A : public sc_module { public: SC_HAS_PROCESS(A); A(sc_module_name name) : sc_module(name) { } }
模块B
class B : public sc_module { public: SC_HAS_PROCESS(B); B(sc_module_name name) : sc_module(name) { } }
连接模块A和B
任务拆解
- 添加TLM相关的头文件
- 模块A添加Initiator Socket
- 模块B添加Target Socket
- 连接模块A和B
添加TLM相关的头文件
#include "tlm.h" #include "tlm_utils/simple_initiator_socket.h"
模块A添加Initiator Socket
public: tlm_utils::simple_initiator_socket<A> socket;
模块B添加Target Socket
public: tlm_utils::simple_target_socket<B> socket;
连接模块A和B
int sc_main(int argc, char* argv[]) { A a("A"); // 实例化模块A B b("B"); // 实例化模块B a.socket(b.socket); // 连接模块A和B sc_start(10, SC_NS); // 仿真运行10纳秒 return 0; }
模块A发送“Hello”到B
任务拆解
- 模块A发送“Hello”
- 模块B接收“Hello”
模块A发送“Hello”
在类A
的构造方法中注册一个用来发送数据的方法hello
A(sc_module_name name) : sc_module(name) {
SC_THREAD(hello);
}
在类A
中创建发送数据的方法hello
void hello() { tlm::tlm_generic_payload *payload = new tlm::tlm_generic_payload(); assert(payload != nullptr); const char *data{"Hello"}; payload->set_data_ptr((unsigned char *) data); sc_time delay = SC_ZERO_TIME; socket->b_transport(*payload, delay); delete payload; }
模块B接收“Hello”
在类B
的构造方法中注册一个用来接收数据的方法hello
B(sc_module_name name) : sc_module(name) { socket.register_b_transport(this, &B::hello); }
在类B
中创建接收数据的方法hello
void hello(tlm::tlm_generic_payload &payload, sc_core::sc_time &delay_time) { const char *data = reinterpret_cast<const char *>(payload.get_data_ptr()); std::cout << data << std::endl; }
附录
运行结果
SystemC 2.3.3-Accellera --- Sep 20 2019 16:02:02 Copyright (c) 1996-2018 by all Contributors, ALL RIGHTS RESERVED Hello Process finished with exit code 0
完整代码
#include "systemc.h" #include "tlm.h" #include "tlm_utils/simple_initiator_socket.h" #include "tlm_utils/simple_target_socket.h" class A : public sc_module { public: SC_HAS_PROCESS(A); A(sc_module_name name) : sc_module(name) { SC_THREAD(hello); } public: tlm_utils::simple_initiator_socket<A> socket; private: void hello() { auto *payload = new tlm::tlm_generic_payload(); assert(payload != nullptr); const char *data{"Hello"}; payload->set_data_ptr((unsigned char *) data); sc_time delay = SC_ZERO_TIME; socket->b_transport(*payload, delay); delete payload; } }; class B : public sc_module { public: SC_HAS_PROCESS(B); B(sc_module_name name) : sc_module(name) { socket.register_b_transport(this, &B::hello); } public: tlm_utils::simple_target_socket<B> socket; private: void hello(tlm::tlm_generic_payload &payload, sc_core::sc_time &delay_time) { const char *data = reinterpret_cast<const char *>(payload.get_data_ptr()); std::cout << data << std::endl; } }; int sc_main(int argc, char* argv[]) { A a("A"); B b("B"); a.socket(b.socket); sc_start(10, SC_NS); return EXIT_SUCCESS; }
参考资料
以上是关于SystemC事务级建模03之DMI的主要内容,如果未能解决你的问题,请参考以下文章