Jump to content

David Long

  • Content Count

  • Joined

  • Last visited

  • Days Won


Posts posted by David Long

  1. Hi Karandeep,


    We presented a paper "A Beginner's Guide to Using SystemC TLM-2.0 IP with UVM" at several European Synopsys User Group (SNUG) meetings in 2012. This included a discussion of using the Generic Payload in a UVM environment which may help. You can download it from the "KnowHow" pages on the Doulos website - http://www.doulos.com/knowhow/sysverilog/SNUG12_uvm_tlm2/




  2. Hi Amit,


    Are the dynamic and static processes or the spawned and unspawned processes same concepts?????


    Pretty much - static processes are created using the SC_METHOD and SC_THREAD macros. Dynamic processes are created by calling sc_spawn. There is one slight complication, calling sc_spawn from a module's constructor will actually create a static process since the LRM defines a dynamic process as one created from "the end_of_elaboration callback or during simulation" (see Glossary B.51). The LRM uses the term "spawned" and "unspawned" to try to avoid this confusion!




  3. Hi Amit,


    The scheduling mechanism for sc_mutex and sc_semaphore is very simple and does not have fifo characteristics (i.e. if several processes are waiting for the mutex/semaphore, they are not granted it based on the order in which they requested it - although there is nothing to stop an implementation of SystemC from executing processes in the same order as they are added to the list of runnable processes, the LRM says that the order is implementation defined).


    The basic operation of a set of processes using a mutex/semaphore could be like this:


    1) a process runs and grabs the free mutex/semaphore, it then hits a wait before releasing it

    2) other processes run and attempt to grab the mutex/semaphore. If it is not free, the processes wait (for an event that is within the mutex/semaphore object)

    3) the process with that has grabbed the mutex/semaphore wakes up and frees the mutex/semaphore - this issues an immediate notification on the mutex/semaphore's internal event

    4) the processes waiting for the mutex/semaphore get added to the list of runnable processes. One of them starts executing and grabs the mutex/semaphore but hits a wait statement before releasing it

    5) the remaining processes in the list of runnable processes will each start executing in the same evaluation phase, but now the mutex/semaphore is locked by the process that started in step 4 so they will block again until the next notifcation of the mutex/semaphore event (as in step 3)

    Steps 3 to 4 are repeated until the end of the simulation or until every process has completed its access to the shared resource


    Hope that is enough to give you the idea!




  4. Hi Amit,


    I think you are talking about semaphore and mutex in the context of an embedded, multi-threaded software system here. SystemC does not provide all of the features required to model that kind of system (for example there is no built-in scheduler that supports process priorities and pre-emption.


    The SystemC mutex and semaphore classes run in the evaluation phase and use immediate event notifications so cannot be used to control which process gets access to a shared resource if several are waiting for the mutex/semaphore. sc_mutex and sc_semaphore use the same scheduling mechanism.




  5. Hi KS,


    By default, proc1 runs once during the initialization phase (unless dont_initialize() is called immediately after SC_METHOD(proc1) in the module constructor).

    Once proc1 has executed, the next_trigger statement changes its sensitivity so that from then on it will be called whenever event x is notified, not when clk has an event.




  6. Hi Amit,


    I would not say that next_trigger is "like a delay element" since it does not hold up execution of an SC_METHOD (which would be illegal). It overrides the static sensititivity of an SC_METHOD and so changes the conditions which next cause the method to execute. There is an example on page 51 of the LRM.




  7. Hi Amit,


    A mutex is used to ensure mutual-exclusive access to a shared resource. Think of it as being like having a single key to unlock access to the resource that you pass between processes that request it. Only one process can have it at a time - any other process that wants it will have to wait until the key becomes available.


    A semaphore is similar but is more like a bucket containing multiple keys. You can set the number of keys in the bucket when it is created, processes request keys just like the mutex and will have to wait ("block") when no key is available. However, unlike the mutex, you can have multiple processes accessing the resource in the same time interval.




  8. Hi KS,


    Hello Dave ,


    Correct me ,


    If I would say the process using static/dynamic sensitivity are static/dynamic process respectively , would be correct statement??????


    If above is true then what would be called for a process implementing both static and dynamic events in the same ??? 





    No, you are mixing up static/dynamic sensitivity with static/dynamic processes. You can for example have a static process (e.g SC_THREAD) that makes use of dynamic sensitivity (e.g wait(x) ) or a dynamic process (sc_spawn) with static sensitivity (using sc_spawn_options - see section 5.5 of the LRM)).




  9. Hi,


    Because process 2 has to suspend and wait for event x, and because event x is only notified by process 1, the state of the instructions seen by process 2 when it wakes up will alway depend on what has happened in process 1 or process 3. Once a process is active, it will remain active until either it reaches the end of the function or it reaches a wait statement. Only one process can be active at the same time. The SystemC scheduler does not currently allow one process to pre-empt another (this feature might be added to a future version).


    This confirms your assumption above  "So the answer to question, that in process P2 does the instruction 3 will get the updated value of instruction 1-2 of the same process P2.?

    is NO."




  10. Hi Amit,


    Static processes are created before the start of simulation, by calling e.g. SC_THREAD macro or sc_spawn in the constructor or end_elaboration callback.


    Dynamic processes are created by calling sc_spawn within another process (which will not be executed until the simulation is running).




  11. Hi KS,


    Before answering your question, it is worth pointing out the way the SystemC scheduler works. After inititialization, it advances time to the earliest time step where there is a scheduled event notification. It adds all processes that are sensitive to that event (or other events at the same time step) into a list of "runnable" processes. It then resumes execution of every process in the list of runnable processes (one at a time) in some non-deterministic order. This is known as the evaluation phase. An immediate event notification can add processes to the list of runnable processes within the current time step, provided such processes are currently waiting for that event.  Once the list of runnable processes is empty, the scheduler proceedes to the update phase where primitive channels (such as sc_signal) that have been written to, get updated. These primitive channels may be in the sensitivity list of other processes, in which case there is another iteration of the evaluate and update phases known as a delta cycle. This continues until there are no more events to process at the current time step, when the scheduler advances to the next time step.


    Now, sssuming all of your processes above are within infinite loops, then after the end of the initialization phase, P1 and P3 will be suspended at their wait() statements and P2 will be waiting for an event on x.


    When the event in P1 and P3's static sensitivity list happens, both processes get added into the list of runnable processes in the current time step. P1 or P3 will then run. If P1 runs first, it will notify event x immediately, this will add P2 to the list of runnable processes. The next process to run could be either P2 or P3.


    Since P2 always waits for the event notified by P1, it will always run after P1 in any simulation cycle.


    It's not clear to me what instruction1,etc are doing. If they are just variables that are being read and written, then P2 could see the values written by P1. However, P3 could be executed after P1 but before P3. In which case P2 would see the values written by P3. We cannot predict what will happen (although the order will always be the same every time the simulation is run). Instruction3 in P2 would see the values of instruction1/2 set by P1 or P3, depending on the order that the scheduler executes the process.


    Hope that makes it a bit clearer for you.




  12. John Aynsley, Doulos CTO will be presenting a FREE webinar on "VHDL versus SystemVerilog versus SystemC" on Friday 3 May 2013


    There will be 2 sessions to enable attendees from different time zones:


    1st run:

    Time: 9am-10am (BST - UK) bullet.gif 10am-11am (CEST) bullet.gif 1.30pm-2.30pm (IST)


    2nd run:

    Time: 9am-10am (PDT) bullet.gif 12pm-1pm (EDT) bullet.gif 5pm-6pm (BST - UK)


    For further details and to register, please see the link on the Doulos website:




  13. You have waits in each process so I am assuming they are all sc_threads (otherwise you will get a run-time error).

    Also, I should point out that by defualt, all processes are executed once, during initialization and will run until either they hit a wait or the end of the function is reached.

    You have not shown any loops in your processes. This means that each process will die (and cannot be resurected) when it gets to the end.


    So ...


    During initialization (at time 0), each process will run, in some unknown order (you must not make any assumptions about which order the processes will be executed in).

    P1 will run until it hits the wait statement, generating an immediate notification (i.e. in the current sim cycle) on event x.

    If P2 happens to run before P1, it will stop at the wait(x) statement. Once P1 has run, it will immediately wake up, continue to the end and then die. If P2 runs after P1, it will stop at the wait(x) statement and never wake up - a process must be waiting BEFORE an event is notified in order to respond to it and P1 does not contain a loop so it will not notify x again!

    P3 runs up until the wait statement.


    When the event in the static sensitivity list occurs, P1 and P3 will wake up (again we do not know in what order), run to the end and then die.


    I suggest you take another look at the LRM if this is not the behaviour you were expecting!




  14. Communication between a producer ("initiator") and consumer ("target") is very common in SystemC models. The model above predates the 1666-2005 standard but shows quite nicely how you could create a fifo to model communication. Things in the SystemC community have moved on a bit since this model was written - most people wanting to model this sort of behaviour are more likely to be using TLM2 type communication with initiator and target sockets connected directly together, rather than having some channel in between (it is more efficient when it comes to CPU time during a simulation).




  15. The driver controls the sequences by sending an acknowledgement back to the sequencer: either implicitly, immediately it has read the transaction by calling set_item_port.get(), or if it calls set_item_port.get_next_item() instead, it must explictly call seq_itme_port.item_done() to send the acknowledgement.


    I would not usually recommend calling low-level sequence methods such as wait_for_grant - start_item followed by finish_item generally provided sufficient control over when sequence items are sent (if you rally want to use the low-level mechanism, sequence items are sent by send_request).




  16. Hi,


    A common way to achieve this is to have a virtual sequence (i.e. not running on a sequencer that sends sequence items to a driver) that controls the sequences running on both agents. If you only need the sequences to start at the same time, the virtual sequence could call start for each sequence at the appropriate time. If you need to do this periodically, the virtual sequence could grab control of each agent's sequencer and only enable them at the required point in the simulation.


    Have a look at section 4.8 in the UVM users guide for further information.




  17. wait() with no arguments is only used for static sensitivity


    next_trigger() has similiar functionality to wait() but is only used within sc_method processes, while wait() is only used within sc_thread processes. The main difference is that sc_methods cannot consume time (wait is illegal) so next_trigger (with an argument) overrides any static sensitivity to control when the sc_method will next be called (after it has completed). There might be multiple calls to next_trigger in the same sc_method - the last one to be executed before the function returns is the one that sets the sensitivity for the next call.




  18. Hi Amit,


    A process has static sensitivity if it contains one or more calls to wait(). The sensitivity is set before the simulation starts running, usually be using "sensitive" in its parent module's constructor.


    Dynamic sensitivity is where a process contains one or more calls to wait(a_time_value) or wait(a_named_event). It is dynamic because the conditions that cause a thread process to wake up change as each wait statement is executed when the simulation runs.


    Here is a very brief example (not tested):


    SC_MODULE(mod) {
      sc_in<bool> clk;
      sc_event e;
      void proc1() {
         wait();  //static sensitivity
    void proc2() {
      while(1) {
        wait(e);  //wait for event (dynamic)
        //do something
        wait(1,SC_NS);  //wait for time (dynamic)
        //do something
      SC_CTOR(mod) {
         sensitive << clk.pos();   //static sensitivity
         SC_THREAD(proc2);     //no static sensitivity, runs during initialization until 1st wait reached


    You can find further details in section 4.2 of the SystemC LRM (1066.2011).




  19. sc_module_name is required as an argument of the constructor to any class derived from sc_module (if there are multiple constructor arguments, sc_module_name is usually the first). It is passed a string argument which is used to create a temporary sc_module_name object that is then passed to the sc_module constructor, and used to create a hiearachical name for every component in a SystemC model (sc_module_name is itself a class and its constructor takes a string).


    If that still seems a bit confusing, I suggest you read through section 5.3 of the SystemC Language Reference Manual (available from http://standards.ieee.org/getieee/1666/download/1666-2011.pdf)




  20. The integer bit length is set when the sc_fix object is created and cannot subsequently be varied. If you want to find the optimum representation, I would suggest an iterative approach where you copy the original number to a new object with a different word length on iteration until you find the best fit. If you want to affect the representation of multiple object from one place, have a look at the sc_context_switch (see sections 7.2.3 and 7.11 in the LRM).


    You might also want to look at the sc_fxcast_switch. This can be used to turn fixed-point represention on and off (sc_fix reverts to floating point when off). This is good to see how your fixed-point representation compares against ideal floating point behaviour.




  • Create New...