Chapter 2: Core Modeling

Modules, Hierarchy, and Elaboration

How SC_MODULE, constructors, object names, and hierarchy registration shape the simulation.

SC_MODULE is a convenience macro around a C++ class derived from sc_module. It exists because SystemC needs more than C++ object construction. The kernel also needs names, hierarchy, and process registration.

#include <systemc>
using namespace sc_core;
 
SC_MODULE(Producer) {
  sc_out<int> out{"out"};
 
  SC_CTOR(Producer) {
    SC_THREAD(run);
  }
 
  void run() {
    for (int i = 0; i != 4; ++i) {
      out.write(i);
      wait(10, SC_NS);
    }
  }
};
 
SC_MODULE(Consumer) {
  sc_in<int> in{"in"};
 
  SC_CTOR(Consumer) {
    SC_METHOD(process);
    sensitive << in;
    dont_initialize();
  }
 
  void process() {
    std::cout << "Consumer received: " << in.read() 
              << " at " << sc_time_stamp() << std::endl;
  }
};
 
SC_MODULE(Top) {
  sc_signal<int> data{"data"};
  Producer producer{"producer"};
  Consumer consumer{"consumer"};
 
  SC_CTOR(Top) {
    producer.out(data);
    consumer.in(data);
  }
};
 
int sc_main(int, char*[]) {
  Top top{"top"};
  sc_start(100, SC_NS);
  return 0;
}

The macro form is popular because it is compact. You can also write explicit C++ classes derived from sc_module, which is useful when templates or inheritance become more important than brevity.

Names Matter

Every SystemC object has a name in the hierarchy. These names show up in reports, traces, and errors. A module created as Producer producer{"producer"} becomes part of the object tree. A port named out becomes producer.out.

Good names are not cosmetic. They are your debugging map.

Elaboration Is the Build Step Inside the Executable

During elaboration, the kernel discovers the object hierarchy and checks structural rules. This is where port binding errors often appear. For example, an unbound port may not fail at C++ compile time, because the compiler only sees objects and function calls. The SystemC kernel detects whether the model graph is valid.

Child Modules

Hierarchy is just composition:

Top modules construct their children and manage connections. (Note: The definitions of Producer, Consumer, and Top are already included in the full example above.)

Construct child modules before binding them. This style keeps topology in the parent constructor, where readers expect to find it.

Source-Code Angle

In the reference implementation, module construction participates in a global simulation context. The context keeps track of the current hierarchy scope while constructors run. That is how a child object can learn where it belongs without you manually passing a full hierarchical path into every port, channel, and module.

The big idea: SystemC uses ordinary C++ construction, but overlays a hierarchy-tracking discipline on top of it.

Comments and Corrections