haidangvu93 Posted June 14, 2019 Report Share Posted June 14, 2019 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 Quote Link to comment Share on other sites More sharing options...
Eyck Posted June 14, 2019 Report Share Posted June 14, 2019 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 David Black 1 Quote Link to comment Share on other sites More sharing options...
haidangvu93 Posted June 17, 2019 Author Report Share Posted June 17, 2019 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 Quote Link to comment Share on other sites More sharing options...
haidangvu93 Posted June 17, 2019 Author Report Share Posted June 17, 2019 Hi Eyck, In fact, "wait()" doesnt work. So can you have a brief utilization of these functions? Kind regards, Hai Dang Quote Link to comment Share on other sites More sharing options...
Eyck Posted June 18, 2019 Report Share Posted June 18, 2019 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 Quote Link to comment Share on other sites More sharing options...
haidangvu93 Posted June 19, 2019 Author Report Share Posted June 19, 2019 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 Quote Link to comment Share on other sites More sharing options...
Eyck Posted June 26, 2019 Report Share Posted June 26, 2019 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 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.