Jump to content


Popular Content

Showing most liked content since 02/19/2018 in all areas

  1. 3 points
    Philipp A Hartmann

    reset during wait(int)

    I agree with your conclusion that the observed behavior of the proof-of-concept implementation does not match the requirements of IEEE 1666-2011. I checked the code and it can be fixed by adding the check for resets to sc_thread_process.h (in the trigger_static() function): diff --git a/src/sysc/kernel/sc_thread_process.h b/src/sysc/kernel/sc_thread_process.h --- a/src/sysc/kernel/sc_thread_process.h +++ b/src/sysc/kernel/sc_thread_process.h @@ -485,5 +486,5 @@ sc_thread_process::trigger_static() #endif // SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS - if ( m_wait_cycle_n > 0 ) + if ( m_wait_cycle_n > 0 && THROW_NONE == m_throw_status ) { --m_wait_cycle_n; I'll take this change to the language working group to get it fixed in a future version of the SystemC PoC kernel. Thanks for reporting! Greetings from Duisburg, Philipp
  2. 2 points
    Hello @ANKUR SAINI, If you are on Linux/UNIX with the Accellera release of SystemC library with the GNU toolchain, you can use the following tutorials for reference: https://sourceware.org/gdb/onlinedocs/gdb/Threads.html https://stackoverflow.com/questions/1695268/multi-threaded-debugging-tutorial-for-gdb-and-c Due to the co-operative multi-tasking implementation of the SystemC library available from Accellera as @Roman Popov has mentioned, much of the debugging tasks are easier since all threads synchronize with the main library thread. Let me know if it helps. Regards, Ameya Vikram Singh
  3. 2 points

    reset during wait(int)

    IEEE 1666-2011 describes wait(int ) as follows: If my interpretation is correct, wait(3); should always be equivalent to wait(); wait(); wait(); However, after applying such an equivalent transformation to tests/systemc/kernel/reset_signal_is/test02/test02.cpp from the regression suite, I got a different simulation output (with systemc-2.3.2): Is this possibly a bug in the reference implementation?
  4. 1 point

    Using Debug mode.

    If you use the Makefile provided along the simple_fifo example, it should get compiled with debug symbols. On the console, you should see that the .cpp files get compiled with the "-g" switch. To actually make use of the debugging symbols, you have to execute the example in a debugger such as gdb (as Roman already pointed out). By the way, "make -d" does not influence which flags are passed to the C++ compiler. It just makes the output of make itself more verbose.
  5. 1 point
    Using your own report handler is a bit extreme; although, instructive. I suggest using the sc_report_handler::set_action() method. Please read the standards document (downloadable from IEEE via link on Accellera). It's quite readable.
  6. 1 point
    SystemC does not execute your threads in parallel, they are executed sequentially. But this is true that inter-thread communtication is hard to debug. Best known debugging method is waveform analysis. Usually it is much faster to identify source of problem on waveform, rather than with text logs. With opensource kernel you can use sc_trace to trace variables. Commerical SystemC debuggers offer GUI with drag-and-drop support.
  7. 1 point
    Roman Popov

    Backtrace with sc_report_error()

    If you want to see stacktrace in LLDB, then just set a breakpoint in sc_report_error(). If you want to see a stacktrace when you run simulation without debugger, then use Boost::Stacktrace http://www.boost.org/doc/libs/1_65_1/doc/html/stacktrace.html
  8. 1 point
    Philipp A Hartmann

    User Guide for systemc 2.3.2

    Annex C in the SystemC standard lists some deprecated features. In the SystemC proof-of-concept implementation, you find detailed information about changes in the RELEASENOTES file, but mostly only relative to the previous version.
  9. 1 point
    The Accellera Portable Stimulus Working Group (PSWG) is proud to announce the release for Public Review of the latest preliminary version of the Portable Test and Stimulus Standard. This Beta release includes additional work done by the PSWG since the release in June, 2017 of the “Early Adopter” version, reflecting progress on a wide range of issues to improve the standard, including user feedback on the EA version. The PSWG continues to make progress on key features targeted for the 1.0 release of the standard and is committed to ensuring that the standard will open new frontiers of productivity for the industry. The Portable Test and Stimulus Standard defines a domain-specific language (DSL) and an accompanying semantically-equivalent C++ library to create a single representation of stimulus and test scenarios, usable by a variety of users across different levels of integration under different configurations. It will permit the generation of multiple scenarios from a single specification of test intent, and allow tools to create different implementations of a scenario that run on a variety of execution platforms, including, but not limited to, simulation, emulation, FPGA prototyping, post-silicon and virtual platforms. With this standard, users can specify a set of behaviors once, from which multiple implementations may be derived. The Portable Test and Stimulus Standard is still a work in progress, which is why we are asking for public feedback. Enhancements to the Beta version being worked on by the PSWG are: Enhanced control of random selection and scheduling of actions Enhanced coverage constructs for coverage of flows, action scheduling, and resource utilization Enhanced features to handle hardware-software interface and product configurable features Enhanced modeling of memory management Enhanced type system to include additional array types and parameterization by type and value Enhanced reactivity of model to environment Enhanced conditional code processing The Public Review Period will be open until Friday, March 30, 2018. Please provide your feedback via the Accellera Portable Stimulus Forum. All comments will be reviewed by the PSWG. Download the Portable Test and Stimulus Standard Beta release here
  10. 1 point
    This has nothing to do with SystemC, but more to do with your declaration. You are declaring an array of pointers to integers on the stack. Stack in SystemC is 64k by default, which means you are limited to 64k/sizeof(int*). I suspect you intended to declare a pointer to an array of ints: int (*matrix)[]; // Pointer to array of int or int** matrix; I suggest you read at least one of the following: https://www.codeproject.com/Articles/7042/How-to-interpret-complex-C-C-declarations https://www.geeksforgeeks.org/complicated-declarations-in-c/ https://medium.com/@bartobri/untangling-complex-c-declarations-9b6a0cf88c96 For simplicity, I like the following tool: https://cdecl.org
  11. 1 point
    David Black

    sc_thread vs pthread

    SystemC follows event driven simulation semantics to simplify hardware modeling. In part, this means using a cooperative multi-tasking model rather than a modern pre-emptive model. In this respect, SystemC is like SystemVerilog and VHDL. This makes it easier to focus on the modeling aspects rather than worrying about mutexes, volatility and other interactions due to multicore and parallel processes. Advanced SystemC users can use OS threads for some tasks, but the synchronization aspects are up to the programmer. So SC_THREAD's are not pre-emptive (nor are SC_METHOD processes) and hence a straightforward SystemC model is single core single threaded from an OS/software point of view. Additionally, you should be aware that the SystemC scheduler is not thread-safe for the most part. If you make use of async_request_update(), you can use multicore and parallel processes to interact with SystemC events. This assumes you are an expert programmer and proficient with C++ (not for beginners). There have been and are some efforts underway to standardize parallelization in SystemC, but it is a volunteer effort and you need to be on the SystemC LWG group to participate. Some commercial entities have developments underway, but keeping those closed for the time being. Always keep in mind that SystemC is not freeware, but was created as part of a commercial coalition to standardize modeling across/between companies. Don't think of SystemC as a free simulator. Also, SystemC is often mistaken as a competitor/alternative to SystemVerilog/VHDL, which it is NOT. SystemC was intended for high-level modeling and abstractions above RTL. The ability to co-simulate with RTL is a requirement for some of the use-cases. SystemC is used quietly by many large corporations to augment specification and verification. It differs from the other languages in that it uses an off-the-shelf C++ compiler and has no requirement of a specialized compiler. This benefits companies with huge software development teams using SystemC Virtual Platform models for early software development. The downside of this approach is the C++ compiler has no understanding of the SystemC domain and has no way to make optimizations that SystemVerilog/VHDL do (e.g. clocks). That is one reason that SystemC coders are advised to avoid explicit clock models to gain performance. Keep the design at as high a level of abstraction as you can.
  12. 1 point

    Socket binding to module itself

    Hello, I am new in the SystemC-TLM world. I am reading the LRM and looking at an example (chapter 13, systemc LRM, page 462). In the module constructor it is written ... init_socket.bind(*this); // Initiator socket bound to initiator itself ... The rest of the code is of no use for the sake of the question. I don't understand why the socket must be bound to the module itself. The example continues and the socket is bound to a target socket, but I don't get this one... Thank you in advance. Leo
  13. 1 point
    This because you need to understand the macro `uvm_oject_utils() See http://go.mentor.com/mcem, then look at the Reference for uvm_object_registry.
  14. 1 point
    I believe 'force' is intended for net types (e.g. wire) and uses the SystemVerilog 'force' statement; whereas, 'deposit' is intended for variables (i.e. var or reg types). Lookup the 'force' and 'release' statements in the SystemVerilog standard for more information.
  15. 1 point

    Socket binding to module itself

    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!
  16. 1 point
    The "sc_export" part of each TLM-2.0 socket needs to be bound to an interface (tlm_bw_transport_if for an initiator, tlm_fw_transport_if for a target socket) in order to provide the implementation of the communication link. As you can see in the referenced example, the Initiator class inherits and implements the backwards interface: struct Initiator: sc_module, tlm::tlm_bw_transport_if<> // Initiator implements the bw interface As a result it can act as the "channel" to provide the behaviour for the sc_export part of the initiator socket. This pattern is a quite common idiom in the TLM-2.0 world, at least if you don't use the convenience sockets. So to answer your question: It's not the "module part" that is bound to the socket. The Initiator is-a backwards interface as well, and this "interface part" is bound. Greetings from Oldenburg, Philipp
  17. 1 point
    Hi Doug, I have done this sort of thing before with callbacks & the uvm_event_pool to synchronise parts of my env to register access: class trigger_reg_field_cbs extends uvm_reg_cbs; `uvm_object_utils(trigger_reg_field_cbs) function new(string name = "trigger_reg_field_cbs"); super.new(name); endfunction: new virtual function void post_predict(input uvm_reg_field fld, input uvm_reg_data_t previous, inout uvm_reg_data_t value, input uvm_predict_e kind, input uvm_path_e path, input uvm_reg_map map); uvm_event access_event; `uvm_info("REG_CBS", $psprintf("post_predict() called for field %s, current value: %04x, previous value: %04x, kind: %s, path: %s", fld.get_name(), value, previous, kind.name(), path.name()), UVM_HIGH); if (kind == UVM_PREDICT_DIRECT) begin access_event = uvm_event_pool::get_global($psprintf("%s_PREDICT", fld.get_name())); access_event.trigger(); end if (kind == UVM_PREDICT_READ) begin access_event = uvm_event_pool::get_global($psprintf("%s_READ", fld.get_name())); access_event.trigger(); end if (kind == UVM_PREDICT_WRITE) begin access_event = uvm_event_pool::get_global($psprintf("%s_WRITE", fld.get_name())); access_event.trigger(); end endfunction endclass: trigger_reg_field_cbs I did a presentation with some callback recipes at a UK conference recently - you might find it interesting: http://testandverification.com/verification-futures/verification-futures-2012/speakers/steve-holloway-dialog-semiconductors/ Regards, Steve