Jump to content

David Black

  • Posts

  • Joined

  • Last visited

  • Days Won


Everything posted by David Black

  1. The reason was to allow the following syntax: SC_MODULE( MyModule ) { SC_CTOR( MyModule, int var = 10 ) : my_var{ var } { /* Body */ } private: int my_var; }; Which would expand to become: struct MyModule : sc_module { MyModule( const sc_module_name& instance, int var = 10 ) : my_var{ var } // Oops, missing sc_module{ instance } { /* Body */ } SC_HAS_PROCESS(MyModule); private: int my_var; }; If they inserted the sc_module{ instance } into the macro, then you would have the awkward syntax of: SC_MODULE( MyModule ) { SC_CTOR( MyModule, int var = 10 ) , MY_VAR{ var } //< Comma looks wrong and is awkward { /* Body */ } private: int my_var; }; So to get around this, they stuck a static variable inside sc_module_name (e.g., latest_str). When you construct an sc_module_name instance, it copies your string into the static. When you call the sc_module() default constructor, it uses the sc_module_name::latest_str. This is a very ugly approach, but works. If you want a module that takes a string for a module constructor, the following works, with the caveat that if somebody inherits from your class, they will not be able to pass in an sc_module_name unless you provide an alternate constructor (i.e., overload): struct MyModule : sc_module { explicit MyModule( const std::string& instance, int var = 10 ) : sc_module{ sc_module_name{ instance.c_str() } } , my_var{ var } { /* Body */ SC_HAS_PROCESS(MyModule); //< if needed, this is the best place } private: int my_var; }; Don't forget that since C++11, you can also delegate constructors (DRY principle). Parting comments: Proficiency in C++ makes you a better SystemC programmer Don't ignore *any* warnings. Compile with -Wall -Wextra -pedantic and don't settle for anything less than zero warnings. 99% of warnings are disguised errors You can suppress individual warnings inside the code if you can convince your coworkers.
  2. Use a proper OS mutex to lock OS processes during access to shared data. Never inject events into SystemC without using async_request_update in a custom primitive channel.
  3. Use a Docker container and install SystemC there.
  4. 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.
  5. 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.
  6. Something like the following might be a clue... uvm_reg regs[$]; regmodel.get_registers(regs); foreach( regs[i] ) begin `uvm_report_info("Register",regs[i].get_name()) end
  7. You could setup the masters to access through a common agent and use the lock/unlock methods in the sequence. This something I teach in Doulos UVM Adopter course.
  8. 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.
  9. 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"}.
  10. 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
  11. IEEE 1666-2023 is the first standard listed on the page! I'm sorry, but you need to try harder. We cannot legally get it for you.
  12. Using AI for coding will likely result in you having very little true understanding of SystemC. I don't think it fair to ask a forum to correct errors introduced by chatGPT; otherwise, we could spend our lives enslaved to answering questions to teach AI.
  13. I don't see an error message and I don't have time to run your project. Please point a snapshot of the error message itself.
  14. 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.
  15. There are three ways to communicate between modules with varying degrees of "niceness": Use channels (either predefined or custom) - this is the preferred mechanism for 99% of SystemC Global access to a shared item - this can be useful for a global clock or reset signal 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.
  16. 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/.
  17. You will need to take that up with IEEE. No additional help will be found here I'm afraid.
  18. The IEEE version is currently free from the IEEE because Accellera paid IEEE to have it so. However, you need a free IEEE account (i.e., you must register) and it is easy to then download the free version. Every copy is registered to the individuals login - the price for free). https://ieeexplore.ieee.org/document/10246125 (you will need to login to access)
  19. For starters: Because SystemC leans heavily on almost all aspects of C++, how well do you know C++? 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. Do you have a copy of the IEEE-1666 standard? The 2023 version is available for free download as a PDF from systemc.org Consider taking a course on SystemC (usually not free). It will help you avoid many mistakes and avoid misconceptions.
  20. Available in a GitHub: https://github.com/dcblack/SCFTGU_BOOK
  21. It can only run in a separate thread if you use the correct semantics. The SystemC kernel is not thread-safe in general. If you use async_request_update and some of the newer 2023 features, you can do a decent job of parallelism.
  22. Restart is not possible and that is by design. See the fourth paragraph of section 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.
  23. 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?
  24. Safer, but never safe. Consider that each component's run-time phase will be in a different state. You need to find a way to safely clean up state before jumping.
  25. 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: Easer to understand Higher performance 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.
  • Create New...