Jump to content

Philipp A Hartmann

  • Posts

  • Joined

  • Last visited

  • Days Won


Everything posted by Philipp A Hartmann

  1. I don't understand, why using the top module with different values of TOP_DEPTH is a showstopper for declaring the DEPTH_MODULE_xxx as static members of my_top. Integer template arguments have to be known at compile-time in order to instantiate the correct type. Would something like the following be sufficient for your situation? template <int DEPTH=10> SC_MODULE(sub_module_xxx); template <int TOP_DEPTH=10> SC_MODULE(my_top) { static const int depth = TOP_DEPTH; // I usually forward template constants to proper member constants static const int depth_a = depth + 1; // or other math on depth static const int depth_b = depth / 2; // ... sub_module_a<depth_a> sub_a; // no need for pointers? sub_module_b<depth_b> sub_b; SC_CTOR(my_top) : sub_a("sub_a") // initialize sub-modules , sub_b("sub_b") {} }; int sc_main(int, char*[]) { my_top<17> t1("t1"); my_top<42> t2("t2"); sc_assert( t1.depth == 17 && t1.depth_a == 18 ); sc_assert( t2.depth == 42 && t2.depth_b == 21 ); return 0; } Greetings from Oldenburg, Philipp
  2. See the IEEE 1666-2011 standard, chapter 4 for details about the SystemC elaboration and simulation semantics. If you don't "need" to run the initialization phase separately, you don't need to worry about this detail. The first invocation of sc_start will take care of completing the elaboration and initialization automatically. There is an example in the SystemC standard (in section 4.5.7), which shows a simulation running in individual steps: In this example, you need the explicit initialization call. /Philipp
  3. You should not use sc_initialize(). It's deprecated and not part of the IEEE 1666 SystemC standard. If you want to prepare the simulation without running it yet, your can complete the elaboration and run the initialization via sc_start( SC_ZERO_TIME ); from within your sc_main() function. Afterwards, you can call sc_start multiple times again, e.g. with non-zero duration arguments, to perform the simulation itself. /Philipp
  4. The answer is slightly more complex than you might think. 1. Arithmetic operations on sc_(u)int<> are performed on 64-bit accuracy internally This is by design, see IEEE 1666-2011, Sections, The limited-precision integer types have a conversion operator to their C++ representation (sc_dt::(u)int64) and the arithmetics are performed according to rules of the C++ standard. 2. Signed modulo expressions in C++ are implementation-defined Quote from ISO/IEC 14882:2003(E), 5.6.(4) (formatting and highlighting by me): 3. C++ integer promotion rules will give you an unsigned operation anyway Integer arithmetics in C++ are subject to operand promotion rules to determine the appropriate common type for the computation (called usual arithmetic conversions). In case of mixed signed and unsigned 64-bit types, this will usually be a 64-bit unsigned type. Details can be found in the C++ standard as well, see clause 5(9). Note: in C++11, the wording has been slightly extended to explicitly cover 64-bit integer types. Hope that helps, Philipp
  5. In case you've found a solution to your question all by yourself, please consider adding an answer with your findings instead of emptying out your previous post. This way, all users can benefit in the long run. Thanks, Philipp
  6. Assuming that you mean "Visual Studio" by mentioning "VS", please see http://forums.accellera.org/topic/71-/ for a solution. BTW, this is documented in the INSTALL instructions of SystemC. /Philipp
  7. I would expect your example to fail (statically) linking already, because you #include <systemc> already. If you want to have SystemC as a dynamic dependency only, you need to hide this behind a properly defined "plugin interface", as you have sketched with "create_object" and "destroy_object" already. Due to the C++ name mangling, this plugin interface should be declared as extern "C". That said, two final remarks: All of this is rather off-topic here, as it is not specific to SystemC itself, but to C++ shared libraries and "plugins" in general. You should always include the error messages you're seeing. Greetings from Oldenburg, Philipp
  8. Conversion from char to sc_logic is not possible in all cases. But fortunately, you can find the solution to your question is Section of the IEEE Std. 1666-2011for SystemC (emphasis added): You can the use ctrlout.write( sc_dt::SC_LOGIC_Z ); to write to the port/signal directly. Greetings from Oldenburg, Philipp
  9. Yes, there is an sc_pause in SystemC (since IEEE 1666-2011 / 2.3.0). By calling this function from within your simulation, you can return to sc_main (see IEEE 1666-2011, Section 4.5.2). Please note that in the context of the SystemC AMS extension, pausing the simulation may be somewhat dangerous, as noted in Section 5.1.1 of the AMS extensions 2.0 LRM: That said, the use cases you have described seem to be blocking in nature. Why not simply call the code to ask for user input directly from the "specified point in the code"? In this case, you don't need to interfere with the simulator directly. NB: sc_halt is not part of IEEE 1666 and is not meant to be used in new code. Greetings from Oldenburg, Philipp
  10. An SC_THREAD runs within its own stack. When an exception is thrown, this stack is unwound until it arrives at a matching exception handler. That's why you can catch your custom exception within the thread itself. If you don't provide your own exception handler, the SystemC kernel's generic exception handler for the thread jumps in and catches the exception on your behalf. Since the SystemC kernel can't know anything about your customException class, it is caught as std::exception (and translated to a new sc_report instance). The only available solution is to wrap your thread implementation (not the sc_start call) with a catch black and to translate and forward it appropriately to your test class (e.g. via a member of the module and then calling sc_stop() to stop the simulation). You can find the translation and forwarding as it is done in the SystemC kernel itself in the (Accellera) kernel's function sc_handle_exception() and its uses. hth, Philipp
  11. As you correctly pointed out, SystemC module constructors have a required "name" parameter. Therefore, you can't create C(++) arrays of such classes by the C++ language rules. If you want to create array-like containers of SystemC modules (or other named SystemC objects), you can use the sc_vector class template, available since IEEE 1666-2011 and SystemC 2.3.0: // in class definition sc_vector< MySC_obj > mysc_vec; // can be used like an array (or rather a std::vector) of MySC_obj // constructor sc_user::sc_user() : mysc_vec( "test", 2 ) // initialize with name and size {} Yes, but you are missing a destructor, which is needed to avoid a memory leak coming from the dynamic allocation. Remember: Whenever you write a "new" somewhere in your program, you should write a matching "delete" as well. These are basic C++ language rules again. /Philipp
  12. As I said, you need to read up on C++ classes, class members, constructors in general first. And of course, you need to understand the difference between a pointer and an object. Of course, you can declare a pointer to an object as a member in your 'sc_user' class. You can then set its contents in the sc_user constructor in the same way as you would do it outside of a constructor. You just can't set it in the body of the class directly, which is what you (kind of) tried in your original code. Last, but not least: Why do you want to use a pointer and a dynamic allocation (new) anyway? If you want to instantiate the MySC_obj object in the constructor, you should definitely prefer a direct member instead of a pointer. But learning the basics of C++ is a prerequisite to all of this. /Philipp
  13. Dynamic processes are especially used in situations when you need to spawn additional parallel execution in your model during the simulation. You cannot use static processes in such cases. /Philipp
  14. You code looks ok on the first glance. The trace file should appear in the directory from where you start the executable (which is not necessarily the directory of the "project"). Which compiler do you use? Which operating system? You can try to open a command prompt in the folder of the generated executable and start the simulation from there. /Philipp
  15. Yes. Side note: You should not prefix your classes with "sc_". These identifiers may be used in the current (or future) SystemC versions. Three problems here: In C++03, you cannot initialize a class member directly in its declaration (and the syntax would be different in C++11). You cannot convert a string literal to an MySC_obj pointer, use a direct member instead (i.e. drop the '*'). You need to add a semicolon at the end of the 'sc_user' class definition) You can then initialize the member in your constructor: sc_user() : test("test") // initializer list { // ... } Please check your favourite C++ book on how to write classes, constructors, etc. hth, Philipp
  16. Try to show the relevant parts of your code, e.g. the 'sc_main' function. Have you added any signals? Has the simulation completed successfully? Did you properly close the file again after the simulation? /Philipp
  17. The following patch fixes this problem in MS Visual Studio 2011 and later: 0001-Check-for-MSVC-version-in-for-scope-bug-hack.patch.txt I don't remember, if this was the only required change for SystemC 2.3.0 to achieve MSVC >= 2011 compatibility. hth, Philipp
  18. This bug has been fixed in SystemC 2.3.0 among many others. You should consider to migrate to the current version. Alternatively, you can put the line using sc_core::SC_ID_ASSERTION_FAILED_; before the offending line. /Philipp
  19. Hakim, contrary to your topic line, the problem is not the way you call C from SystemC, but actually the other way round: How to come back to SystemC from a C implementation of an ISS to access the rest of the virtual platform again. Note: I have not used this particular ISS and everything in my answer may just be the tip of the iceberg. Did you see that comment: In all of the C callback functions, e.g. read_addr(), the NativeWrapper assumes that 'get_instance()' returns a pointer to the one and only NativeWrapper object in the system. Instead of using this singleton function, add a new function to NativeWrapper to get the "current" CPU, based on the wrapping SystemC thread: // add to NativeWrapper class static NativeWrapper* get_current_instance(); // add to NativeWrapper.cpp static NativeWrapper* NativeWrapper::get_current_instance() { sc_core::sc_object* current_cpu_process = sc_core::sc_get_current_process_handle(); sc_assert( current_cpu_process ); NativeWrapper* current_native_wrapper = dynamic_cast<NativeWrapper*>( current_cpu_process->get_parent_object() ); sc_assert( current_native_wrapper ); return current_native_wrapper; } And then replace the calls to 'get_instance()' in the C callback functions with this 'get_current_instance()' function. You may still have problems with other parts of the ISS implementation and its assumptions on the current platform configuration. The first approach will always return the "one and only" NativeWrapper object. Since you already managed to get access to the constructor (which has been private in your original example), you should not use it in your model. Use the second approach with my sketched solution from above. Otherwise, the first call to get_instance() from one of the callbacks will try to create a new CPU, even though the simulation is already running. Side note: You should receive a proper error message instead of a call to std::terminate when using SystemC 2.3.0. Greetings from Oldenburg, Philipp
  20. Yes, you can. You can use the function "sc_elab_and_sim" to invoke the simulation externally. See IEEE 1666-2011. Just be careful about synchronisation between your application and the SystemC simulation thread. /Philipp
  21. You can invoke sc_start several times from within sc_main, see Section in IEEE 1666-2011. Just add your user interface "in between" the different calls to sc_start. The functions in Section 4.5 may be helpful as well. /Philipp
  22. In order to fix this problem, you would need to compile SystemC as a 64-bit library as well. Unfortunately. the current SystemC proof-of-concept implementation (2.3.0) does not support 64-bit builds on MS Visual Studio. It is possible to port SystemC to MSVC 64-bit, but this requires some effort and will likely be part of the next version of SystemC. /Philipp
  23. The "sc_export" part of each TLM-2.0 socket needs to be bound to an interface (tlm_bw_transport_if for an initiator, tlm_fw_transport_if for a target socket) in order to provide the implementation of the communication link. As you can see in the referenced example, the Initiator class inherits and implements the backwards interface: struct Initiator: sc_module, tlm::tlm_bw_transport_if<> // Initiator implements the bw interface As a result it can act as the "channel" to provide the behaviour for the sc_export part of the initiator socket. This pattern is a quite common idiom in the TLM-2.0 world, at least if you don't use the convenience sockets. So to answer your question: It's not the "module part" that is bound to the socket. The Initiator is-a backwards interface as well, and this "interface part" is bound. Greetings from Oldenburg, Philipp
  24. You need to create the ports while the correct instantiation context is established. Since you can't do so during construction of the module, you need to defer it to the 'before_end_of_elaboration()' callback of SystemC. For this matter, you need to temporarily store the signals, in e.g. a vector of pointers. See the following (untested) sketch: SCA_TDF_MODULE(waste) { sca_tdf::sca_in<double> in; // Main 'in' port sc_core::sc_vector< sca_tdf::sca_in<double> > secondary_ins; // prefer sc_vector over vectors of pointers SCA_CTOR(waste) : in("in"), secondary_ins( "secondary_in" ) { } // temporarily store signal pointer void bind(sca_tdf::sca_signal<double> &s) { sc_assert( sc_core::sc_get_status() == sc_core::SC_ELABORATION ); secondary_signals.push_back( &s ); } void processing() { //... } private: // actually do the binding virtual void before_end_of_elaboration() { // create the secondary ports secondary_ins.init( secondary_signals.size() ); // bind the ports for( std::size_t i = 0; i < secondary_ins.size(); ++i ) secondary_ins[i].bind( *secondary_signals[i] ); // cleanup temporary signals secondary_signals.clear(); // be nice and call the base class callback sca_tdf::sca_tdf_module::before_end_of_elaboration(); } // temporarily hold additional inputs during elaboration std::vector< sca_tdf::sca_signal<double>* > secondary_signals; }; Hope that helps, Philipp
  25. You probably call 'sc_main' within your 'sc_run' function, otherwise you have just built an infinite recursion. Secondly, you should try to avoid the 'sc_' prefix in your own code. That said, did you look at section 4 of the IEEE 1666-2011 standard, as I suggested in my previous answer? Your 'sc_run' function is provided by SystemC already under the name sc_elab_and_sim (see 4.3.2). From the standard's perspective, your question is partly answered already there. Quoting (emphasis mine): The Accellera proof-of-concept implementation does not support multiple calls to 'sc_elab_and_sim'. /Philipp
  • Create New...