Jump to content


Popular Content

Showing content with the highest reputation since 08/23/2018 in all areas

  1. 3 points
    The Accellera SystemC AMS Working Group released the 2020 edition of the SystemC AMS User's Guide. You will find the user's guide on this page: https://www.accellera.org/downloads/standards/systemc This version of the user's guide is fully compatible with the SystemC AMS standard released as IEEE Std. 1666.1-2016. It describes all the features introduced in the SystemC AMS language standard during the last decade. For example, the user’s guide now explains the use of the dynamic timed data flow capabilities, to make AMS system simulations even more efficient and running even faster. The SystemC AMS Working Group is currently preparing the release of the user's guide application examples as separate download. Availability of these application examples will be communicated at a later stage. Please use this forum to post your questions or remarks on the user's guide.
  2. 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
  3. 3 points
    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...
  4. 2 points

    sc_clock Doubt

    sc_clock triggers itself based on the period and the (in your case default) constructor settings. The period is the default_time_unit.
  5. 2 points

    TLM CPU modeling

    There is no such thing as CPU TLM modeling. Usually you write a C/C++ processor model with the needed accuracy (instruction accurate, cycle approximate, cycle accurate) and wrap it in a way that you translate memory accesses into TLM socket accesses. Along with that you need to manage to syncronization of the time of your model and the SystemC time (to run e.g. in loosly timed mode). Another task is to take the returned execution time of the bus accesses into account for the execution of the CPU model. This involves also the selection and implementation of the accesses (DMI & blocking or non-blocking). You can find a complete example of an instruction accurate VP at https://git.minres.com/DVCon2018/RISCV-VP (or https://git.minres.com/VP/RISCV-VP which is a newer version). The wrapper for the C++ model in SystemC can be found at https://git.minres.com/DVCon2018/RISCV-VP/src/branch/develop/riscv.sc/incl/sysc/core_complex.h To put it straight: doing this correctly is a non-trivial task as it is the implementation of a micro-architecture model of a CPU. One option is to build an instruction accurate ISS and add a microarchitecture model like it is done in the ESECS project (https://github.com/MIPS/esesc) BR
  6. 2 points
    You are initailaizing fl_ptr during consturction, not during execution. In generator.hpp you have: float* fl_ptr = reinterpret_cast<float*>(dmi_mem); //ovo sam ja pisao This never updates fl_ptr to the actual value of dmi_ptr. Actually your access should look like: if (dmi_valid) { dmi_mem = dmi.get_dmi_ptr(); //dmi_mem is pointer to ram[] array in memory.h float* fl_ptr = reinterpret_cast<float*>(dmi_mem); for (int i = 0; i != 20; ++i) fl_ptr[i] = 12.7; }
  7. 2 points
    Your sc_trace function is a member function of the TraceList class and cannot be called like the sc_trace functions coming with the SystemC reference implementation. Those are free functions in the sc_core namespace. Moreover your sc_trace implementation is non-static so it cannot be used without a TraceList object. You need to move the function out of the class scope. Basically this is a valid approach to setup complex types. But under performance considerations I would suggest to use a different container. Best choices are std::vector or std::dqueue. And if you are using C++ 11 I would replace the while loop with a range based loop, something like: for(auto& val: var.lst) { // use namespace, compiler otherwise chooses wrong function sc_core::sc_trace(tf, val, nm + std::to_string(pos++)); }
  8. 2 points
    2 days! That's fast response Exactly! If you're not open in the design/pre-release phase you're likely to miss use cases and if the members have committed themselves to solutions and switched their focus to other tasks I imagine that there will be an unwillingness to go back and redo things even if new important insights have been revealed. I think most users would like a code base they can build upon, not one that needs adaptations to make it work. Being fully transparent about the code in the making will reduce the risk for such adaptations What I'm suggesting is free and efficient access to the collective intelligence of the entire community at a point in the development cycles where it makes the most difference. I'm not suggesting a shift in the rights to make the final decisions. That's exclusive to the paying members. What's preventing this from happening within Accellera?
  9. 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;
  10. 2 points
    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. 2 points
    David Black

    Systemc performance

    Perhaps you would like to share your code for measurements via GitHub? Measuring performance can be tricky to say the least. How you compile (compiler, version, SystemC version) and what you measure can really change results. Probably helps to specify your computer's specifications (Processor, RAM, cache, OS version) too. Processor (vendor, version) L1 cache size L2 cache size L3 cache size RAM OS (name, version) Compiler (name, version) Compiler switches (--std, -O) SystemC version SystemC installation switches How time is measured and from what point (e.g. start_of_simulation to end_of_simulation) Memory consumption information if possible This will help to make meaningful statements about the measurements and allow others to reproduce/verify your results. It is also important to understand how these results should be interpreted (taken advantage of) and compared. As with respect to TLM, it will get a lot more challenging. For example, what style of coding: Loosely Timed, Approximately Timed. Are sc_clock's involved?
  12. 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
  13. 2 points
    David Black

    Heartbeat, clock and negedge

    You can use it however you like. We didn't use it everywhere and I'm sure there are more areas where it might be applicable. The main point is that "Performance is a function of simulator CPU activity and how well it used." In some cases such as clocks, there is a lot of activity that goes unused. Many designs really only use the positive edge of the clock. In some designs, the activity can even be reduced significantly. Another instance is timers that often are only touched when they are set up and timeout after N clocks. The RTL approach to modeling a timer decrements the timer value on every clock. A behavioral approach would be: void set_timer( int N ) { assert( N > 0 ); delay = N * clock.period(); setup_time = sc_time_stamp(); projected_time = setup_time + delay; timeout_event.notify( delay ); } The current value of the timer can always be had with: int get_timer_value( void ) { return ( projected_time - sc_time_stamp() ) % clock.period() ); } So you really don't even need the clock in many instances. Instead replace clock.period() with a simple constant. Fast and smart SystemC models don't use sc_clock at all.
  14. 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
  15. 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
  16. 2 points
    Thanks! I can reproduce the behavior and verified that removing the dynamic sensitivity in sc_thread_process::kill_process fixes the issue: void sc_thread_process::kill_process(sc_descendant_inclusion_info descendants ) { // ... if ( sc_is_running() && m_has_stack ) { m_throw_status = THROW_KILL; m_wait_cycle_n = 0; remove_dynamic_events(); // <-- add this line to avoid the exception simcontext()->preempt_with(this); } // ... } I'm not sure, if it is necessary to do the same for the static sensitivity. At least I haven't come up with a similar scenario, where the error is actually "incorrect".
  17. 2 points
    The problem is, when you integrate RTL IP into Loosely-Timed VP that way, the whole simulator will have a performance of cycle-accurate model. Because clock generator will be always on, and Verilated model will be triggered even if it is idle. So don't try to boot Linux with such a simulator. If your RTL IP supports power gating or clock gating, it is a good idea to disable clock generation when RTL IP is turned off. In that case you don't pay for what you don't use: you can boot your OS quickly and then enable clock generator when you start to debug IP-specific driver code.
  18. 2 points
    Hello @kallooran, What version of SystemC library are you using? This issue has been fixed in the release of SystemC-2.3.2. You can find the latest release of SystemC-2.3.3 here: http://accellera.org/downloads/standards/systemc Hope it helps. Regards, Ameya Vikram Singh
  19. 2 points
    David Black

    Seeking Feedback on Datatypes

    Actually, it adds a lot of value. std::array can be passed by reference in a function call and the function can then determine the proper size of the array. This is much better than passing pointers, the C standard. You can also copy an array, which should be synthesizable, which reduces coding and greatly improves readability. It should be possible to implement some #include <algorithm>s on std::array too. Also, you can have bounds checking for additional safety; although, that aspect is probably not synthesizable. Additionally, constexpr should be quite helpful for the synthesis aspect.
  20. 2 points
    Hi, I'm not an implementer of the reference simulator but as far as I can judge the re-throw is used to find a more specific type of exception (since sc_elab_and_sim() just uses a catch-all) and uses sc_handle_exception() to convert it into an sc_report so it can be handled by the SystemC reproting system. Actually I agree it would be better to handle it directly in sc_elab_and_sim() but this would duplicate code. A side note rgd. debugging: if you use gdb there is a command 'catch throw' which stops execution right at the point where the (original) exception is thrown. This comes pretty handy in such cases. Best regards
  21. 1 point
    David Black

    sc_clock Doubt

    There is no default_time_unit in SystemC; however, the sc_clock default constructor does supply a default value of 1 ns. Be careful you don't set the time resolution larger than 1 ns, if you are going to use the default time. You could of course be more explict: sc_time clock{ "clock", 1, SC_NS }; //< assumes C++11 or better and using namespace sc_core
  22. 1 point
    David Black

    How to generate sc_signal at runtime?

    Sc_signals are not data types. Sc_signals are channels, which represent hardware being modeled and are used as mechanisms to transport data between processes. As such, channels are only allowed to be created during the “elaboration phase” that occurs prior to simulation starting up. Also, strictly speaking, sc_port’s are not normal pointers; although, an underlying mechanism uses pointers for efficiencies sake. The operator->() is overloaded on sc_port<IF_TYPE>. You could of course create an sc_vector< sc_signal<T> >, N >, where N was a maximum of the number of signals required and then allocate specific index to each spawned process.
  23. 1 point
    David Black

    SC_CTHREAD slows down simulation

    You are missing at minimum a single wait() in the infinite loop. SystemC is an event driven simulator and as such concurrency is modeled using co-operative multi-tasking. An infinite loop is an infinite loop. No pre-emption.
  24. 1 point
    Timur Kelin

    Implement sc_trace for std::string

    The basic idea: calculate hash for the string call sc_trace for the hash value update a translation file which maps hash values and the string contents. Exemplar github project which utilizes this approach: https://github.com/timurkelin/simschd In this project the translation file is written before the simulation starts raw 64-bit hash values: simvision mmap translation applied: simvision mmap is generated automatically and translates string hash (%x=) into string value (-label {}). mmap new -reuse -name schd -radix %x -contents { {%x=0000000000000000 -label { } -bgcolor #000000 -font -*-courier-medium-i-normal--12-* -shape z -textcolor #F8F8FF -linecolor green} {%x=613d30040ed92e78 -label {delay_chain.dly10} -bgcolor #000000 -font -*-courier-medium-i-normal--12-* -shape bus -textcolor #F8F8FF -linecolor green} {%x=d1a020f2dd73715f -label {delay_chain.dly10} -bgcolor #000000 -font -*-courier-medium-i-normal--12-* -shape bus -textcolor #F8F8FF -linecolor green} {%x=69071983ebd1b6d4 -label {delay_chain.dly10} -bgcolor #000000 -font -*-courier-medium-i-normal--12-* -shape bus -textcolor #F8F8FF -linecolor green} {%x=3a5413510c68f021 -label {run_80.exec_80()} -bgcolor #808000 -font -*-courier-medium-i-normal--12-* -shape bus -textcolor #F8F8FF -linecolor green} {%x=55691ef70e86d835 -label {run_60.exec_60()} -bgcolor #8b0000 -font -*-courier-medium-i-normal--12-* -shape bus -textcolor #F8F8FF -linecolor green} {%x=6f9e19f9823cb15c -label {run_40.exec_40()} -bgcolor #4b0082 -font -*-courier-medium-i-normal--12-* -shape bus -textcolor #F8F8FF -linecolor green} } generated gtkwave translation file for the similar appearance 0000000000000000 ?grey0? 613d30040ed92e78 ?grey0?delay_chain.dly10 d1a020f2dd73715f ?grey0?delay_chain.dly10 69071983ebd1b6d4 ?grey0?delay_chain.dly10 3a5413510c68f021 ?OliveDrab?run_80.exec_80() 55691ef70e86d835 ?DarkRed?run_60.exec_60() 6f9e19f9823cb15c ?navy blue?run_40.exec_40()
  25. 1 point
    Since you are talking about timing I would stick to a more AT like modeling style using the non-blocking transport functions. In this case you should use a memory manager (see section 14.5 of the IEEE standard). For this you need to implement the tlm::tlm_mm_interface (there a few implementations out there, you may google them). The mechanism works similar to a C++ shared pointer. The initiator always pulls a new transaction from the memeory manager and sends via its socket. Each component dealing with the transaction calls acquire() on the payload and release() once it is finished with it. Upon the last release() call the transaction is automatically returned to the memory manager and can be reused. HTH
  26. 1 point
    Fix published in https://github.com/accellera-official/systemc/commit/5a94360d. Thanks for the report! Greetings from Duisburg, Philipp
  27. 1 point

    sc_fifo.read() does not work

    You are not writing to output2 of fork, hence printer input fifo is not filled. For debugging use num_available() to get the number of available items in the fifo. "value = input.read()" is not breaking out of the loop, here read() is a blocking call, as fifo is empty it kept blocking the thread. As there are no other pending events or waits simulation stopped naturally. Ram
  28. 1 point
    You have multiple instances of the "bundles" in your monitor class: inherited directly as additional members in the nested classes sim and stub To avoid the name clashes, you can make sim and stub modules themselves via: struct sim : sc_module , if_inputs, if_outputs { SC_CTOR(sim) {} } sim { "sim" };
  29. 1 point
    e.notify(); // immediate notification is executed "immediately" - Thread2 added to set of runnable processes e.notify(3,SC_NS); // e added to kernel event queue, it will be triggered in 3 ns e.notify(3,SC_NS); // e added to kernel event queue to be triggered in 3 ns e.notify(); // previous notification canceled, and instead event is notified immediately, Thread2 added to set of runnable processes
  30. 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 ... }
  31. 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.
  32. 1 point

    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
  33. 1 point

    tlm model with clocks & code sample

    You should consult the LRM again.:SC_THREAD does not have a sensitivity list. Moreover you create a memory leak creating the transaction object using new and not deleting it. And your thread ends after 10 accesses. Basically you need to wait for the clock explicitly while (1) { // wait for the rising edge wait(clk.posedge_event()); tlm::tlm_generic_payload trans; // setup the transaction ... // execute the access i_socket->b_transport(*trans, delay); } In your solution the loop in your threads are based on timed delays hence it is not reactiong on your clocks at all. Best regards
  34. 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>.
  35. 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.
  36. 1 point

    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
  37. 1 point

    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.
  38. 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.
  39. 1 point
    Your calls to the configure script don't include the option --prefix to specify the destination directory for installation. This is strongly recommended as the SystemC installation layout does not match well with the standard Unix directory layout for a conflict-free installation. Personally, I prefer to install SystemC on Unix-like platforms to /opt/systemc-2.3.3 (or similar). After make install, you can make sure that the include and lib-* directory below the prefix contains the necessary files. When building against this SystemC version, you will have to pass the proper include and linker flags. I recommend that you read the INSTALL and RELEASENOTES files, which are part of the SystemC PoC implementation. You may also consider to use the experimental CMake-based build system instead of the autotools.
  40. 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
  41. 1 point
    To answer the question of a fifo multiple writers and one reader, I would suggest either of two approaches: Create a module with a vector of inputs (1 per writer) and the sc_fifo output. A simple method process can then arbitrate and facilitate placing incoming data onto the output. This has the advantage of allowing a custom arbitration scheme Create an internal std::queue and limit access with a mutex (sc_mutex might work). Since the queue doesn't have a limitation, it will be up to you to manage maximum depth issues. Downside is that arbitration is managed by the mutex and may not be ideal. For a fifo with multiple readers, you probably need a manager to decide arbitrate requests, which is similar to 1 above.
  42. 1 point
    Lukas Jakober

    Seeking Feedback on Datatypes

    Some feedback on AC datatypes: We have found AC datatypes to be an invaluable tool for large DSP ASIC designs. My experience is mostly on the simulation front where speed, bit- (but not necessarily cycle-) accuracy, and seamless integration with standard C++ code is important. AC datatypes provide all the relevant digital system design features (clipping/rounding/bit-slicing), as well as support for complex data types, with very little overhead. The ability to customize/expand AC datatype functionality via private headers (for simulation only) is another great benefit that minimizes the need for instrumentation code around HLS code during system simulations.
  43. 1 point
    Roman Popov

    How to connect array of ports?

    Usually you should use sc_vector instead of array. The problem with array is that names of signals and ports in array will be initialized to meaningless values (port_0 ... port_1 ). If you still want to use arrays, then bind with a loop. Here is example, both for array and sc_vector. #include <systemc.h> static const int N_PORTS = 4; struct dut : sc_module { sc_in<int> in_array[N_PORTS]; sc_vector<sc_in<int>> in_vector{"in_vector", N_PORTS}; SC_CTOR(dut) {} }; struct test : sc_module { dut d0{"d0"}; sc_signal<int> sig_array[N_PORTS]; sc_vector<sc_signal<int>> sig_vector{"sig_vector", N_PORTS}; SC_CTOR(test) { for (size_t i = 0; i < N_PORTS; ++i) { d0.in_array[i](sig_array[i]); } d0.in_vector(sig_vector); } };
  44. 1 point
    Roman Popov

    using gtkwave

    I don't work on Windows. But as far as I remember executable should be somewhere in project sub-directory called "Release" or "Debug". Sorry, can't help you more here.
  45. 1 point
    Well, the answer is i bit more complex. The main difference is that the standart requires that during the nb_transport call no sc_wait is allowed while in b_transport it si allowed. So any implementation adhereing to the standart guarantees this. Let's first look at the non-blockig implementation. tlm_phase do not denote a phase directly rather time -points o the protocol. Actually you have to phases: request and response which are denote by 2 time points each. So the initiator can indicate a start or end of a phase of a transaction and be sure that the call is not blocked by a call to wait(). So you can model the behavior and timing of a bus transaction in a fairly granular way and do something while the transaction is on-going. You can even have 2 transactions in parallel, one being in the request while the other one is in the response phase (or even more if you have more phases defined). The transaction are pipelined. Looking at the b_transport situation is different. The target can delay the transaction by calling wait() until it is ready to respond. During that time no other transaction can be ongoing, the initiator is blocked and cannot react to it. Blocking accesses can be used if timing of the communication is not of interest/not modeled (the other scenarion is loosly timed models, but that's a different story). They are easy to implement and easy to use. Non-blocking is used if the timing of the communication needs to be modeled in more detail. E.g. this allows to model, simulate and analyse bus contention situations as it allows to attach timing to all phases of a bus transaction lile grant, address phase, data phase. I hope this sheds some light -Eyck
  46. 1 point

    Install SystemC on Visual Studio 2017

    I am trying to install systemC on visual studio 2017 but it seems that I cannot find the guide for it. So I had to follow the guide of installing systemC on VS2010 :( In fact, I have got systemC.lib but when I configured the project for systemC, i.e, the project->property->C/C++->Code Generation->Runtime Library->balabalabala... finished all of them and build solutions, there are some errors. So...what should I do? Totally confused because I know nothing about VS =_= PS: the guide is here
  47. 1 point
    David Black

    sytemc temperal decoupling

    Read IEEE 1666-2011 sections 9 & 10. Available for free download from http://www.accellera.org/downloads/ieee. Or watch a free video from https://www.doulos.com/knowhow/systemc/. Or take a class on SystemC & TLM from https://www.doulos.com/content/training/systemc_training.php. TLM 2.0 is a marketable skill and I get many requests for job references. You will need to become proficient at C++, SystemC fundamentals, and then TLM 2.0 in addition to having a good basic knowledge of hardware and software design.
  48. 1 point


    hi, this is the source code for the interface registry along with 3 examples and the paper/ppt from dvcon2015 illustrating the package. The package itself provides a simple scheme to connect DUV and TB using bind, interface self registration and a database. regards /uwe
  49. 1 point
    An other way to understand this is to look at SystemC/TLM as pure C++ code and see what is going on.. Let us assume that you have two classes, "Initiator" and "Target", that need to communicate with each other. Target implements a function called "transport" to be called by Initiator, and Initiator implements a function called "response" - that is called by target. For the sake of the explanation here, the payload itself is not important, which we will assume is plain "int" in both directions. You would normally do this as following: // Interface classes: class initiator_if { public: void response(int i) = 0; }; class target_if { public: void transport(int i) = 0; }; class Initiator : public initiator_if { public: // Implement the interface void response(int i) { cout << "Got: " << i << " from target" << endl; } void bind(target_if &_if) { // Store the pointer locally m_target = &_if; } }; class Target : public target_if { public: // Implement the interface void transport(int i) { cout << "Got: " << i << " from initiator " << endl; } void bind(initiator_if &_if) { // Store the pointer locally m_initiator = &_if; } }; Next we instantiate the objects and "bind" them: Initiator initiator; Target target; initiator.bind(target); target.bind(initiator); I hope you are seeing where we are going with this. What has been done above is a crude equivalent of sc_port binding. There is one problem however with the approach above. What if the class "Target" doesn't implement the target_if directly? Like so: class TargetGrandChild : public target_if { public: void transport(int i) { // Implement the interface.. cout << "Got " << i << " from initiator (in grand child)" << std::endl; } }; class TargetChild { public: TargetGrandChild gch; /* Other stuff.. */ }; class Target { public: TargetChild ch; /* Other stuff.. */ }; One way to deal with this is to change the way bind function is called: initiator.bind(target.ch.gch); This is ugly. Firstly, it makes the client of bind function dependent on an internal design aspect of the "Target" class. For example, if the Target class changes tomorrow (to let the TargetChild implement the "target_if" directly), the bind function call needs to change. Also, to allow the client to call the bind function as above, the elements "ch" and "gch" must be made public, which may not be necessarily a good thing. A way out is to have an additional indirection. Let us call this as simple_export (a very simplified version of sc_export): class simple_export : public target_if { public: void transport(int i) { // One level of indirection p_real_target->transport(i); } void bind(target_if &_if) { p_real_target = &_if; } private: target_if *p_real_target; }; The new version of the Target class now looks like the following: class TargetGrandChild : public target_if { public: void transport(int i) { // Implement the interface.. cout << "Got " << i << " from initiator (in grand child)" << std::endl; } }; class TargetChild { public: TargetGrandChild gch; /* Other stuff.. */ }; class Target { public: simple_export port; private: // private is ok TargetChild ch; /* Other stuff.. */ Target() { // Tell "export" where the real implementation is port.bind(ch.gch); } }; The initiator will be "bound" to the target like so: initiator.bind(target.port); So for the simple_export to work, you need two binds: First is where the initiator is bound to the simple_export instance Second is when the "real" implementation is bound to the simple_export instance The simple_export class acts like a bridge. It forward the calls from the initiator to the "real" implementation. In case the "Target" itself implements the interface, the bind would look like: class Target : public target_if { public: simple_export port; private: // private is ok TargetChild ch; /* Other stuff.. */ Target() { // Tell "export" where the real implementation is port.bind(*this); } }; I hope this explains the line you pointed out in the code. The TLM socket has both a port and an export. Please note that the code snips above does not correspond to how OSCI simulator actually implements sc_port/sc_export!
  50. 1 point
    Hi. The never ending wait may be caused by race conditions. a) Notify with no argument means immediate notification. I.e., all processes sensitive to this event are made runnable in the same delta cycle. This may lead to non-deterministic behavior and should be used with care. Notify means all processes sensitive to this event are made runnable. The process in your case is sensitive to the event when its execution reaches the wait instruction. When the notify instruction is executed before the wait instruction is reached, no process is sensitive to the event. Event notifications are not stored for later waits. Assume the following example: p1(){ wait(ev1); cout << "wait done"; } p2(){ ev1.notify(); } When p1 starts first, it executes until wait is reached. Then p1 is suspended and p2 continues. The notification of ev1 is executed, p1 is made runnable again, and the message is printed. When p2 starts first, the notification of ev1 is done without any process waiting. Hence, it has no effect. Then p1 is started. It reaches the wait statement and will wait forever because the event notification has been executed before. No message will occur. Since SystemC contains no guaranty about the order in which processes runnable in the same delta cycle are executed, a model like the example leads to non-deterministic behavior. Greetings Ralph
  • Create New...