Jump to content

Roman Popov

  • Content count

  • Joined

  • Last visited

  • Days Won


Everything posted by Roman Popov

  1. Why SystemC does not allow to pass event directly to SC_CTHREAD macro? For example: #include <systemc.h> SC_MODULE(test) { sc_clock clkgen{"clkgen", 10, SC_NS}; sc_in_clk clk{"clk"}; SC_CTOR(test) { clk(clkgen); SC_CTHREAD(test_cthread, clk.pos()); // OK SC_CTHREAD(test_cthread, clkgen.posedge_event()); // Compile error! } void test_cthread(); }; If I inline macro I can do what I want: { ::sc_core::sc_process_handle test_cthread_handle = sc_core::sc_get_curr_simcontext()->create_cthread_process( "test_cthread", false, static_cast<sc_core::SC_ENTRY_FUNC>(&SC_CURRENT_USER_MODULE::test_cthread), this, 0); /// this->sensitive.operator()(test_cthread_handle, clkgen.posedge_event()); /// Error sc_sensitive::make_static_sensitivity(test_cthread_handle,clkgen.posedge_event()); /// OK }; This looks to me as inconvenience without a good reason.
  2. Roman Popov

    Passing event to SC_CTHREAD macro

    There is a difference: in SC_CTHREADs you can't wait on event. Since this would not be synthesizable. sc_clock clk{"clk", 1, SC_NS}; SC_CTOR(test) { SC_THREAD(test_thread); sensitive << clk.posedge_event(); SC_CTHREAD(test_cthread, clk); } void test_thread() { wait(clk.negedge_event()); // OK } void test_cthread() { wait(clk.negedge_event()); // RUNTIME ERROR } So I always use SC_CTHREADs in synthesizable code, to specify my intent and prevent accidental calls to non-synthesizable methods with wait(event). Indeed, did not know about it. This works for me. In my practice I did not yet encountered a case where I need to create a CTHREAD sensitive to negedge.
  3. Roman Popov

    How SystemC kernel is implemented !!

    SC_THREADS are coroutines https://en.wikipedia.org/wiki/Coroutine. SystemC uses different coroutines implementations depending on platform (Fibers, QuickThreads..). Function of sc_simcontext is not standartized. But in open-source SystemC it contains main simulator loop.
  4. Roman Popov

    How SystemC kernel is implemented !!

    You should probably read a book about multi-threaded programming to understand what thread means. A good book about standard C++ threads is C++ Concurrency in Action by Anthony Williams. SystemC is indeed a single thread. Most of other cycle-accurate (RTL) and TLM simulators are also single-threaded. In theory, you can write a parallel scheduler that can utilize multiple HW threads to evaluate a single delta-cycle (because SystemC standard does not restrict the order of process evaluation inside delta cycle) . However, amount of work performed in a single delta cycle is usually small, so instead of speedup you will get a slow down. To utilize power of multicore CPUs you should parallelize your test environment. Instead of running multiple tests sequentially in a single simulator, you can run different tests in parallel on different simulators. Personally, I integrate my tests with CTest : https://cmake.org/cmake/help/latest/manual/ctest.1.html and then run in parallel simply by specifying number processes I want to utilize, for example "ctest -j 8"
  5. Roman Popov

    sc_spawn and anthoer process

    If you want to pass a parameter to process, then you can use sc_spawn and std::bind to bind parameters.
  6. Roman Popov

    Graph Generation

    In some cases yes, you can do it by playing with dynamic casts. For example: #include <systemc.h> SC_MODULE(test) { sc_signal <int> xsig{"xsig"}; sc_signal <unsigned> xsig2{"xsig2"}; sc_in <int> xin{"xin"}; sc_out <unsigned> xout{"xout"}; SC_CTOR(test) { xin(xsig); xout(xsig2); } }; int sc_main(int argc, char **argv) { test t0{"t0"}; sc_start(SC_ZERO_TIME); cout << hex; for (auto * obj : t0.get_child_objects()) { cout << obj->kind() << " " << obj->name() << " @ " << obj; if(sc_port_base* port = dynamic_cast<sc_port_base*>(obj)) if (sc_prim_channel * chan = dynamic_cast<sc_prim_channel*>(port->get_interface())) std::cout << " ( binded to " << chan->name() << " @ " << chan << ")"; cout << endl; } return 0; } Possible output: sc_signal t0.xsig @ 0x111f878 sc_signal t0.xsig2 @ 0x111f938 sc_in t0.xin @ 0x111f9e8 ( binded to t0.xsig @ 0x111f878) sc_out t0.xout @ 0x111fa90 ( binded to t0.xsig2 @ 0x111f938) SystemC however does not store information about hierarchical bindings.
  7. Roman Popov

    sc_spawn and anthoer process

    sc_spawn allows to create process during simulation runtime. SC_* macro can be used only at elaboration time. Please read more details in IEEE SystemC standard. Here is small usage example: #define SC_INCLUDE_DYNAMIC_PROCESSES #include <systemc.h> SC_MODULE(spawn_demo) { SC_CTOR(spawn_demo) { SC_THREAD(static_thread); } void static_thread() { sc_spawn_options opts; sc_spawn([&]() { wait(1, SC_NS); cout << "spawned @ " << sc_time_stamp() << "\n"; }, "spawned_thread", &opts); wait(1, SC_NS); cout << "static @ " << sc_time_stamp() << "\n"; } }; int sc_main(int argc, char **argv) { spawn_demo demo0{"demo0"}; sc_start(); return 0; }
  8. Roman Popov

    Implement sc_trace for std::string

    Unfortunately current implementation was not designed to be extensible by user. So you will have to hack SystemC kernel itself. Tracing part is relatively small so it's should not be very hard. Just follow the implementation for existing types. In general however it should be better to redesign tracing API so it will be extensible for user-supplied types. In addition to accepting fixed set of datatypes, it should also accept abstract interfaces that can be implemented by end user. For example: // currently does not exist struct BitVecConvertible { virtual sc_dt::sc_bv_base to_bv() = 0; } sc_trace(sc_trace_file* tf, BitVecConvertible &obj, onst std::string& name); In that case user can trace any type as a bit vector, by implementing an interface or providing a proxy-class.
  9. Roman Popov

    Possible Bug in VCD tracing

    Thanks for reporting! Here is a small reproducer for this bug: #include <systemc> int sc_main(int argc, char ** argv ) { sc_core::sc_trace_file *tf = sc_core::sc_create_vcd_trace_file("vcdtrace"); sc_core::sc_close_vcd_trace_file(tf); return 0; } Probably the easiest way to fix is to do zero check before printing last time stamp.
  10. The problem is that both sockets are binded to same target interface implementation. So: In[0].get_interface() == In[1].get_interface(); When you bind same interface twice to a single port, SystemC considers this a design error. Solution depends on your modeling needs. Usually TLM sockets are connected point-to-point and to model interconnect a separate module that forwards transactions from initiator to targets is created.
  11. You can use sc_vector: sc_vector<tlm_utils::multi_passthrough_initiator_socket<Router, 32, tlm::tlm_base_protocol_types,1,sc_core::SC_ZERO_OR_MORE_BOUND >> Out{"Out", 10};
  12. No, this is not allowed by SystemC LRM "5.3.3 Constraints on usage":
  13. What do you want exactly? Can you use sc_vector<My> that automatically initializes names? Can you concatenate name and ID before module construction? SystemC elaboration relies on the fact that sc_module_name will be constructed before module. This way it can create correct hierarchical names for module fields. Modern way to declare module is like this: struct my_module : sc_module { my_module(sc_module_name) { } }; More compact way is to use SystemC macros: SC_MODULE(my_module) { SC_CTOR(my_module) { } };
  14. Roman Popov

    SC_METHOD Eception

    I mean a small complete code sample I can run on my computer to reproduce the your error.
  15. Roman Popov

    SC_METHOD Eception

    No, I don't see problems in your code. It can be a problem with your visual studio settings, since expection you get comes from vs runtime. Can't help without reproducer.
  16. Roman Popov

    SC_METHOD Eception

    I don't see a problem in a given code sample. Can you provide a small complete reproducer for problem?
  17. Roman Popov

    Passing collected events to sensitive

    You can write function that will add collection of events to sensitivity. You can even overload operator << if that's what you want.
  18. Roman Popov

    Use of callback before_end_of_elaboration

    In a current implementation sc_start() finishes elaboration and starts simulation. You can look into source code for details. But at very high level you can think of sc_start like this: void sc_start() { finish_elaboration(); // complete binding, call before_end_of_elaboration start_simulation(); // start scheduler } I recommend to run sc_start() in debugger step-by-step to understand what happens inside.
  19. Roman Popov

    Use of callback before_end_of_elaboration

    No, changing the structure of design is not possible after elaboration. You can't create signals, ports and modules during simulation. But you can spawn new processes, this is commonly used in verification environments, to model different streams of test stimulus.
  20. Roman Popov

    Using Debug mode.

    I don't know how autotools flow works. But in case you can use CMake, it is very easy to complie in debug mode, just add -DCMAKE_BUILD_TYPE=Debug when generating Makefile. $ mkdir build_debug $ cd build_debug $ cmake ../ -DCMAKE_BUILD_TYPE=Debug $ make -j8 simple_fifo $ gdb ./examples/sysc/simple_fifo/simple_fifo
  21. Roman Popov

    Use of callback before_end_of_elaboration

    As I understood you want to read value from port during elaboration process? This is not how ports are supposed to be used. They are simulation-time mechanism. If you want to initialize a vector with some value, why don't you just pass it as a constructor parameter? sub_module(::sc_core::sc_module_name, int a ) { b.init(a); }
  22. Roman Popov

    Debugging Multi threaded program in SystemC

    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.
  23. Roman Popov

    Backtrace with sc_report_error()

    Did you checked SystemC standard? 8.3 sc_report_handler. You can try doing it like this: void my_handler(const sc_report& r, const sc_actions & a) { sc_report_handler::default_handler(r,a); } sc_report_handler::set_handler(my_handler);
  24. Roman Popov

    SC_METHOD and next_trigger() diagnostics

    Can you give a complete small reproducer of your problem? Otherwise I can just guess. Who calls getByte? Some sc_thread? About SC_HAS_PROCESS - it should be fine unless you defne couple of modules in same translation unit.
  25. Roman Popov

    SC_METHOD and next_trigger() diagnostics

    Most likely you are calling WaitAccessing from somewhere else, not shown in your code sample. Just set a breakpoint on error and check call stack. Also, why do you put SC_HAS_PROCESS to global namespace?