Jump to content

multiple initiator sockets and single target socket


Recommended Posts

Hello everyone,

I want to create a system of 7 initiator sockets (masters) connect to a Bus and then to one target socket (slave). I use the multi_passthrough_initiator_socket and multi_passthrough_target_socket.

        tlm_utils::multi_passthrough_initiator_socket<Bus> initiator_socket;
        tlm_utils::multi_passthrough_target_socket<Bus>    target_socket;

Then i connect the masters and slave to the bus.

    bus << master_0;
    bus << master_1;
    bus << master_2;
    bus << master_3;
    bus << master_4;
    bus << master_5;
    bus << master_6;
    bus << sharedmemory;

In the b_transport function, i use sc_mutex.

void Bus::b_transport(int id, tlm::tlm_generic_payload& trans, sc_core::sc_time& delay)
{

    sc_dt::uint64 global_addr = trans.get_address();
    int slaveid               = this->address_to_slaveid(global_addr);
    if(slaveid < 0)
    {
        trans.set_response_status(tlm::TLM_ADDRESS_ERROR_RESPONSE);
        std::cout << "\e[1;31m" << this->name() << ": "  << "\e[1;31mInvalid address " << global_addr << std::endl;
        return;
    }
    sc_dt::uint64 slave_addr  = global_addr - this->starts[slaveid];


    this->bus_mutex.lock();

    trans.set_address(slave_addr);
    this->initiator_socket[slaveid]->b_transport(trans, delay);
    trans.set_address(global_addr);
    std::cout << "Master ID" << id << std::endl;    // I print the ID to check if they are working
    sc_core::wait(this->bus_delay);
    this->bus_mutex.unlock();
}

When i run the program, there are always 3/7 masters working, so the program is blocked. What's the problem here?

Thank you alot for your helps.

Kind regards,

HD

Link to comment
Share on other sites

From the snippets you provide it looks ok.

Assuming that bus_mutex is a sc_mutex this is you problem. sc_mutex does not do arbitration. It selects randomly which waiting thread to grant the lock (actually the next activated process base on an even notification) . But what you expect is arbitration. So either you write an arbiter or you may use and ordered semaphore with an initial counter value of 1. You may find an implementation here: https://git.minres.com/SystemC/SystemC-Components/src/branch/master/incl/scc/ordered_semaphore.h

The semaphore grant access based on a queue. So eventually you get first-comes-first-serves (FCFS) behavior, but all requestors have equal priority.

Best regards

Link to comment
Share on other sites

Hi Eyck,

It works with your solution. I initialized the counter value from 0 then i tried with 1, it seems that there is no difference (or small difference).

void Bus::b_transport(int id, tlm::tlm_generic_payload& trans, sc_core::sc_time& delay)
{

    sc_dt::uint64 global_addr = trans.get_address();
    int slaveid               = this->address_to_slaveid(global_addr);
    if(slaveid < 0)
    {
        trans.set_response_status(tlm::TLM_ADDRESS_ERROR_RESPONSE);
        std::cout << "\e[1;31m" << this->name() << ": "  << "\e[1;31mInvalid address " << global_addr << std::endl;
        return;
    }
    sc_dt::uint64 slave_addr  = global_addr - this->starts[slaveid];


    this->post();

    trans.set_address(slave_addr);
    this->initiator_socket[slaveid]->b_transport(trans, delay);
    trans.set_address(global_addr);
    //std::cout << "\e[1;31m MB " << id << std::endl;
    sc_core::wait(this->bus_delay);

}

And i have a doubt that: "post()" or "wait()" is better in this case?

Thank you a lot for your helps.

HD

 

Link to comment
Share on other sites

Hi,

from the snippets I see it does not get clear what you are doing. Basically you would Instantiate the ordered_semphore

scc:ordered_semaphore sem{1}

and in b_transport() you wait() and post():

void Bus::b_transport(int id, tlm::tlm_generic_payload& trans, sc_core::sc_time& delay)
{
    sc_dt::uint64 global_addr = trans.get_address();
    int slaveid               = this->address_to_slaveid(global_addr);
    if(slaveid < 0)
    {
        trans.set_response_status(tlm::TLM_ADDRESS_ERROR_RESPONSE);
        std::cout << "\e[1;31m" << this->name() << ": "  << "\e[1;31mInvalid address " << global_addr << std::endl;
        return;
    }
    sc_dt::uint64 slave_addr  = global_addr - this->starts[slaveid];
    trans.set_address(slave_addr);
    // make sure we are allowed to get access
    sem.wait();
    this->initiator_socket[slaveid]->b_transport(trans, delay);
    // return back the token so that others can access
    sem.post();
    trans.set_address(global_addr);
} 

BR

Link to comment
Share on other sites

Hi Eyck,

In fact, when using sem.wait() and sem.post(), the program is also blocked. So that i only use sem.post() and i dont know whether the semaphore can do the arbitration or not? But the program is running.  How is your opinion? 

void Bus::b_transport(int id, tlm::tlm_generic_payload& trans, sc_core::sc_time& delay)
{
    sc_dt::uint64 global_addr = trans.get_address();
    int slaveid               = this->address_to_slaveid(global_addr);
    if(slaveid < 0)
    {
        trans.set_response_status(tlm::TLM_ADDRESS_ERROR_RESPONSE);
        std::cout << "\e[1;31m" << this->name() << ": "  << "\e[1;31mInvalid address " << global_addr << std::endl;
        return;
    }
    sc_dt::uint64 slave_addr  = global_addr - this->starts[slaveid];
    trans.set_address(slave_addr);
    // make sure we are allowed to get access
    sem.wait();
    this->initiator_socket[slaveid]->b_transport(trans, delay);
    // return back the token so that others can access
    sem.post();
    trans.set_address(global_addr);
}

 

 

BR,

Hai Dang

 

Link to comment
Share on other sites

Hi Hai Dang,

wait() takes a token from the semaphore (and waits for it if there is none) and post() puts a token back. In fact it decrements a counter until zero upon wait() and increments it upon post(), the initial value is given as constructor argument. Instantiating the semaphore with an initial value of one has the behavior of a mutex.

So just posting the semaphore only increments it and obviously your program runs.

If the code above fails then I would assume your initiators or targets have an issue since this is a proven pattern. Does the target call wait or does it just return an annotated time?

How did you setup your initiators?

BR

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...