Jump to content

Philipp A Hartmann

Members
  • Posts

    547
  • Joined

  • Last visited

  • Days Won

    135

Posts posted by Philipp A Hartmann

  1. First of all, it somewhat depends on the preemption scheme you need to support.  Are the serial threads preemptible while running one of their phases?  If not (and it looks like this in your description), you can refactor the model to only use M "real" SystemC threads, one for each parallel thread.

    The serial threads would then have an explicit "state" (i.e. the functional state and the phase they're) and the phases could be implemented as individual functions.  When a serial thread is resumed, you can simply call the corresponding phase function from its assigned "parallel thread".  Details left to the reader. ;-)

     

    hth,
      Philipp

  2. You can query the event() function of the signal, to check whether it has been triggered in the previous update phase (see IEEE 1666-2011, 6.4.9).  Of course, multiple signals might have been updated even though your process is only invoked once.

     

    Greetings from Oldenburg,
      Philipp

  3. No. The evaluation order of runnable processes is implementation-defined in SystemC, see IEEE 1666-2011, 4.2.1.2. There is no (standardized) backdoor API to influence the process scheduling of the kernel.

     

    Of course, you can add additional layers of scheduling on top of the SystemC scheduler, e.g. by defining your process dependencies and notifying properly crafted sc_events to trigger the successor process(es).

     

    Another option might be to model the system with the SystemC AMS extensions, which provides the timed dataflow (TDF) model of computation.  But this somewhat depends on the real requirements.  Additionally, the resulting TDF schedule can only be implicitly defined by constraining the scheduler in terms of process dependencies (AFAIK).
     

    Greetings from Oldenburg,
      Philipp

  4. I tried the SystemC installation with Pthread implementation, however, I got the following error message:

    "ERROR - could not create thread", which I believe is issued by sc_cor_pkg_pthread::create().

     

    You could try to print the return value of the pthread_create call via strerror (untested):

        int notok = pthread_create( &cor_p->m_thread, &attr,
                 &sc_cor_pthread::invoke_module_method, (void*)cor_p );
        if ( notok )
        {
            std::fprintf(stderr, "ERROR - could not create thread: %s\n", strerror(notok) );
        }
    

    You either set a too small stack size (EINVAL), or are running out of resources (number of allowed threads, memory limits) (EAGAIN).

     

     

    Also, I cannot use SC_METHODs as there is communication between threads using wait().

     

    You may need to rethink your modeling approach, given the huge number of processes you have.

     

     

    I am trying to switch to a 64-bit OS. However, it will take some time, as I need to re-install my whole system and application software to the new OS to be able to continue developing my project under the new system.

     

    Before reinstalling your OS, you can try to use a MinGW compiler, as mentioned in my previous answer.  If you run configure from within your Cygwin environment, specify the MinGW target and the MinGW compiler on the command-line:

    ../configure --target=i686-pc-mingw32 CXX=/path/to/mingw32/g++.exe
    

    BTW, I noticed a note by you from previous posts (see below) saying "Secondly, you should _NOT_

    use pthreads for your SystemC processes unless needed for very specific reasons".

    Could you explain why?

     

     

    Because performance-wise, Cygwin with Pthreads is probably the worst combination on Windows platforms.

     

     

    hth,

      Philipp

  5. That change allowed it to complete the linking. However, shouldn't the install scripts normally detect which compiler to use? The install scripts did not ask me for that information.

     

    There is indeed an issue in the Makefile.rules file, used when compiling the examples manually.  Due to some incomplete try to stay backwards-compatible with the old TLM Makefiles (which used CC instead of CXX), the Makefiles prefer CC over CXX (even for the linking) if explicitly set by the user.

     

    You should be able to fix the problem by changing all occurrences of $(CC) to $(CXX) in both examples/sysc/Makefile.rules and examples/tlm/build-unix/Makefile.rules. I'll queue up this change for a future release of the proof-of-concept simulator.

     

    Thanks for reporting,

      Philipp

  6. I think it would be fairly straight-forward to add an sc_event_or_list overload to set_sensitivity, as it would just be expanded and appended to the set of events the process is statically sensitive to.  For symmetry reasons, users would certainly want to have an sc_event_and_list overload as well, but this "mixed expression" sensitivity is currently not easy to add (e.g. to the proof-of-concept implementation) and nobody cared enough to propose an implementation.

     

    I agree that in your case there is some additional burden to work around this limitation.

     

    /Philipp

  7. Sure, set_sensitivity can be called after the start of the simulation.

     

    And yes, there are no overloads to use sc_event_and/or_lists for static sensitivity, mostly for historical reasons (and limitations in some implementations).

     

    But why not simply use them with dynamic sensitivity?  Simply store (a copy of) the event list in your module and use wait( event_list ) instead of a plain wait() inside your spawned process.

     

    hth,
      Philipp

  8. Oh, I should have mentioned that you can try to build your SystemC kernel with a Pthread threading implementation:

    ../configure [...] --enable-pthreads
    

    The stack size requirements might be different there.

     

    Alternatively, you can use a MinGW32 compiler (http://mingw-w64.sourceforge.net/), which then uses the native Windows threading facilities (WinFiber) under the hood.

     

    hth,
    Philipp

  9. Short answer: You can't.

     

    The current proof-of-concept simulator employs a stack protection mechanism to detect stack overflows by using the OSs memory protection mechanisms.  This requires an additional memory page (as a red zone) after the "real" stack.  As you have seen, this requires the minimum stack size to exceed a certain value.  0x1000 is certainly too small here. I would have expected that 0x10000 could work, but this seems not to be the case.

     

    If your threads are so small and simple, maybe you can port them to SC_METHODs.  Alternatively, you can try to switch to a 64-bit OS.

     

    /Philipp

  10. Q1) Is there a way to get the size of stack for each thread? Is there a method/function

    like get_stack_size()?

    No.  In SystemC 2.3.1, the platform-specific defaults are defined in sc_thread_process.h.  To obtain the default value used on your platform, you can query the SC_DEFAULT_STACK_SIZE constant in your application.

     

     

    Q2) How can I use set_stack_size() when invoking sc_spawn()?

    Use sc_spawn_options, see Section 5.5 in IEEE 1666-2011:

    sc_spawn_options opt;
      opt.set_stack_size(0x10000);
    sc_spawn( func, "func", &opt );
    

    Q3) My simulation is run in CygWin under Windows 7 (32-bit). Does 32-bit the OS impose a limitation

    to the stack size? In other words, can the problem be fixed using a 64-bit OS?

     

    Yes, on 32-bit OSs, the overall memory space for user applications is usually limited to 2GB (on Windows) and 3GB (on Linux).  On 64-bit OSs, this limitation is lifted.

     

    hth,

      Philipp

  11. In general, it is not different from a classical C++ shared library.  The details can't be answered without a more detailed question and/or problem description.

     

    If your "SystemC program" contains an sc_main, you can afterwards call "sc_elab_and_sim" from your scripting language to setup the kernel and the simulation model.  See Section 4.3.2 in the IEEE 1666-2011 standard.

     

    hth,
      Philipp

  12. The file visualc.hpp is part of the external Boost library, where a rather old version is partially packaged with SystemC.

     

    The documentation in the README file is correct.  You can safely ignore the warning during the build.

     

    The version check inconsistency has been fixed in SystemC 2.3.1 (among many other things).
    I would encourage you to update to the latest version.

     

    Greetings from Oldenburg,
      Philipp

  13. With the plain socket (interfaces), there is no way to determine the socket through which an interface function has been called.
     
    There are so called "tagged" convenience sockets provided as part of the TLM utilities (see IEEE 1666-2011, Section 16.1.3, including an example at the end of the section).
     
    This topic has been discussed here recently in this thread.
     
    hth,
      Philipp

  14. You can't use the "implement interface and export" idiom in this case, as you obviously can implement each function only once (for each transaction type).

     

    You can use a small wrapper instead:

    SC_MODULE(abc)
    {
      typedef int T;
      sc_core::sc_export<tlm::tlm_analysis_if<T> > exp_1, exp_2;
    
      SC_CTOR(abc)
        : exp_1("exp_1")
        , exp_2("exp_2")
        , aw_1(*this,&abc::write_1) // create wrapper for each implementation
        , aw_2(*this,&abc::write_2)  
      {
        exp_1(aw_1); // bind wrappers
        exp_2(aw_2);
      }
    
    private:
    
      void write_1( const T& ); // implementation for each export
      void write_2( const T& );
    
      struct analysis_wrapper
        : sc_core::sc_object, tlm::tlm_analysis_if<T>
      {
        typedef void (abc::*write_func)( const T& ); // pointer to member function with implementation
    
        analysis_wrapper( abc& owner, write_func f )
          : sc_core::sc_object(sc_core::sc_gen_unique_name("analysis_if"))
          , this_(owner), f_(f){}
    
        void write( const T& v ) { (this_.*f_)(v); } // forward call to registered implementation
    
       private:
        abc& this_;
        write_func f_;
      };
    
      analysis_wrapper aw_1, aw_2;
    };
    

    Hope that helps,
       Philipp

  15. I tried exactly this, but as the IEEE Standard §5.14.3 says, it should not be derived from sc_object.

     

    Yes, sc_interface itself is not derived from sc_object. But the channel that is bound to the port/socket is frequently derived from sc_object.  I didn't look up the details in the standard, but to me it may be a reasonable assumption that the bound object is indeed a proper part of the SystemC object hierarchy.

     

    For the convenience sockets simple_*_socket, this is also the case. I think I need to modify the binding operation to save the name of the binded Object.

     

    Indeed, the current implementation of the simple sockets use internal classes not derived from sc_object to provide the interface implementations.  To me, this is at least an inconvenience for use cases like yours.  I'll take this to the LWG/TLMWG for discussion.

     

    You may still be able to "lookup" the correct socket by traversing the object hierarchy (5.16.7) looking for candidate sockets and comparing the original result of 'get_interface()' with the interfaces of the candidates.  Or derive your own socket and override the bind() function to store the name.  Make sure to call the base-class bind() to actually perform the binding.

     

    /Philipp

  16. Would you say that sockets are the preferred construct for most data communication?

     

    I'm not sure, if I understand the question right.  How do you use 'b_transport' without sockets?

    Of course, technically, you can just use

    sc_core::sc_port<tlm::tlm_blocking_transport_if<my_payload> > > my_transport_port;

    but the you are quite far away from TLM-2.0. ;-)

     

    Sockets (or ports and exports) in general are a good idea to separate communication and computation.  This improves the modularity of your design.

     

    Using tlm_analysis_ports for data communication (in the modelled system) is probably not what you want either.

    But on the other hand, I don't know the details of your use case.

     

    /Philipp

  17. You can use b_transport and the convenience sockets with your custom payload class.

     

    First, you'll need the "my_protocol_types" traits class earlier in this thread.

    Secondly, due to the blocking/non-blocking conversions, the simple sockets depend on some features of the generic payloads internally (e.g. the memory management and extensions).  If you don't want to use this functionality, you can provide dummy implementations for these GP parts.  If you want the B/NB conversion to work, you should implement them properly, e.g. by reuising the relevant parts of the tlm_generic_payload class. 

     

    Instead, I would suggest to use the passthrough sockets, that don't perform any protocol conversions, see Section 16.1 in IEEE 1666-2011:

    SC_MODULE(my_module)
    {
      tlm_utils::passthrough_target_socket<my_module,32,my_protocol_types> socket;
      // ...
    
      SC_CTOR(my_module)
      {
        socket.register_b_transport(this,&my_module::my_b_transport);
      }
    
      void my_b_transport(my_item& trans, sc_time& delay)
      {
        // ...
      }
    };
    

    In general, TLM-2.0 is about interoperability.  It is meant to cover a wide range of modeling requirements across tool and model providers.  If you don't care about interoperability with third-party models, you're free to ignore many of the rules (and simply return an error for unsupported features, like byte enables, DMI, etc.).

     

    But I agree, the API and all details of the TLM-2.0 rules are quite complex and not made for beginners.  Model writers often rely on in-house or vendor-specific convenience layers on top.

     

    hth,
      Philipp

  18. I'm assuming, it is ok for you to have different sockets for these two b_transport functions.  The simplest solution is to use two tlm_utils::simple_target_socket instances and just register different functions for each of those:

    SC_MODULE(target)
    {
      tlm_utils::simple_target_socket<target> socket1;
      tlm_utils::simple_target_socket<target> socket2;
    
      SC_CTOR(target)
        : socket1("socket1")
        , socket2("socket2")
      {
        socket1.register_b_transport(this, &target::first_b_transport);
        socket2.register_b_transport(this, &target::second_b_transport);
      }
    
      void first_b_transport( tlm::tlm_generic_payload &, sc_core::sc_time & );
      void second_b_transport( tlm::tlm_generic_payload &, sc_core::sc_time & );
    };
    

    Alternatively, you can use tagged sockets and dispatch to different implementations based on the ID parameter.

     

    hth,
      Philipp

  19. 1) I am working on Visual C++ express 2010(windows 7 - 64 bit host) and To set 64 bit environment I have used:

    CALL "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /x64"

     

    Surprisingly using "vcvarsall.bat x64" throws following error:

    The specified configuration type is missing. The tools for the configuration might not be installed.

     

    The correct name of the configuration type for 64-bit differs between the MSVC toolchain versions/variants.

    Try one of 'amd64' or 'x86_amd64'. See READMEcommandlinemsvc.txt in examples/tlm/build-msvc.

     

    /Philipp

  20. Command Line:

    cl /FoHelloWorld.obj /c HelloWorld.cpp /TP /nologo /EHsc /GR /vmg /I<path_of_systemc-2.3.1>\src

    link /nologo /OUT:helloworld.exe /LIBPATH:<path_of_systemc-2.3.1>\msvc80\SystemC\x64\Release systemc.lib HelloWorld.obj

     

    Now, this gives me the same error for different systemc module: (Previously I got error w.r.t. to my other project)

    systemc.lib<sc_simcontext.obj> : fatal error LNK1112: module machine type 'x64' conflicts with target machine type 'x86'

     

    You still have not configured the correct target machine type for your application. Add '/MACHINE:X64' to your linker command-line.

     

    hth,

      Philipp

  21. My guess would be, that you didn't configure your application project in MSVC to be built as 64-bit application.  You need to (add and) select the 'x64' platform and make sure that the settings are consistent with the SystemC library project. You can use the project files for the examples as a starting point.

     

    Update: I should read the question properly.  Please forget the above answer.

     

    Using the command-line requires to select the "correct" set of tools for the platform you want to use.  Have a look at the TLM examples (examples/tlm/build-msvc), which provide command-line Makefiles for MSVC as well.  Most importantly, have a look at "vsvars.bat" in this folder, which can be used to choose the correct MSVC command-line configuration.

     

    You can then derive additional command-line settings from the "Makefile.config" file in the same directory.

     

    /Philipp

×
×
  • Create New...