Jump to content

David Black

Members
  • Posts

    681
  • Joined

  • Last visited

  • Days Won

    152

Posts posted by David Black

  1. You are correct in the assessment that you have an infinite loop. You need some form of wait. wait(SC_ZERO_TIME) is not the best solution though.

    How about waiting on the sc_fifo::data_written_event()?

    Also, with the new version of SystemC (2.3.0), you can even create an sc_event_or_list so you can do the following (untested):

    sc_event_or_list fifo_written_event;

    for(int i=0; i!=10; ++i) {

    fifo_written_event |=fifo.data_written_event();

    }

    while(1){

    wait(fifo_written_event);

    for(int i=0; i!=10; ++i) { // Process all received

    if(fifo_in.nb_read(packet)){

    cout << "Packet received from Robot " << i << "\n";

    // processing

    }

    }

  2. I should probably note that using a non-default delay in my example probably does not make sense. Also this example could lose notifications in the sense that if SystemC has not yet serviced a notification, a subsequent notification will simply overwrite the previous one. I generally setup a handshake to ensure the external notifier knows it was received. You could also make a more elaborate notify method that sets/clears a "busy" flag. Be careful to properly protect shared data as Philipp points out.

  3. struct thread_safe_event_if

    : sc_core::sc_interface

    {

    virtual void notify(sc_core::sc_time delay = SC_ZERO_TIME) = 0;

    virtual const sc_core::sc_event& default_event(void) const = 0;

    protected:

    virtual void update(void) = 0;

    };

    struct thread_safe_event_channel

    : sc_core::sc_prim_channel, thread_safe_event_if

    {

    thread_safe_channel(const char* name);

    void notify(sc_core::sc_time delay = SC_ZERO_TIME);

    const sc_core::sc_event& default_event(void) const;

    protected:

    virtual void update(void);

    private:

    sc_core::sc_event m_event;

    sc_core::sc_time m_delay;

    };

    // The following may be safely called from outside the SystemC OS thread

    void thread_safe_event_channel::notify(sc_core::sc_time delay)

    {

    m_delay = delay;

    async_request_update();

    }

    const sc_core::sc_event& thread_safe_event_channel::default_event(void)

    {

    return m_event;

    }

    virtual void update(void)

    {

    m_event.notify(m_delay);

    }

  4. We're missing a lot of information. This forum is about SystemC coding, but you provided no code for us to comment on. I have no idea what your platform looks like nor what it is supposed to do. About the best advice I can give you at this point is to use a debugger (GDB) and set a breakpoint on sc_core::sc_stop. You can then look at the stack trace to determine where the code stopped. It does look like your design did something even though SystemC time did not appear to move forward. I am guessing this is a loosely timed (LT) model with 4 CPU cores. Don't have any idea what architecture.

    BOTTOM LINE: GIve us more information about the design if you want a more substantial answer.

  5. You are correct that SystemC does not automatically delete objects.

    The reason many coders ignore destructors for SystemC modules/objects is several fold:

    1. sc_object's (which includes sc_module's, sc_port's, sc_signal's, sc_prim_channel's, etc...) are created during elaboration and would not need to be destructed until the end of simulation when typically a SystemC program simply exits. Thus the operating system will mop up for you. For example:
      int sc_main(int argc, char* argv[])
      {
      top_module top_instance("top_instance); //< Construct the design hierarchy aka elaborate
      sc_start(); //< run the simulation
      return 0; //< exit the simulator and allow OS to clean up
      }
    2. SystemC coders are somewhat lazy and given the above example rationalize it away
    3. This is how they were taught (sad but true)

    That stated, it is probably worth noting that this situation may not always be the case, and some SystemC coders do write destructors (e.g. myself).

    It should be noted that in a co-simulation environment, the assumption of exiting after simulation may not be true. A vendor simulator might even presume to restart a simulation. Thus I argue it is better to create destructors as good C++ programming habit.

    TIP: Use the C++11 std::unique_ptr<T> instead of raw pointers. Assumes you can use this class. For older versions of C++, you might consider std::auto_ptr<T>, which is deprecated as I understand it.

  6. First, I never use sc_fifo_in<T> or sc_fifo_out<T> ports. Use sc_port<sc_fifo_in_if<T>> or sc_port<sc_fifo_out_if<T>>. The reason for the existence of those two specialized ports was backwards compatibility with SystemC 1.0 (Does anybody still use 1.0?).

    Just use the TLM FIFO and the TLM 1.0 interface appropriate to your needs. It's all part of SystemC 2.3.

    If you just have to use sc_fifo<> somehow (for what reason I cannot imagine), then derive a new FIFO class from sc_fifo<> and implement your own peek, but it will be non-standard. You could probably add multiple inheritance of the tlm_peek_if<T>.

  7. Actually, what happened in your first attempt was:

    1. At the class level you defined fifo_rx1

    2. Because you did not initialize it, the default constructor was used which has a default depth of 16.

    3. Inside your constructor, you created a second fifo with the same name and an explicit depth. Unfortunately because it was declared as data on the stack (how normal variables inside a function/method are created), this fifo immediately got deleted when the constructor function exited.

    Consider:

    void f(int a)
    double b = sqrt(a);
    }
    
    int sc_main(int argc, char* argv[]) {
    f(5);
    std::cout << "b=" << b << std::endl;
    }
    
    

    The above won't work because 'b' is only defined inside the function f().

  8. Since we do not see your source code, it is impossible to give you decent advice. Could you post the relevant source code?

    My second question (probably answered when you post): Where are you declaring/defining the FIFO? In a module as module data? Inside the constructor (bad idea)? In sc_main (not recommended)?

  9. WangYuchen,

    I am just adding to Philipps comment...

    Perhaps you do not understand the difference between channels (e.g. primitive channels such as sc_signal<T> or sc_fifo<T>) and data types (e.g. int or double). Channels represent hardware behaviors. In SystemC, hardware is only allowed to be declared and constructed before simulation begins during the "elaboration phase". Channels are used to transfer data between processes. They are NOT containers (e.g. array, struct or std::vector<T>). Thus sc_signal<int> is not a new type of data, but rather it specifies hardware that is able to safely transfer data between processes.

×
×
  • Create New...