Jump to content
mola

sc_port binding from parent module to module error

Recommended Posts

I have the following code:

class Top : public sc_core::sc_module{public:...  sc_port<tlm::tlm_fifo_get_if<tlm::tlm_generic_payload*> > read_pTx;  sc_port<tlm::tlm_fifo_put_if<tlm::tlm_generic_payload*> > write_pTx;...
private:  mysubmodule  *pmysubmodule;}
class mysubmodule: public sc_core::sc_module{public:

...

    sc_port<tlm::tlm_fifo_get_if<tlm::tlm_generic_payload*> > read_pTx;    sc_port<tlm::tlm_fifo_put_if<tlm::tlm_generic_payload*> > write_pTx;

...

}

In Top constructor:

SC_HAS_PROCESS(Top);Top::Top(...){pmysubmodule = new mysubmodule(...);pmysubmodule->read_pTx(read_pTx);pmysubmodule->write_pTx(write_pTx);}

 

It compliles well. But when I run the test, I got Segmentation fault error at line:

pmysubmodule->write_pTx(write_pTx);

In debug tool, it shows that it stops at

void
 sc_port_base::bind( this_type& parent_ )
 {
     if( m_bind_info == 0 ) {
         // cannot bind a parent port after elaboration
         report_error( SC_ID_BIND_PORT_TO_PORT_, "simulation running" );
     }

...

}

 

Does anyone know why and how to fix it?

 

Thanks a lot!

Share this post


Link to post
Share on other sites

Hi. 

 

For me, it is hard to say what the problem is without some more information. 

 

First, yes it is not allowed to bind ports after the elaboration phase. How and when do you instantiate the Top module? If you do this after calling sc_start, the mentioned error occurs. But this does no expllain a segmentation fault. 

 

Second, is there any channel bound to your ports?

In SystemC, you are allowed to bind ports to ports to cross hierarchy in the model. But finally, you have to bind a channel at any end of your hierarchy. The port solely forwards the interface of a channel. A channel provides the actual interface. 

 

Third, why do you use a pointer to a generic_payload object in your interface? Actually this is two questions. Why do you use a pointer?

And why do you use tlm_generic_payload? tlm_fifo_get_if belongs to TLM 1 modelling, tlm_generic_payload is part of the TLM 2 modelling concept. It is not forbidden to mix them. But you should have any reason to do so.

 

Greetings

Ralph

Share this post


Link to post
Share on other sites

Hi. 

 

For me, it is hard to say what the problem is without some more information. 

 

First, yes it is not allowed to bind ports after the elaboration phase. How and when do you instantiate the Top module? If you do this after calling sc_start, the mentioned error occurs. But this does no expllain a segmentation fault. 

 

Second, is there any channel bound to your ports?

In SystemC, you are allowed to bind ports to ports to cross hierarchy in the model. But finally, you have to bind a channel at any end of your hierarchy. The port solely forwards the interface of a channel. A channel provides the actual interface. 

 

Third, why do you use a pointer to a generic_payload object in your interface? Actually this is two questions. Why do you use a pointer?

And why do you use tlm_generic_payload? tlm_fifo_get_if belongs to TLM 1 modelling, tlm_generic_payload is part of the TLM 2 modelling concept. It is not forbidden to mix them. But you should have any reason to do so.

 

Greetings

Ralph

1. I instantiate the Top module before sc_start.

2. Yes. Channel will be bound to the Top port after Top is instantiated. But segmentation fault happens while Top is being instantiated.

3. I use a pointer because I think it more efficient than using the whole structure. Because I am using sockets and needs tlm_generic_payload. I tried to use sc_fifo. However, sc_fifo doesn't include the peek function. So I did some search and find the tlm_fifo is the way to go.

 

Thanks.

Share this post


Link to post
Share on other sites

Hi.

 

I tried to reproduce the problem but i couldn't. 

I used the following example and it did as expected.

 

#include <systemc.h>
#include <tlm.h>

class mysubmodule: public sc_core::sc_module
{
public:
    sc_port<tlm::tlm_fifo_get_if<tlm::tlm_generic_payload*> > read_pTx;
    sc_port<tlm::tlm_fifo_put_if<tlm::tlm_generic_payload*> > write_pTx;

SC_CTOR(mysubmodule)
{
}
};

