实施 SystemC TLM Testbench 构建失败
Implementing SystemC TLM Testbench Build Fail
我正在尝试为我使用基本 simple_initiator_socket
和 simple_target_socket
.
创建的加法器模块实现 SystemC 基本 TLM 测试平台
目前构建失败,我无法诊断原因。
以下是三个主要模块的实现:加法器、测试台以及实例化这两个模块并启动数据流的主模块。
main.cc
#include "systemc.h"
#include "tlm_utils/simple_initiator_socket.h"
#include "tlm_utils/simple_target_socket.h"
#include "tlm_utils/tlm_quantumkeeper.h"
using namespace sc_core;
using namespace sc_dt;
using namespace std;
#include "test_bench.h"
#include "adder.h"
SC_MODULE(Top)
{
test_bench *tb;
adder *ad;
sc_signal<bool> rst;
Top(sc_module_name name) :
rst("rst")
{
tb = new test_bench("test_bench");
ad = new adder("adder");
tb->socket.bind(ad->socket);
}
};
int sc_main(int argc, char *argv[])
{
Top *top = new Top("Top");
}
test_bench.cc
#define SC_INCLUDE_DYNAMIC_PROCESS
#include "tlm_utils/simple_initiator_socket.h"
#include "tlm_utils/simple_target_socket.h"
using namespace sc_core;
using namespace std;
using namespace sc_dt;
#include "test_bench.h"
#include <fstream>
#include <iostream>
test_bench::test_bench(sc_module_name name):
sc_module(name), socket("socket")
{
SC_THREAD(run_tests);
}
void test_bench::run_tests()
{
ifstream infile("../adder.golden.dat");
ofstream ofs;
ofs.open("../adder.dat", ofstream::out | ofstream::app);
while(infile >> data[0] >> data[1])
{
tlm::tlm_generic_payload *trans = new tlm::tlm_generic_payload;
sc_time delay = sc_time(10, SC_NS);
trans->set_data_ptr((unsigned char*)data);
socket->b_transport(*trans, delay);
ofs << data[0] << data[1] << data[2];
delete trans;
}
infile.close();
ofs.close();
printf ("Comparing against output data \n");
if (system("diff -w sha1.dat sha1.golden.dat"))
{
cout << "*******************************************" << endl;
cout << "FAIL: Output DOES NOT match the golden output" << endl;
cout << "*******************************************" << endl;
}
else
{
cout << "*******************************************" << endl;
cout << "PASS: The output matches the golden output!" << endl;
cout << "*******************************************" << endl;
}
}
adder.cc
#define SC_INCLUDE_DYNAMIC_PROCESS
#include "tlm_utils/simple_initiator_socket.h"
#include "tlm_utils/simple_target_socket.h"
using namespace sc_core;
using namespace std;
#include "adder.h"
adder::adder(sc_module_name name)
: sc_module(name), socket("socket")
{
socket.register_b_transport(this, &adder::b_transport);
socket.register_transport_dbg(this, &adder::transport_dbg);
}
void adder::b_transport(tlm::tlm_generic_payload& trans, sc_time& delay)
{
tlm::tlm_command cmd = trans.get_command();
sc_dt::uint64 addr = trans.get_address();
uint32_t *ptr = (uint32_t*)trans.get_data_ptr();
unsigned int len = trans.get_data_length();
unsigned char *byt = trans.get_byte_enable_ptr();
unsigned int wid = trans.get_streaming_width();
addend1 = *ptr;
addend2 = *(ptr++);
add();
memcpy(ptr + sizeof(uint32_t) * 2, (char*) &sum, sizeof(uint32_t));
}
unsigned int adder::transport_dbg(tlm::tlm_generic_payload& trans)
{
return 0;
}
void adder::add()
{
sum = addend1 + addend2;
}
这是我在编译时看到的错误。
In file included from
/home/epi/jfrye_xilinx/SystemC/systemc-2.3.2/include/sysc/kernel/sc_module.h:35:0,
from /home/epi/jfrye_xilinx/SystemC/systemc-2.3.2/include/systemc:74,
from /home/epi/jfrye_xilinx/SystemC/systemc-2.3.2/include/tlm:23,
from /home/epi/jfrye_xilinx/SystemC/systemc-2.3.2/include/tlm_utils/simple_initiator_socket.h:23,
from /home/test_benches/adder/test_bench.cc:3:
/home/test_benches/adder/test_bench.cc:
In constructor ‘test_bench::test_bench(sc_core::sc_module_name)’:
/home/epi/jfrye_xilinx/SystemC/systemc-2.3.2/include/sysc/kernel/sc_module.h:463:29:
error: ‘SC_CURRENT_USER_MODULE’ has not been declared
SC_CURRENT_USER_MODULE, \
/home/epi/jfrye_xilinx/SystemC/systemc-2.3.2/include/sysc/kernel/sc_process.h:151:46: note: in definition of macro ‘SC_MAKE_FUNC_PTR’
static_cast(&callback_tag::func)
/home/epi/jfrye_xilinx/SystemC/systemc-2.3.2/include/sysc/kernel/sc_module.h:461:5:
note: in expansion of macro ‘declare_thread_process’
declare_thread_process( func ## _handle, \
/home/test_benches/adder/test_bench.cc:17:2: note: in expansion of
macro ‘SC_THREAD’ SC_THREAD(run_tests);
make: ***
[/home//test_benches/adder/obj/test_bench.o]
Error 1
我最好的猜测是我没有正确设置套接字。测试台有一个simple_initiator_socket
,加法器有一个simple_target_socket
。我是否需要使用模块的 b_transport
方法注册 simple_target_socket
?我在启动器中这样做了,但在下面的教程中我没有看到对目标这样做的要求。我猜数据流是这样的:
simple_initiator_socket
(test_bench
的成员)注册到模块的 b_transport
方法和另一个模块的 simple_target_socket
(在顶层模块中)
- 启动器模块 (
test_bench
) 使用需要发送到目标 (adder
) 的数据设置 tlm_generic_payload
b_transport
simple_initiator_socket
的方法(test_bench
的成员)调用 tlm_generic_payload
被传递(加法器的加数)
- 目标套接字(目标)接收并解码传递的
tlm_generic_payload
(加值)。
- 目标套接字(
adder
)执行操作(添加解码的加数)并修改tlm_generic_payload
(按值传递)(通过将计算的总和写回有效负载内存)
- 发起者 (
test_bench
) 查看修改后的 tlm_generic_payload
(现在包含总和)并执行一些过程(检查理论总和)
我试图效仿这个例子。
https://www.doulos.com/knowhow/systemc/tlm2/tutorial__1/
更新
test_bench.h
class test_bench:
public sc_core::sc_module
{
public:
tlm_utils::simple_initiator_socket<test_bench> socket;
sc_out<bool> irq;
test_bench(sc_core::sc_module_name name);
void run_tests();
private:
uint32_t data[3];
};
在 SystemC 中有两种声明模块的方法。
第一个是通过使用SC_MODULE
宏:
SC_MODULE(mymodule) {
SC_CTOR(mymodule)
{
}
};
没有它的第二个:
class mymodule : public sc_core::sc_module {
SC_HAS_PROCESS(mymodule);
public:
mymodule(sc_core::sc_module_name)
{ }
};
我更喜欢第二个,因为:
- 它尽可能避免那些讨厌的宏。
- 它允许您从另一个模块继承。
现在为什么需要 SC_MODULE
或 SC_HAS_PROCESS
宏。原因是宏 SC_METHOD
和 SC_THREAD
需要知道他们正在使用的模块类型来完成他们的工作。由于 SystemC 是基于 1998 年发布的旧版 C++ 语言,因此无法自动执行此操作。所以辅助宏 SC_HAS_PROCESS
被定义为:
#define SC_HAS_PROCESS(user_module_name) typedef user_module_name SC_CURRENT_USER_MODULE
这允许 SC_METHOD
和 SC_THREAD
使用 SC_CURRENT_USER_MODULE
作为它们正在使用的模块的同义词。宏 SC_MODULE
已经在后面使用 SC_HAS_PROCESS
窗帘.
另一个建议 - 如果您使用 C++11 兼容编译器,您可以为自己声明一个辅助宏:
#define DECL(name, ...) name{#name, __VA_ARGS__}
这可以帮助您在声明命名对象时无需输入两次名称:
sc_in<bool> DECL(clk);
任何提及此端口并包含其专有名称的错误消息。
也可以用在构造函数中初始化成员字段:
mymodule(sc_core::sc_module_name)
: DECL(clk)
{
}
我正在尝试为我使用基本 simple_initiator_socket
和 simple_target_socket
.
目前构建失败,我无法诊断原因。
以下是三个主要模块的实现:加法器、测试台以及实例化这两个模块并启动数据流的主模块。
main.cc
#include "systemc.h"
#include "tlm_utils/simple_initiator_socket.h"
#include "tlm_utils/simple_target_socket.h"
#include "tlm_utils/tlm_quantumkeeper.h"
using namespace sc_core;
using namespace sc_dt;
using namespace std;
#include "test_bench.h"
#include "adder.h"
SC_MODULE(Top)
{
test_bench *tb;
adder *ad;
sc_signal<bool> rst;
Top(sc_module_name name) :
rst("rst")
{
tb = new test_bench("test_bench");
ad = new adder("adder");
tb->socket.bind(ad->socket);
}
};
int sc_main(int argc, char *argv[])
{
Top *top = new Top("Top");
}
test_bench.cc
#define SC_INCLUDE_DYNAMIC_PROCESS
#include "tlm_utils/simple_initiator_socket.h"
#include "tlm_utils/simple_target_socket.h"
using namespace sc_core;
using namespace std;
using namespace sc_dt;
#include "test_bench.h"
#include <fstream>
#include <iostream>
test_bench::test_bench(sc_module_name name):
sc_module(name), socket("socket")
{
SC_THREAD(run_tests);
}
void test_bench::run_tests()
{
ifstream infile("../adder.golden.dat");
ofstream ofs;
ofs.open("../adder.dat", ofstream::out | ofstream::app);
while(infile >> data[0] >> data[1])
{
tlm::tlm_generic_payload *trans = new tlm::tlm_generic_payload;
sc_time delay = sc_time(10, SC_NS);
trans->set_data_ptr((unsigned char*)data);
socket->b_transport(*trans, delay);
ofs << data[0] << data[1] << data[2];
delete trans;
}
infile.close();
ofs.close();
printf ("Comparing against output data \n");
if (system("diff -w sha1.dat sha1.golden.dat"))
{
cout << "*******************************************" << endl;
cout << "FAIL: Output DOES NOT match the golden output" << endl;
cout << "*******************************************" << endl;
}
else
{
cout << "*******************************************" << endl;
cout << "PASS: The output matches the golden output!" << endl;
cout << "*******************************************" << endl;
}
}
adder.cc
#define SC_INCLUDE_DYNAMIC_PROCESS
#include "tlm_utils/simple_initiator_socket.h"
#include "tlm_utils/simple_target_socket.h"
using namespace sc_core;
using namespace std;
#include "adder.h"
adder::adder(sc_module_name name)
: sc_module(name), socket("socket")
{
socket.register_b_transport(this, &adder::b_transport);
socket.register_transport_dbg(this, &adder::transport_dbg);
}
void adder::b_transport(tlm::tlm_generic_payload& trans, sc_time& delay)
{
tlm::tlm_command cmd = trans.get_command();
sc_dt::uint64 addr = trans.get_address();
uint32_t *ptr = (uint32_t*)trans.get_data_ptr();
unsigned int len = trans.get_data_length();
unsigned char *byt = trans.get_byte_enable_ptr();
unsigned int wid = trans.get_streaming_width();
addend1 = *ptr;
addend2 = *(ptr++);
add();
memcpy(ptr + sizeof(uint32_t) * 2, (char*) &sum, sizeof(uint32_t));
}
unsigned int adder::transport_dbg(tlm::tlm_generic_payload& trans)
{
return 0;
}
void adder::add()
{
sum = addend1 + addend2;
}
这是我在编译时看到的错误。
In file included from /home/epi/jfrye_xilinx/SystemC/systemc-2.3.2/include/sysc/kernel/sc_module.h:35:0, from /home/epi/jfrye_xilinx/SystemC/systemc-2.3.2/include/systemc:74, from /home/epi/jfrye_xilinx/SystemC/systemc-2.3.2/include/tlm:23, from /home/epi/jfrye_xilinx/SystemC/systemc-2.3.2/include/tlm_utils/simple_initiator_socket.h:23, from /home/test_benches/adder/test_bench.cc:3: /home/test_benches/adder/test_bench.cc:
In constructor ‘test_bench::test_bench(sc_core::sc_module_name)’: /home/epi/jfrye_xilinx/SystemC/systemc-2.3.2/include/sysc/kernel/sc_module.h:463:29: error: ‘SC_CURRENT_USER_MODULE’ has not been declared SC_CURRENT_USER_MODULE, \
/home/epi/jfrye_xilinx/SystemC/systemc-2.3.2/include/sysc/kernel/sc_process.h:151:46: note: in definition of macro ‘SC_MAKE_FUNC_PTR’ static_cast(&callback_tag::func)
/home/epi/jfrye_xilinx/SystemC/systemc-2.3.2/include/sysc/kernel/sc_module.h:461:5: note: in expansion of macro ‘declare_thread_process’ declare_thread_process( func ## _handle, \
/home/test_benches/adder/test_bench.cc:17:2: note: in expansion of
macro ‘SC_THREAD’ SC_THREAD(run_tests);
make: *** [/home//test_benches/adder/obj/test_bench.o] Error 1
我最好的猜测是我没有正确设置套接字。测试台有一个simple_initiator_socket
,加法器有一个simple_target_socket
。我是否需要使用模块的 b_transport
方法注册 simple_target_socket
?我在启动器中这样做了,但在下面的教程中我没有看到对目标这样做的要求。我猜数据流是这样的:
simple_initiator_socket
(test_bench
的成员)注册到模块的b_transport
方法和另一个模块的simple_target_socket
(在顶层模块中)- 启动器模块 (
test_bench
) 使用需要发送到目标 (adder
) 的数据设置 b_transport
simple_initiator_socket
的方法(test_bench
的成员)调用tlm_generic_payload
被传递(加法器的加数)- 目标套接字(目标)接收并解码传递的
tlm_generic_payload
(加值)。 - 目标套接字(
adder
)执行操作(添加解码的加数)并修改tlm_generic_payload
(按值传递)(通过将计算的总和写回有效负载内存) - 发起者 (
test_bench
) 查看修改后的tlm_generic_payload
(现在包含总和)并执行一些过程(检查理论总和)
tlm_generic_payload
我试图效仿这个例子。
https://www.doulos.com/knowhow/systemc/tlm2/tutorial__1/
更新
test_bench.h
class test_bench:
public sc_core::sc_module
{
public:
tlm_utils::simple_initiator_socket<test_bench> socket;
sc_out<bool> irq;
test_bench(sc_core::sc_module_name name);
void run_tests();
private:
uint32_t data[3];
};
在 SystemC 中有两种声明模块的方法。
第一个是通过使用SC_MODULE
宏:
SC_MODULE(mymodule) {
SC_CTOR(mymodule)
{
}
};
没有它的第二个:
class mymodule : public sc_core::sc_module {
SC_HAS_PROCESS(mymodule);
public:
mymodule(sc_core::sc_module_name)
{ }
};
我更喜欢第二个,因为:
- 它尽可能避免那些讨厌的宏。
- 它允许您从另一个模块继承。
现在为什么需要 SC_MODULE
或 SC_HAS_PROCESS
宏。原因是宏 SC_METHOD
和 SC_THREAD
需要知道他们正在使用的模块类型来完成他们的工作。由于 SystemC 是基于 1998 年发布的旧版 C++ 语言,因此无法自动执行此操作。所以辅助宏 SC_HAS_PROCESS
被定义为:
#define SC_HAS_PROCESS(user_module_name) typedef user_module_name SC_CURRENT_USER_MODULE
这允许 SC_METHOD
和 SC_THREAD
使用 SC_CURRENT_USER_MODULE
作为它们正在使用的模块的同义词。宏 SC_MODULE
已经在后面使用 SC_HAS_PROCESS
窗帘.
另一个建议 - 如果您使用 C++11 兼容编译器,您可以为自己声明一个辅助宏:
#define DECL(name, ...) name{#name, __VA_ARGS__}
这可以帮助您在声明命名对象时无需输入两次名称:
sc_in<bool> DECL(clk);
任何提及此端口并包含其专有名称的错误消息。
也可以用在构造函数中初始化成员字段:
mymodule(sc_core::sc_module_name)
: DECL(clk)
{
}