Luis.Cargnini Posted May 12, 2015 Report Share Posted May 12, 2015 Hello, I'm trying to model a packet switcher, for such I broke the packet assignment of different ports in different methods, because I need to evaluate each port in parallel, however the system complains of multiple access at the same signal. To try to avoid this, before execution, I had a sc_mutex placed, but it didn't seem to have worked, my code follows the following ruleset (I'll copy only two methods to avoid long threads): enum sqstate_t {SQINIT,SQIDLE,LRS0,LRS1, LRS2,LRS2N,LRS2S,LRS2W,LRS2E}; sc_signal < sqstate_t > sqControlQ0; sc_signal < sqstate_t > sqControlQ1; sc_mutex _qmux; void SwitchFabric::sendDataQueues0(){ Packet _temp; if(rstn.read() == false){ if(_qmux.trylock() > 0){ _bufferIn_read[0].write(false); _bufferOut_write[0].write(false); _qmux.unlock(); } sqControlQ0 = SQINIT; } else{ //TODO: Working to transform it into a FSM /** * Cycle across multiple queues */ switch(sqControlQ0){ case SQINIT: _bufferIn_read[0].write(false); _bufferOut_write[0].write(false); sqControlQ = SQIDLE; break; case SQIDLE: //for(int i = 0; i < _NPORTS; i++){ if(_bufferIn_busyOut[0].read() != false){ _temp = _inpktOut[0].read(); _bufferIn_read[0].write(true); sqControlQ0 = LRS0; } else{ _bufferIn_read[0].write(false); sqControlQ0 = SQIDLE; } //} break; case LRS0: _bufferIn_read[0].write(false); sqControlQ0 = LRS1; break; case LRS1: if(addressing_logic){ if(_bufferOut_busyIn[1].read() == false){ if(_qmux.trylock() > 0){ _outpktIn[1].write(_temp); _bufferOut_write[1].write(true); //_qmux.unlock(); sqControlQ0 = LRS2S; } else{ sqControlQ0 = LRS1; } } else{ sqControlQ0 = LRS1; } } else { if(_bufferOut_busyIn[3].read() == false){ if(_qmux.trylock() > 0){ _outpktIn[3].write(_temp); _bufferOut_write[3].write(true); //_qmux.unlock(); sqControlQ0 = LRS2E; } else{ sqControlQ0 = LRS1; } } else{ sqControlQ0 = LRS1; } } } else{ if(addressing_logic){ if(_bufferOut_busyIn[2].read() == false){ if(_qmux.trylock() > 0){ _outpktIn[2].write(_temp); _bufferOut_write[2].write(true); //_qmux.unlock(); sqControlQ0 = LRS2W; } else{ sqControlQ0 = LRS1; } } else{ sqControlQ0 = LRS1; } } else { if(_bufferOut_busyIn[0].read() == false){ if(_qmux.trylock() > 0){ _outpktIn[0].write(_temp); _bufferOut_write[0].write(true); //_qmux.unlock(); sqControlQ0 = LRS2N; } else{ sqControlQ0 = LRS1; } } else{ sqControlQ0 = LRS1; } } } break; case LRS2N: _bufferOut_write[0].write(false); _qmux.unlock(); sqControlQ0 = SQIDLE; //TODO: or maybe some other state break; case LRS2S: _bufferOut_write[1].write(false); _qmux.unlock(); sqControlQ0 = SQIDLE; //TODO: or maybe some other state break; case LRS2W: _bufferOut_write[2].write(true); _qmux.unlock(); sqControlQ0 = SQIDLE; //TODO: or maybe some other state break; case LRS2E: _bufferOut_write[3].write(true); _qmux.unlock(); sqControlQ0 = SQIDLE; //TODO: or maybe some other state break; default: break; } } } void SwitchFabric::sendDataQueues1(){ Packet _temp; if(rstn.read() == false){ if(_qmux.trylock() > 0){ _bufferIn_read[1].write(false); _bufferOut_write[1].write(false); _qmux.unlock(); } sqControlQ1 = SQINIT; } else{ //TODO: Working to transform it into a FSM /** * Cycle across multiple queues */ switch(sqControlQ1){ case SQINIT: //for(int i = 0; i < _NPORTS; i++){ _bufferIn_read[1].write(false); _bufferOut_write[1].write(false); //} sqControlQ = SQIDLE; break; case SQIDLE: //for(int i = 0; i < _NPORTS; i++){ if(_bufferIn_busyOut[1].read() != false){ _temp = _inpktOut[1].read(); _bufferIn_read[1].write(true); sqControlQ1 = LRS0; } else{ _bufferIn_read[1].write(false); sqControlQ1 = SQIDLE; } //} break; case LRS0: _bufferIn_read[1].write(false); sqControlQ1 = LRS1; break; case LRS1: if(Adressing_logic){ if(_bufferOut_busyIn[1].read() == false){ if(_qmux.trylock() > 0){ _outpktIn[1].write(_temp); _bufferOut_write[1].write(true); //_qmux.unlock(); sqControlQ1 = LRS2S; } else{ sqControlQ1 = LRS1; } } else{ sqControlQ1 = LRS1; } } else { if(_bufferOut_busyIn[3].read() == false){ if(_qmux.trylock() > 0){ _outpktIn[3].write(_temp); _bufferOut_write[3].write(true); //_qmux.unlock(); sqControlQ1 = LRS2E; } else{ sqControlQ1 = LRS1; } } else{ sqControlQ1 = LRS1; } } } else{ if(Adressing_logic2) ){ //this->_bufferOut[1].dataIn = _temp; if(_bufferOut_busyIn[2].read() == false){ if(_qmux.trylock() > 0){ _outpktIn[2].write(_temp); _bufferOut_write[2].write(true); //_qmux.unlock(); sqControlQ1 = LRS2W; } else{ sqControlQ1 = LRS1; } } else{ sqControlQ1 = LRS1; } } else { if(_bufferOut_busyIn[0].read() == false){ if(_qmux.trylock() > 0){ _outpktIn[0].write(_temp); _bufferOut_write[0].write(true); //_qmux.unlock(); sqControlQ1 = LRS2N; } else{ sqControlQ1 = LRS1; } } else{ sqControlQ1 = LRS1; } } } break; case LRS2N: _bufferOut_write[0].write(false); _qmux.unlock(); sqControlQ1 = SQIDLE; //TODO: or maybe some other state break; case LRS2S: _bufferOut_write[1].write(false); _qmux.unlock(); sqControlQ1 = SQIDLE; //TODO: or maybe some other state break; case LRS2W: _bufferOut_write[2].write(true); _qmux.unlock(); sqControlQ1 = SQIDLE; //TODO: or maybe some other state break; case LRS2E: _bufferOut_write[3].write(true); _qmux.unlock(); sqControlQ1 = SQIDLE; //TODO: or maybe some other state break; default: break; } } } Please, if anyone could advise me on how to proceed to have this as parallel process in any way, even if I have to t everything in the same process, but working as Threads I would appreciate it. P.S.: I saw in the internet people saying to use export SC_SIGNAL_WRITE_CHECK=DISABLE, and the problem disappear, it may disappear, but I'm not sure if this is the right fix in this case. Quote Link to comment Share on other sites More sharing options...
apfitch Posted May 12, 2015 Report Share Posted May 12, 2015 If you really want to do this, sc_signal has a template argument WRITER_POLICY which can be set to SC_MANY_WRITERS to allow you to have multiple writers to the same signal (as long as the writes occur in different deltas). See section 6.4.4 in the LRM. This may be what you want - but of course writing to a single object from parallel threads is always going to be "interesting" :-) regards Alan Quote Link to comment Share on other sites More sharing options...
Luis.Cargnini Posted May 12, 2015 Author Report Share Posted May 12, 2015 Thanks Alan, In HDL I would place this in separated process (different signals) and use a last process to unify, everything, or place this multiple process as one process and, since pretty much everyone is in a different channel. I was trying with for() interactions, but the problem is I have to test them independently not sequentially. Do you know if there is a way to have threads inside of a process ? this would make more sense than splitting into different process (in HDL would occur concurrence) in SystemC I'm not sure if things will happen sequentially, locking the entire processes flow in any given moment, especially in the following test: if(_bufferOut_busyIn[*].read() == false){ ...... } This line is the reason why I broke into multiple processes to avoid starvation in any interface with data while some may not have, and to control the flow of the ack signals. Also, could I wrote some code like : SwitchFabric:::SwitchFabric(){ SC_METHOD(sendDatasAcrossQueues) sensitive << rstn; sensitive clk.pos(); } ... void SwitchFabric::sendDatasAcrossQueues(){ SC_THREAD(sendDataQueues0); sensitive << rstn; sensitive clk.pos(); SC_THREAD(sendDataQueues1); sensitive << rstn; sensitive clk.pos(); SC_THREAD(sendDataQueues1); sensitive << rstn; sensitive clk.pos(); SC_THREAD(sendDataQueues1); sensitive << rstn; sensitive clk.pos(); } Regards Vitorio. Quote Link to comment Share on other sites More sharing options...
David Black Posted May 13, 2015 Report Share Posted May 13, 2015 You can launch processes from within a method using sc_spawn(). The SC_THREAD and SC_METHOD macros are only valid inside module constructors. By default sc_spawn() specifies SC_THREAD style behavior. If you need to specify static sensitivity, you will need to use sc_spawn_options. You could also use dynamic sensitivity and process control as an alternative. Quote Link to comment Share on other sites More sharing options...
Luis.Cargnini Posted May 15, 2015 Author Report Share Posted May 15, 2015 Thanks David,, I f using sc_spawn, ca I ahve multiple threads drivng a vector signal ? Because this is my main problem, currently. I have a process 0 that writes in vector[0] and process1 in vector[1], during simulation if raises a flag tha ttwo separated methods are trying to drive teh same signal, it is thea sam signal but not in the same position. I tried to fix that using 'consolidation approach' as explained in "a systemC Primer" page 135, but now I had the same problem. So now I'm trying the sc_spawn, but I'm not finding the way to use sc_spawn_options to set the sensitive list of the spawned process in the main process. Any links for examples ? Quote Link to comment Share on other sites More sharing options...
apfitch Posted May 16, 2015 Report Share Posted May 16, 2015 Hi Vitorio, the way the sc_signal code works is that it keeps track of the process handle of the first writer, and then if a write from a different process handle occurs, it is considered an error. Using dynamic processes and sc_spawn will still be considered as multiple writers, and you'll get the same error. There's an example of of sc_spawn/sc_spawn_options on page 66 of the Language Reference Manual. regards Alan 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.