class Top : public sc_core::sc_module
{
public:
  sc_port<tlm::tlm_fifo_get_if<tlm::tlm_generic_payload*> > read_pTx;
  sc_port<tlm::tlm_fifo_put_if<tlm::tlm_generic_payload*> > write_pTx;
private:
  mysubmodule  *pmysubmodule;

public:
SC_CTOR(Top)
{
pmysubmodule = new mysubmodule("sub");
pmysubmodule->read_pTx(read_pTx);
pmysubmodule->write_pTx(write_pTx);
}
};

int sc_main(int,char*[])
{
  tlm::tlm_fifo<tlm::tlm_generic_payload*> fifo("fifo");
  
  Top top("top");
  top.read_pTx(fifo);
  top.write_pTx(fifo);
  
  sc_start(20,SC_NS);
  
  return 0;
}

Share this post


Link to post
Share on other sites

Thank you Ralph.

I tried to debug it more and was able to fix it by adding

read_pTx("read"),

write_pTx("write")

to mysubmodule constructor explicitly.

I don't understand why I have to do this.

 

 

Share this post


Link to post
Share on other sites

hey
 


 
Second, is there any channel bound to your ports?
In SystemC, you are allowed to bind ports to ports to cross hierarchy in the model. But finally, you have to bind a channel at any end of your hierarchy. The port solely forwards the interface of a channel. A channel provides the actual interface. 
 

Hey Ralph, I have similar question:
 
I have class father, it has different classes inside, son1, son2.but these classes have the same generic class definition, say class son
then there is an another class, say,  class mother
 
now I want to use sc_method to run a function in class mother, which is sensitive to a variable called flag in class son...(i.e. there are actually two variables, in son1 and son2, but the definition of this variable is generic, which is in class son)
 
What I did is to define like following:
top: sc_signal<>flag
son: sc_out<>flag
mother: sc_in<>flag
 
 
And for binding the signal, i did like this
father1.son1.flag(flag)
mother1.flag(flag)
 
father1.son1.flag(flag)
mother1.flag(flag)
 
There is no compile error. But it doesn´t wrong..
 
The error is like below:


Error: (E112) get interface failed: port is not bound: port 'Top_1.intController1.int0.port_0' (sc_out)

In file: c:\data\systemc-2.3.0\src\sysc\communication\sc_port.cpp:230

 

You said it´s possible to bind cross hierachy, but how it´s realised

 

Thanks

 

Share this post


Link to post
Share on other sites

Generally, you should go through the hierarchy step by step. And you should name your ports and signals by passing an name argument to its constructor. That helps understanding the error messages. 

 

In sc_main: 

 

Father father("father");

Mother mother("mother");

sc_signal< > s_flag("s_flag")

 

// bind s_flag to father.flag and mother.flag

mother.flag(s_flag);

father.flag(s_flag);

 

 

In father: 

sc_in < > flag;

Son son;

 

SC_CTOR(Father) :

    flag("flag")

  , son("son")

{

  // bind father flag to son flag

  son.flag(flag);

}

Share this post


Link to post
Share on other sites

Hey Ralph,

 

thanks a lot. It works now. At the same time, I also found a similar example on cross hierarchy.

 

Now I came to question of sc_event on cross hierarchy. I set the sc_event as the sc_signal like above. but it does not work. any suggestion?

Share this post


Link to post
Share on other sites

Hi. 

 

Plain events (sc_event, not signal/channel events) are not bound to anything. If you want to use an event declared in module A inside of module B, you need a handle to that event. 

 

You can use named events (name them by passing a const char * argument to its constructor). Named events can be found either by searching the sc_object hierarchy manually (get_child_objects ...) or by calling sc_find_event. sc_find_event expects the *hierarchical* name of the event as an argument. 

 

For more information see section 5.10 in the SystemC LRM (IEEE 1666 - 2011).

 

Greetings

Ralph

Share this post


Link to post
Share on other sites

Hey Ralph, thanks.

 

