Jump to content

Philipp A Hartmann

Members
  • Content Count

    525
  • Joined

  • Last visited

  • Days Won

    126

Everything posted by Philipp A Hartmann

  1. 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
  2. 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
  3. 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
  4. 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
  5. 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
  6. 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
  7. 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
  8. 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
  9. 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
  10. 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
  11. 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
  12. You can invoke sc_start several times from within sc_main, see Section 4.3.4.2 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
  13. 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
  14. 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
  15. 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
  16. 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
  17. Yes. Have a look at IEEE 1666-2011, Section 4, especially 4.3.4.2 (sc_start, the starvation policy, and sc_pause). ("suspend" and "resume" are functions for individual SystemC processes, sc_start/sc_pause/sc_stop control the overall simulation). /Philipp
  18. The sc_dt::scfx_ieee_float class supports setting the individual parts via member functions as well. Therefore, you can do the bitvector to float conversion by using the following algorithm sketch: Extract the corresponding bits from vector by using the "range()" functions for sign, mantissa and exponent Convert these ranges to integers, e.g. by using the to_(u)int() functions Set the individual parts of an sc_dt::scfx_ieee_float object to these integers Assign/copy the sc_dt::scfx_ieee_float object to a plain float. /Philipp
  19. I've sketched the double to bitvector conversion in an earlier answer already: To do it analogously for 32-bit floats, just use sc_dt::scfx_ieee_float instead of sc_dt::scfx_ieee_double, adjust the sizes of the exponent and mantissa variables according to the 32-bit IEEE 754 representation, and read the mantissa value by a single call to the "mantissa()" function of sc_dt::scfx_ieee_float, instead of the two calls to mantissa0/1. Generally speaking, I would suggest to start with a good C++ book before delving deeper into SystemC. The new one from Bjarne Stroustrup is a very good one for starters. Greetings from Oldenburg, Philipp
  20. Why do you convert the unsigned integer to a string before assigning it to the bitvector? A direct assignment should work just fine. If you indeed need to construct/assign a bitvector from a (C++) string, you need to pass the "C string" representation to the bitvector: in1.to_string(SC_BIN).c_str(); As I said in my answer, there are two bitfield classes available: scfx_ieee_double and scfx_ieee_float. For single precision, use the second one and adjust the sizes of the intermediate variables according to the 32-bit floating point representation. To do this conversion, you need to assign the value to an (unsigned) integer variable in between, as no direct conversion is provided here. Just shift the fractional bits beyond the fixed point and then do an assignment to the bitvector afterwards. sc_unsigned us( fx.wl() ); // temporary unsigned integer variable of appropriate size us = ( fx << (fx.wl()-fx.iwl()) ); // shift to integer bits only sc_bv<32> bv = us; // assign to bitvector See the IEEE Std. 1666-2011 SystemC standard for details on the datatype APIs in SystemC. /Philipp
  21. Your second solution won't work due to the way inheritance works in C++. You would need to use virtual inheritance from all of the interfaces used in sc_fifo_id and sc_fifo. sc_fifo does not use virtual inheritance from the sc_fifo_in/out_if interfaces, which is why you can't "extend" these interfaces and still automatically inherit the implementation from sc_fifo. If you really need the separate interface definitions sc_fifo_id_in/out_if, I would suggest to wrap an sc_fifo instance (in terms of a member object) with your sc_fifo_id class and add forwarding functions to the sc_fifo member to implement the plain FIFO functions. hth, Philipp
  22. char is a datatype to represent a single character. There is the std::string datatype for strings C++, which should be used in SystemC as well. There is no explicit support for these conversions provided by SystemC already. In the proof-of-concept implementation provided by Accellera, there are the (non-standard) classes sc_dt::scfx_ieee_(double/float), which define bitfields for the individual parts of a float or double type. With this, you should be able to do the conversion in terms of a concatenation (beware of endianness). The following is untested: double d = ...; sc_dt::scfx_ieee_double id(d); // convert to IEEE 754 bitfield // prepare parts bool sgn = id.negative(); sc_dt::sc_uint<11> exp = id.exponent(); sc_dt::sc_uint<53> mnt = ( sc_dt::uint64( id.mantissa1() ) << 20 ) | id.mantissa0(); // concatenate parts to bitvector sc_dt::sc_bv<64> bv = ( sgn, exp, mnt ); The reverse conversion is left to the reader. ;-) C++ provides float and double datatypes already. Usually, C++ implementations follow the IEEE 754 representation internally. There is no explicit separate SystemC datatype for IEEE 754 floating point numbers. You can convert sc_fix(ed) numbers via the to_float and to_double member functions. Greetings from Oldenburg, Philipp
  23. In order to give you any suggestions about your "problem", please try to post some more details. What kind of "problem" do you face? What are your compiler errors, if any? Can you post a stripped-down code example, showing the relevant parts of the code (and preferably being self-contained and ready to compile)? One good starting point to learn about defining your own (primitive) channel can be found on the Doulos website. (Season's) Greetings from Oldenburg, Philipp
  24. Bernhard, thanks for the report. I can't confirm this on Linux: $ tar -tzf systemc-2.3.0.tgz | grep req_rsp/tlm_ch systemc-2.3.0/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/ systemc-2.3.0/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/Makefile.am systemc-2.3.0/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/Makefile.in systemc-2.3.0/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/ systemc-2.3.0/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_req_rsp_channels/ systemc-2.3.0/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_req_rsp_channels/Makefile.am systemc-2.3.0/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_req_rsp_channels/Makefile.in systemc-2.3.0/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_req_rsp_channels/tlm_put_get_imp.h systemc-2.3.0/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_req_rsp_channels/tlm_req_rsp_channels.h systemc-2.3.0/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/circular_buffer.h systemc-2.3.0/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/Makefile.am systemc-2.3.0/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/Makefile.in systemc-2.3.0/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo.h systemc-2.3.0/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_peek.h systemc-2.3.0/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_put_get.h systemc-2.3.0/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_resize.h Also on Windows with the 7-zip archiver, the contents are displayed correctly here. Therefore, I assume that WinZip has a problem with such long paths. This is probably due to the fact that the path in question exceeds 99 characters in length, which has been a historical limit in tar archives. Newer tar format variants may not be supported by some versions of tar (or other software used to access the archive, like WinZip in your case). I would suggest to try another archive software, like the aforementioned 7-zip archiver, and check whether it still fails to extract the systemc-2.3.0 archive correctly on your system. Greetings from Oldenburg, Philipp
  25. As I said in my initial answer, the SystemC package already contains quite some starting material in the examples/tlm directory, already available on your computer. ;-) The definite document about SystemC TLM-2.0, including the description of the concepts, terminologies and modeling guidelines is of course the IEEE 1666-2011 standard. You can download the standard free-of-charge (sponsored by the Accellera Systems Initiative) from http://standards.ieee.org/getieee/1666/download/1666-2011.pdf. A very good starting point can be the video tutorials available from the Accellera TLM community pages at http://www.accellera.org/community/systemc/about_systemc_tlm/ All of this should keep you busy for a while. /Philipp
×
×
  • Create New...