我正在尝试为使用基本simple_initiator_socketsimple_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;
}

这是编译时出现的错误。



我最好的猜测是我没有正确设置套接字。测试台具有simple_initiator_socket,加法器具有simple_target_socket。我是否需要使用simple_target_socket方法为模块注册b_transport?我是在启动器中执行此操作的,但在下面的教程中,我没有看到对目标执行此操作的要求。我的猜测是数据流是这样的:
  • simple_initiator_socket(test_bench的成员)已注册到模块的b_transport方法和另一个模块(位于顶部模块中)的simple_target_socket
  • 发起程序模块(test_bench)设置tlm_generic_payload及其需要发送到目标的数据(adder)
  • 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_MODULESC_HAS_PROCESS宏。原因是宏SC_METHODSC_THREAD需要知道用于执行其工作的模块的类型。由于SystemC基于1998年发布的C++语言的旧版本,因此无法自动执行此操作。因此,辅助宏SC_HAS_PROCESS定义为:
    #define SC_HAS_PROCESS(user_module_name) typedef user_module_name SC_CURRENT_USER_MODULE
    

    这使得SC_METHODSC_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)
    {
    }
    

    关于c++ - 实现SystemC TLM Testbench构建失败,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47929657/

    10-11 15:12