Jump to content


  • Content count

  • Joined

  • Last visited

  • Days Won


Everything posted by maehne

  1. For what it is worth, there are several open-source tools developed by academia available, which translate SystemC RTL descriptions to Verilog and vice versa: SC2V: https://opencores.org/project,sc2v GSC: https://opencores.org/project,gsc SysC2Ver: http://sysc2ver.sourceforge.net Verilator: https://www.veripool.org/wiki/verilator Verilog2C++: http://verilog2cpp.sourceforge.net ... and probably others, which can be found through a web search. The development of most of these projects was not very active over the past years, but as they are open-source, you're free to pick them up. Otherwise, I fully agree with David's statement that it is not the task of Accellera to develop such tools and also not in the commercial interest of EDA tool vendors, as it is in an area, where they can differentiate themselves most from their competition. For academia and industry there might be some interest for open-source tools as a base for custom tooling, which has to fulfil very particular needs.
  2. Memory Allocation In SystemC

    How to initialise your memory content from a file is very HLS tool-specific. Check its documentation! They may or may not support it. Maybe, you'll have to use a specific IP block provided by your tool vendor.
  3. Memory Allocation In SystemC

    Dynamic memory allocation in behavioural description is indeed not synthesizable, as there is no sensible mapping to digital hardware. You will have to use static memory allocation instead. Check the SystemC Synthesis Subset and the documentation of your HLS toolchain for details on how to write proper synthesizable code in SystemC.
  4. SystemC for Hardware Design

    I think you have a misconception about SystemC. It is just a library on top of the C++ language, which helps you to describe the structure and behaviour of your hardware and software system. What will be considered as hardware and what as software depends on the language elements you use: An SC_MODULE with ports will or sockets will be considered as hardware due to the semantics associated to the used classes. A header or CPP file as well as as generic functions, classes, or structs do not have any particular semantic attached to it, which would qualify them from the beginning as hardware. They only have the semantics, which are imposed by the ISO C++ standard. Grouping parameters describing different aspects of your systems in structs is a good approach. I use it for any module, which has several parameters, which interdepend from each other. I usually default initialise all members to form a sensible parameter set. The user then may alter these parameters before passing the whole struct as argument to the module's constructor. It is in the constructor, where I do consistency checks between the parameters to ensure that the module gets properly configured. If you have different sets of parameters for different use cases of your module (e.g., system-level parameters during the top-down design phase and back-annotated device-level data for bottom-up verification), they can be grouped into separate structs. Overload-resolution can then automatically choose the appropriate constructor, which derives internal secondary parameters, which are then actually used in the behavioural description of your module. To describe properties of whole systems, you may group these module parameter structs into bigger structures, to pass a single struct to your top-level module. To get better tooling support, you may consider to have a look to the SystemC CCI standard, which is currently in the public review phase: Though, I think it is a good idea that you get first familiar with C++ itself and the foundations of SystemC before continuing to model a complex system. A good book on SystemC is, e.g., "SystemC from the Ground Up" by David C. Black, Jack Donovan, et al.
  5. Using sc_uint_base directly?

    Thanks for the background information on your use case. Your justification for using sc_uint_base is sound for me.
  6. Passing Arguments in the process in SystemC

    By the way, Visual Studio 2013 already has some support for C++'11 including Lambdas: https://msdn.microsoft.com/en-us/library/hh567368.aspx
  7. Passing Arguments in the process in SystemC

    You can find the requested example in the above cited clause 5.5.6 of IEEE Std 1666-2011.
  8. Passing Arguments in the process in SystemC

    You can use sc_bind() for this purpose, which is described in clause 5.5.6 of IEEE Std 1666-2011. Though, you might need to use sc_spawn instead of SC_THREAD to register your process with the SystemC kernel. If your compiler supports C++'11, you can also use a Lambda function instead of sc_bind(). Cf. to the Doulos white paper "What C++11 means to SystemC?" by David C. Black for details.
  9. Passing Arguments in the process in SystemC

    You can use sc_bind() for this purpose, which is described in clause 5.5.6 of IEEE Std 1666-2011. Though, you might need to use sc_spawn instead of SC_THREAD to register your process with the SystemC kernel. If your compiler supports C++'11, you can also use a Lambda function instead of sc_bind(). Cf. to the Doulos white paper "What C++11 means to SystemC?" by David C. Black for details.
  10. Using sc_uint_base directly?

    I don't see any issue from the point of the LRM. From a methodology perspective, I think it depends on the abstraction level and use case you are targeting. On the side of modules representing actual hardware, I would probably prefer to have a port type stating clearly the width to have the compiler statically check for me the correct binding of ports and interfaces. For stimuli generators and monitors, a more generic base type is OK for me. Where it then interfaces with HW modules, I would insert a small adaptor. You may also consider to have a channel, which can bind to sc_int<W> and sc_int_base, and which then checks at elaboration time that the widths on all bound ports match.
  11. How to synchronize Qt5 and SystemC?

    Your Qt5 GUI and the SystemC model should run in separate threads. Access to shared state will have to be protected using the appropriate synchronisation primitives of your threading library. IEEE Std 1666-2011 provides some facilities to control the execution of a SystemC model, see, e.g., this nice presentation by John Ainsley at DATE 2012 on the "IEEE Std 1666-2011: The New SystemC Standard" from slide 17 onwards. The presentation also explains how to implement interactions between SystemC and OS threads using async_request_update() (slide 36 and onwards). There was also an interesting discussion on async_request_update in an older SystemC forum thread, which also includes an example by David C. Black. David also developed an interesting demonstrator showing some advanced techniques in SystemC.
  12. Some comments to your code snippets: Prefer to #include "systemc" instead of "systemc.h" to avoid namespace pollution. You'll then have to prefix SystemC symbols with the appropriate namespace prefix (recommended in most cases, especially headers). In the context of functions and implementation files, you can selectively import symbols from the SystemC namespaces with appropriate using statements. Consider also to put your own classes, functions, typedefs and other declarations and definitions in a dedicated namespace to facilitate future code reuse! #include "iomanip" -> #include <iomanip> (because it is a system header) Initialization of global variables should not happen in the header file, but in the .cpp implementation file! To this end, you have to inp_image as extern. Try to avoid using preprocessor macros as much as possible! They are only rarely needed in C++. Your NBITS*() macros could be replaced by inline functions, which are optionally templatized to an arbitrary argument type T. Starting from C++'11, you could even declare them as constexpr, so that a compiler may evaluate them already at compile time. If your tool supports C++'11+, you may also declare your constants as constexpr.
  13. Errors in code

    From a quick glance into your source files, I see: Your headers are missing #include guards. You don't include SPPS.h in your header SPPS48.h, but your members M1, M2, and M3 are of type SPPS, which you define in SPPS.h I recommend that you don't use the header <systemc.h>, as it seriously pollutes your public namespace. Use header <systemc> instead and import only the symbols in your current namespace, which you actually use. Your constructor allocates manually memory for the members M1, M2, and M3 using "new", but lacks a destructor, which would release the objects using "delete". Anyway, this is not considered "Modern C++". Instead of raw pointers to objects of type SPPS, use a smart pointer. In your case, std::unique_ptr is probably the appropriate choice. All members of your SC_MODULE are exposed to public. This may be good for debugging, but it is better to only expose those members, which constitute the public interface of your module (i.e., at least the input/output ports, constructor, and destructor). Your SC_METHODs and SC_THREADs don't need to be public. Your approach to generate a clock signal in sc_main() is tedious the most. A clk signal of type sc_core::sc_clock is a more comfortable solution. To generate more comfortably complex stimuli, I recommend that you implement them in an own stimuli module. Therein, you can register an SC_THREAD, which performs the stimuli generation and which can easily wait for delays or event before proceeding to the next stimulus. In the same way a monitor for your output signal can be implemented. I repeat my recommendation to learn first the basics of modern C++ and to read a good book on SystemC to get more efficient in your modelling attempts!
  14. Alan's code snippet already shows you how to write constructors with additional arguments. The only thing, which is omitted in the snippet, but mentioned in his post is the necessary call to the SC_HAS_PROCESS macro with the name of the module class as argument so that you can use SC_THREADs and SC_METHODs in your module. I tend to write it just in front of the declaration of the first constructor. Thus, Alan's example would look like: #include "systemc.h" SC_MODULE(mod) { int i; SC_HAS_PROCESS(mod) mod(sc_module_name nm) : sc_module(nm) { // ... } mod(sc_module_name nm, int i_) : sc_module(nm), i(i_) { // ... } }; You can find more information in clause 5.2.6 to 5.2.8 of IEEE Std 1666-2011. I suggest that you read an introductory book on SystemC, e.g., "SystemC from the Ground Up" by David Black and Jack Donovan. Also, get familiar with C++: https://isocpp.org/get-started
  15. using simple bus

    I totally agree with David, a good read for an introduction on SystemC is, e.g., "SystemC from the Ground Up" by David Black and Jack Donovan.
  16. The error message indicates that you use a custom data type "com" with the sc_fifo, which does not support the output stream operator. For a custom data type to be compatible with sc_fifo (and other SystemC channels), it has to fulfil a certain number of conditions, which are documented in the SystemC LRM (IEEE Std 1666-2011). In the case of sc_fifo, the constraints are listed in clause 6.23.3 of IEEE Std 1666-2011. In summary, your type "com" needs to implement: The output stream operator: std::ostream& operator<< ( std::ostream&, const com& ); The copy operator (default version automatically generated by the compiler may suffice): const com& operator= ( const com& ); If any constructor has been defined for data type com, there must be a default constructor taking no arguments
  17. David's proposal is semantically very clear. The phasing of the before_end_of_elaboration(), end_of_elaboration(), and end_of_simulation() callbacks ensure that the actions to set up the tracing of implementation details are executed in the right order. IMHO, setting up tracing belongs semantically into the elaboration phase and not into the start of simulation. Then, you have to be aware that there is no guarantee in which order one type of callback is executed for all modules in your design. Therefore, you need to use two separate callbacks to open the trace file (before_end_of_elaboration()) and to register the signals for tracing (end_of_elaboration()).
  18. before_end_of_elaboration callback

    To learn more about the different elaboration and simulation callbacks, I suggest you have a closer look to Clause 4.4 in IEEE Std 1666-2011. I states for each callback which kind of actions are allowed at the different moments and which are not.
  19. before_end_of_elaboration callback

    The different elaboration and simulation phase callbacks in SystemC are provided to allow external libraries to hook additional functionality into the elaboration and simulation phases of the SystemC kernel. E.g., the SystemC AMS extensions make heavy use of it to implement the elaboration of the AMS sub-models, which need to be clustered to sub-models that require their own dedicated solver, which handles then the execution of the sub-model and synchronisation with the SystemC kernel. Setting up specialised monitoring and tracing for your SystemC model, which goes beyond the sc_trace mechanism is also a common use case.
  20. Reading a binary File

    Yes, you can use C's fread() function for this purpose. However, you should not use malloc()/free() to handle allocation/deallocation of your buffers. Instead, use C++'s new/delete operators or even better a suitable standard container such as std::array<T, N> or std::vector<T>. C++'s <iostream> library also offers you the possibility to read/write binary data from/to files. SystemC is a C++ library. Therefore, I suggest that you get familiar with C++ first. Confer, e.g., to: https://isocpp.org/get-started http://www.cplusplus.com/reference/iolibrary/ https://stackoverflow.com/questions/8798127/binary-input-output-in-c
  21. before_end_of_elaboration callback

    You are right. It is usually best practice to bind the ports of a module to the corresponding channels in the constructor of the parent module. However, there are cases, where modules have ports, which do not correspond to physical ports of the component, but which rather expose internal state of the module for debug/monitoring purposes. Designers don't want to bind these ports under all circumstances in their parent/top-level module, but rather want to make that optional. However, all ports need to get bound for simulation. Therefore, SystemC provides you with the before_end_of_elaboration() callback as a mechanism to bind yet unbound ports to some dummy or global channels to make the elaborated model structure well-formed for simulation.
  22. ]

    In the above example, you forgot to close the trace file after the last call to sc_start(). You have to explicitly call sc_close_vcd_trace_file(dummy) before you return from sc_main(). Otherwise, the trace file is not guaranteed to be complete and flushed to the disk. The same holds true for the equivalent tracing functions in SystemC AMS. This is essentially equivalent to the file handling with fopen() and fclose() in C, which the original designers of SystemC seem to have tried to mimic as much as possible to not "scare" away hardware designers with "too complex/strange" C++ syntax. ;-)
  23. ]

    Your problem description is a bit vague. Did the errors really occur when you tried to compile the unmodified QPSK example? The warnings you are showing point to a file header.h, which does neither exist in the SystemC-AMS PoC simulator sources nor the TUV library sources. You should check the lines referenced by the compiler warnings to understand the cause of the warnings. Probably, std::time_t is on your platform 64 bit long whereas unsigned int is 32 bit long. Try to use unsigned long instead. Nevertheless, the warnings are most probably unrelated to why no VCD trace files get generated. Tracing is usually set up in the sc_main() function (located in main.cpp in the QPSK example). First a handle for the trace file needs to be created with sca_util::sca_create_vcd_trace_file(). Then, the signals to be traced have to be selected by calling sca_util::sca_trace() on them. After simulation (sc_start() call), the trace file needs to be closed using sca_util::sca_close_vcd_trace_file(). In the QPSK example, tracing is set up to be written to a file named "tr.vcd". You will find it in your current working directory, from where you called the executable.
  24. Initialization of nested sc_vector< sc_vector< > >

    Once you are familiar with the C++ fundamentals, you might also have a look at "Effective Modern C++" by Scott Meyers.
  25. Initialization of nested sc_vector< sc_vector< > >

    Have a look here: https://isocpp.org/get-started