From e4ab2c8d5decae2f6c0f89766d127b107f3b9f15 Mon Sep 17 00:00:00 2001 From: Junwei Guo Date: Wed, 14 Jan 2026 16:07:32 +0800 Subject: [PATCH 1/2] optimize timed event implementation --- src/sysc/kernel/sc_event.cpp | 38 +++++++++++++++++++------------ src/sysc/kernel/sc_event.h | 25 +++++++++++++------- src/sysc/kernel/sc_simcontext.cpp | 36 +++++++++++++++++++++++++---- src/sysc/kernel/sc_simcontext.h | 9 ++------ src/sysc/utils/sc_pq.cpp | 2 +- src/sysc/utils/sc_pq.h | 7 ++++++ 6 files changed, 81 insertions(+), 36 deletions(-) diff --git a/src/sysc/kernel/sc_event.cpp b/src/sysc/kernel/sc_event.cpp index 74b6cae3f..3ddc95a3b 100644 --- a/src/sysc/kernel/sc_event.cpp +++ b/src/sysc/kernel/sc_event.cpp @@ -58,6 +58,24 @@ sc_event::basename() const return p ? (p + 1) : m_name.c_str(); } +void +sc_event::cancel_timed() { + auto head = m_timed->m_event; + if( head == this) { + m_timed->m_event = head->m_event_with_the_same_stamp; + } else { + while( head != nullptr) { + if( head->m_event_with_the_same_stamp == this) { + head->m_event_with_the_same_stamp = this->m_event_with_the_same_stamp; + break; + } + head = head->m_event_with_the_same_stamp; + } + } + this->m_event_with_the_same_stamp = {}; + m_timed = 0; +} + void sc_event::cancel() { @@ -72,8 +90,7 @@ sc_event::cancel() case TIMED: { // remove this event from the timed events set sc_assert( m_timed != 0 ); - m_timed->m_event = 0; - m_timed = 0; + this->cancel_timed(); m_notify_type = NONE; break; } @@ -120,8 +137,7 @@ sc_event::notify( const sc_time& t ) if( m_notify_type == TIMED ) { // remove this event from the timed events set sc_assert( m_timed != 0 ); - m_timed->m_event = 0; - m_timed = 0; + this->cancel_timed(); } // add this event to the delta events set m_delta_event_index = m_simc->add_delta_event( this ); @@ -144,14 +160,10 @@ sc_event::notify( const sc_time& t ) return; } // remove this event from the timed events set - m_timed->m_event = 0; - m_timed = 0; + this->cancel_timed(); } // add this event to the timed events set - sc_event_timed* et = new sc_event_timed( this, m_simc->time_stamp() + t ); - m_simc->add_timed_event( et ); - m_timed = et; - m_notify_type = TIMED; + m_simc->add_timed_event(this, m_simc->time_stamp() + t); } static void sc_warn_notify_delayed() @@ -190,11 +202,7 @@ sc_event::notify_delayed( const sc_time& t ) m_notify_type = DELTA; } else { // add this event to the timed events set - sc_event_timed* et = new sc_event_timed( this, - m_simc->time_stamp() + t ); - m_simc->add_timed_event( et ); - m_timed = et; - m_notify_type = TIMED; + m_simc->add_timed_event(this, m_simc->time_stamp() + t); } } diff --git a/src/sysc/kernel/sc_event.h b/src/sysc/kernel/sc_event.h index d7884f6b3..09c8ba0e9 100644 --- a/src/sysc/kernel/sc_event.h +++ b/src/sysc/kernel/sc_event.h @@ -280,7 +280,7 @@ class SC_API sc_event ~sc_event(); void cancel(); - + void cancel_timed(); const char* basename() const; const char* name() const { return m_name.c_str(); } @@ -328,6 +328,9 @@ class SC_API sc_event void trigger(); +public: + sc_event* m_event_with_the_same_stamp{}; + private: enum notify_t { NONE, DELTA, TIMED }; @@ -375,8 +378,18 @@ class SC_API sc_event_timed : m_event( e ), m_notify_time( t ) {} - ~sc_event_timed() - { if( m_event != 0 ) { m_event->m_timed = 0; } } + ~sc_event_timed() { + auto event = m_event; + sc_event* tmp{}; + while( event != nullptr ) { + event->m_timed = 0; + tmp = event; + event = event->m_event_with_the_same_stamp; + tmp->m_event_with_the_same_stamp = {}; + } + + m_event = {}; + } sc_event* event() const { return m_event; } @@ -429,11 +442,7 @@ sc_event::notify_internal( const sc_time& t ) m_delta_event_index = m_simc->add_delta_event( this ); m_notify_type = DELTA; } else { - sc_event_timed* et = - new sc_event_timed( this, m_simc->time_stamp() + t ); - m_simc->add_timed_event( et ); - m_timed = et; - m_notify_type = TIMED; + m_simc->add_timed_event(this, m_simc->time_stamp() + t); } } diff --git a/src/sysc/kernel/sc_simcontext.cpp b/src/sysc/kernel/sc_simcontext.cpp index 065dc6bdb..10d82fffb 100644 --- a/src/sysc/kernel/sc_simcontext.cpp +++ b/src/sysc/kernel/sc_simcontext.cpp @@ -210,6 +210,31 @@ sc_notify_time_compare( const void* p1, const void* p2 ) } } +void +sc_simcontext::add_timed_event( sc_event* e, const sc_time& t) +{ + if( SC_LIKELY_((m_timed_events->size() > 0) && (t >= m_timed_events->top()->notify_time()) && (t <= this->m_max_event_time))) { + for(int i = 1; i <= m_timed_events->size(); ++i) { + auto pq_item = this->m_timed_events->operator[](i); + if(( t == pq_item->notify_time())) { + e->m_event_with_the_same_stamp = pq_item->m_event; + pq_item->m_event = e; + e->m_timed = pq_item; + e->m_notify_type = sc_event::TIMED; + return; + } + } + } + + sc_event_timed* et = new sc_event_timed(e, t); + this->m_timed_events->insert(et); + e->m_timed = et; + e->m_event_with_the_same_stamp = {}; + e->m_notify_type = sc_event::TIMED; + + if( t > this->m_max_event_time ) { this->m_max_event_time = t; } + +} // +============================================================================ // | CLASS sc_invoke_method - class to invoke sc_method's to support @@ -950,11 +975,12 @@ sc_simcontext::simulate( const sc_time& duration ) do { sc_event_timed* et = m_timed_events->extract_top(); - sc_event* e = et->event(); - delete et; - if( e != 0 ) { - e->trigger(); - } + auto tmp_event = et->event(); + while( tmp_event != nullptr) { + tmp_event->trigger(); + tmp_event = tmp_event->m_event_with_the_same_stamp; + } + delete et; } while( m_timed_events->size() && m_timed_events->top()->notify_time() == t ); diff --git a/src/sysc/kernel/sc_simcontext.h b/src/sysc/kernel/sc_simcontext.h index 7788281f3..5d0e9514c 100644 --- a/src/sysc/kernel/sc_simcontext.h +++ b/src/sysc/kernel/sc_simcontext.h @@ -343,7 +343,7 @@ class SC_API sc_simcontext int add_delta_event( sc_event* ); void remove_delta_event( sc_event* ); - void add_timed_event( sc_event_timed* ); + void add_timed_event( sc_event*, const sc_time& ); void trace_cycle( bool delta_cycle ); @@ -421,6 +421,7 @@ class SC_API sc_simcontext sc_time_params* m_time_params; sc_time m_curr_time; + sc_time m_max_event_time{}; sc_invoke_method* m_method_invoker_p; sc_dt::uint64 m_change_stamp; // "time" change occurred. @@ -676,12 +677,6 @@ sc_simcontext::add_delta_event( sc_event* e ) return static_cast( m_delta_events.size() - 1 ); } -inline -void -sc_simcontext::add_timed_event( sc_event_timed* et ) -{ - m_timed_events->insert( et ); -} // ---------------------------------------------------------------------------- diff --git a/src/sysc/utils/sc_pq.cpp b/src/sysc/utils/sc_pq.cpp index 7911d38e6..c0b267f35 100644 --- a/src/sysc/utils/sc_pq.cpp +++ b/src/sysc/utils/sc_pq.cpp @@ -75,7 +75,7 @@ sc_ppq_base::insert( void* elem ) int i = m_heap_size; // resize the heap in case there's not enough memory - if( m_heap_size > m_size_alloc ) { + if( SC_UNLIKELY_( m_heap_size > m_size_alloc )) { m_size_alloc += m_size_alloc / 2; void** new_heap = new void*[m_size_alloc + 1]; for( int j = 1; j < m_heap_size; ++ j ) { diff --git a/src/sysc/utils/sc_pq.h b/src/sysc/utils/sc_pq.h index 5499d1a54..b9d17d0ce 100644 --- a/src/sysc/utils/sc_pq.h +++ b/src/sysc/utils/sc_pq.h @@ -64,6 +64,10 @@ class SC_API sc_ppq_base bool empty() const { return (m_heap_size == 0); } + void* operator [](int index) { + return m_heap[index]; + } + protected: int parent( int i ) const @@ -119,6 +123,9 @@ class sc_ppq T extract_top() { return (T) sc_ppq_base::extract_top(); } + T operator [](int index) + { return (T) sc_ppq_base::operator[](index); } + // insert a new element to the priority queue. void insert( T elem ) From 0e7c5ae9bc82957fadc38f9ef97d7989098956ff Mon Sep 17 00:00:00 2001 From: Junwei Guo Date: Thu, 15 Jan 2026 19:18:31 +0800 Subject: [PATCH 2/2] fix m_timed_event corner case --- src/sysc/kernel/sc_event.cpp | 4 ++++ src/sysc/kernel/sc_event.h | 1 + src/sysc/kernel/sc_simcontext.cpp | 13 +++++++++++-- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/sysc/kernel/sc_event.cpp b/src/sysc/kernel/sc_event.cpp index 3ddc95a3b..92eafdfb5 100644 --- a/src/sysc/kernel/sc_event.cpp +++ b/src/sysc/kernel/sc_event.cpp @@ -63,9 +63,13 @@ sc_event::cancel_timed() { auto head = m_timed->m_event; if( head == this) { m_timed->m_event = head->m_event_with_the_same_stamp; + if (m_timed->m_event == nullptr) { + m_timed->m_event_tail = 0; + } } else { while( head != nullptr) { if( head->m_event_with_the_same_stamp == this) { + m_timed->m_event_tail = head; head->m_event_with_the_same_stamp = this->m_event_with_the_same_stamp; break; } diff --git a/src/sysc/kernel/sc_event.h b/src/sysc/kernel/sc_event.h index 09c8ba0e9..4c8f340ec 100644 --- a/src/sysc/kernel/sc_event.h +++ b/src/sysc/kernel/sc_event.h @@ -413,6 +413,7 @@ class SC_API sc_event_timed sc_event* m_event; sc_time m_notify_time; + sc_event* m_event_tail; private: diff --git a/src/sysc/kernel/sc_simcontext.cpp b/src/sysc/kernel/sc_simcontext.cpp index 10d82fffb..3d7cf5e89 100644 --- a/src/sysc/kernel/sc_simcontext.cpp +++ b/src/sysc/kernel/sc_simcontext.cpp @@ -217,8 +217,16 @@ sc_simcontext::add_timed_event( sc_event* e, const sc_time& t) for(int i = 1; i <= m_timed_events->size(); ++i) { auto pq_item = this->m_timed_events->operator[](i); if(( t == pq_item->notify_time())) { - e->m_event_with_the_same_stamp = pq_item->m_event; - pq_item->m_event = e; + //e->m_event_with_the_same_stamp = pq_item->m_event; + if (pq_item->m_event_tail == nullptr) { + pq_item->m_event = e; + pq_item->m_event_tail = e; + } + else { + pq_item->m_event_tail->m_event_with_the_same_stamp = e; + pq_item->m_event_tail = e; + } + // pq_item->m_event = e; e->m_timed = pq_item; e->m_notify_type = sc_event::TIMED; return; @@ -228,6 +236,7 @@ sc_simcontext::add_timed_event( sc_event* e, const sc_time& t) sc_event_timed* et = new sc_event_timed(e, t); this->m_timed_events->insert(et); + et->m_event_tail = e; e->m_timed = et; e->m_event_with_the_same_stamp = {}; e->m_notify_type = sc_event::TIMED;