Jump to content

Leaderboard


Popular Content

Showing content with the highest reputation since 12/20/2018 in all areas

  1. 3 points
    SystemC 2.3.2 (and later) does support a query whether an event was triggered in the previous delta cycle (or immediately in the current evaluation cycle). This is similar to the sc_signal<>::event() function. With this, you can ask every element in your array, whether it was triggered and may have caused a wakeup of the process. Of course, multiple events can have triggered simultaneously and will only cause a single wakeup of the process. for( const auto ev& : e ) { if ( ev.triggered() ) { // ... } } Hope that helps, Philipp
  2. 2 points
    Please be aware, that an sc_and_event_list does not imply that the events in the list are triggered at the same time. I would suggest to keep the only the clock sensitivity and act on the triggers in the body of the method instead: SC_METHOD(func2); sensitive << clk.pos(); dont_initialize(); // ... void func2() { if( nreset.posedge() ) { // nreset went high in this clock cycle // ... } } Alternatively, you can be sensitive to nreset.pos() and check for clk.posedge() (as a consistency check), if you don't have anything else to do in the body of the method. With this approach, you might be able to avoid unnecessary triggers of the method. Side note to Eyck: There's a small typo in the example above, which should should use "&=" to append to an sc_event_and_list. ev_list &= nreset;
  3. 2 points
    David Black

    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
  4. 2 points
    The issue is likely caused because you access a port (via -> or for example calling functions like .read()) already inside the module constructor. You should only access ports after binding has completed, this means from within a SystemC process or in end_of_elaboration() / start_of_simulation() callbacks. Hope that helps, Philipp
  5. 2 points
    This means that a port is not bound to an interface. A port is just a kind of a forwarder of an interface. So if none is bound nothing can be forwarded. E.g. if you have a sc_in<bool> it forwards the sc_signal_in_if which allows you to read and wait for events. But there needs to be 'something on the other side' which is usually a signal (implementing the sc_signal_in_if) being bound to the socker. But without further information it is hard to provide more help. Best regards
  6. 1 point
    Eyck

    bind multi ports to other port.

    Another option would be to use a resolved signal and connect all output ports to it. But this is already about techincal implementation options. The question to me is: what would you like to model? Is this the right way to model the intend? Best regards
  7. 1 point
    You have controversial requirements: a) put stored value when enable == 1 , which sounds like a dff with output_enable b) put input to output when enable == 1, which sounds more like a latch Anyway, in both cases you will need to make process sensitive to enable signal. And usually such low-level logic is modeled with SC_METHODs. In SystemC context "register" usually means some memory-mapped CSR on TLM bus 🙂
  8. 1 point
    If you want immediate communications between threads, then you should use regular SC_THREADs and wait on event, like wait(some_signal.value_changed_event());
  9. 1 point
    You would want to use an sc_event_and_list. See IEEE1666 section 5.8. As its intended use is with next_trigger() and wait() you would need to move the sensitivity into your method. So the constructor part becomes SC_METHOD(func2); and func2 should something like (snippet of your module): sc_core::sc_event_and_list ev_list; void end_of_elaboration(){ ev_list |= clk.posedge_event(); ev_list |= nreset; } void func2(){ next_trigger(ev_list); // your code here ... }
  10. 1 point
    Unfortunately I'm not with a member company. I was hoping that I'd have read permissions regardless of my current affiliation. As a user I'd like to see the connection between discussions in the official forum, the issues reported to the issue management system, and the code being developed in response to that. The ability to immediately test that code and possibly give feedback as code comments or a pull request. More like Github, Gitlab and other platforms. Seems to me that this would be a more efficient way to give and get user feedback.
  11. 1 point
    Hmm, not sure if I understand you correctly. Your C++ code has an entry function, right? If you just call this entry function from a SC_THREAD it runs in a thread context and can call wait to let other parts of the simulation continue. The other option you have is to run your C++ code in a second (OS) thread, e.g. a std::thread. This allows to use the usual syncronization primitives of the OS like mutexes and alike. BR
  12. 1 point
    There are several ways to do this: you might use a different way to carry signals which are more TLM like. One option would be to use tlm_signal. The other common option is if your CPU writes into the register of your interrupt controller via TLM it carries the delay which is essentially the offset of the CPU local time to the SystemC kernel time. If you here just break the quantum and call a wait() so that the SystemC kernel can sync up and the signal change propagates you should be fine.
  13. 1 point
    Eyck

    tracing waveforms in tlm

    You may use the tlm recorder of the SystemC components lib (SCC, esp. here: https://git.minres.com/SystemC/SystemC-Components/src/branch/master/incl/scv4tlm). This writes into a text database (the SCV default). You can view this e.g. with Impulse (https://toem.de/index.php/projects/impulse) or SCViewer (https://git.minres.com/VP-Tools/SCViewer, binaries here: https://github.com/Minres/SCViewer/releases). Basically you instantiate scc::tlm2_recorder_module and connect it's initiator and target sockets. to your target and initiator socket. Your sc_main should then look like: int sc_main(int argc, char *argv[]) { scv_startup(); scv_tr_text_init(); scv_tr_db db("my_db.txlog"); scv_tr_db::set_default_db(&db); dut_mod dut("dut"); sc_start(1.0, SC_MS); return 0; } The database is closed upon destruction of the db object. Best regards
  14. 1 point
    Roman Popov

    Systemc performance

    Real-life simulation performance usually depends a lot on modeling style. For high-level TLM-2.0 models share of simulation time consumed by SystemC primitives is usually much lower, comparing to time consumed by "business logic" of models. Efficiency of simulation kernel (like context switches and channels) is much more important for low-level RTL simulations.
  15. 1 point
    Vegh, Janos

    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.
  16. 1 point
    Philipp A Hartmann

    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.
  17. 1 point
    From the snippets you provide it looks ok. Assuming that bus_mutex is a sc_mutex this is you problem. sc_mutex does not do arbitration. It selects randomly which waiting thread to grant the lock (actually the next activated process base on an even notification) . But what you expect is arbitration. So either you write an arbiter or you may use and ordered semaphore with an initial counter value of 1. You may find an implementation here: https://git.minres.com/SystemC/SystemC-Components/src/branch/master/incl/scc/ordered_semaphore.h The semaphore grant access based on a queue. So eventually you get first-comes-first-serves (FCFS) behavior, but all requestors have equal priority. Best regards
  18. 1 point
    Philipp A Hartmann

    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 );
  19. 1 point
    Eyck

    tlm model with clocks & code sample

    My fault, SC_THREAD has a sensitivity list and you can call wait() for the default event. In my experience -and this guided my answer- it is better to have no sensitivity list and wait explicitly for events. When specifying a port in the sensitivity list you need to use an event finder (with .pos()) as the port is not bound yet and hence does not have an event associated. In the thread itself you can use the pos_edge event. So your code shown above is correct. BR
  20. 1 point
    Eyck

    using clocks in tlm

    Adding to Davids answer: you can supply clocks to the modules having initiator and/or target sockets. This is can be done using the usual signal/sc_in/sc_out means as David mentioned. There is also the option to have 'tick-less' clock as David presented many years ago (http://www.nascug.org/events/12th/nascug12_david_black.pdf). This can also be achieved by distributing a signal just carrying the clock period as sc_time and caculating the time points in the modules. This way it is even possible to model timers or PWM (e.g. https://git.minres.com/DBT-RISE/DBT-RISE-RISCV/src/branch/develop/platform/incl/sysc/SiFive/pwm.h). This modelling style avoids the many context switches implied by toggling clocks. All this holds true for LT and PV modelling, if you think about AT modelling the story becomes different. But this is as usual: you trade speed for accuracy. BR
  21. 1 point
    Unfortunately, there is currently no way to obtain the name of the affected signals/variables in this message. You can suppress the warning via: sc_core::sc_report_handler::set_actions(sc_core::SC_ID_TRACING_VCD_DUPLICATE_TIME_, sc_core::SC_DO_NOTHING);
  22. 1 point
    David Black

    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>.
  23. 1 point
    Philipp A Hartmann

    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.
  24. 1 point
    At first glance, you can call b_transport from C++, but it must be C++ that is inside a SystemC process during simulation phase if the b_transport call invokes sc_core::wait(). You can read the details in the IEEE-1666-2011 specification. Or perhaps you should signup for the Doulos SystemC TLM-2.0 course and get expert hands-on training. Fundamentally, b_transport is a simple function call; however, it may use SystemC semantics to accomplish its work. Hence you should also be knowledgable on SystemC SC_THREADs (may not be used in SC_METHODs). Technically, you could write a b_transport method in the target that did not call sc_core::wait, which is desirable anyhow. If you did this, then you may call from pretty much anywhere; however, SystemC is not thread-safe without special precautions. In any event, there is a lot to learn about the subtleties of the generic payload and extensions too.
  25. 1 point
    Eyck

    why is,what is, and how is tlm used ?

    Well, in TLM1.0 there is even a tlm::tlm_fifo channel which provides something similar what you use. The sockets defined in TLM2.0 are more geared towards memory-mapped busses and provide facilities to model for speed (DMI, loosly-timed blocking interfaces) or accurracy (approximately-timed non-blocking interfaces). To achive this with pure SystemC provided classes takes some effort and it ends to be proprietary... BR -Eyck
  26. 1 point
    From SystemC standard: SystemC requires that you add sc_module_name as a parameter to module constructors, like this: MULT(sc_module_name, int var_a, int var_b); MULT(sc_module_name); This is a hack that allows SystemC kernel to track lifetime of constructor.
  27. 1 point
    If you code your FFT as a pure C++ function, Vivado HLS will generate inputs and outputs automatically from function parameters and based on INTERFACE pragmas. And you can import generated RTL into Vivado IP integrator. Check out Xilinx documentation, and ask on Xilinx forums. Please also note that you can implement FFT in a various ways (with different micro-architectures), and achieve various performance vs area numbers. And HLS also requires quite a lot of learning to achieve good results.
  28. 1 point
    Xilinx HLS tools have very limited SystemC support, you should probably code your FFT in pure C++.
  29. 1 point
    You paint a very bleak and incorrect picture of the HLS tool. I will suggest that you need to get some training on its use. Xilinx have many examples and their documentation is quite good. Document UG902 clearly documents the HLS math library which supports all manner of synthesizable operations. For instance: Trigonometric Functions: acos, atan, cospi, acospi, atan2, sin, asin, atan2pi, sincos, asinpi, cos, sinpi, tan, tanpi Hyperbolic Functions: acosh, asinh, cosh, atanh, sinh, tanh Exponential Functions: exp, exp10, exp2, expm1, frexp, idexp, modf Logarithmic Functions: ilogb, log, log10, log1p Power Functions: cbrt, hypot, pow, rsqrt, sqrt Error Functions: erf, erfc Gamma Functions: lgamma, lgamma_r, tgamma Rounding Functions: ceil, floor, llrint, llround, lrint, lround, nearbyint, rint, round, trunc and that's only a few. Perhaps your grasp of C++ and what can or cannot be synthesized is limited. For instance, dynamically allocated memory is forbidden because it is not reasonable to expect silicon to grow new logic during operation. Please read the fine manual (RTFM).
  30. 1 point
    maehne

    Making a port optional

    If you don't use the member functions added that were added for convenience to `sc_in`, `sc_out`, and `sc_inout` to, e.g., call `read()`, `write()`, and the event member functions via the `.` operator than via the corresponding member function in the interface accessed via the `->` operator, you might be able to avoid entirely the derivation of new port classes. Instead, you could simply use a template alias, which was introduced with C++'11: template<typename T> using sc_in_opt = sc_core::sc_port<sc_signal_in_if<T>, 1, SC_ZERO_OR_MORE_BOUND>; template<typename T> using sc_inout_opt = sc_core::sc_port<sc_signal_inout_if<T>, 1, SC_ZERO_OR_MORE_BOUND>; template<typename T> using sc_out_opt = sc_core::sc_port<sc_signal_inout_if<T>, 1, SC_ZERO_OR_MORE_BOUND>; If you want to also provide all member functions of `sc_in`, `sc_out`, and `sc_inout`, you will have to derive from the `sc_port` class and implement the full interface as defined in IEEE Std 1666-2011.
  31. 1 point
    I gave it a shot locally and noticed that there are indeed quite some compiler warnings due to differences between __declspec(...) and __attribute__((visibility(...))). Most of these warnings can be ignored for now, but are certainly annoying. Additionally, you need to explicitly mark the following with SC_API as well: // src/sysc/communication/sc_port.h template <class IF> class SC_API sc_port_b template <class IF> class SC_API sc_port // src/sysc/communication/sc_prim_channel.h class SC_API sc_prim_channel_registry // src/sysc/communication/sc_signal.h template< class T, sc_writer_policy POL > class SC_API sc_signal_t template< class T, sc_writer_policy POL > class SC_API sc_signal // src/sysc/datatypes/sc_proxy.h template <class X> class SC_API sc_proxy // src/sysc/datatypes/sc_proxy.h extern "C" SC_API int sc_main(int argc, char* argv[]) // src/sysc/utils/sc_temporary.h template<class T> class SC_API sc_vpool For compiling SystemC itself with -fvisibility=hidden, some further changes to the .cpp files are needed. And some of the above changes might break the Windows DLL support. But for me, the above changes work with the examples in the SystemC distribution (i.e. "gmake check CXXFLAGS='-fvisibility=hidden"). Long story short: The feature to SystemC build models with limited symbol visibility will require more changes and testing. I will forward this topic to the Language Working Group for further discussion.
  32. 1 point
    You cannot not check typeid() against a string as this is compiler dependend. What you shoudl do is void write_out{ if(typeid(T) == typeid(sc_dt::sc_logic){ out.write(SC_LOGIC_Z); }else{ out.write(0); } } } But actually this is more a C++ related question, in my experience Stackoverflow is a good source of help. Cheers
  33. 1 point
    Eyck

    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
  34. 1 point
    Eyck

    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
  35. 1 point
    You should start with learning your synthesis tool documentation. C++/SystemC synthesis is very tool-specific.
  36. 1 point
    David Black

    Temporal Decoupling

    I believe it would be fair to say that there are no universally accepted best practices, and the system design will dictate much of the implementation. In the case of shared memory, the target would need to have some idea that the memory of interest is shared. So you would need somewhere in the system to have a mapping. It might be the entire device, or a memory map might exist as a configurable object. When the target receives a read request for shared memory, it would then synchronize in order to be certain that any writes from the past are completed in other initiators. Depending on your design, you might be able to reduce the number of synchronizations if you can know apriori the nature of the sharing. E.g. if a block of memory was shared using a mutex, then synchronization might be limited to the mutex with the assumption that if you own the mutex, then the block is not written to by other initiators. This of course has some risks in the face of software defects.
  37. 1 point
    swami-cst

    TLM_INCOMPLETE_RESPONSE

    You seem to be probing the transaction response, before driving your transaction :) Since the default transaction status is TLM_INCOMPLETE_RESPONSE, you are getting that message. Try moving the call to b_transport before checking the trans.is_response_error() ...
  38. 1 point
    The release contains a file docs/scv/scvref/vwg_1_0e.pdf which (sort of) clarifies this.
  39. 1 point
    Hi Maxim, After reading some SCV documentation, it looks like we're not allowed to use smart pointers in your preferred way. E.g. we need to use "addr()" (without specific member functions like "range(int, int)") as a basis for building the expression we are using in a later stage. In your case, a practical solution would be to have no constraint on the generated address but to mask the 2 LSB after generation. -- greetz, Bas
  40. 1 point
    Hi Maxim, "addr" is a pointer, so you need to access its fields and methods by using operator-> : SCV_CONSTRAINT(addr->range(1,0) == 0); -- greetz, Bas
  41. 1 point
    What you can do is build your driver software as a shared library with a main function. In a SC_THREAD you just load the library and execute the main function. Along with this you have to implement a few utility functions (read, write, wait) which interact with the SystemC kernel or your DUT and being used by the main function (and the called functions from there). This is called host based or host compiled simulation (you may check the search engine of your choice for it). With some infrastructure it is even possible to mimic interrupt. Another option is to use some instruction set simulator (e.g. QEMU, DBT-RISE-RISCV, or some commercial alternatives) and do you driver development using a virtual prototype... Best regards
  42. 1 point
    Minimal example of the actual underlying issues posted here: http://forums.accellera.org/topic/6232-killing-a-process-with-an-included-sc_event_andor_list/
  43. 1 point
    dynamic_cast to sc_module* would only give you access to methods of sc_module that were overridden in A. fun() and function() are not part of sc_module.
  44. 1 point
    Eyck

    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
  45. 1 point
    Eyck

    TLM transaction tracing

    Maybe a little bit late but there are socket implementations available which do trace tlm transactions int a SCV database. They can be found at https://github.com/Minres/SystemC-Components/tree/master/incl/scv4tlm and are used e.g. at https://github.com/Minres/SystemC-Components/blob/5f7387ab7e3dfc2ff6a7cac6fbe834ed7ec8ae36/incl/sysc/tlmtarget.h which in turn serve as building blocks in https://github.com/Minres/SystemC-Components-Test/tree/master/examples/simple_system The setup given by Kai is put into sysc::tracer where all the tracing setup (VCD & SCV) is impelemted. Best regards -Eyck
  46. 1 point
    David Black

    approximately timed

    IEEE 1666-2011 section 10.2 states: IEEE 1666-2011 section 10.3.4 states:
  47. 1 point
    Actually, you can start a sequence in any phase. It is more important to understand the domain/scheduling relationships between the task based (i.e. runtime) phases. UVM undergoes a number of pre-simulation phases (build, connect, end_of_elaboration, start_of_simulation) that are all implemented with functions. Once those are completed, the task based phases begin. The standard includes two schedules. One is simply the run_phase, which starts executing at time zero and continues until all components have dropped their objections within the run_phase. The other schedule contains twelve phases that execute parallel to the run phase. They are: pre_reset, reset, post_reset, pre_config, config, post_config, pre_main, main, post_main, pre_shutdown, shutdown, and post_shutdown. They execute in sequence. Every component has the opportunity to define or not define tasks to execute these phases. A phase starts only when all components in the previous phase have dropped their objections. A phase continues to execute until all components have dropped their objections in the current phase. Many companies use the run_phase for everything because there are some interesting issues to consider when crossing phase boundaries. In some respects it may be easier to use uvm_barriers for synchronization. Drivers and monitors (things that touch the hardware) are usally run exclusively in the run_phase, but there is nothing to prevent them also having reset_phase, main_phase, etc...
  48. 1 point
    apfitch

    user defined data type signal assignment

    Hi Zarie, that's what I meant by "you must wait a delta". If no time passes, a primitive channel does not update. Kocha's solution will work (adding a call to sc_start - in fact even sc_start(SC_ZERO_TIME) should work. regards Alan
  49. 1 point
    apfitch

    user defined data type signal assignment

    How do you know the assignment is not working? When are you printing out the assigned value? Remember that you must wait at least a delta for a primitive channel to update. There's more about user defined types and sc_signal here http://www.doulos.com/knowhow/systemc/faq/#q1 regards Alan
  50. 1 point
    David Long

    static and dynamic sensitivity

    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 e.notify(); } 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) { SC_METHOD(proc1); 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). Regards, Dave
×
×
  • Create New...