Aaron Yang Posted June 5, 2019 Report Posted June 5, 2019 Hey Guys, I am kinda new to this language so bear with me if question sounds naive. I am building cycle accurate system C model. When I run performance profiler, some process triggered by clk consume a lot resources(clk is always running). So I am looking for tricks to improve the performance: Original code: SC_METHOD(process_output); sensitive << reset; sensitive << clk.pos(); ... void fir::process_output() { if (reset.read() == 0) { //reset sequence } else { if(enable.read()) { //normal operation } } } One way to avoid triggered the process every time clk toggles is that create a event: void fir::enable_event() { if (enable.read()) { enable_rise.notify(); } } ... void fir::process_output() { if (reset.read() == 0) { //reset seq } else { if (enable.read() == 0) { next_trigger(enable_rise);//Correct me if I am wrong, based on my understanding, next_trigger() overrides the static sensitivity list. } else { next_trigger(); //normal op } } } The other way is to use .suspend() and .resume(); SC_THREAD(monitor_trig_event); sensitive << reset << enable; ... void fir::monitor_trig_event() { sc_spawn_options opt; opt.set_sensitivity(&clk.pos()); sc_process_handle handle = sc_spawn(sc_bind(&fir::process_output, this), "run_fir", &opt); handle.suspend(); while (1) { wait(); if (!reset) reset(); else { if (enable.read()) { handle.resume(); break; } else if (enable.read() == 0) { handle.suspend(); } } } In this case, process output won't have next_trigger() statement anymore. For those two methods above, which one is more recommended? Or is there any clean and straightforward way to implement the improvement? Thank you all in advance. Quote
karthickg Posted June 5, 2019 Report Posted June 5, 2019 Are you only looking at disabling process_output from getting triggered when reset is on? In that case, it is as simple as: void fir::process_output() { if (reset.read() == 0) { //reset sequence next_trigger(reset.pos()); } else if (clk.read() == 0) { //Ignore the trigger just after reset is de-asserted and //sync to next clock edge next_trigger(clk.pos()); // Note: will work even if we comment out line above, due to static sensitivity } else { if(enable.read()) { //normal operation } } } But this may not really get you a significant improvement in itself. You may want to check what is going on in "normal operation" - and see if you can optimize that. Roman Popov 1 Quote
Eyck Posted June 18, 2019 Report Posted June 18, 2019 I would stick with the two methods where the one calls enable() and disable() for the second mehtod. Why enable()/disable()? The LRM says (section 5.6.6): Quote The distinction between suspend/resume and disable/enable lies in the sensitivity of the target process during the period while it is suspended or disabled. With suspend, the kernel keeps track of the sensitivity of the target process while it is suspended such that a relevant event notification or time-out while suspended would cause the process to become runnable immediately when resume is called. With disable, the sensitivity of the target process is nullified while it is suspended such that the process is not made runnable by the call to enable, but only on the next relevant event notification or time-out subsequent to the call to enable. In other words, with suspend/resume, the kernel keeps a record of whether the target process would have awoken while in fact being suspended, whereas with disable/enable, the kernel entirely ignores the sensitivity of the target process while disabled. Also see 5.2.12 regarding clocked thread processes. So with suspend() you still have the sensitivity handling in place while with disable() you don't. Moreover if there is an event while being supended it becomes immediately runnable. So falling edge of reset implies a process activation although there is not rising edge on clock. An implementation could look like: // class declaration: sc_core::sc_process_handle process_output_hndl; // constructor body: SC_METHOD(process_output); sensitive<<clk.pos()<<reset; SC_METHOD(process_output_enable); sensitive<<enable; // function implementation: void fir::process_output() { if(!process_output_hndl.valid()) process_output_hndl = sc_process_handle(sc_get_current_process_handle()); if (reset.read() == 0) { //reset sequence } else { //normal operation } } void fir::process_output_enable() { if (enable.read()) { if(process_output_hndl.valid()) process_output_hndl.enable(); } else { if(process_output_hndl.valid()) process_output_hndl.disable(); } } BR Quote
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.