Jump to content

TRANG

Members
  • Content Count

    51
  • Joined

  • Last visited

  • Days Won

    1

Posts posted by TRANG


  1. Master and Slave use same clock, so I think Slave need only care data_in.

    class slave : public sc_module {
        public:
        sc_in<bool> clk;
        sc_in<uint32_t> data_in;
        slave(sc_module_name name):clk("clk"),data_in("data_in"){
            SC_HAS_PROCESS(slave);
            SC_METHOD(run);
            dont_initialize();
            sensitive << data_in;
        }
        void run(){
            cout<<hex<<data_in.read()<<endl;
        }
        ~slave(){
        }
    };

    or

    class slave : public sc_module {
        public:
        sc_in<bool> clk;
        sc_in<uint32_t> data_in;
        slave(sc_module_name name):clk("clk"),data_in("data_in"){
            SC_HAS_PROCESS(slave);
            SC_THREAD(run);
            dont_initialize();
            sensitive << data_in;
        }
        void run(){
            cout<<hex<<data_in.read()<<endl;
        }
        ~slave(){
        }
    };

     


  2. 5 hours ago, Philipp A Hartmann said:

    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.

    Thank for your support,


  3. 7 hours ago, Eyck said:

    But what is the issue with running the simulation for 3*period?

    Best regards

    I'm sorry make you confused.

    Summary:

    if my test case is:

    sc_start(2*period,time_unit);
    while (sc_pending_activity_at_current_time()) {
            sc_start(SC_ZERO_TIME);
        }

    or

    sc_start(3*period,time_unit);

    then compare match occur.( is correct)

    If my test case is:

    sc_start(2*period,time_unit);

    then compare match don't occur .

    I want to my source code detect when time simulate near the over to pending to execute event m_update before over.


  4. 11 minutes ago, Philipp A Hartmann said:

    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.

    i try :

    void GTimer::end_of_simulation()
    {
        while (sc_pending_activity_at_current_time()) {
            sc_start(SC_ZERO_TIME);
        }
    }

    But It is not true?

    My problem is the time simulates is over before trigger event. I want to force trigger event before end simulate.


  5. 3 hours ago, Philipp A Hartmann said:

    You can run the delta cycles at the current time until everything settles:

    
    while( sc_pending_activity_at_current_time() )
      sc_start( SC_ZERO_TIME );

     

    Thanks @Philipp A Hartmann

    it is OK if I use :

    sc_start(2*period,time_unit);
    while( sc_pending_activity_at_current_time() )
      sc_start( SC_ZERO_TIME );

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


  6. 4 hours ago, Eyck said:

    If you run a simulation until a certain point it time the kernel stops before evaluating the processes at this time point. So if you schedule an event for lets say 100ns and simulate for 100ns then the process being sensitive to this event will not be executed (yet). So this is intended behavior.

    BR

    Thank @Eyck

    I understand that. Do you have any idea for this problem? How to resolve?

    Thanks very much.


  7. Hi all,

    I'm using systemC to build timer model. ( Timer support compares match, overflow, underflow)

    //constructor
        SC_METHOD(evaluate_method);
        dont_initialize();
        sensitive << m_evaluate;
    
        SC_METHOD(update_method);
        dont_initialize();
        sensitive << m_update;
    void GTimer::evaluate_method()
    {
        //check if compare match
        if(CNT_value == compare_match_value){
             compare_match_handling();
        }
        ...
         m_update.notify((double)period * compare_match_value, time_unit);
    }
    void GTimer::update_method()
    {
        CNT_value = get_counter_value();
        m_evaluate.notify();
    }
    GT_API unsigned int GTimer::get_counter_value()
    {
        unsigned int value;
        sc_time current_time = sc_time_stamp();
        value = (current_time.to_double() - start_time.to_double()) / period;
        return value;
    }

    Ex:

    I set compare_match_value = 2;

    period = 1000.0

    time_unit = SC_PS

    when I start timer and simulate on 2* period

    sc_start(2*period ,time_unit)

    compare match don't occur. because the time simulate is over but m_update event not trigger.

    If I start timer and simulate on 3* period

    compare match occur.

    Do you have any idea? ( I want to compare match occur when I start timer and simulate on 2*period)

    Thank all.


  8. On 12/13/2017 at 4:15 AM, CapUnderPantsRLZ said:

    "Personally, I prefer to put SC_HAS_PROCESS directly into the constructor body, which works very reliably. All that SC_HAS_PROCESS does is to create a  "

    : "All that SC_HAS_PROCESS does is to create a ", now explain to your compiler to 'construct' something, that it was not defined before the constructor call. do you do that? ) That it is precisely why the authors of SystemC: From the Ground Up, explained to place SC_HAS_PROCESS before the constructors.

    GCC,  lets this kind of 'thing' pass, try with Clang++ now.

     

    don't place that in the header file, instead, it is in , ., (whatever extension you are using) that will contain it inside your own namespace if it is the case.

    Hi @CapUnderPantsRLZ

    in 1666-2011.pdf

    Quote

    macro SC_HASS_PROCESS shall be invoked within the class definition or the constructor body of the module.

    So, I think @David Black is exactly.

    https://stackoverflow.com/questions/45308468/systemc-multiple-module-implementations-in-single-cpp-file


  9. 12 hours ago, David Black said:

    Notify (either case) is non-blocking, so your call to notify followed by initialize will happen. Then after you return, the notified element(s) may execute.

    Notify() implies execution will be in the same delta-cycle; whereas, notify(SC_ZERO_TIME) postpones to the next one and allows other processes in the current delta-cycle to complete.

    Take a look at <https://github.com/dcblack/SystemC-Engine/blob/master/Engine_v2.4.pdf>.

    Thank you so much, @David Black


  10. Hi all,

    I try code bellow

    SC_METHOD(APMMethod);
    sensitive << mAPMEvent;
    ...
    void APMMethod(){
      printf("Reset port\n");
      ...
    }
    ...
    void Initialize()
    {
       for(unsigned int i=0; i< 50; i++){
           mAPM_reg[i].value = 0;
           printf("Initialize %s\n",mAPM_reg[i].name);
        }
    }
    ...
    void EnableReset(){
        //reset port
        mAPMEvent.notify(SC_ZERO_TIME);
        //initialize reg
        Initialize();
    }
     

    When EnableReset occur. 

    My output is:

    Intialize APM_REG1
    Intialize APM_REG2
    ...
    
    Reset port

    I try with 

    mAPMEvent.notify();

    But the same output.

    1. why Initialize() call before APMMethod().

    2. when to use notiffy() or notify(SC_ZERO_TIME)?

    Thanks all.


  11. 36 minutes ago, Philipp A Hartmann said:

    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.

    I can't see that because my lib is 2.3.1.

    So, with 2.3.1, we don't have a solution.

    Thank Philipp.

     


  12. On 5/23/2019 at 5:01 PM, David Black said:

    You can only specify sensitivity on objects that have events or event finders directly accessible at the time of construction. Normally this means using either a suitable channel, port or explicit event. If you wrap your int's with a channel such as sc_signal<T>, you can do it.

    Example - https://www.edaplayground.com/x/5vLP

    Hi @David Black,

    If I have

    sc_event event1;
    sc_event event2;
    ...
    SC_METHOD( My_method );
    sensitive << event1 << event2;
    dont_initialize();

    How to detect My_method sensitive by event1 or event2?


  13. I read some source code.

    class TlmExtension : public tlm_extension<TlmExtension>
    {
      ...
    };
    void setExtension(tlm::tlm_generic_payload &in, tlm::tlm_generic_payload &out)
    {
        TlmExtension *input  = (TlmExtension *)0;
        TlmExtension *output = new TlmExtension;
        in.get_extension(input);
        if (input != NULL) {
            output->setNum(input->getNum());
            output->setChannel(input->getChannel());
            out.set_extension(output);
        }
    }

     

    I think above code is wrong. Because of when exit  setExtension  function. We cant delete object create by new operator (output )

    How to resolve this problem?  Thanks.

    BR.

     


  14. I'm learning simple socket with 2 examples:

    ex1: https://www.doulos.com/knowhow/systemc/tlm2/tutorial__3/tlm2_getting_started_3.cpp

    ex2: in lib : systemc-2.3.3\examples\tlm\common\include\models\SimpleBusLT.h

    I know that :

    //Initiator
    tlm_utils::simple_initiator_socket<Initiator>            initiator_socket;
    ...
    tlmTrans.set_data_length(emdata_length);
    tlmTrans.set_data_ptr(emdata_ptr);
    initiator_socket->b_transport(tlmTrans, localTime);
    ...
    //Target
    tlm_utils::simple_target_socket<Target>            target_socket;
    ...
    target_socket.register_b_transport(this, &Target::b_transport);
    ...
    virtual void b_transport(tlm::tlm_generic_payload& trans, sc_time& delay)
    {
    	//receive data from tlmTrans Initiator
    }

    I only understand "register_b_transport" function.  But I see others function , Can you explain it? and how to use?

    //Initiator
    initiator_socket.register_invalidate_direct_mem_ptr(this, &Initiator::invalidateDMIPointers);
    
    ...
    //Target
    target_socket.register_b_transport(this, &Target::initiatorBTransport);
    target_socket.register_transport_dbg(this, &Target::transportDebug);
    target_socket.register_get_direct_mem_ptr(this, &Target::getDMIPointer);

     


  15. 24 minutes ago, AmeyaVS said:

    Hello @TRANG,

    You probably need to change from this:

    
    sc_vector< simple_initiator_socket_tagged<Router >* > initiator_socket;

    to this:

    
    sc_core::sc_vector< tlm_utils::simple_initiator_socket_tagged<Router > > initiator_socket;

    And to understand the better use of sc_vector you can probably search and find many references on  using sc_vector in the forum or on stackoverflow such as these ones:

    Hope these helps.

    Regards,

    Ameya Vikram Singh

    Thanks @AmeyaVS

    how to set base name for each initiator_socket?

    Suppose, I have initiator_socket[4]. I only initialize initiator_socket as bellow code.

    sc_core::sc_vector< tlm_utils::simple_initiator_socket_tagged<Router > > initiator_socket;
    ...
    ///
    Router::Router():initiator_socket("initiator_socket",4)
    {}

    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"


  16. 4 hours ago, Eyck said:

    Just looked further: there is a typo in case 1. It should read

    
    //bind
      for(int i=0;i<3;i++){
        objA->initiator_socket[i]->bind(*(objB->target_socket[i]));
      }

    as you use an array of pointers. Again, sc_vector eases your life:

    
    //Model A
    sc_core::sc_vector<tlm_utils::simple_initiator_socket_tagged<ModelA>> initiator_socket;
      ...
    // Model B
    sc_core::sc_vector<tlm_utils::simple_target_socket_tagged<ModelB>> target_socket;
      ...
    //bind
      for(int i=0;i<3;i++){
        objA->initiator_socket[i].bind(objB->target_socket[i]);
      }
                         
        

    The same applies to case 2:

    
    //bind
    objA->initiator_socket1->bind(*(objB->target_socket2));
    objA->initiator_socket2->bind(*(objB->target_socket3));
    objA->initiator_socket3->bind(*(objB->target_socket1));

    Best regards

    Thank @Eyck @David Black

     

    ///Constructor 
    for (unsigned int channel = 0 ; channel < NUM_CHANNEL ; channel++) {
        char socketName[100];
        sprintf(socketName,"initiator%d",channel);
        initiator_socket[channel] = new tlm_utils::simple_initiator_socket_tagged<ModelA>(socketName);
    }
    ....

    I want to use pointer to set name for each inittiator_socket[channel] (as above code I used "socketName" variable)

    @Eyck Can you show me how to use sc_vector and set name for each inittiator_socket? 

    Thanks all.


  17. Hi all,

    I want to understand more about simple_initiator_sọket and simple_target_socket. How is it working??

    Suppose, "Model A 3 initiator" -->  <-- "3 target Model B"

    Case 1:

    //Model A
    tlm_utils::simple_initiator_socket_tagged<ModelA>* initiator_socket[3];
      ...
    // Model B
    tlm_utils::simple_target_socket_tagged<ModelB>* target_socket[3];
      ...
    //bind
      for(int i=0;i<3;i++){
        objA->initiator_socket[i]->bind(objB->target_socket[i]);
      }

    Case 2:

    //Model A
    tlm_utils::simple_initiator_socket_tagged<ModelA>* initiator_socket1;
    tlm_utils::simple_initiator_socket_tagged<ModelA>* initiator_socket2;
    tlm_utils::simple_initiator_socket_tagged<ModelA>* initiator_socket3;
      ...
    // Model B
    tlm_utils::simple_target_socket_tagged<ModelB>* target_socket1;
    tlm_utils::simple_target_socket_tagged<ModelB>* target_socket2;
    tlm_utils::simple_target_socket_tagged<ModelB>* target_socket3;
      ...
    //bind
    objA->initiator_socket1->bind(objB->target_socket2)
    objA->initiator_socket2->bind(objB->target_socket3)
    objA->initiator_socket3->bind(objB->target_socket1)
    

     

    Question 1: Is both above code is correct?                   

    Question 2: In case 2,  I set "bind" between Model A and Model B (unordered declare, initiator_socket1 with target_socket2 ,..... ). Is it right?         

    Thanks all.


  18. On 12/15/2018 at 7:24 PM, David Black said:

    The 'initialize(T)' method is a leftover from SystemC 1.0 circa 1999, when SystemC had not yet properly abstracted the port/channel concept. At that point in time, there was a stronger emphasis on making SystemC look like Verilog or VHDL. The 'initialize(T)' method is only present on the 'sc_out<T>' and 'sc_inout<T>' port classes, as part of their partial template specialization. The 'initialize(T)' method is not generally available to 'sc_port<>'.

    I usually don't mention it because then the reader gets the wrong impression that 'initialize(T)' should be present everywhere. In fact, it is only useful for RTL aspects. Certainly, this is not part of TLM.

    Since SystemC is more about abstraction and modeling, I avoid it. It is straightforward to override start_of_simulation.

    @TRANGIt is important for you to understand this distinction. I realize that the specification may say that "port is initialized to zero" or some such, but the concept of port in the specification is quite different than the concept of port in SystemC. If you don't understand this, you will hobble your understanding of SystemC. So there are three ways in SystemC of modeling what the specification says regarding an output pin on a hardware design.

    1. Depend on the underlying datatype's initial value to initialize the signal (not very flexible)
    2. If using the specialized ports (sc_out and sc_inout only), call the initialize(T) method.
    3. Write to the port during start_of_simulation, which is the most general and powerful approach.

    Challenge: How would you initialize an sc_fifo< float > connected to an sc_fifo< float > channel with four values?

    Key concepts:

    • SystemCis a modeling language mapped on top of C++.
    • SystemC ports are not signals or pins.
    • sc_in<T>, sc_out<T> and sc_inout<T> are partial template specializations of sc_port<T> on the respective sc_signal<T> interface classes.
    • For historic reasons (SystemC 1.0), there are extra methods added to these specializations including initialize(T), read(), and write(T) that can later confuse novice SystemC programmers.

    I usually don't use sc_fifo ( only use sc_signal, sc_in, sc_out ). But I don't see any function  initialize the value for sc_fifo . Both "write()" and "nb_write()" (sc_fifo) will call to sc_prim_channel::request_update() . So I think , sc_fifo can set value for buffer ( this isn't called initialize the value forbuffer )

    Thank you so much!!! @David Black

×