Jump to content

David Black

Members
  • Posts

    681
  • Joined

  • Last visited

  • Days Won

    152

Posts posted by David Black

  1. Assuming your processes only write on the posedge clock, you could use an sc_buffer<bool> and make the last process sensitive to the buffer instead of the clock. Every time the queue is written, also write to the buffer (true). Since all the other processes will be enabled at the posedge clock, the buffer will not be processed until one delta-cycle after the clock has been processed. You would probably want to create a simple wrapper for the queue and processing. I suggest using an unbounded tlm_fifo<T> for the queue.

  2. The difference between sc_buffer and sc_signal is that sc_buffer<T>::write issues an event on every write; whereas, sc_signal<T>::write only issues an event if the value changes (e.g., from 0 to 1 or 1 to 0).

    I would have to see all your code (preferably on EDA playground) to understand the issue.

     

  3. SystemC is not designed to allow more than one sc_main to run. If you want more than one kernel to run, you will need to launch a separate OS process and use IPC. You will probably also need to learn how to use the new sc_suspend_all method and its cousins from section 4.6.3 in IEEE-1666-2023. This also requires you to use SystemC 3.0 (released just over a week ago on March 29th, 2024) and C++17. async_request_update can then be used to resume.

    Please note this is an advanced topic and requires have a solid grasp of SystemC simulation semantics including the subtle differences between SystemC processes (SC_THREAD and SC_METHOD) and OS processes vs OS threads. [Hint: SystemC is mostly not OS thread-safe; hence, the need for async_request_update and the suspend mcchanisms.]. You will also need a strong understanding of software concurrency including  thread_local variables, std::mutex, std::lock_guard, and std::atomic. In other words, you need to be a proficient Modern C++ programmer. Hacking, googling, and even AI won't do the job.

     

  4. For slightly less typing and better consistency, I suggest using SC_NAMED macro, which was officially introduced in IEEE-1666-2023. It works under SystemC 2.3.3 and newer.

    Also, for better performance, unless you are synthesizing, I suggest using int32_t instead of sc_int<32>, and bool instead of sc_uint<1>.

    Anyhow, here is another take on naming ports, modules, and signals:

    SC_MODULE(rv_thunder) {
    	sc_out<sc_int<32>> SC_NAMED(add);
    	sc_out<sc_int<32>> SC_NAMED(d_dmem_data);
    	sc_out<sc_uint<1>> SC_NAMED(d_memwrite);
        sc_out<sc_uint<1>> SC_NAMED(d_memread);
    	sc_out<sc_uint<2>> SC_NAMED(doutdmem_mask);
    	//...
        // Can do the same with modules and signals:
        Some_module SC_NAMED(other);
        sc_signal<bool> SC_NAMED(status);

    The macro SC_NAMED simply translates SC_NAMED(abc) into abc{"abc"}.

     

  5. In SystemC, there is no "_imp" because in SystemC, the implementation is called a channel and we simply bind an export to the channel. UVM (SystemVerilog) used the "_imp" approach because when it was invented, SystemVerilog did not have the concept of interface classes like C++.

    Checkout my github for more insight on the port/channel relationship in SystemC: https://github.com/dcblack/portexport

    Callee is the target module, which is also called a hierarchical channel and represents the implementation.

    Two files to examine: README.md and portexport.cpp

     

     

     

  6. Some folks use sc_signal<int>, sc_buffer<bool> or sc_signal_resolved<1> as an inexpensive (less to code) alternative to a custom channel. Keep in mind that sc_signal only sends an event  on changes to the underlying value. sc_buffer provides an event on every write.

     

     

     

  7. There are three ways to communicate between modules with varying degrees of "niceness":

    1. Use channels (either predefined or custom) - this is the preferred mechanism for 99% of SystemC
    2. Global access to a shared item - this can be useful for a global clock or reset signal
    3. Direct hierarchical access - this is frowned upon because it makes code too fragile

    The channel approach is quite nice, but does require ports, interfaces, and channel objects. It is explicit and portable. You could create a simple event channel:

    I have an example event channel here -> https://github.com/dcblack/systemc-event-channel

    Globals are potentially dangerous; however, you can protect them through use of a singleton class design and accessors. This enables checking usage against abuse and facilitates debug if something goes wrong. I would only recommend globals for items that are truly global in scope such as a distributed reset signal. Do not use globals to share point-to-point communications. Port/channel connections make it much more clear where things are going and coming from.

  8. We have an upcoming online Fundamentals of SystemC course the week after next. The timing for this session is set up for the Americas. You will also see that there are other options for Europe and Asia. Learn more and signup via https://www.doulos.com/training/soc-design-and-verification/systemc-tlm-20/fundamentals-of-systemc-online/.

    Warning: I am biased as I am employed by Doulos. I am also the assigned instructor for this session. You may see my bio at https://www.linkedin/in/dcblack

    You may see other company offers in training via https://systemc.org/resources/training/.

  9. For starters:

    1. Because SystemC leans heavily on almost all aspects of C++, how well do you know C++?
      1. If you have only loose knowlege (e.g., you really only know the C subset), then you should take a course on C++. There are many sources both online and in-person.
    2. Do you have a copy of the IEEE-1666 standard? The 2023 version is available for free download as a PDF from systemc.org
    3. Consider taking a course on SystemC (usually not free). It will help you avoid many mistakes and avoid misconceptions.
  10. Restart is not possible and that is by design. See the fourth paragraph of section 4.4.5.3 in IEEE-1666-2023 (download free copy via ). Also see figure 1 in section 4.6.10.

    However, you could save your parameters in a file (e.g., YAML or JSON) on exiting and read them on subsequent runs.

    Also, you possibly misunderstand sc_pause and sc_start. You should never call sc_pause() from sc_main(), but only within the context of SystemC processes (SC_THREAD, SC_CTHREAD or SC_METHOD).

    With respect to sc_start, read section 4.6.8 carefully. The example code could significantly slow down your simulation, but it does allow for single stepping the simulation.

    Observation: sc_start is sort of misnamed. The first time it is called, it "starts" the simulation. Subsequent calls "resume" the simulation. You should never attempt to advance time outside of SystemC processes. Also, time can never be negative or go backwards.

     

     

     

  11. It's even harder when you consider that you may be importing 3rd party VIP, which may not take phase jumping into account.

    I would also suggest to you that the real definition of all these phases is also not well defined. For example, some components might distinguish between hard and soft resets differently. What about components that can selectively power on/off? Should all components be reset at the same time (other than at power up?

     

  12. The general SystemC way of doing things is to use ports, whether builtin, TLM-2, or convenience. Prefer TLM-2 over custom solutions when possible. With respect to the selection of channels, it is highly dependent on what you are modeling. There is no one way that is "the right way". You should prefer higher levels of abstraction in general for several reasons:

    1. Easer to understand
    2. Higher performance
    3. Faster to code

    What should you avoid? Low-level communications generally (e.g., sc_signal). Signals are fine for limited applications, but too often I see folks writing RTL with SystemC. RTL should be done with SystemVerilog or VHDL, which are designed for this and have many features to enhance performance.

     

  13. SystemC processes use a cooperative multitasking model of computation. Thus on face-value, the answer is "no"; however, proficient C++ programmers can obtain a level of pre-emptive concurrency by careful and proper application of proper mutexes or atomics in combination with creation of asynchronous primitive channels using async_request_update() in the channel. The new IEEE-1666-2023 standard introduces some essential new components to make this work properly. A public review version of the SystemC version 3.0 PoC library should be released this week and supports this.

    IMPORTANT: IEEE-1666-2023 requires C++17 (Modern C++) or later for this to work. There are no alternatives. This usually requires use of the -std=c++17 compiler switch both for library installation and compiling your applications. Proficient C++ programmers won't have any issue with this.

    See https://systemc.org/events/scef202309/ for more information. Also, download the latest IEEE standard.

    I highly suggest using the CMake configuration and installation process to simplify your life.

    By "proficient", I mean practitioners with proper formal C++ training. Googling, hacking and chatGPT simply won't cut it. Either you know and understand C++ fully or you will have a very tough time getting it right.

     

×
×
  • Create New...