Jump to content

Roman Popov

  • Content Count

  • Joined

  • Last visited

  • Days Won


Everything posted by Roman Popov

  1. You can enable delta_cycle tracing with sc_trace_delta_cycles(tf, true) and try to find a signal in VCD gui. Since VCD format does not actually support delta cycles, SystemC traces them as 1ps steps.
  2. Probably you talk about cycle-based simulators? Like for example Verilator (https://www.veripool.org/wiki/verilator). Cycle-based simulators are faster than discrete-event simulators if you have a cycle-accurate model like RTL. Also cycle-based simulation is easier to parallelize. Oftern pin-level interfaces are used to integrate some RTL into C++ simulators. Or opposite, integrate high-level C++ simulators into RTL verification environment. Commercial simulators like VCS can automatically generate SystemC pin-level wrapper for Verilog, or Verilog wrapper for SystemC. Then you can do cosimulation. Another usage for pin-level interfaces is High-Level Synthesis. HLS tools from Cadence and Mentor take SystemC models with pin-level interfaces as an input.
  3. Roman Popov

    SC_VECTOR declaration causes Exception thrown.

    Looks like null pointer dereference. I don't immediately see a problem in code samples you provide. Probably bug is somewhere else. Use debugger to identify the root cause of problem.
  4. Roman Popov

    Synthetizable FFT function in SystemC

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

    Synthetizable FFT function in SystemC

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

    Synthetizable FFT function in SystemC

    Xilinx HLS tools have very limited SystemC support, you should probably code your FFT in pure C++.
  7. Roman Popov

    write different types of data in a custom port

    But even this won't fix your error. Because compiler will still complain about assigning sc_logic to double, even if it is in always false branch. What you need is if-constexpr and std::is_same if you have C++17. Or SFINAE, if you don't. Something like this may work: if constexpr (std::is_same_v<T, sc_dt::sc_logic>) { out = SC_LOGIC_Z; } else { out = 0; }
  8. Roman Popov

    SystemC implementation from C-code sources

    You should start with learning your synthesis tool documentation. C++/SystemC synthesis is very tool-specific.
  9. Roman Popov

    primitive port that responds to sensitivity ???

    Yes, you can design ports that will behave the way you described. Together with special ports I suggest you to also create a special kind of module that will encapsulate power control events. Then you can make power aware ports to be automatically sensitive to power events of module they belong to.
  10. Roman Popov

    What effect option DISABLE_VIRTUAL_BIND has?

    If you run It will install to any directory you want. If you want to to have multiple SystemC versions installed, you can install them in different directories. Then just add all installed directories to CMAKE_PREFIX_PATH and select required version in your application CMakeLists.txt For application using 2.4.0 find_package(SystemCLanguage 2.4.0 CONFIG REQUIRED) message("Using SystemC from ${SystemCLanguage_DIR}") message("Using C++ Standard: ${SystemC_CXX_STANDARD}") For application using 2.3.3 find_package(SystemCLanguage 2.3.3 CONFIG REQUIRED) message("Using SystemC from ${SystemCLanguage_DIR}") message("Using C++ Standard: ${SystemC_CXX_STANDARD}")
  11. In our environment we have one simulator that uses SystemC hierarchy and elaboration, but does not use SystemC scheduler. There is no problem with check-pointing : when we need to restore from checkpoint we just re-run SystemC elaboration and then apply checkpoint state. But using TLM-2.0 without SystemC elaboration is not possible, because internally it has core SystemC objects like ports and exports. So probably you don't need SystemC at all.
  12. At least you need to finish elaboration, using sc_start(SC_ZERO_TIME); But usually TLM-2.0 models cannot be used without SystemC scheduler, since TLM models are allowed to use SystemC primitives like processes and events.
  13. Roman Popov

    What effect option DISABLE_VIRTUAL_BIND has?

    When you don't manually set CMAKE_INSTALL_PREFIX, it tries to install into ${SYSTEMC_HOME} or ${SYSTEMC_ROOT_DIR}. One nasty thing about SystemC CMake build system is that it exports targets from build directory, so you can use find_package even without installing SystemC. This may be very confusing. (But some people find it convenient - you don't need to install, just build and use) This is probably what you are encountering - You have old C++98 SystemC build directory somewhere, and find_package founds it, instead of installed modern C++ SystemC build. So I would recommend to print some informational messages in your application CMakeLists.txt: find_package(SystemCLanguage CONFIG REQUIRED) message("Using SystemC from ${SystemCLanguage_DIR}") message("Using C++ Standard: ${SystemC_CXX_STANDARD}") set (CMAKE_CXX_STANDARD ${SystemC_CXX_STANDARD}) When you run cmake it will print something like this: Using SystemC from F:/work/systemc-2.3.3/cmake-build-debug Using C++ Standard: 17
  14. Roman Popov

    What effect option DISABLE_VIRTUAL_BIND has?

    You don't need to run configure if you use CMake. configure is for autotools, another build system. Most likely you have it in CMake Cache. Read how CMake set(...) works here : https://cmake.org/cmake/help/latest/command/set.html Because SystemC standard is written on top of C++03. Unfortunately it looks like we will have to wait another year or two for next IEEE SystemC standard on top of more modern C++. Because SystemC 2.3.1 had no C++11 features. But Accellera releases after 2.3.1 start to include some features made with modern C++. Thus, SystemC 2.3.3 compiled with -std=c++11 and -std=c++98 may be incompatible. More on that here: http://forums.accellera.org/topic/5738-support-for-c1114-in-systemc-232/ Yes, basically the only thing you need to do is to recompile SystemC library with C++ standard you use for your application. I linked SystemC with GTest without any issues. In general, I understand your frustration, because if you use modern Linux with gcc or clang, you get used to good binary compatibility between compiler and libraries versions. However the rest of the world is not like that. On Windows/MSVC for example you usually have to match compiler versions and flags for all libraries you link. If you are unlucky to work in semiconductor industry, you will soon find out that you are forced not only to use specific C++ standard, but also specific Linux (RHEL) and specific outdated GCC version.
  15. Roman Popov

    tlm_fifo nb_peek

    Oh nice, seems my workaround was wrong. I did not know that qualified name lookup suppresses dynamic dispatch of virtual functions. https://en.cppreference.com/w/cpp/language/virtual C++ is full of such traps 🙂
  16. Roman Popov

    tlm_fifo nb_peek

    This is strange, tlm_nonblocking_peek_if is an abstract class, so compiler should not allow you to construct it. Can you give small complete example reproducing the problem?
  17. Roman Popov

    Killing a process with an included sc_event_[and|or]_list

    Here is comment from Accellera SystemC 2.3.3: void sc_event_list::report_premature_destruction() const { // TDB: reliably detect premature destruction // // If an event list is used as a member of a module, // its lifetime may (correctly) end, although there // are processes currently waiting for it. // // Detecting (and ignoring) this corner-case is quite // difficult for similar reasons to the sc_is_running() // return value during the destruction of the module // hierarchy. // // Ignoring the lifetime checks for now, if no process // is currently running (which is only part of the story): I don't know what "TDB" means here, but it seems like the case when sc_event_list resides on SC_THREAD stack was not considered here. So we have two options how to fix this: Remove report_premature_destruction check. Register sc_event_lists inside process handler, and notify them when thread is terminated so it longer waits for event.
  18. Roman Popov

    Count number of SC_THREAD and/or SC_METHOD

    int n_methods = 0; int n_threads = 0; int n_cthreads = 0; void count_procs_recursive(sc_object * parent) { if (std::string ( parent->kind() ) == "sc_method_process" ) n_methods++; if (std::string(parent->kind()) == "sc_thread_process") n_threads++; if (std::string(parent->kind()) == "sc_cthread_process") n_cthreads++; for (sc_object * child : parent->get_child_objects()) { count_procs_recursive(child); } } void before_end_of_elaboration() override { for (sc_object * obj : sc_get_top_level_objects()) { count_procs_recursive(obj); } cout << "n_methods = " << n_methods << "\n"; cout << "n_threads = " << n_threads << "\n"; cout << "n_cthreads = " << n_cthreads << "\n"; } ( Not tested. )
  19. Roman Popov

    Assembling submodule status bits in a word

    Check section 4.2 "Simulation" of SystemC standard. Values of signals change in "Update Phase", so they don't depend on process evaluation order.
  20. Roman Popov

    Assembling submodule status bits in a word

    Can you explain what you mean by "ugly"? You don't want to create many events? Or you don't want to connect every module manually? Second problem can be solved with a loop.
  21. Because of dynamic dispatch. https://en.cppreference.com/w/cpp/language/virtual
  22. Roman Popov

    How can I implement SC_FORK JOIN_ANY /SC_FORK JOIN_NONE

    Ok, thanks a lot for example. I'm not using UVM myself and have no idea what it does. But it looks like UVM does not allow you to call wait() inside run_phase, because it terminates the thread immediately. If you rewrite your code this way: void run_phase(uvm::uvm_phase& phase) { cout<< " run: before fork/join" << endl; // cout << "run: after fork/join" << endl; wait(40,SC_NS); cout<<"Current time is "<< sc_time_stamp() << endl; } You will see that "Current time is.." won't get printed. And because thread is terminated, event_list got destroyed and you see the error you see. From my perspective it is UVM-SystemC bug, it should prevent you from calling wait() from run_phase, by reporting something like "wait() is not allowed inside run_phase". I suggest you to post the issue to UVM SystemC support forum (http://forums.accellera.org/forum/38-systemc-verification-uvm-systemc-scv/) and see if anyone of UVM-SystemC developers can help/comment. If you put your code in a regular SC_THREAD you will see that everything works as expected .
  23. Roman Popov

    How can I implement SC_FORK JOIN_ANY /SC_FORK JOIN_NONE

    This is interesting, comment in source code says that it reports this error when event_list is destroyed, but some process is still waiting for it. Can you provide a small reproducer (complete code example) showing how you use it?
  24. SystemC has no special concept similar to SystemVerilog interfaces. Instead you can use regular SystemC modules to work as SystemVerilog interfaces. SystemC has it's own notion of interface that is similar to interface notion in object-oriented programming: interface is basically a set of pure virtual functions. So for example you can define a simple memory interface as a set of mem_read and mem_write functions. SystemC requires that interfaces inherit virtually from sc_interface: struct memory_if : virtual sc_interface { virtual uint32_t mem_read( uint32_t address) = 0; // reads data from memory at given address virtual void mem_write( uint32_t address, uint32_t data) = 0; // writes data to memory at given address }; Next you can define a module that implements and exports this interface. For example: struct memory_module : sc_module, memory_if { sc_export<memory_if> mem_export{"mem_export"}; SC_CTOR(memory_module) { mem_export.bind(*this); } private: std::array<uint32_t , 1024> mem; uint32_t mem_read(uint32_t address) override { return mem.at(address >> 2); } void mem_write(uint32_t address, uint32_t data) override { mem.at(address >> 2) = data; } }; You can have other modules implementing memory_if. For example you can write a module that translates mem_read and mem_write function calls into a cycle-accurate signal-level memory protocol. And this is what SystemVerilog interfaces often do. Now the closest analog to SystemVerilog virtual interface is SystemC sc_port. For example you can define a test_module that has a sc_port<memory_if> and sends memory reads and writes using this port: struct test_module : sc_module { sc_port<memory_if> mem_port{"mem_port"}; SC_CTOR(test_module) { SC_THREAD(test_thread); } private: void test_thread() { cout << " test_thread \n"; const int TEST_SIZE = 10; for (int i = 0; i < TEST_SIZE; ++i) { cout << hex << "Write mem[" << i * 4 << "] = " << i << "\n"; mem_port->mem_write(i*4, i); } for (int i = 0; i < TEST_SIZE; ++i) { cout << hex << "Read mem[" << i * 4 << "] == " << mem_port->mem_read( i * 4 ) << "\n"; } } }; To create a simulation you instantiate both memory_module and test_module and bind port to export: int sc_main (int argc, char **argv) { test_module tmod{"tmod"}; memory_module mmod{"mmod"}; tmod.mem_port.bind(mmod.mem_export); sc_start(); return 0; }
  25. It is explained in section 14.13 of SystemC standard. You should read all items from a) to n) to understand all usage details. From my experience, most models that I've seen do not use byte enables. But let's consider a basic example. Suppose we have a a memory target and it receives following transaction: { command = TLM_WRITE_COMMAND, address = 0x0, data[4] = { 0x1, 0x2, 0x3, 0x4 } byte_enable[4] = { 0x0, 0xff, 0x0, 0xff } } byte_enable [ N ] == 0x0 means that N'th byte of data should be ignored by target. Consider that memory had following values before processing the transaction: memory[ 0 ] == 0xA; memory[ 1 ] == 0xB; memory[ 2 ] == 0xC; memory[ 3 ] == 0xD; Since byte_enable[0] and byte_enable[2] are equal to 0x0, it means that corresponding bytes will be ignored during processing of transaction. So after processing the transaction memory will hold following values: memory[ 0 ] == 0xA; memory[ 1 ] == 0x2; memory[ 2 ] == 0xC; memory[ 3 ] == 0x4;