hakimelectronics Posted January 30, 2014 Report Share Posted January 30, 2014 I have a platform for native simulation, composed with sc_main.cpp, native_wrapper.cpp, native_wrapper.h, hardware.... I have to implement another CPU but I didn't find a method to make this. Because extern "C" is needed since the software is compiled in C and is linked against native_wrapper.cpp, which is compiled in C++, for this, we call methods of soft in a this manner, using “NativeWrapper::get_instance()->method_name()” below you can see code of sc_main.cpp, native_wrapper.cpp and native_wrapper.h.Thanks for your help code for native_wrapper.h #include "ensitlm.h" #include "native_wrapper.h" /* extern "C" is needed since the software is compiled in C and * is linked against native_wrapper.cpp, which is compiled in C++. */ extern "C" int __start(); extern "C" void __interrupt(); extern "C" void write_mem(uint32_t addr, uint32_t data) { //abort(); // TODO NativeWrapper::get_instance()->write_mem(addr, data); } extern "C" unsigned int read_mem(uint32_t addr) { //abort(); // TODO return NativeWrapper::get_instance()->read_mem(addr); } extern "C" void cpu_relax() { //abort(); // TODO NativeWrapper::get_instance()->cpu_relax(); } extern "C" void wait_for_irq() { //abort(); // TODO NativeWrapper::get_instance()->wait_for_irq(); } NativeWrapper * NativeWrapper::get_instance() { static NativeWrapper * instance = NULL; if (!instance) instance = new NativeWrapper("native_wrapper"); return instance; } NativeWrapper::NativeWrapper(sc_core::sc_module_name name) : sc_module(name), irq("irq") { SC_THREAD(compute); SC_METHOD(interrupt_handler_internal); sensitive << irq ; dont_initialize(); } void NativeWrapper::write_mem(unsigned int addr, unsigned int data) { tlm::tlm_response_status stat = socket.write(addr, data); } unsigned int NativeWrapper::read_mem(unsigned int addr) { //abort(); // TODO uint32_t localbuf; tlm::tlm_response_status stat = socket.read(addr,localbuf); return localbuf; } void NativeWrapper::cpu_relax() { //abort(); // TODO wait(1000, sc_core::SC_MS); /* temps arbitraire */ } void NativeWrapper::wait_for_irq() { if (!interrupt) wait(interrupt_event); interrupt = false; } void NativeWrapper::compute() { //abort(); // TODO __start(); } void NativeWrapper::interrupt_handler_internal() { interrupt = true; interrupt_event.notify(); __interrupt(); } and native_wrapper.h : #ifndef NATIVEWRAPPER_H #define NATIVEWRAPPER_H #ifndef ENSITLM_H #error Please include file "ensitlm.h" #endif SC_MODULE(NativeWrapper) { ensitlm::initiator_socket<NativeWrapper> socket; sc_core::sc_in<bool> irq; private: SC_CTOR(NativeWrapper); public: /* We use a singleton here. This is a limitation since it doesn't allow multiple NativeWrapper instances (multiple CPU in the platform), but it considerably reduces the complexity of Makefiles, hal.h, ... */ static NativeWrapper * get_instance(); void write_mem(unsigned int addr, unsigned int data); unsigned int read_mem(unsigned int addr); void cpu_relax(); void wait_for_irq(); void compute(); void interrupt_handler_internal(); bool interrupt; sc_core::sc_event interrupt_event; }; #endif sc_main.cpp #include "ensitlm.h" #include "native_wrapper.h" #include "memory.h" #include "bus.h" #include "timer.h" #include "vga.h" #include "intc.h" #include "gpio.h" int sc_main(int, char**) { NativeWrapper& cpu = *NativeWrapper::get_instance(); Memory memory("Memory", 0x00100000); Bus bus("bus"); TIMER timer("timer", sc_core::sc_time(20, sc_core::SC_NS)); Vga vga("vga"); Intc intc("intc"); Gpio gpio("gpio"); ...... Quote Link to comment Share on other sites More sharing options...
dakupoto Posted January 31, 2014 Report Share Posted January 31, 2014 I have a platform for native simulation, composed with sc_main.cpp, native_wrapper.cpp, native_wrapper.h, hardware.... I have to implement another CPU but I didn't find a method to make this. Because extern "C" is needed since the software is compiled in C and is linked against native_wrapper.cpp, which is compiled in C++, for this, we call methods of soft in a this manner, using “NativeWrapper::get_instance()->method_name()” below you can see code of sc_main.cpp, native_wrapper.cpp and native_wrapper.h.Thanks for your help code for native_wrapper.h #include "ensitlm.h" #include "native_wrapper.h" /* extern "C" is needed since the software is compiled in C and * is linked against native_wrapper.cpp, which is compiled in C++. */ extern "C" int __start(); extern "C" void __interrupt(); extern "C" void write_mem(uint32_t addr, uint32_t data) { //abort(); // TODO NativeWrapper::get_instance()->write_mem(addr, data); } extern "C" unsigned int read_mem(uint32_t addr) { //abort(); // TODO return NativeWrapper::get_instance()->read_mem(addr); } extern "C" void cpu_relax() { //abort(); // TODO NativeWrapper::get_instance()->cpu_relax(); } extern "C" void wait_for_irq() { //abort(); // TODO NativeWrapper::get_instance()->wait_for_irq(); } NativeWrapper * NativeWrapper::get_instance() { static NativeWrapper * instance = NULL; if (!instance) instance = new NativeWrapper("native_wrapper"); return instance; } NativeWrapper::NativeWrapper(sc_core::sc_module_name name) : sc_module(name), irq("irq") { SC_THREAD(compute); SC_METHOD(interrupt_handler_internal); sensitive << irq ; dont_initialize(); } void NativeWrapper::write_mem(unsigned int addr, unsigned int data) { tlm::tlm_response_status stat = socket.write(addr, data); } unsigned int NativeWrapper::read_mem(unsigned int addr) { //abort(); // TODO uint32_t localbuf; tlm::tlm_response_status stat = socket.read(addr,localbuf); return localbuf; } void NativeWrapper::cpu_relax() { //abort(); // TODO wait(1000, sc_core::SC_MS); /* temps arbitraire */ } void NativeWrapper::wait_for_irq() { if (!interrupt) wait(interrupt_event); interrupt = false; } void NativeWrapper::compute() { //abort(); // TODO __start(); } void NativeWrapper::interrupt_handler_internal() { interrupt = true; interrupt_event.notify(); __interrupt(); } and native_wrapper.h : #ifndef NATIVEWRAPPER_H #define NATIVEWRAPPER_H #ifndef ENSITLM_H #error Please include file "ensitlm.h" #endif SC_MODULE(NativeWrapper) { ensitlm::initiator_socket<NativeWrapper> socket; sc_core::sc_in<bool> irq; private: SC_CTOR(NativeWrapper); public: /* We use a singleton here. This is a limitation since it doesn't allow multiple NativeWrapper instances (multiple CPU in the platform), but it considerably reduces the complexity of Makefiles, hal.h, ... */ static NativeWrapper * get_instance(); void write_mem(unsigned int addr, unsigned int data); unsigned int read_mem(unsigned int addr); void cpu_relax(); void wait_for_irq(); void compute(); void interrupt_handler_internal(); bool interrupt; sc_core::sc_event interrupt_event; }; #endif sc_main.cpp #include "ensitlm.h" #include "native_wrapper.h" #include "memory.h" #include "bus.h" #include "timer.h" #include "vga.h" #include "intc.h" #include "gpio.h" int sc_main(int, char**) { NativeWrapper& cpu = *NativeWrapper::get_instance(); Memory memory("Memory", 0x00100000); Bus bus("bus"); TIMER timer("timer", sc_core::sc_time(20, sc_core::SC_NS)); Vga vga("vga"); Intc intc("intc"); Gpio gpio("gpio"); ...... Hello Sir, A viable workaround would be to use the following header files in the .h file: #include <cstdlib> #include <cstring> /* And so on ..*/ The modules may then be compiled happily with g++ (NOT gcc) and executed. Hope that helps. Quote Link to comment Share on other sites More sharing options...
hakimelectronics Posted February 3, 2014 Author Report Share Posted February 3, 2014 Tanks dakupoto but i would like to add another CPU, like: NativeWrapper& cpu1 = *NativeWrapper::get_instance(); NativeWrapper& cpu2 = *NativeWrapper::get_instance(); Or NativeWrapper cpu1("cpu1") NativeWrapper cpu2("cpu2") In second solution when I execute the simulation a message is displayed:"terminate called Expired Effective throwing an instance of 'sc_core :: sc_report'what (): error (E529) insert Module failed: simulation runningIn file: ../../../../src/ csys/kernel/sc_module_registry.cpp: 69In process: cpu1.compute @ 0 s " Quote Link to comment Share on other sites More sharing options...
dakupoto Posted February 4, 2014 Report Share Posted February 4, 2014 Tanks dakupoto but i would like to add another CPU, like: NativeWrapper& cpu1 = *NativeWrapper::get_instance(); NativeWrapper& cpu2 = *NativeWrapper::get_instance(); Or NativeWrapper cpu1("cpu1") NativeWrapper cpu2("cpu2") In second solution when I execute the simulation a message is displayed: "terminate called Expired Effective throwing an instance of 'sc_core :: sc_report' what (): error (E529) insert Module failed: simulation running In file: ../../../../src/ csys/kernel/sc_module_registry.cpp: 69 In process: cpu1.compute @ 0 s " Hello Sir, The NativeWrapper constructor as you have provided reads as: NativeWrapper::NativeWrapper(sc_core::sc_module_name name) : sc_module(name), irq("irq") { SC_THREAD(compute); SC_METHOD(interrupt_handler_internal); sensitive << irq ; dont_initialize(); } However, the constructor is invoked as: NativeWrapper cpu1("cpu1") Where is the interrupt request object ? That is, has the IRQ object been created BEFORE the NativeWrapper constructors are invoked ? Hope that helps. Quote Link to comment Share on other sites More sharing options...
Philipp A Hartmann Posted February 7, 2014 Report Share Posted February 7, 2014 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: /* We use a singleton here. This is a limitation since it doesn't allow multiple NativeWrapper instances (multiple CPU in the platform), but it considerably reduces the complexity of Makefiles, hal.h, ... */ 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. Tanks dakupoto but i would like to add another CPU, like: NativeWrapper& cpu1 = *NativeWrapper::get_instance(); NativeWrapper& cpu2 = *NativeWrapper::get_instance(); Or NativeWrapper cpu1("cpu1") NativeWrapper cpu2("cpu2") In second solution when I execute the simulation a message is displayed:"terminate called Expired Effective throwing an instance of 'sc_core :: sc_report'what (): error (E529) insert Module failed: simulation runningIn file: ../../../../src/ csys/kernel/sc_module_registry.cpp: 69In process: cpu1.compute @ 0 s " 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 Quote Link to comment Share on other sites More sharing options...
hakimelectronics Posted February 11, 2014 Author Report Share Posted February 11, 2014 thank you very much dear friend Philipp, I did everything you said but an error message is displayed: native_wrapper.cpp:44: error: 'SC_ID_ASSERTION_FAILED_ ' was not declared in this scope. the problem is in the line where we have: sc_assert (current_cpu_process); thanks for your help! Quote Link to comment Share on other sites More sharing options...
Philipp A Hartmann Posted February 11, 2014 Report Share Posted February 11, 2014 native_wrapper.cpp:44: error: 'SC_ID_ASSERTION_FAILED_ ' was not declared in this scope. 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 Quote Link to comment Share on other sites More sharing options...
hakimelectronics Posted February 14, 2014 Author Report Share Posted February 14, 2014 thank you Philipp, it's fine! Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.