How to connect two modules by systemC tlm_fifo<float>?

1.2k views Asked by At

I am still a novice for writing systemC-TLM. Now, I want to connect two modules by tlm_fifoFF. I am searching examples for a long time on net. But no use. Please help to give some ideas or examples how to achieve this.

This is my architecture:

enter image description here

and,this is my error information:

enter image description here


this is "main.cpp"

#include <systemc.h>
#include <iostream>
#include <stdio.h>
#include <stdlib.h> 
#include "merlin2.h"

#include "tlm.h"
#include <tlm_utils/simple_target_socket.h>
#include <tlm_utils/simple_initiator_socket.h>
#include <tlm_utils/multi_passthrough_initiator_socket.h>
#include <tlm_utils/multi_passthrough_target_socket.h>
#include <tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo.h>
#include <tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_fifo_ifs.h>
using namespace sc_core;
using namespace tlm;
using namespace tlm_utils;
using namespace std;

int sc_main(int argc, char** argv){

    Merlin2 merlin_test("merlin2_JW");

    sc_start();
    cout << "end" << endl;
    return 0;
} 

this is "merlin2.cpp"

#include "merlin2.h"
Merlin2::Merlin2(const sc_module_name& name)
{
    ProcessEngine PE_TEST("test_PE");
    test_PE TP("PE_test");
    tlm::tlm_fifo <float> FF ("fifo");

    TP.out(FF);
    PE_TEST.in(FF);
}

this is "merlin2.h"

#ifndef __MERLIN2_H__
#define __MERLIN2_H__
#include <fstream>
#include <string>
#include <systemc.h>

#include "pe.h"
#include "test_PE.h"

class Merlin2: public sc_module 
{
    public:

        SC_HAS_PROCESS(Merlin2);
        Merlin2(const sc_module_name& name);

};

#endif

this is "pe.cpp"

#include <systemc.h>
#include <iostream>
#include "pe.h"

using namespace std;
ProcessEngine::ProcessEngine(const sc_module_name& name):in("in")
{ 
    cout << "before SC_THREAD(run)" << endl;
    SC_THREAD(run);
    cout << "after SC_THREAD(run)" << endl;
}

void ProcessEngine::run()
{   
    int N = in.nb_get();
    cout <<  " N=" << N << endl;

    wait(1,SC_NS);
}

this is "pe.h"

#ifndef __PE_H__
#define __PE_H__

#include <iostream>
#include <bitset>
#include "tlm.h"
#include <tlm_utils/simple_target_socket.h>
#include <tlm_utils/simple_initiator_socket.h>
#include <tlm_utils/multi_passthrough_initiator_socket.h>
#include <tlm_utils/multi_passthrough_target_socket.h>
#include <tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo.h>
#include <tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_fifo_ifs.h>
using namespace sc_core;
using namespace tlm;
using namespace tlm_utils;
using namespace std;


class ProcessEngine: public sc_module
{
    public:

        tlm::tlm_fifo<float>  in;
        void run();

        ProcessEngine(const sc_module_name& name);
        SC_HAS_PROCESS(ProcessEngine);


};

#endif

this is "test_PE.cpp"

#include <systemc.h>
#include <iostream>
#include "test_PE.h"
using namespace std;

test_PE::test_PE(const sc_module_name& name):out("out")
{ 
    cout << "before start_test " << endl;
    SC_THREAD(start_test);
    cout << "After start_test " << endl;
}

void test_PE::start_test()
{
    float A=5;
    in.nb_put(A);
    cout << "A=" << A << endl;
    wait(1,SC_NS);
}

this is "test_PE.h"

#ifndef __TESTPE_H__
#define __TESTPE_H__
#include <fstream>
#include <string>
#include <systemc.h>

#include "tlm.h"
#include <tlm_utils/simple_target_socket.h>
#include <tlm_utils/simple_initiator_socket.h>
#include <tlm_utils/multi_passthrough_initiator_socket.h>
#include <tlm_utils/multi_passthrough_target_socket.h>
#include <tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo.h>
#include <tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_fifo_ifs.h>

