Jump to content

DS1701

Members
  • Posts

    62
  • Joined

  • Last visited

  • Days Won

    1

Reputation Activity

  1. Like
    DS1701 reacted to Roman Popov in sequence processing   
    SystemC standard does not guarantee any order of process evaluation within a single delta cycle. So in first example  both 2,4 and 4,2 will be correct.
  2. Like
    DS1701 reacted to Eyck in Bus width of socket   
    Again, in your case you model a burst read which means in reality data gets transfered in several beats (32 in your case). Since your model does not deal with timing you wont notice that, all you see is that your data gets transfered.
    Look, TLM2.0 implements a generic bus protocol. Most of the real-world protocols have a so called burst transfer (e.g. checkout the AMBA specs). So the way to model this in an abstract way is to have a bust with and the amount of bytes being transfered in on bus transaction not in one beat. This way it is also possible to describe byte and half-word transfers.
    HTH
  3. Like
    DS1701 reacted to Vegh, Janos in Systemc performance   
    I'll surely do, but this was the first verified (by me) measurement. And, I wanted to know if it can be interesting for this audience. I will clean up the code and upload in the coming days. Although the absolute values of the data are not so meaningful, even I did the measurements in debug mode.
  4. Like
    DS1701 reacted to Philipp A Hartmann in timer with systemC   
    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.
  5. Like
    DS1701 reacted to Philipp A Hartmann in timer with systemC   
    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.
  6. Like
    DS1701 reacted to Philipp A Hartmann in timer with systemC   
    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 );  
  7. Like
    DS1701 reacted to Eyck in timer with systemC   
    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
  8. Like
    DS1701 reacted to David Black in How to Method work with event?   
    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>.
  9. Like
    DS1701 reacted to David Black in Timing in TLM   
    @Eyck I would point out that Timing Annotation is not limited to Loosely-Timed (LT) modeling, but can also be applied to Approximately-Timed (AT) models (see section 11.1 of IEEE-1666-2011); however, there is an important difference. LT timing annotation describes temporal decoupling as you explained. AT timing annotation is a way of indicating where a phase applies. This has some odd implications that are not immediately obvious.
    For instance, I can start an nb_transport_fw transaction with a non-zero annotated delay:
    tlm_phase phase { BEGIN_REQ }; sc_time time { 50_ns }; auto status = nb_transport_fw( payload, phase, time ); ///< begin transaction 50 ns in the future // Note that ns_transport_fw may increase the time (same as b_transport); however, it may not decrease the time. Section 11.1.3.1 describes this in detail.
    Why would this be done? Perhaps the initiator knows wants to dispatch a transaction and doesn't want to wait around to its initiation.
    I cannot immediately think of why the returned value might change, but it is legal.
    The main rule about time in SystemC requires that time never goes backward. No playing Dr. Who.
  10. Like
    DS1701 reacted to Philipp A Hartmann in sensitivity list   
    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.
  11. Like
    DS1701 reacted to Eyck in Timing in TLM   
    All of these relate to the concept of loosly-timed simulation. The basic principle behind this is that parts of the design can simulate larger time slices without returning control to the simulation kernel; the run ahead of the rest of the simulation. This is used e.g. for processors and alike as for quite some parts the do not interact with the rest of the design and create (a memory read does not really trigger any action other than returning some data). This way the simulation speed and hence the simulation performance can be drasticalliy improved but you trade performance for accuracy.
    This domain (or part of the simulation) running ahead of the simulation kernel is temporally decoupled. As such it needs some mechanism to control its local time (the amount it is ahead of the simulation kernel). This is done by the quantum keeper, the quantum is the amount of time the decoupled domain is allowd to be ahead at max. To allow interaction with the rest of the design all interaction need to carry some information what the local time in the dcoupled domain is, this is called timing annotation. This information is needed to either schedule events in the simulation kernel to happen at the correct time or to decide to break the quantum which means the decoupled domain is stopped and control is returned to the simulation kern until it reaches the local time of the decoupled domain, they are in sync then.
    HTH
  12. Like
    DS1701 reacted to David Black in sensitivity list   
    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
  13. Like
    DS1701 reacted to Eyck in TLM extension   
    Actually this is done in the desrtuctor of the tlm_generic_payload. This part calls for all extensions the free() function. So if out is handled properly destroyed all extensions are destroyed as well. The other option is to call free_all_extensions() explicitly which also calls free() for all extensions as well as for auto extensions (those might be registered when a memory manager for the generic payload is used, usually in AT style modelling using the non-blocking interfaces).
    HTH
  14. Like
    DS1701 reacted to David Black in sc_uint and unsigned int   
    First, let me say that I would never use sc_signal<unsigned int>. Instead use sc_signal<std::uint32_t> for portability reasons.
    There are two considerations:
    sc_signal<uint32_t> is likely to be significantly faster than sc_signal<sc_uint<32>>. Especially if using the PoC implementation. sc_signal<sc_uint<32>> may be required by some synthesis tools if that is something you care about. If you want to be agnostic to both situations, you could set up a typedef header for your project and use your own names.
  15. Like
    DS1701 reacted to Eyck in sc_uint and unsigned int   
    unsigned int has always the length defined by the underlying platform while sc_uint<> lets you specify the exact bit with of the type. In your case case I would use 'unsigned int' as it is faster and has less overhead.
    Best regards
  16. Like
    DS1701 reacted to David Black in simple socket   
    I would suggest that those for-loops need a better bound and should be coded:
    sc_assert( objA->initiator_socket.size() >= objB->target_socket.size() && objB->target_socket.size() > 0 ); for( int i=0;i<objA->initiator_socket.size(); ++i ) { objA->initiator_socket[i].bind(objB->target_socket[i]); } Coding rule: NEVER use a literal constant when a reasonable alternative is possible.
    Even when "in a hurry", you will not be disappointed if you use this rule.
     
  17. Like
    DS1701 reacted to Eyck in simple socket   
    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
  18. Like
    DS1701 reacted to David Black in Initial value port   
    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.
    Depend on the underlying datatype's initial value to initialize the signal (not very flexible) If using the specialized ports (sc_out and sc_inout only), call the initialize(T) method. 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?
    #include <systemc> #include <list> #include <iostream> using namespace sc_core; using namespace std; SC_MODULE( Source ) { sc_fifo_out< float > send_port; SC_CTOR( Source ) { SC_THREAD( source_thread ); } void source_thread( void ) { wait( 10, SC_NS ); send_port->write( 99.7 ); wait( 10, SC_NS ); std::cout << "Finished" << std::endl; sc_stop(); } // How to initialize output to contain following initial values? // { 4.2, -8.3e9, 0.0, 3.14 } // Do not add this to the thread. Instead, ensure that it happens before any thread executes. } }; SC_MODULE( Sink ) { sc_fifo_in< float > receive_port; SC_CTOR( Sink ) { SC_THREAD( sink_thread ); }; void sink_thread( void ) { for(;;) { std::cout << "Received " << setw(12) << receive_port->read() << " at " << sc_time_stamp() << std::endl; } } }; SC_MODULE( Top ) { // Constructor SC_CTOR( Top ) { m_source.send_port .bind( m_fifo ); m_sink.receive_port.bind( m_fifo ); } // Local modules Source m_source { "source" }; Sink m_sink { "sink" }; // Local channels sc_fifo< float > m_fifo; }; int sc_main( int argc, char* argv[] ) { Top top { "top" }; sc_start(); return 0; } Key concepts:
    SystemC is 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.
  19. Like
    DS1701 reacted to Roman Popov in Initial value port   
    Nice, I didn't know such a method exists! Looks like it does what you want.
  20. Like
    DS1701 got a reaction from Roman Popov in Initial value port   
    Thank @David Black and @Roman Popov
    Thank you so much!!!
    But I think that, initialize the value depend on specification model require.
    Ex:  Model A can reset Model B  with reset port active with LOW level
    Then sc_out<bool> resetPort; in the Model A must be set initialize the value for resetPort is 1 on constructor
    So I think that , Should set initialize the value of port on constructor
     -->  Clearly
    -->  Easy maintain source code
    / //A.h class A: public sc_module { public: sc_in<bool> clkAPM; sc_out<bool> resetPort; sc_signal<bool> sig; ... ///A.cpp A::A(sc_module_name name) :sc_module(name) // Initializing ,clkAPM("clkAPM") ,resetPort("resetPort") ,sig("sig") {//{{{ /// Initializing resetPort.initialize(true); sig.write(true); SC_METHOD(AMethod); dont_initialize(); sensitive << sig ; ...  
  21. Like
    DS1701 reacted to Philipp A Hartmann in Process sensitivity with sc_vector   
    Assuming you're using plain signal ports, you can use the event member function to check, whether a specific port has been triggered in the current delta cycle:

    sc_vector< sc_in< int> > in_vec; // ... SC_METHOD(proc); for( unsigned i= 0; i<in_vec.size(); ++i ) sensitive << in_vec[i]; // ... void proc() { for( unsigned i= 0; i<in_vec.size(); ++i ) if( in_vec[i]->event() ) std::cout << "in_vec[" << i << "] triggered." << std::endl; }
    Greetings from Oldenburg,
    Philipp
  22. Like
    DS1701 reacted to Roman Popov in Why sc_signal<T>::trace() is deprecated ?   
    Hi all, For debugging purposes it may be useful to add all signals in design to trace file. However, sc_signal::trace() which may allow to do it automatically is deprecated. Why is that?   In general I think it will be useful to add trace method to sc_interface, so that all channels that support tracing can implement it. And then it will be possible to implement something like: sc_trace_all(sc_trace_file *tf) // add all objects that support tracing to trace file.
  23. Like
    DS1701 reacted to David Black in Scope of SC_HAS_PROCESS   
    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 typedef called SC_CURRENT_USER_MODULE which refers to .... the current module name. It is only used in the three macros SC_THREAD, SC_METHOD and SC_CTHREAD. Syntactically, C++ allows a typedef to be created within a function (in this case the constructor function).
    Advantages of this approach:
    It's defined very close to the point of usage. The user of a header file, does not need to see it. /.h #import <systemc> // I never use systemc.h ... class Blah: sc_module { Blah(sc_module_name); ~Blah(); } //.cpp file #include "Blah.h" using namespace sc_core; Blah::Blah(sc_module_name nm): sc_module(nm) { SC_HAS_PROCESS(Blah); SC_THREAD(blah_thread); ... } Blah::~Blah(){ }  
  24. Thanks
    DS1701 reacted to Roman Popov in sc_spawn and anthoer process   
    If you want to pass a parameter to process, then you can use sc_spawn and std::bind to bind parameters.
  25. Thanks
    DS1701 reacted to Philipp A Hartmann in initialization problem with <sc_dt::sc_logic> port   
    The purpose of the initialize() function of the signal ports is to set the value of the bound signal at the beginning of the simulation through the given port.
×
×
  • Create New...