Jump to content


  • Content count

  • Joined

  • Last visited

About katang

  • Rank
    Advanced Member

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. I have an event handling method, It is sensitive to thean event. and generates a notify event, though notiying it, I want to insert calling a new (lengthy) procedure, for example refreshing the graphic display, or stepwise operation. That is the chain of event handling is suspended, I need to change some activity, like pressing the "Step" knob. Can I keep event handling activity in this without making troubles in handling? Or, is there some tested idea for implementing an interactive SystemC program? Next_event_thread(void) { while(true) { // DEBUG_PRINT_SC("Waiting for instruction"); wait(Next_event); ---- // intercept here wait(WAIT_TIME); MyObject->MEvents->norify(); }
  2. katang

    wait in SC_CTOR()

    Or, a more simple solution: you may put a "call" to an initialization routine, like SC_THREAD(Initialize_method); If you do NOT use dont_initialize() after that line, the SystemC engine waits until the constructor finishes (and gets registered), and after that executes the thread 'Initialize_method' where you are enabled to use wait(). This happens at the same (simulated) time, so I think it closely matches 'initial', which you want to imitate.
  3. In my project, I have a base set of object (they should be synthesized, i.e optimized for speed and footprint) and a subclassed set of objects, which are for visualization, testing, demonstration etc. (i.e. optimized for usability). The two sets must have the same functionality concerning the base object (of course). In the MWE below, I am using a 'StandAlone' mode (synthesis only), using a logic variable. The 'business logic' is completely comprised in the base modules. The MWE below produces the following output: MWEbase standalone MWEbase created MWE starting MWEbase created MWE created Initialized MWEbase Initialized MWEbase Initialized MWE MWE waiting: MWE MWEbase waiting: MWEbase MWE terminated My questions: 1./ Any better idea to implement what I want to do (or any points against) 2./ The dynamic_cast<MWE*>(MWEbase::getME()) seems to be safe for me: although the pointer is of type base class, the object it points to is of derived class, and without casting (if used in standalone mode by the base object) it points to the right object. Any points against doing so? (or better idea, which avoids duplicating code and not error-prone)? 3./ BTW: is there any standard synthesizable way of using addresses of object (like cores in a processor)? 4./ It looks like that a virtual function of the base object registered with SystemC, does not work (from SystemC point of view: despite that Initialize_method is virtual, the registered in the base object code runs also from the derived class). What is exactly the case with registering a virtual function? (Is it dangerous, can be repeated in the derived class, ???) #ifndef MVE_H #define MWE_H #include <systemc> #include <iostream> SC_MODULE(MWEbase) { public: MWEbase(sc_core::sc_module_name nm, bool StandAlone = true); SC_HAS_PROCESS(MWEbase); virtual ~MWEbase(void); virtual void Initialize_method(void); virtual MWEbase* getME(void){return this;} void setMy(bool B){mMy = B;} void print_thread(void); sc_core::sc_event m_request; sc_core::sc_event m_inited; protected: bool mMy; MWEbase* mME; }; class MWE : public MWEbase { public: MWE(sc_core::sc_module_name nm); SC_HAS_PROCESS(MWE); virtual ~MWE(void); virtual void Initialize_method(void); virtual MWEbase* getME(void){return dynamic_cast<MWE*>(MWEbase::getME());} void print_thread(void); }; #endif // MWE_H #include "MWE.h" using namespace sc_core; // This is for synthesis MWEbase::MWEbase(sc_core::sc_module_name nm, bool StandAlone) : sc_core::sc_module(nm) { if(StandAlone) { mME = this; SC_THREAD(print_thread); sensitive << m_request; std::cerr << "MWEbase standalone\n"; } SC_METHOD(Initialize_method); std::cerr << "MWEbase created\n"; } MWEbase::~MWEbase(void){} // This is for simulation MWE::MWE(sc_core::sc_module_name nm) : MWEbase(nm,false){ mME = this; SC_THREAD(print_thread); sensitive << m_request; // SC_METHOD(Initialize_method); std::cerr << "MWE created\n"; } MWE::~MWE(void){} void MWEbase::print_thread(void){ wait(m_inited); while(true) { std::cerr << "MWEbase waiting: " << getME()->name() << '\n'; wait(m_request); } std::cerr << "This is MWEbase\n"; } void MWE::print_thread(void){ wait(m_inited); while(true) { std::cerr << "MWE waiting: " << getME()->name() << '\n'; wait(m_request); } std::cerr << "This is MWE\n"; } void MWEbase::Initialize_method(void) { m_request.notify(SC_ZERO_TIME); std::cerr << "Initialized MWEbase\n"; m_inited.notify(SC_ZERO_TIME); } void MWE::Initialize_method(void) { MWEbase::Initialize_method(); m_request.notify(SC_ZERO_TIME); std::cerr << "Initialized MWE\n"; m_inited.notify(SC_ZERO_TIME); } #include <systemc> #include "MWE.h" using namespace sc_core; int sc_main(int argc, char* argv[]) { sc_set_time_resolution(1,SC_NS); MWEbase MyMWEbase("MWEbase"); std::cerr << "MWE starting\n"; MWE MyMWE("MWE"); sc_start(); std::cerr << "MWE example terminated\n"; if (not sc_end_of_simulation_invoked()) sc_stop(); return 0;
  4. For my subclassed constructor My::My(sc_core::sc_module_name nm, int ID) : sc_core::sc_module(((string(nm).append(1,ID<26 ?'A'+ID : 'A'+ID +6)).c_str())) I receive Warning: (W569) sc_module(const char*), sc_module(const std::string&) have been deprecated, use sc_module(const sc_module_name&) Why utilizing those two simple argument types are deprecated, and how can I legally do what I want?
  5. I want to simulate a memory, that when accessed replies with some delay. During the initial setting up the event handling I wanted to test if it works as expected. After setting up the main program, creating the MWE object and starting event handling, I wanted to create an event, with notify. The MWE below produces the output Requested 0 s Replied 0 s Replied 20 ns MWE created INFO: Exiting simulation This said to me that during initialization the two methods are executed correctly, the reply event correctly notified. However, the text "MWE created" is printed only after no more events in the system. My questions: 1./ Does it actually mean that there is no programmed way to "inject" an event for the simulator? (even just for debugging like this) 2./ The name of sc_start() suggests that after initiating the system, the control returns to the instruction following the call. Actually, what it makes, is sc_do_simulation(), and that is the mistake in my approach? 3./ What is the "best" way to simulate what I want, i.e. that the memory is accessed (with address and access attributes), and after some delay returns the required content? (A simulator must run with minimum offset activity. My best idea is that the requesting processor runs a thread which waits for the 'reply' event from the memory, which itself runs two threads for receiving request and reply. It seems to me too complicated, and maybe slow.) 4./ Is there any essential performance difference to implement as thread or method what I want? 5./ Is there any "trick" to "embed" some event handling in a normal (parametrized) method? 6./ As the MWE is, it processes all available events, the event triggered after that produces no error message, and sc_stop() does nothing with that event. Is it by design? 7./ Is there any way to force printing correct time units, even when the value is zero? // File main.cpp #include <systemc> #include "MWE.h" using namespace sc_core; unsigned errors = 0; const char* simulation_name = "EMPA_processor"; int sc_main(int argc, char* argv[]) { sc_set_time_resolution(1,SC_NS); MWE MyMWE("The_MWE"); sc_start(); MyMWE.m_request.notify(10,SC_NS); std::cerr << "MWE created\n"; if (not sc_end_of_simulation_invoked()) sc_stop(); std::cerr << "Exiting simulation\n"; return errors?1:0; } // File MWE.h #ifndef MWE_H #define MWE_H #include <systemc> #include <iostream> SC_MODULE(MWE) { public: MWE(sc_core::sc_module_name nm); SC_HAS_PROCESS(MWE); virtual ~MWE(void); void request_method(void); void reply_method(void); sc_core::sc_event m_request; sc_core::sc_event m_reply; }; #endif // MWE_H // File mwe.cpp #include "MWE.h" using namespace sc_core; MWE::MWE(sc_core::sc_module_name nm ) : sc_core::sc_module(nm){ SC_METHOD(request_method); sensitive << m_request; // dont_initialize(); SC_METHOD(reply_method); sensitive << m_reply; // dont_initialize(); } MWE::~MWE(void){} void MWE::request_method(void){ std::cerr << "Requested " << sc_time_stamp() << "\n"; m_reply.notify(20,SC_NS); } void MWE::reply_method(void){ std::cerr << "Replied " << sc_time_stamp() << "\n"; }
  6. katang

    SC_METHOD and next_trigger() diagnostics

    OK, I will try to make an MWE. This module is part of a bigger project.
  7. katang

    SC_METHOD and next_trigger() diagnostics

    Well, the full code of the member function calling WaitAccessing() is byte_t getByte(scCore* FromCore, SC_ADDRESS_TYPE Address){ AccessMemory(FromCore, scMemoryRead, Address, 1); // Request a content WaitAccessing(); return storage->contents[Address]; } Of course I set a breakpoint in the member function above (this is the only place where WaitAccessing() is called from) and it is exactly called from this place. Concerning your namespace question: I simple followed the example in SCFTGU, page 55 //FILE: module_name.cpp SC_HAS_PROCESS(module_name); module_name::module_name( sc_module_name instname[, other_argsā€¦]) : sc_module(instname) Is it wrong (or can be wrong)?
  8. I receive the message Error: (E520) next_trigger() is only allowed in SC_METHODs: in SC_THREADs and SC_CTHREADs use wait() instead when running my code (the relevant fragments are shown below). Any idea, what could be wrong? (what else is needed?) SC_MODULE(scMemory) { sc_core::sc_in<bool> Clock; public: void WaitAccessing(void) { next_trigger(memory_accessed); } void ReceivedClock(void); sc_event memory_accessed; // memory access finished }; SC_HAS_PROCESS(scMemory); scMemory::scMemory(sc_core::sc_module_name nm, int Size ) : sc_core::sc_module(nm), mClocks(0), Length(Size), my_state(STANDBY) { SC_METHOD(ReceivedClock); sensitive << Clock.pos(); SC_METHOD(WaitAccessing); sensitive << memory_accessed; dont_initialize(); // Do not receive clock during initialization } the error message changes to Error: (E519) wait() is only allowed in SC_THREADs and SC_CTHREADs: in SC_METHODs use next_trigger() instead if I change the code to SC_THREAD(WaitAccessing); void WaitAccessing(void) { wait(memory_accessed); } I surely do something wrong, but surely the diagnostic messages are not on the top, too.
  9. Is some situations (say when simulating memory access) using simple clocking is in most cases just wasting time during simulation, only a small fraction of invocations results in real action. From this point on, it would be advantageous to use next_trigger(). Some other modules, however, make actions on every clock tick. Is there any way to distinguish whether a member function is called as the result of the Clock or next_trigger()? What happens if I mix them? (I mean using one for one module and another for another module) I guess that using Clock is synthesizable, and next_trigger() is not. Is there some standard methodology to develop a source that supports both? (BTW: is there some support in SystemC which supports using synthesizable constructions only? I mean it flags non-synthetizable constructs with a warning?)
  10. What is exactly the relation and the efficiency of SC_THREAD, SC_METHOD and system thread? I am making a simulator, where both the exact timing and the execution speed counts. I addition, I might need a separate Qt5 GUI thread. What are the means either in Qt5 or SystemC to support those synchronization requirements?
  11. I am attempting to make an application where the engine runs a SystemC model, and its state is displayed for the user though a Qt5 GUI. The GUI can run in a stepwise mode (i.e. the user can stop at some breakpoints and browse actual status), or run continuously. I.e. i have two event queues which should be synchronized. How can i flush the events and synchronize the two queues, in order to display a consistent state? Is there any difference if I call sc_start() in sc_main(), before or after mainWin.show(); or inside mainWin?
  12. I want to test the basic functionality of my design with gtest. It does not have yet the SystemC functionality, but heavily uses SystemC modules and data structures. I create a fresh copy of my top-level module for the individual gtests, and receive tons of warnings that I already defined an module with that name. It is harmless, but annoying. Any idea, how can I suppress it?
  13. katang

    Left shift with zero results in

    Sorry for bothering you. I named it as MASK_WIDTH and set it as MASK_MAXIMUM_VALUE. Later I believed to myself that the definition was really a width.
  14. katang

    Left shift with zero results in

    In a config file, I have #define CORE_BUS_WIDTH 5 In my SC_MODULE I have // sc_dt::sc_uint<CORE_BUS_WIDTH> int mID; ///< internal ID (sequence number) of the core Changing the data type from int to sc_unit provokes the error message, with all others unchanged. Works also with line sc_dt::sc_uint<5>
  15. In my program, I have a member variable sc_dt::sc_uint<MASK_WIDTH> mymask; ///< One-hot bitmask corresponding to ID In my constructor, I can initialize that variable like mymask(ID ? 1 << ID : 1) because using only mymask(1 << ID ) SC library results in Error: (E5) out of bounds: sc_uint[_base] initialization: length = -2147483648 violates 1 <= length <= 64 In file: ../../../../src/sysc/datatypes/int/sc_uint_base.cpp:342 I see nothing against shifting a value by zero position. Is there any deeper reason?