Реализация сбоя сборки SystemC TLM Testbench

Я пытаюсь реализовать базовый тестовый стенд SystemC TLM для модуля сумматора, который я создал с использованием базовых 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;
}

Вот ошибка, которую я вижу при компиляции.

В файле, включенном из /home/epi/jfrye_xilinx/SystemC/systemc-2.3.2/include/sysc/kernel/sc_module.h:35:0, из /home/epi/jfrye_xilinx/SystemC/systemc-2.3.2/include /systemc:74, из /home/epi/jfrye_xilinx/SystemC/systemc-2.3.2/include/tlm:23, из /home/epi/jfrye_xilinx/SystemC/systemc-2.3.2/include/tlm_utils/simple_initiator_socket.h :23, из /home/test_bench/adder/test_bench.cc:3: /home/test_bench/adder/test_bench.cc:

В конструкторе '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: ошибка: 'SC_CURRENT_USER_MODULE' имеет не был объявлен SC_CURRENT_USER_MODULE, \

/home/epi/jfrye_xilinx/SystemC/systemc-2.3.2/include/sysc/kernel/sc_process.h:151:46: примечание: в определении макроса ‘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: примечание: в расширении макроса ‘declare_thread_process’ declare_thread_process( func ## _handle, \

/home/test_bench/adder/test_bench.cc:17:2: примечание: в расширении

макрос ‘SC_THREAD’ SC_THREAD(run_tests);

make: *** [/home//test_bench/adder/obj/test_bench.o] Ошибка 1

Я думаю, что я неправильно настроил сокеты. У испытательного стенда simple_initiator_socket, а у сумматора simple_target_socket. Нужно ли мне регистрировать simple_target_socket методом b_transport для модуля? Я сделал это в инициаторе, но в приведенном ниже руководстве я не увидел требования сделать это для цели. Я предполагаю, что поток данных был таким:

  1. simple_initiator_socket (участник test_bench) зарегистрирован в методе b_transport модуля и simple_target_socket другого модуля (в верхнем модуле)
  2. Модуль инициатора (test_bench) настраивает tlm_generic_payload с данными, которые он должен отправить на цель (adder)
  3. b_transport метод simple_initiator_socket (члена test_bench), вызываемый с передачей tlm_generic_payload (с дополнениями для сумматора)
  4. Целевой сокет (target) получает и декодирует tlm_generic_payload (добавленные значения), которые были переданы.
  5. Целевой сокет (adder) выполняет операции (добавляет декодированные слагаемые) и изменяет tlm_generic_payload (передается по значению) (путем записи вычисленной суммы обратно в память полезной нагрузки)
  6. Инициатор (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];
};

person John Frye    schedule 21.12.2017    source источник
comment
Вы должны опубликовать свой файл test_bench.h. Кажется, вы не объявляете модуль test_bench с помощью макроса SC_MODULE. Он должен быть объявлен так же, как вы объявляете Top модуль.   -  person StaceyGirl    schedule 21.12.2017
comment
я наследую. adder.cc компилируется в объект с той же парадигмой   -  person John Frye    schedule 21.12.2017


Ответы (1)


Есть два способа объявить модули в 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 основан на старой версии языка C++, выпущенной в 1998 году, не было возможности сделать это автоматически. Таким образом, вспомогательный макрос 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 за кулисами.


Еще один совет - если вы используете компилятор, совместимый с С++ 11, вы можете объявить вспомогательный макрос для себя:

#define DECL(name, ...) name{#name, __VA_ARGS__}

Это может помочь вам объявить именованные объекты, не вводя их имя дважды:

sc_in<bool> DECL(clk);

Любое сообщение об ошибке, в котором упоминается этот порт, содержит его правильное имя.

Также может использоваться в конструкторе для инициализации поля-члена:

mymodule(sc_core::sc_module_name)
    : DECL(clk)
{
}
person StaceyGirl    schedule 21.12.2017
comment
так он построен, и как быстрый отдельный вопрос, если вы не возражаете: не похоже, что метод run_tests() класса test_bench не работает, когда я запускаю исполняемый файл. есть ли способ вызвать SC_THREAD. как он сначала создает экземпляры и привязки tlm, а затем запускает методы. мне нужно сделать потоки чувствительными и запустить порт test_bench из верхнего модуля? - person John Frye; 21.12.2017
comment
Все потоковые процессы планируются для выполнения после начала моделирования. Вам не нужно ничего делать. Вы звонили sc_start? Может быть, он вызывался, но был заблокирован в b_transport? - person StaceyGirl; 21.12.2017
comment
нет, не было. это вызвало реакцию. на самом деле теперь я получаю странный ответ, который восходит к моему первоначальному беспокойству о подключении tlm --- Ошибка: (E109) ​​полная привязка не удалась: порт не привязан: порт 'Top.adder.port_0' (sc_out) - person John Frye; 21.12.2017
comment
@JohnFrye Тогда вам нужно связать это. Рекомендуется давать каждому объекту свое имя, чтобы сообщения об ошибках были читаемы. Я обновил свой ответ небольшим советом по именованию объектов. - person StaceyGirl; 21.12.2017
comment
Я изменил имя порта на сумматоре, чтобы сокеты имели разные имена, и я все еще получаю ту же ошибку с тем же сообщением. Ошибка ясно дает понять, что существует проблема с simple_target_socket в сумматоре. Это единственный порт, входящий или выходящий из сумматора. У меня есть ощущение, что проблема кроется в этом, но я понятия не имею, что это на самом деле - person John Frye; 21.12.2017