But as you said sc_event is not bound to anything. So it´s could only be applied in the same module/ sub module, right?

 

The thing is, I have multiple modules instantiated in top. and between these modules I need to write to a shared memory. and there is one module which will read from this shared memory, i.e. module A/B/C/D, write to it, and module E read it.

 

But for sc_signal, it´s not allowed. I´m considering to use sc_semaphore, but after reading some reference books, i could not find this cross module application examples. 

 

thanks

Share this post


Link to post
Share on other sites

Hello again. 

 

 

To your first question: No. You can declare an sc_event wherever you want. And you can use them wherever you want. All you need to use them is a handle to the event and that is what you get from sc_find_event. 

A short example showing sc_find_event: 

#include <systemc.h>

SC_MODULE(A)
{
  sc_event ev;
  
  void proc()
  {
    std::cout << "notify ev: " << ev.name() << std::endl;
    ev.notify(5,SC_NS);
  }
  
  SC_CTOR(A) : ev("ev")
  {
    SC_METHOD(proc);
  }
};

SC_MODULE(
{
  sc_event ev;
  
  void proc()
  {
    wait(2, SC_NS);
    sc_event* evp = sc_find_event("modA.ev");
    if (evp != NULL)
    {
      wait(*evp);
      std::cout << "mod B activated" << std::endl;
    }
    else 
    {
      std::cout << "ev not found" << std::endl;
    }
  }
  
  void meth()
  {
    std::cout << "mod B method activated" << std::endl;
  }
  
  SC_CTOR( : ev("ev")
  {
    SC_THREAD(proc);
    
    SC_METHOD(meth);
    dont_initialize();
    sensitive << *sc_find_event("modA.ev");
  }
};

int sc_main(int, char*[])
{
  A a("modA");
  B b("modB");
  
  sc_start();
  return 0;
}

 

If you use sc_find_event in a static sensitivity list in the way shown here, be careful because the function might return NULL if the event is not found. In this case you get a memory access violation. Better check for NULL return before usage. 

 

 

In fact I am not sure if that solves your problem. at which level of abstraction do you want to model? Semaphores are high level constructs, signals RT level. In the sense of digital hardware at RTL, you should model explicit access infrastructure for the memory if you have multiple processes using it. You need some kind of arbiter an access protocol to handle concurrent access. At a higher level, with less timing accuracy, you can use a semaphore to arbitrate concurrent accesses and synchronize with sc_events. 

 

Greetings

Ralph

Share this post


Link to post
Share on other sites

Hey Ralph,

 

thanks. This really helps. The example is neat and easy to understand...I have not found the sc_find_event in my golden reference guide. 

 

##################################################

After rechecking my codes, I ran into another problem. 

I have a signal which is set to true in modules A and to false in module B.

A process in module C is sensitive to the signal. For triggering the process in module C, I tried to use two buffers: set_sig and clear_sig, with either the  sensitive list or event notification. Both work fine. Yet. I need to know the value of the signal for if-else calculation.

 

The values of the two signals are actually the same. I tried to use the sc_signal_resolved, with which I only need a signal. Yet the value of the signal remains the same, i.e. "X" (A="0", B="1")

 

Any suggestion?

Share this post


Link to post
Share on other sites

Think as an engineer.

A signal is the model of an electrical wire. If driver A sets a voltage of 5 V, and driver B sets a voltage 0 V to the same wire, what do you think what happens?

Thats why multiple drivers are not allowed for sc_signal. And thats why sc_signal_resolved becomes 'X' when you write '1' and '0' at the same time. You have to solve this problem in your architecture. Whenever multiple components may access the same resource, you should arbitrate them. Use whatever design pattern or bus-model you want, but you have to think about what should happen when two components access the memory at the same time.

Greetings

Ralph

PS: For new problems without connection to the topic of this thread, it might be better to open a new one.

Share this post


Link to post
Share on other sites

Hey Rahlph,

 

thanks for the explanation. Yes, you are right. That´s actually a hardware understanding..

 

I figured it with event and global variable,  though it´s not a good solution, since the shared memory issue of global variables. but it works...

 

thanks

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×