Jump to content


Popular Content

Showing content with the highest reputation since 05/21/2017 in all areas

  1. 2 points
    Hi Jarodw, Thanks for your report. I can confirm and reproduce the issue in SystemC 2.3.2. It looks indeed like a regression compared to SystemC 2.3.0/1 that has been introduced by the fix for optionally unbound sockets, see: It seems, the SystemC regression tests didn't cover the hierarchical binding for the multi sockets, so it wasn't caught before the release. Your example can be fixed by changing line 228 in src/tlm_utils/multi_passthrough_target_socket.h: if (unbound && !m_hierarch_bind) return; // ^-- add check for hierarchical binding here Hope that helps, Philipp
  2. 2 points
    Philipp A Hartmann

    makefile SystemC

    You can check out the example Makefiles in the installation (examples/build-unix/Makefile.{config,rules} and e.g. examples/sysc/simple_bus/Makefile) as a starting point. The files in examples/build-unix are reasonably generic, and you may "just" need to adjust the settings in Makefile.config. In the project's Makefile itself, you then set the PROJECT variable and your SRCS (to point to your source files). Admittedly, documentation could be better (as usual), but you can ask here, if you have further questions. The CMake support included in SystemC 2.3.2 is still experimental and is mostly targeted for early adopters with CMake knowledge. Greetings from Duisburg, Philipp
  3. 2 points
    Hello @Roman Popov, You can have a look here: Hope it helps. Regards, Ameya Vikram Singh
  4. 2 points

    Clock to Q Propagation Delay

    Hello, In SystemC you can use SC_THREAD's to model delays by using wait statements but you will incur performance penalty. Instead you can use event's and event queues to model delays using in SystemC as mentioned here: http://workspace.accellera.org/Discussion_Forums/helpforum/archive/msg/msg?list_name=help_forum&monthdir=200803&msg=msg00061.html You can replace the SC_THREAD example given in the above mentioned link with SC_METHOD removing the infinite while loop. Here's the modified example listed from the above mentioned link: template<typename T> class delay_transport : public sc_module { public: sc_in<T> in; sc_out<T> out; SC_HAS_PROCESS(delay_transport); delay_transport(sc_module_name name_, sc_time tdelay_) : sc_module(name_), tdelay(tdelay_), in("in"), out("out") { SC_METHOD(mi); sensitive << in.default_event(); SC_METHOD(mo); sensitive << eq; } sc_time tdelay; void mi() { val = in.read(); vq.push(val); eq.notify(tdelay); } void mo() { val = vq.front(); out.write(val); vq.pop(); } sc_event_queue eq; std::queue<T> vq; T val; }; Regards, Ameya Vikram Singh
  5. 2 points
    Yes, but you need to write the constructors yourself (don't use the SC_CTOR macro). Something like #include "systemc.h" SC_MODULE(mod) { int i; mod(sc_module_name nm) : sc_module(nm) { // ... } mod(sc_module_name nm, int i_) : sc_module(nm), i(i_) { // ... } }; If you use SC_THREAD or SC_METHOD you must also include the SC_HAS_PROCESS macro. Try looking up SC_HAS_PROCESS in 1666-2011 and you should find an example near there, regards Alan
  6. 2 points
    Manikanta's solution assumes temp is public. If not public, you can take the opposite approach and simply call sc_trace from within the module itself. You could even do it conditionally based on run-time command-line arguments: sc_core::sc_trace_file trace_file = 0; //< initialize to indicate not open top::before_end_of_elaboration() { for (int i=1; i<sc_argc(); ++i) { if ( trace_file == 0 && std::string(sc_core::sc_argv()[i]) == "-trace" ) trace_file = sc_core::sc_create_vcd_trace_file("your.vcd"); }//endfor } top::end_of_simulation() { if ( trace_file != 0 ) sc_core::sc_close_trace_file(trace_file); } ... extern sc_core::sc_trace_file trace_file; void dut::end_of_elaboration() { if (trace_file != 0) { sc_core::sc_trace(trace_file, temp,"temp"); } } Of course I am assuming fp is made public as shown, and that you have opened it before end of elaboration:
  7. 2 points

    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!
  8. 1 point
    I can also add a quote from the Verilog Standard IEEE 1364-2005, $timescale, describing the grammar rules for the timescale support in VCD: So even here, only powers of 10 are allowed.
  9. 1 point
    Roman Popov

    Bug at file sc_trace_file_base.cpp

    Thanks a lot for reporting! I can confirm that 2.3.2 does not supports v that it is not a multiple of 10. I agree that set_time_unit API is bad (error-prone), and should be changed. Good news that you've received a runtime error early and did not spent lots of time . Do you need support for fractional timeunits? Or just more clear API? I've also checked 2.3.1. It does not works properly with 0.5 either: int sc_main (int argc, char **argv) { sc_trace_file* tf; tf = sc_create_vcd_trace_file("traces"); sc_signal<int> isig{"isig",0}; tf->set_time_unit(0.5, SC_NS); sc_trace(tf, isig, "isig" ); sc_start(0.5, SC_NS); isig = 1; sc_start(2.5, SC_NS); isig = 2; sc_start(3.5, SC_NS); isig = 4; sc_start(3.5, SC_NS); sc_close_vcd_trace_file(tf); return 0; } VCD is incorrect: $date Dec 05, 2017 11:50:52 $end $version SystemC 2.3.1-Accellera --- Dec 5 2017 11:40:15 $end $scope module SystemC $end $var wire 32 aaaaa isig [31:0] $end $upscope $end $enddefinitions $end $comment All initial values are dumped below at time 0 sec = 0 timescale units. $end $dumpvars b0 aaaaa $end #1 b1 aaaaa #6 b10 aaaaa #13 b100 aaaaa So 2.3.2 is better. But not perfect :(
  10. 1 point
    If you use SC_THREAD that means that you are using sc_event under the hood. Because every SC_THREAD in SystemC has event that activates the process. You can for example spawn a SC_THREAD process to do delayed assignment like this: #include <systemc.h> struct spawned_assignment_demo : sc_module { SC_CTOR(spawned_assignment_demo) { SC_THREAD(test_thread); } sc_signal<int, SC_MANY_WRITERS> out{"out", 0}; void print_out_value() { cout << " out value = " << out.read() << " at " << sc_time_stamp() << "\n"; } void test_thread() { print_out_value(); sc_spawn([&]() { wait(10, SC_NS); out = 42; }); wait(5, SC_NS); print_out_value(); sc_spawn([&]() { wait(10, SC_NS); out = 124; }); wait(6, SC_NS); print_out_value(); wait(6, SC_NS); print_out_value(); } }; int sc_main (int argc, char**argv) { spawned_assignment_demo demo{"demo"}; sc_start(); sc_stop(); } Output will be as expected: out value = 0 at 0 s out value = 0 at 5 ns out value = 42 at 11 ns out value = 124 at 17 ns But when you call wait(10,SC_NS) you create timed event notification. You can use debugger to step into wait() to see what happens there.
  11. 1 point

    SCV library installation

    Hi Aixeta, this is already fixed in the upcoming release of the SCV. Meanwhile you can workaround by casting directly to sc_logic: sc_dt::sc_logic_value_t(this->_get_instance()->get_bit(i))
  12. 1 point

    Transaction Data Pointer

    Hi. Normally the initiator is considered as owner of the payload, i.e. he should take care of allocating and de-allocating it. The target should decide how to use the data. If the target wants to keep it/store it, the target should make a copy of the data. In that sense, the transaction is completed when b_transport returns because the initiator transfered it to the target and the target had a chance to handle it. A benefit of this is that you do not need dynamic allocation of the buffer buf. Greetings Ralph
  13. 1 point
    Philipp A Hartmann

    Explicit parent object

    Both versions are non-portable, as the SystemC simcontext is not part of the standard either. I am even surprised that the hierarchy_push/pop functions are not restricted (as they should be). So the first solution might in fact break in future versions of SystemC as you shall not mess with the object hierarchy stack yourself. Whether or not the "hierarchy scope guard" can be extended to become a standardized solution will likely require some discussions first, especially how to avoid breaking the object hierarchy. Certainly, this internal hierarchy stack is not something to arbitrarily use from the model side, other than from the sc_module_name usage today. For the particular use case, you can now look into the new "optionally bound convenience sockets" in SystemC 2.3.2, which you can safely leave unbound when not used. An arbitrary number of sockets can be bound to the multi_passthrough_*_socket, without having to do any such magic above. For a generic pattern to request additional structural things to "appear later", you can use an sc_vector with delayed initialization (since SystemC 2.3.2). This is (currently) limited to a single call, but I could envision to extend this to support distributed emplace_back() calls during elaboration. Such an approach would at least restrict the external modification of the hierarchy to much more controllable contexts. Regarding your current use case: How does the destination module actually use these newly added ports/sockets? /Philipp
  14. 1 point
    For all of the bitwise modifiedWrite functions (oneToClear, oneToSet, oneToToggle, zeroToClear, zeroToSet, zeroToToggle) the specified bit write value changes the target bit and the opposite bit write value leaves the target bit unchanged. This provides atomic write access to modify a single bit within a field within a single write transaction. For fields with normal write behavior the write replaces the target field value with the write value. This feature was inherited and expanded from Accellera SystemRDL 1.0 standard which at least has equations for the few bitwise write behaviors it supports. The IEEE 1800.2-2017 UVM standard inherited this feature from IP-XACT and has a slightly better description. We'll make sure that the next version of the standard specifies more completely the behavior of modifiedWrite.
  15. 1 point
    Any eventual copy returned from read() by value will never be optimized away, as the source location continues to exist in the signal. The simplest solution is to change your signal converter as follows (untested): template <typename Treal, typename Tcasted> class signal_interface_converter : public sc_core::sc_signal<Treal> , public sc_core::sc_signal_in_if<Tcasted> // only read allowed { typedef sc_core::sc_signal<Treal> real_type; public: explicit signal_interface_converter(const char* nm) : real_type(nm), casted_val() {} const Tcasted &read() const override { return casted_val; } private: void update() override { real_type::update(); casted_val = static_cast<Tcasted>(real_type::read()); ] Tcasted casted_val; }; So the idea is basically to leverage the update phase to update the casted value. If the above doesn't work due to read() overloads based on the return type only, you may need to wrap it differently to separate the two conflicting interfaces (e.g. by using an internal signal with an overridden update() function, triggering the update of the casted value in the converter). Hope that helps, Philipp
  16. 1 point
    Philipp A Hartmann

    multiple event in next trigger

    I cannot tell, if I understand your question at all. I'll just add the comment that you can use next_trigger(); without any arguments to restore the static sensitivity. Hope that helps, Philipp
  17. 1 point

    systemC design

    Hello @yosri ben salah, As far as my experience is OpenCV image processing algorithms cannot be directly translated to synthesized design. It would involve manual translation of the algorithms in it's current form, but the work is progressing as mentioned here about utilizing the FPGA's. Regards, Ameya Vikram Singh
  18. 1 point

    refine Code

    There are many issues in your code: You do not instantiate your module ImageProcessing in sc_main(). The member function ImageProcessing::synchronisation() is never used. From the code, you probably want that it shall be executed as a SC_THREAD. You mix C and C++ for memory allocation and IO. I suggest you to use <iostream> instead of <stdio.h> for your input and output needs. Use new and delete instead of malloc() and free() if you really need it. However, it is usually better to use a suitable container, e.g., std::vector instead of raw pointers and manually allocated memory. Prefer to #include <systemc> over <systemc.h>, <cstdlib> over <stdlib.h>, etc. to avoid polluting the public namespace. The variable b, used in your code, doesn't seem to have been declared. If b is an int, the division by 196608 won't yield the floating point result, which you expect as an integer division will be performed. ... These are just the ones, which jump to the eye. It seems you are not only struggling with SystemC, but also with C++. I suggest you to read a good introductory book on C++ (Stroustrup: "Programming: Principles and Practice Using C++" or "The C++ Programming Language") as well as on SystemC (e.g. Black, Donovan et al.: "SystemC from the Ground Up").
  19. 1 point
    Because clocked threads are sensitive to an explicit clock. This clock does not have to be active during the start of the simulation. Greetings from Duisburg, Philipp
  20. 1 point



    Hello, This contribution includes the updated examples for the second edition of the UVM Book: A Practical Guide to Adopting the Universal Verification Methodology (UVM) Second Edition. Enjoy! Kathleen Meade and Sharon Rosenberg
  21. 1 point

    Randomization in an initial block

    This is the correct functionality. There is a random number generator (RNG) for every module instance in your design, and it is seeded with a RNG from the module instance it starts from. All all modules instances start out with identical seeds. Every thread that starts inside a module instance grabs a new RNG. Threads in parallel blocks get seeded in declaration order, not in the indeterminate order they might actually start. Objects that get constructed get seeded with an RNG from the thread calling the constructor. This random stability model has a few problems that the UNM attempts to correct by using a path name as an initial seed. You just need to make sure your path names are unique enough to generate distinctive seeds. A good paper to read on this topic is: Random Stability, Don't leave it to chance.
  22. 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.
  23. 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
  24. 1 point
    Short answer: The standard requires an sc_trace overload for a user-defined (signal) datatype if and only if you actually trace this particular type. Defining the virtual function sc_object::trace would require an overload for each and every data type used within a primitive channel supporting traces, even if those signals are never traced. This would be quite inconvenient. /Philipp
  25. 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