Jump to content
ANKUR SAINI

before_end_of_elaboration callback

Recommended Posts

I created a simple example to see how the callbacks are being called by the systemc simulation kernel. But I am little surprised with the output.
Can somebody explain or justify the output ?

CODE:
=============================

class analyzer : public sc_module {
  public:
  sc_out<bool> out_portA;
  sc_in<bool> in_portA;
  analyzer(sc_module_name nm) : out_portA("OUT_PORT_A"),in_portA("IN_PORT_A")
        {
            std::cout << "I am in analyzer constructor " << std::endl;
        }
  void before_end_of_elaboration(){
            std::cout << "I am in before_end_of_elaboration of " << name() << std::endl;
        }
  
};

class producer : public sc_module {
  public:
  sc_out<bool> out_portP;
  producer(sc_module_name nm) : out_portP("OUT_PORT_P")
        {
            std::cout << "I am in producer constructor " << std::endl;
        }
  void before_end_of_elaboration(){
            std::cout << "I am in before_end_of_elaboration of " << name() << std::endl;
        }
};

class consumer : public sc_module {
  public:
  sc_in<bool> in_portC;
  consumer(sc_module_name nm) : in_portC("IN_PORT_C")
        {
            std::cout << "I am in consumer constructor " << std::endl;
        }
  void before_end_of_elaboration(){
            std::cout << "I am in before_end_of_elaboration of " << name() << std::endl;
        }
};

class top_module : public sc_module {
  public:
  sc_signal<bool> sig1;
  producer p1;
  consumer c1;
  
  top_module(sc_module_name nm):sig1("SIG1"),p1("P1"),c1("C1")
        {
            std::cout << "I am in top constructor " << std::endl;
            p1.out_portP(sig1);
            c1.in_portC(sig1);
        }
  void before_end_of_elaboration(){
            std::cout << "I am in before_end_of_elaboration of " << name() << std::endl;
            analyzer a1("A1");
            //p1.out_portP(sig1);a1.in_portA(sig1);
            //sc_signal<bool> sig2;
            //a1.out_portA(sig2);c1.in_portC(sig2);
        }

};


int sc_main(int argc, char *argv[])
{
        top_module top("TOP");

        sc_start(1,SC_MS);
        sc_stop();
        return 0;
}

OUTPUT:
=============================
SystemC 2.3.0-ASI --- Feb 1 2014 18:12:06
Copyright (c) 1996-2012 by all Contributors,
ALL RIGHTS RESERVED

I am in producer constructor
I am in consumer constructor
I am in top constructor
I am in before_end_of_elaboration of TOP
I am in analyzer constructor
I am in before_end_of_elaboration of TOP.P1
I am in before_end_of_elaboration of TOP.C1

Info: /OSCI/SystemC: Simulation stopped by user.

Why it has not called the analyzer before_end_of_elaboration() callback ?
Also, can I alter/modify/redefine the port bindings in the top level before_end_of_elaboration callback (see the commented lines in top level callback)?

Share this post


Link to post
Share on other sites
13 hours ago, ANKUR SAINI said:

Why it has not called the analyzer before_end_of_elaboration() callback ?

Because your "analyzer" instance is a local variable in the before_end_of_elaboration function, which gets destructed immediately, when the function returns.  So there is no analyzer left to call the callback on later (same holds for the local signal sig2, btw.).  You would need to allocate the module dynamically instead.

 

13 hours ago, ANKUR SAINI said:

Also, can I alter/modify/redefine the port bindings in the top level before_end_of_elaboration callback (see the commented lines in top level callback)?

You cannot alter/modify/redefine any existing port binding at any time.  You can only add new bindings, including during before_end_of_elaboration.

Hope that helps,
  Philipp

Share this post


Link to post
Share on other sites

@Philipp A Hartmann

I really want to know the significance of "before_end_of_elaboration" callback in SystemC. On Doulos website (https://www.doulos.com/knowhow/systemc/new_standard/), it is mentioned that it can be used in the scenarios where we bind the module monitor ports to the top level singleton monitor channel.

Referring to the attached example, why are we not binding the module monitor ports to the top level monitor channel in the top level constructor ? Why the binding of ports is done in the particular module callback function ?

Also, what is the need of providing an additional callback function to instantiate module/ports when we can do the same thing in the constructor itself ?

monitor_channel.PNG

Share this post


Link to post
Share on other sites

You are right. It is usually best practice to bind the ports of a module to the corresponding channels in the constructor of the parent module. However, there are cases, where modules have ports, which do not correspond to physical ports of the component, but which rather expose internal state of the module for debug/monitoring purposes. Designers don't want to bind these ports under all circumstances in their parent/top-level module, but rather want to make that optional. However, all ports need to get bound for simulation. Therefore, SystemC provides you with the before_end_of_elaboration() callback as a mechanism to bind yet unbound ports to some dummy or global channels to make the elaborated model structure well-formed for simulation.

Share this post


Link to post
Share on other sites

@maehne: I got your point to some extent. So that means this callback is just provided to bind/create additional hierarchy which is not part of the actual design but rather helpful for debugging and understanding !!

Apart from this is there any other use-case of this callback which you think is worth explaining its existence inside the standard (Just to get little insight)

Share this post


Link to post
Share on other sites
8 hours ago, maehne said:

Designers don't want to bind these ports under all circumstances in their parent/top-level module, but rather want to make that optional. However, all ports need to get bound for simulation. Therefore, SystemC provides you with the before_end_of_elaboration() callback as a mechanism to bind yet unbound ports to some dummy or global channels to make the elaborated model structure well-formed for simulation.

If I am right, with SystemC 2.x onwards, it gave us a flexibility to still leave the ports unbound if they are defined with SC_ZERO_OR_MORE_BOUND binding policy.
Correct me in-case I am wrong.

Share this post


Link to post
Share on other sites
7 hours ago, ANKUR SAINI said:

@maehne: I got your point to some extent. So that means this callback is just provided to bind/create additional hierarchy which is not part of the actual design but rather helpful for debugging and understanding !!

Apart from this is there any other use-case of this callback which you think is worth explaining its existence inside the standard (Just to get little insight)

The different elaboration and simulation phase callbacks in SystemC are provided to allow external libraries to hook additional functionality into the elaboration and simulation phases of the SystemC kernel. E.g., the SystemC AMS extensions make heavy use of it to implement the elaboration of the AMS sub-models, which need to be clustered to sub-models that require their own dedicated solver, which handles then the execution of the sub-model and synchronisation with the SystemC kernel. Setting up specialised monitoring and tracing for your SystemC model, which goes beyond the sc_trace mechanism is also a common use case.

Share this post


Link to post
Share on other sites

To learn more about the different elaboration and simulation callbacks, I suggest you have a closer look to Clause 4.4 in IEEE Std 1666-2011. I states for each callback which kind of actions are allowed at the different moments and which are not.

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

×