using namespace sc_core;
using namespace tlm;
using namespace tlm_utils;
using namespace std;

class test_PE:public sc_module
{
    public:
        tlm::tlm_fifo<float>  out;  
        test_PE(const sc_module_name& name);
        SC_HAS_PROCESS(test_PE);
        void start_test();
    private:
        float A;
};
#endif

1

There are 1 answers

3
Guillaume On BEST ANSWER

You're mixing SystemC/TLM notions and especially ports and channels.

  • tlm_fifo is a channel. It can be used to connect two ports. It's the yellow part of your image.

However, you can't directly connect a channel to a module. Instead, you need to use ports in each module you want to connect the channel. A port is associated to an interface defining methods you can use. In your case, you use nb_get(...) and nb_put(...).

For tlm_fifo, you can use these ports:

  • sc_port< tlm_nonblocking_put_if<float> >
  • sc_port< tlm_nonblocking_get_if<float> >

TLM-1.0 example

Finally, you create instances of your modules in your Merlin2 constructor. Objects are not persisted and deleted at the end of the constructor. They should be member of the class. Here is a complete working example of TLM-1.0 using tlm_fifo with non blocking interface.

Note: You're mixing TLM-2.0 and TLM-1.0 headers. I removed useless headers.


main.cpp

#include <systemc>
#include "merlin2.h"

using namespace sc_core;
using namespace std;

int sc_main(int argc, char** argv) {
    Merlin2 merlin_test("merlin2_JW");
    sc_start();
    cout << "end" << endl;
    return 0;
}

merlin2.h

#ifndef __MERLIN2_H__
#define __MERLIN2_H__
#include <fstream>
#include <string>
#include <systemc>

#include "pe.h"
#include "test_PE.h"

class Merlin2: public sc_module
{
public:
    Merlin2(const sc_module_name& name);
    tlm::tlm_fifo <float> FF;
    ProcessEngine PE_TEST;
    test_PE TP;
};
#endif

merlin2.cpp

#include "merlin2.h"

Merlin2::Merlin2(const sc_module_name& name):
        PE_TEST("test_PE"),
        TP("PE_test"),
        FF("fifo")
{
    TP.out(FF);
    PE_TEST.in(FF);
}

pe.h

#ifndef __PE_H__
#define __PE_H__

#include <fstream>
#include <string>
#include <systemc>
#include <tlm>

using namespace sc_core;
using namespace tlm;
using namespace std;

class ProcessEngine: public sc_module
{
public:
    sc_port< tlm_nonblocking_get_if<float> >  in;
    void run();
    ProcessEngine(const sc_module_name& name);
    SC_HAS_PROCESS(ProcessEngine);
};

#endif

pe.cpp

#include <systemc.h>
#include "pe.h"

using namespace std;

ProcessEngine::ProcessEngine(const sc_module_name& name):
        in("in")
{
    SC_THREAD(run);
}

void ProcessEngine::run()
{
    sc_core::wait(1, SC_NS);
    float N = 0;
    bool r = in->nb_get(N);
    cout <<  " N=" << N << endl;
}

test_PE.cpp

#include <systemc>
#include "test_PE.h"

using namespace std;

test_PE::test_PE(const sc_module_name& name):
        out("out")
{
    SC_THREAD(start_test);
}

void test_PE::start_test()
{
    float A=5;
    out->nb_put(A);
    cout << "A=" << A << endl;
    sc_core::wait(1, SC_NS);
}

test_PE.h

#ifndef __TESTPE_H__
#define __TESTPE_H__

#include <fstream>
#include <string>
#include <systemc>
#include <tlm>

using namespace sc_core;
using namespace tlm;
using namespace std;

class test_PE:public sc_module
{
public:
    sc_port< tlm_nonblocking_put_if<float> >  out;
    test_PE(const sc_module_name& name);
    SC_HAS_PROCESS(test_PE);
    void start_test();
private:
    float A;
};
#endif