Jump to content

Philipp A Hartmann

  • Content Count

  • Joined

  • Last visited

  • Days Won


Posts posted by Philipp A Hartmann

  1. The match will occur (almost) at the "correct" point in time during the simulation.  However, if you sample the value from an unrelated process, there might be some process evaluation ordering dependency (i.e. whether the update_method had already been run).  It depends on your requirements, whether this might be an issue. 

    If you do the checks outside of the simulation, i.e. between sc_start calls, you would need to complete the deltas (as per the loop sketched above) before every check. You cannot call sc_start during end_of_simulation.

  2. 27 minutes ago, TRANG said:

    But I want to pending in my code. Is it possible?

    I don't fully understand the question?  My snippet above runs all remaining delta cycles at the current time without advancing the time any further. You can wrap your original sc_start call with the loop in a small helper function (e.g. sc_start_including_deltas(...) , if you find yourself copying the snippet too often.

  3. sc_get_curr_process_kind() is non-standard.  You can use something like this:

    void stop_now()
       // Assuming: sc_set_stop_mode( SC_STOP_IMMEDIATE ); to avoid running other processes?
       auto p = sc_get_current_process_handle();
       bool is_thread_or_cthread = p.valid() && p.proc_kind() != SC_METHOD_PROC_;
       if( is_thread_or_cthread )


  4. Generally speaking, it would be a bug if the whole SystemC simulation is hanging inside a timed wait.  I suspect that you have in face a separate (set of) process(es) that are running indefinitely without advancing SystemC time (beyond these 4 ns).

    You can try to find the culprit by setting a breakpoint in a debugger on the affected line above, continue the simulation for a bit and then break, checking in which SystemC process you end up.  Maybe you are missing a similar "wait" on the consumer side?

    Hope that helps,

  5. 53 minutes ago, TRANG said:

    How to detect My_method sensitive by event1 or event2?

    In SystemC 2.3.2 and later, you can use the sc_event::triggered() member function to query, if an event was triggered (and thus might have caused your method to run):

    if( event1.triggered() ) {
      std::cout << "event1 got triggered";
    if( event2.triggered() ) {
      std::cout << "event2 got triggered";

    Please note that if both events were triggered in/for the same evaluation phase, your method might well be run only once.

  6. I gave it a shot locally and noticed that there are indeed quite some compiler warnings due to differences between __declspec(...) and __attribute__((visibility(...))). Most of these warnings can be ignored for now, but are certainly annoying.

    Additionally, you need to explicitly mark the following with SC_API as well:

    // src/sysc/communication/sc_port.h
    template <class IF>
    class SC_API sc_port_b
    template <class IF>
    class SC_API sc_port
    // src/sysc/communication/sc_prim_channel.h
    class SC_API sc_prim_channel_registry
    // src/sysc/communication/sc_signal.h
    template< class T, sc_writer_policy POL >
    class SC_API sc_signal_t
    template< class T, sc_writer_policy POL >
    class SC_API sc_signal
    // src/sysc/datatypes/sc_proxy.h
    template <class X>
    class SC_API sc_proxy
    // src/sysc/datatypes/sc_proxy.h
    extern "C" SC_API int sc_main(int argc, char* argv[])
    // src/sysc/utils/sc_temporary.h
    template<class T>
    class SC_API sc_vpool

    For compiling SystemC itself with -fvisibility=hidden, some further changes to the .cpp files are needed.  And some of the above changes might break the Windows DLL support.   But for me, the above changes work with the examples in the SystemC distribution (i.e. "gmake check CXXFLAGS='-fvisibility=hidden").

    Long story short: The feature to SystemC build models with limited symbol visibility will require more changes and testing.  I will forward this topic to the Language Working Group for further discussion.

  7. The INSTALL notes currently say the following about the SC_CPLUSPLUS preprocessor switch (emphasis mine):



    This setting allows downgrading the assumed version of the underlying C++ standard on the current platform.  By default, the latest supported version is chosen.

    Supported values are

    • SC_CPLUSPLUS=199701L (C++03, ISO/IEC 14882:1998, 14882:2003)
    • SC_CPLUSPLUS=201103L (C++11, ISO/IEC 14882:2011)
    • SC_CPLUSPLUS=201402L (C++14, ISO/IEC 14882:2014)
    • SC_CPLUSPLUS=201703L (C++17, ISO/IEC 14882:2017)


    This means, that you can explicitly opt-out of some SystemC features, that would generally be supported by your compiler's C++ language support.  Selecting a newer C++ standard version than supported by your compiler (setup) will typically not work - as you have experienced.

    That said, adding a preprocessor flag on the compiler command-line does not affect the language mode of the compiler.  How to switch your compiler to C++17 mode is outside of the scope of SystemC.  Your compiler (version) seems to require the -std=c++17 switch to enable this mode.  The SC_CPLUSPLUS flag is then not needed as it will be set automatically to the selected version.

    Hope that helps,

  8. 7 hours ago, taog said:

    It seems I can not use tlm2 socket like simple_initiator_socket/simple_target_socket in a pure C++ class which do not inherent from sc_module. Is TLM2 socket tight coupling with sc_module? Can I decouple this relationship?

    Yes, TLM sockets are dependent on SystemC and can only be used inside of a SystemC module.  This is because they are implemented via SystemC ports/exports, which can itself only be instantiated in SystemC modules as per the SystemC standard.

    If you want to bridge into a pure C++ model, you can pass the corresponding interface pointers into your C++ model via your own code (via get_interface() after elaboration).  This way, you only depend on sc_interface from SystemC (which is a base class of all SystemC/TLM interface classes) inside your C++ model.

    I'm not sure, what you are trying to achieve, though.  Why can't you use SystemC (which is just C++ at the end anyway)?

    Greetings from Duisburg,

  9. SystemC 2.3.2 (and later) does support a query whether an event was triggered in the previous delta cycle (or immediately in the current evaluation cycle).  This is similar to the sc_signal<>::event() function.  With this, you can ask every element in your array, whether it was triggered and may have caused a wakeup of the process.  Of course, multiple events can have triggered simultaneously and will only cause a single wakeup of the process.

    for( const auto ev& : e ) {
      if ( ev.triggered() ) {
        // ... 

    Hope that helps,

  10. 18 hours ago, Stephan Gerth said:


    Thanks! I can reproduce the behavior and verified that removing the dynamic sensitivity in sc_thread_process::kill_process fixes the issue:

    void sc_thread_process::kill_process(sc_descendant_inclusion_info descendants )
        // ...
        if ( sc_is_running() && m_has_stack )
            m_throw_status = THROW_KILL;
            m_wait_cycle_n = 0;
            remove_dynamic_events(); // <-- add this line to avoid the exception
        // ...

    I'm not sure, if it is necessary to do the same for the static sensitivity.  At least I haven't come up with a similar scenario, where the error is actually "incorrect".

  11. 14 hours ago, Roman Popov said:

    I don't know what "TDB" means here, but it seems like the case when sc_event_list resides on SC_THREAD stack was not considered here.

    I did write the above comment and the case where a (e.g. temporary) list lives inside a thread is certainly one of the reasons why we need a check for premature destruction.  Due to the nature how event lists are internally handled, we will run into a memory corruption if list is destroyed while a process is still waiting for it.

    What was not considered is the explicit kill() of a process that is current waiting on such a list.

    The easiest fix would be to cancel (dynamic) sensitivity before doing the stack unwinding when killing the process.

    @Stephan Gerth: Can you submit a pull-request with your example above as testcase against the SystemC regressions repository?

  12. 22 hours ago, KEVIN CHACKO said:

    If the threads in top_uvm2 are in a SC_JOIN or SC_JOIN_None implementation(both commented in code) the whole system works fine without any errors but the issue is with the SC_JOIN_ANY implementation. 

    If you use SC_JOIN or your SC_JOIN_ANY, you want to keep the run_phase active until all (or at least one) of the threads terminate(s).  Why can't you raise an objection here?  You will drop the objection after the join, so the phase can successfully complete. (Without joining, it's fine not to raise an objection).

  13. The error looks strange to me, as terminated_events is not destroyed before exiting run_phase, i.e. after the wait() has returned.  However, I don't know how the objections are implemented in UVM SystemC and whether or how wait() is supported without raising an objection.  Can you check with a debugger, if an exception is thrown while your run_phase function is inside the wait()?

    Hope that helps,

  14. 52 minutes ago, TRANG said:

    I can't set base name for each initiator_socket as my expected.

    ex:   initiator_socket[0]   : " initiator_0_socket"

             initiator_socket [ 1]    : " initiator_1_socket"

             initiator_socket [ 2]    : " initiator_2_socket"

             initiator_socket [ 3]    : " initiator_3_socket"

    For this, you can use a custom creator, e.g. a lambda function in C++11.  For a tagged socket, you anyway need to specify the tag in the for the callbacks, so doing the registration in the creator saves you another loop in your code:

    sc_core::sc_vector< tlm_utils::simple_initiator_socket_tagged<Router > > initiator_socket;
      [this](const char* /*unused*/, size_t idx) {
        std::stringstream ss;
          ss << "initiator_" << idx << "_socket";
        auto * socket = new tlm_utils::simple_initiator_socket_tagged<Router >( ss.str().c_str() );
        //socket->register_invalidate_direct_mem_ptr( ..., idx );
        return socket;


    Hope that helps,