systemc-2.3.3/0000755000175000017500000000000013360325173013071 5ustar carstencarstensystemc-2.3.3/src/0000755000175000017500000000000013360325173013660 5ustar carstencarstensystemc-2.3.3/src/tlm.pc.in0000644000175000017500000000272313360325173015411 0ustar carstencarsten# Licensed to Accellera Systems Initiative Inc. (Accellera) under one or # more contributor license agreements. See the NOTICE file distributed # with this work for additional information regarding copyright ownership. # Accellera licenses this file to you under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with the # License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. See the License for the specific language governing # permissions and limitations under the License. # # ------------------------------------------------------------------------- # # tlm.pc.in -- # pkg-config definition file (template) for TLM-2.0 # (http://www.freedesktop.org/wiki/Software/pkg-config/) # # Author: Philipp A. Hartmann, OFFIS, 2013-05-07 # # Note: The "real" definition (tlm.pc) is generated by "configure" # during the build configuration. # # ------------------------------------------------------------------------- # prefix=@prefix@ exec_prefix=@exec_prefix@ includedir=@includedir@ Name: TLM-2.0 Description: Accellera TLM-2.0 proof-of-concept library Version: @TLM_PACKAGE_VERSION@ URL: @PACKAGE_URL@ Requires: systemc >= 2.1.v1 Cflags: -I${includedir} systemc-2.3.3/src/README_TLM.txt0000644000175000017500000000201713360325173016072 0ustar carstencarsten TLM-2.0 standard header files ============================= Dir: include/ SubDirs: tlm_core/ tlm_1/ tlm_2/ tlm_utils/ Files: README.txt tlm tlm.h Comments ======== To use the TLM-2.0 interoperability standard, a user should only include the tlm or tlm.h header file. The same holds for the TLM-1.0 implementation that is included as part of this kit; only include tlm or tlm.h. These header files refer to all the header files within the tlm_core/ subdirectory, everything within tlm or tlm.h is contained in the tlm namespace. The tlm_utils subdirectory contains a set of additional definitions supported by the TLM-2.0 standard, but which are not part of the interoperability requirements. It contains ease-of-use and convenience implementations for the interoperability standard. All objects defined in the tlm_utils directory are contained in the tlm_util namespace. See the README.txt files in the subdirectories for an explanation of the internal organization of the header files. systemc-2.3.3/src/Makefile.am0000644000175000017500000000543613360325173015724 0ustar carstencarsten## **************************************************************************** ## ## Licensed to Accellera Systems Initiative Inc. (Accellera) under one or ## more contributor license agreements. See the NOTICE file distributed ## with this work for additional information regarding copyright ownership. ## Accellera licenses this file to you under the Apache License, Version 2.0 ## (the "License"); you may not use this file except in compliance with the ## License. You may obtain a copy of the License at ## ## http://www.apache.org/licenses/LICENSE-2.0 ## ## Unless required by applicable law or agreed to in writing, software ## distributed under the License is distributed on an "AS IS" BASIS, ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or ## implied. See the License for the specific language governing ## permissions and limitations under the License. ## ## **************************************************************************** ## ## src/sysc/Makefile.am -- ## Process this file with automake to produce a Makefile.in file. ## ## Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 ## ## **************************************************************************** ## ## MODIFICATION LOG - modifiers, enter your name, affiliation, date and ## changes you are making here. ## ## Name, Affiliation, Date: ## Description of Modification: ## ## **************************************************************************** include $(top_srcdir)/config/Make-rules.sysc # order of SUBDIRS is important, sysc needs to go first: SUBDIRS = \ sysc \ tlm_core \ tlm_utils \ . H_FILES = \ systemc \ systemc.h \ tlm \ tlm.h nobase_include_HEADERS = $(H_FILES) libarchdir = $(libdir)$(LIB_ARCH_SUFFIX) libarch_LTLIBRARIES = libsystemc.la pkgconfigdir = $(libarchdir)/pkgconfig pkgconfig_DATA = \ systemc.pc \ tlm.pc EXTRA_DIST += \ README_TLM.txt \ CMakeLists.txt # no own sources here libsystemc_la_SOURCES = # dummy C++ source to cause C++ linking nodist_EXTRA_libsystemc_la_SOURCES = sc_nonexistent.cpp # add main libraries libsystemc_la_LIBADD = \ tlm_utils/libtlm_utils.la \ tlm_core/libtlm_core.la \ sysc/libsysc.la # either for async_update locking or pthread processes if USES_PTHREADS_LIB # Libtool/GCC do not play well together on some platforms # with C++ libraries and libpthread dependency, see e.g. # http://lists.gnu.org/archive/html/libtool/2012-02/msg00003.html libsystemc_la_LIBADD+=$(EXPLICIT_LPTHREAD) endif libsystemc_la_LDFLAGS = $(EXTRA_LDFLAGS) -release $(VERSION) uninstall-hook: test ! -d "$(includedir)" || rmdir --ignore-fail-on-non-empty "$(includedir)" test ! -d "$(pkgconfigdir)" || rmdir --ignore-fail-on-non-empty "$(pkgconfigdir)" test ! -d "$(libarchdir)" || rmdir --ignore-fail-on-non-empty "$(libarchdir)" ## Taf! systemc-2.3.3/src/systemc0000644000175000017500000001074313360325173015277 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** systemc - Top-level namespace-based include file for the SystemC library. Original Author: Stan Y. Liao, Synopsys, Inc. *****************************************************************************/ /***************************************************************************** MODIFICATION LOG - modifiers, enter your name, affiliation, date and changes you are making here. Name, Affiliation, Date: Andy Goodrich, Forte Design Systems, 31 Mar 2005 Description of Modification: This is the old systemc.h without usings. *****************************************************************************/ // $Log: systemc,v $ // Revision 1.6 2011/08/04 17:12:07 acg // Andy Goodrich: moved systemc and systemc.h back to src level because // of MSVC not doing an install. // // Revision 1.1 2011/07/02 13:26:48 acg // Andy Goodrich: moved header files up one level. // // Revision 1.4 2011/02/18 20:28:27 acg // Andy Goodrich: Updated Copyright. // // Revision 1.3 2011/01/20 16:52:09 acg // Andy Goodrich: changes for IEEE 1666 2011. // // Revision 1.2 2009/11/17 19:57:51 acg // Andy Goodrich: changes for boost. // // Revision 1.1.1.1 2006/12/15 20:20:04 acg // SystemC 2.3 // // Revision 1.5 2006/04/11 23:11:16 acg // Andy Goodrich: remove inclusions that exposed sc_method_process, // sc_thread_process, and sc_cthread_process internals. // // Revision 1.4 2006/01/25 00:48:29 acg // Andy Goodrich: added capture of CVS logging messages in the source. // #ifndef SYSTEMC_INCLUDED #define SYSTEMC_INCLUDED // include this file first #include "sysc/kernel/sc_cmnhdr.h" #include "sysc/kernel/sc_externs.h" #include "sysc/kernel/sc_except.h" #include "sysc/kernel/sc_module.h" #include "sysc/kernel/sc_simcontext.h" #include "sysc/kernel/sc_process_handle.h" #include "sysc/kernel/sc_ver.h" #include "sysc/communication/sc_buffer.h" #include "sysc/communication/sc_clock.h" #include "sysc/communication/sc_clock_ports.h" #include "sysc/communication/sc_event_queue.h" #include "sysc/communication/sc_export.h" #include "sysc/communication/sc_fifo.h" #include "sysc/communication/sc_fifo_ports.h" #include "sysc/communication/sc_mutex.h" #include "sysc/communication/sc_semaphore.h" #include "sysc/communication/sc_signal.h" #include "sysc/communication/sc_signal_ports.h" #include "sysc/communication/sc_signal_resolved.h" #include "sysc/communication/sc_signal_resolved_ports.h" #include "sysc/communication/sc_signal_rv.h" #include "sysc/communication/sc_signal_rv_ports.h" #include "sysc/datatypes/bit/sc_bit.h" #include "sysc/datatypes/bit/sc_logic.h" #include "sysc/datatypes/bit/sc_bv.h" #include "sysc/datatypes/bit/sc_lv.h" #include "sysc/datatypes/int/sc_bigint.h" #include "sysc/datatypes/int/sc_biguint.h" #include "sysc/datatypes/int/sc_int.h" #include "sysc/datatypes/int/sc_uint.h" #include "sysc/datatypes/misc/sc_concatref.h" #ifdef SC_INCLUDE_FX # include "sysc/datatypes/fx/fx.h" #endif // SC_INCLUDE_FX #include "sysc/tracing/sc_trace.h" #include "sysc/utils/sc_utils_ids.h" #include "sysc/utils/sc_pvector.h" #include "sysc/utils/sc_string_view.h" #include "sysc/utils/sc_vector.h" #endif // !defined(SYSTEMC_INCLUDED) #ifdef SC_INCLUDE_DYNAMIC_PROCESSES # include "sysc/kernel/sc_dynamic_processes.h" #endif // SC_INCLUDE_DYNAMIC_PROCESSES #ifdef SC_USE_SC_STRING_OLD # include "sysc/utils/sc_string.h" #endif // SC_USE_SC_STRING_OLD #ifdef SC_INCLUDE_EXTRA_STD_HEADERS # include # include #endif // SC_INCLUDE_EXTRA_STD_HEADERS systemc-2.3.3/src/CMakeLists.txt0000644000175000017500000006600013360325173016422 0ustar carstencarsten############################################################################### # # Licensed to Accellera Systems Initiative Inc. (Accellera) under one or # more contributor license agreements. See the NOTICE file distributed # with this work for additional information regarding copyright ownership. # Accellera licenses this file to you under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with the # License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. See the License for the specific language governing # permissions and limitations under the License. # ############################################################################### ############################################################################### # # src/CMakeLists.txt -- # CMake script to configure the SystemC sources and to generate native # Makefiles and project workspaces for your compiler environment. # # Original Author: Torsten Maehne, Université Pierre et Marie Curie, Paris, # 2013-06-11 # ############################################################################### ############################################################################### # # MODIFICATION LOG - modifiers, enter your name, affiliation, date and # changes you are making here. # # Name, Affiliation, Date: # Description of Modification: # ############################################################################### ############################################################################### # Configure QuickThreads ############################################################################### # Set QuickThread sources used by SystemC depending on target platform if (QT_ARCH STREQUAL "sparc") add_custom_command (OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/sysc/packages/qt/md/sparc.s COMMAND sed 's/_qt_/qt_/' ${CMAKE_CURRENT_SOURCE_DIR}/sysc/packages/qt/md/sparc.s > ${CMAKE_CURRENT_BINARY_DIR}/sysc/packages/qt/md/sparc.s DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/sysc/packages/qt/md/sparc.s) endif (QT_ARCH STREQUAL "sparc") if (APPLE) if (N_OSX_ARCHITECTURES EQUAL 1) if (QT_ARCH STREQUAL "i386") set (CMAKE_ASM_FLAGS "-arch i386") elseif (QT_ARCH STREQUAL "x86_64") set (CMAKE_ASM_FLAGS "-arch x86_64") elseif (QT_ARCH STREQUAL "powerpc_mach") set (CMAKE_ASM_FLAGS "-arch ppc") endif(QT_ARCH STREQUAL "i386") else (N_OSX_ARCHITECTURES EQUAL 1) set (CMAKE_ASM_FLAGS "") endif (N_OSX_ARCHITECTURES EQUAL 1) endif (APPLE) ############################################################################### # Build rules for SystemC library ############################################################################### add_library (systemc sysc/communication/sc_clock.cpp sysc/communication/sc_event_finder.cpp sysc/communication/sc_event_queue.cpp sysc/communication/sc_export.cpp sysc/communication/sc_interface.cpp sysc/communication/sc_mutex.cpp sysc/communication/sc_port.cpp sysc/communication/sc_prim_channel.cpp sysc/communication/sc_semaphore.cpp sysc/communication/sc_signal.cpp sysc/communication/sc_signal_ports.cpp sysc/communication/sc_signal_resolved.cpp sysc/communication/sc_signal_resolved_ports.cpp sysc/datatypes/bit/sc_bit.cpp sysc/datatypes/bit/sc_bv_base.cpp sysc/datatypes/bit/sc_logic.cpp sysc/datatypes/bit/sc_lv_base.cpp sysc/datatypes/fx/sc_fxcast_switch.cpp sysc/datatypes/fx/sc_fxdefs.cpp sysc/datatypes/fx/sc_fxnum.cpp sysc/datatypes/fx/sc_fxnum_observer.cpp sysc/datatypes/fx/sc_fxtype_params.cpp sysc/datatypes/fx/sc_fxval.cpp sysc/datatypes/fx/sc_fxval_observer.cpp sysc/datatypes/fx/scfx_mant.cpp sysc/datatypes/fx/scfx_pow10.cpp sysc/datatypes/fx/scfx_rep.cpp sysc/datatypes/fx/scfx_utils.cpp sysc/datatypes/int/sc_int_base.cpp sysc/datatypes/int/sc_int_mask.cpp sysc/datatypes/int/sc_length_param.cpp sysc/datatypes/int/sc_nbexterns.cpp sysc/datatypes/int/sc_nbutils.cpp sysc/datatypes/int/sc_signed.cpp sysc/datatypes/int/sc_uint_base.cpp sysc/datatypes/int/sc_unsigned.cpp sysc/datatypes/misc/sc_concatref.cpp sysc/datatypes/misc/sc_value_base.cpp sysc/kernel/sc_attribute.cpp sysc/kernel/sc_cor_fiber.cpp sysc/kernel/sc_cor_pthread.cpp sysc/kernel/sc_cor_qt.cpp sysc/kernel/sc_cthread_process.cpp sysc/kernel/sc_event.cpp sysc/kernel/sc_except.cpp sysc/kernel/sc_join.cpp sysc/kernel/sc_main.cpp sysc/kernel/sc_main_main.cpp sysc/kernel/sc_method_process.cpp sysc/kernel/sc_module.cpp sysc/kernel/sc_module_name.cpp sysc/kernel/sc_module_registry.cpp sysc/kernel/sc_name_gen.cpp sysc/kernel/sc_object.cpp sysc/kernel/sc_object_manager.cpp sysc/kernel/sc_phase_callback_registry.cpp sysc/kernel/sc_process.cpp sysc/kernel/sc_reset.cpp sysc/kernel/sc_sensitive.cpp sysc/kernel/sc_simcontext.cpp sysc/kernel/sc_spawn_options.cpp sysc/kernel/sc_thread_process.cpp sysc/kernel/sc_time.cpp sysc/kernel/sc_ver.cpp sysc/kernel/sc_wait.cpp sysc/kernel/sc_wait_cthread.cpp sysc/tracing/sc_trace.cpp sysc/tracing/sc_trace_file_base.cpp sysc/tracing/sc_vcd_trace.cpp sysc/tracing/sc_wif_trace.cpp sysc/utils/sc_hash.cpp sysc/utils/sc_list.cpp sysc/utils/sc_mempool.cpp sysc/utils/sc_pq.cpp sysc/utils/sc_report.cpp sysc/utils/sc_report_handler.cpp sysc/utils/sc_stop_here.cpp sysc/utils/sc_string.cpp sysc/utils/sc_utils_ids.cpp sysc/utils/sc_vector.cpp # TLM sources tlm_core/tlm_2/tlm_generic_payload/tlm_gp.cpp tlm_core/tlm_2/tlm_generic_payload/tlm_phase.cpp tlm_core/tlm_2/tlm_quantum/tlm_global_quantum.cpp tlm_utils/convenience_socket_bases.cpp tlm_utils/instance_specific_extensions.cpp # SystemC headers sysc/communication/sc_buffer.h sysc/communication/sc_clock.h sysc/communication/sc_clock_ports.h sysc/communication/sc_communication_ids.h sysc/communication/sc_event_finder.h sysc/communication/sc_event_queue.h sysc/communication/sc_export.h sysc/communication/sc_fifo.h sysc/communication/sc_fifo_ifs.h sysc/communication/sc_fifo_ports.h sysc/communication/sc_host_mutex.h sysc/communication/sc_host_semaphore.h sysc/communication/sc_interface.h sysc/communication/sc_mutex.h sysc/communication/sc_mutex_if.h sysc/communication/sc_port.h sysc/communication/sc_prim_channel.h sysc/communication/sc_semaphore.h sysc/communication/sc_semaphore_if.h sysc/communication/sc_signal.h sysc/communication/sc_signal_ifs.h sysc/communication/sc_signal_ports.h sysc/communication/sc_signal_resolved.h sysc/communication/sc_signal_resolved_ports.h sysc/communication/sc_signal_rv.h sysc/communication/sc_signal_rv_ports.h sysc/communication/sc_writer_policy.h sysc/datatypes/bit/sc_bit.h sysc/datatypes/bit/sc_bit_ids.h sysc/datatypes/bit/sc_bit_proxies.h sysc/datatypes/bit/sc_bv.h sysc/datatypes/bit/sc_bv_base.h sysc/datatypes/bit/sc_logic.h sysc/datatypes/bit/sc_lv.h sysc/datatypes/bit/sc_lv_base.h sysc/datatypes/bit/sc_proxy.h sysc/datatypes/fx/fx.h sysc/datatypes/fx/sc_context.h sysc/datatypes/fx/sc_fix.h sysc/datatypes/fx/sc_fixed.h sysc/datatypes/fx/sc_fx_ids.h sysc/datatypes/fx/sc_fxcast_switch.h sysc/datatypes/fx/sc_fxdefs.h sysc/datatypes/fx/sc_fxnum.h sysc/datatypes/fx/sc_fxnum_observer.h sysc/datatypes/fx/sc_fxtype_params.h sysc/datatypes/fx/sc_fxval.h sysc/datatypes/fx/sc_fxval_observer.h sysc/datatypes/fx/sc_ufix.h sysc/datatypes/fx/sc_ufixed.h sysc/datatypes/fx/scfx_ieee.h sysc/datatypes/fx/scfx_mant.h sysc/datatypes/fx/scfx_other_defs.h sysc/datatypes/fx/scfx_params.h sysc/datatypes/fx/scfx_pow10.h sysc/datatypes/fx/scfx_rep.h sysc/datatypes/fx/scfx_string.h sysc/datatypes/fx/scfx_utils.h sysc/datatypes/int/sc_bigint.h sysc/datatypes/int/sc_biguint.h sysc/datatypes/int/sc_int.h sysc/datatypes/int/sc_int_base.h sysc/datatypes/int/sc_int_ids.h sysc/datatypes/int/sc_length_param.h sysc/datatypes/int/sc_nbdefs.h sysc/datatypes/int/sc_nbexterns.h sysc/datatypes/int/sc_nbutils.h sysc/datatypes/int/sc_signed.h sysc/datatypes/int/sc_uint.h sysc/datatypes/int/sc_uint_base.h sysc/datatypes/int/sc_unsigned.h sysc/datatypes/misc/sc_concatref.h sysc/datatypes/misc/sc_value_base.h sysc/kernel/sc_attribute.h sysc/kernel/sc_cmnhdr.h sysc/kernel/sc_constants.h sysc/kernel/sc_cor.h sysc/kernel/sc_cor_fiber.h sysc/kernel/sc_cor_pthread.h sysc/kernel/sc_cor_qt.h sysc/kernel/sc_cthread_process.h sysc/kernel/sc_dynamic_processes.h sysc/kernel/sc_event.h sysc/kernel/sc_except.h sysc/kernel/sc_externs.h sysc/kernel/sc_join.h sysc/kernel/sc_kernel_ids.h sysc/kernel/sc_macros.h sysc/kernel/sc_method_process.h sysc/kernel/sc_module.h sysc/kernel/sc_module_name.h sysc/kernel/sc_module_registry.h sysc/kernel/sc_name_gen.h sysc/kernel/sc_object.h sysc/kernel/sc_object_int.h sysc/kernel/sc_object_manager.h sysc/kernel/sc_phase_callback_registry.h sysc/kernel/sc_process.h sysc/kernel/sc_process_handle.h sysc/kernel/sc_reset.h sysc/kernel/sc_runnable.h sysc/kernel/sc_runnable_int.h sysc/kernel/sc_sensitive.h sysc/kernel/sc_simcontext.h sysc/kernel/sc_simcontext_int.h sysc/kernel/sc_spawn.h sysc/kernel/sc_spawn_options.h sysc/kernel/sc_status.h sysc/kernel/sc_thread_process.h sysc/kernel/sc_time.h sysc/kernel/sc_ver.h sysc/kernel/sc_wait.h sysc/kernel/sc_wait_cthread.h sysc/packages/boost/bind/apply.hpp sysc/packages/boost/bind/arg.hpp sysc/packages/boost/bind/bind_cc.hpp sysc/packages/boost/bind/bind_mf_cc.hpp sysc/packages/boost/bind/bind_template.hpp sysc/packages/boost/bind/make_adaptable.hpp sysc/packages/boost/bind/mem_fn_cc.hpp sysc/packages/boost/bind/mem_fn_template.hpp sysc/packages/boost/bind/mem_fn_vw.hpp sysc/packages/boost/bind/placeholders.hpp sysc/packages/boost/bind/protect.hpp sysc/packages/boost/bind.hpp sysc/packages/boost/config/compiler/borland.hpp sysc/packages/boost/config/compiler/comeau.hpp sysc/packages/boost/config/compiler/common_edg.hpp sysc/packages/boost/config/compiler/compaq_cxx.hpp sysc/packages/boost/config/compiler/digitalmars.hpp sysc/packages/boost/config/compiler/gcc.hpp sysc/packages/boost/config/compiler/greenhills.hpp sysc/packages/boost/config/compiler/hp_acc.hpp sysc/packages/boost/config/compiler/intel.hpp sysc/packages/boost/config/compiler/kai.hpp sysc/packages/boost/config/compiler/metrowerks.hpp sysc/packages/boost/config/compiler/mpw.hpp sysc/packages/boost/config/compiler/sgi_mipspro.hpp sysc/packages/boost/config/compiler/sunpro_cc.hpp sysc/packages/boost/config/compiler/vacpp.hpp sysc/packages/boost/config/compiler/visualc.hpp sysc/packages/boost/config/platform/aix.hpp sysc/packages/boost/config/platform/amigaos.hpp sysc/packages/boost/config/platform/beos.hpp sysc/packages/boost/config/platform/bsd.hpp sysc/packages/boost/config/platform/cygwin.hpp sysc/packages/boost/config/platform/hpux.hpp sysc/packages/boost/config/platform/irix.hpp sysc/packages/boost/config/platform/linux.hpp sysc/packages/boost/config/platform/macos.hpp sysc/packages/boost/config/platform/solaris.hpp sysc/packages/boost/config/platform/win32.hpp sysc/packages/boost/config/posix_features.hpp sysc/packages/boost/config/select_compiler_config.hpp sysc/packages/boost/config/select_platform_config.hpp sysc/packages/boost/config/select_stdlib_config.hpp sysc/packages/boost/config/stdlib/dinkumware.hpp sysc/packages/boost/config/stdlib/libcomo.hpp sysc/packages/boost/config/stdlib/libstdcpp3.hpp sysc/packages/boost/config/stdlib/modena.hpp sysc/packages/boost/config/stdlib/msl.hpp sysc/packages/boost/config/stdlib/roguewave.hpp sysc/packages/boost/config/stdlib/sgi.hpp sysc/packages/boost/config/stdlib/stlport.hpp sysc/packages/boost/config/stdlib/vacpp.hpp sysc/packages/boost/config/suffix.hpp sysc/packages/boost/config/user.hpp sysc/packages/boost/config.hpp sysc/packages/boost/detail/endian.hpp sysc/packages/boost/detail/workaround.hpp sysc/packages/boost/get_pointer.hpp sysc/packages/boost/mem_fn.hpp sysc/packages/boost/mpl/aux_/adl_barrier.hpp sysc/packages/boost/mpl/aux_/config/adl.hpp sysc/packages/boost/mpl/aux_/config/gcc.hpp sysc/packages/boost/mpl/aux_/config/intel.hpp sysc/packages/boost/mpl/aux_/config/msvc.hpp sysc/packages/boost/mpl/aux_/config/static_constant.hpp sysc/packages/boost/mpl/aux_/config/workaround.hpp sysc/packages/boost/mpl/bool.hpp sysc/packages/boost/mpl/bool_fwd.hpp sysc/packages/boost/mpl/integral_c_tag.hpp sysc/packages/boost/non_type.hpp sysc/packages/boost/ref.hpp sysc/packages/boost/type.hpp sysc/packages/boost/utility/addressof.hpp sysc/packages/boost/utility/enable_if.hpp sysc/packages/boost/utility/string_view.hpp sysc/packages/boost/utility/string_view_fwd.hpp sysc/tracing/sc_trace.h sysc/tracing/sc_trace_file_base.h sysc/tracing/sc_tracing_ids.h sysc/tracing/sc_vcd_trace.h sysc/tracing/sc_wif_trace.h sysc/utils/sc_hash.h sysc/utils/sc_list.h sysc/utils/sc_machine.h sysc/utils/sc_mempool.h sysc/utils/sc_pq.h sysc/utils/sc_pvector.h sysc/utils/sc_report.h sysc/utils/sc_report_handler.h sysc/utils/sc_stop_here.h sysc/utils/sc_string.h sysc/utils/sc_string_view.h sysc/utils/sc_temporary.h sysc/utils/sc_typeindex.h sysc/utils/sc_utils_ids.h sysc/utils/sc_vector.h systemc systemc.h # TLM headers tlm tlm.h tlm_core/tlm_1/tlm_analysis/tlm_analysis.h tlm_core/tlm_1/tlm_analysis/tlm_analysis_fifo.h tlm_core/tlm_1/tlm_analysis/tlm_analysis_if.h tlm_core/tlm_1/tlm_analysis/tlm_analysis_port.h tlm_core/tlm_1/tlm_analysis/tlm_analysis_triple.h tlm_core/tlm_1/tlm_analysis/tlm_write_if.h tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_core_ifs.h tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_fifo_ifs.h tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_master_slave_ifs.h tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_tag.h tlm_core/tlm_1/tlm_req_rsp/tlm_adapters/tlm_adapters.h tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/circular_buffer.h tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo.h tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_peek.h tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_put_get.h tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_resize.h tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_req_rsp_channels/tlm_put_get_imp.h tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_req_rsp_channels/tlm_req_rsp_channels.h tlm_core/tlm_1/tlm_req_rsp/tlm_ports/tlm_event_finder.h tlm_core/tlm_1/tlm_req_rsp/tlm_ports/tlm_nonblocking_port.h tlm_core/tlm_1/tlm_req_rsp/tlm_req_rsp.h tlm_core/tlm_2/tlm_2_interfaces/tlm_2_interfaces.h tlm_core/tlm_2/tlm_2_interfaces/tlm_dmi.h tlm_core/tlm_2/tlm_2_interfaces/tlm_fw_bw_ifs.h tlm_core/tlm_2/tlm_generic_payload/tlm_array.h tlm_core/tlm_2/tlm_generic_payload/tlm_endian_conv.h tlm_core/tlm_2/tlm_generic_payload/tlm_generic_payload.h tlm_core/tlm_2/tlm_generic_payload/tlm_gp.h tlm_core/tlm_2/tlm_generic_payload/tlm_helpers.h tlm_core/tlm_2/tlm_generic_payload/tlm_phase.h tlm_core/tlm_2/tlm_quantum/tlm_global_quantum.h tlm_core/tlm_2/tlm_quantum/tlm_quantum.h tlm_core/tlm_2/tlm_sockets/tlm_base_socket_if.h tlm_core/tlm_2/tlm_sockets/tlm_initiator_socket.h tlm_core/tlm_2/tlm_sockets/tlm_sockets.h tlm_core/tlm_2/tlm_sockets/tlm_target_socket.h tlm_core/tlm_2/tlm_version.h tlm_utils/convenience_socket_bases.h tlm_utils/instance_specific_extensions.h tlm_utils/instance_specific_extensions_int.h tlm_utils/multi_passthrough_initiator_socket.h tlm_utils/multi_passthrough_target_socket.h tlm_utils/multi_socket_bases.h tlm_utils/passthrough_target_socket.h tlm_utils/peq_with_cb_and_phase.h tlm_utils/peq_with_get.h tlm_utils/simple_initiator_socket.h tlm_utils/simple_target_socket.h tlm_utils/tlm_quantumkeeper.h # QuickThreads $<$: sysc/packages/qt/qt.c $<$: ${CMAKE_CURRENT_BINARY_DIR}/sysc/packages/qt/md/sparc.s> $<$:sysc/packages/qt/md/hppa.s> $<$:sysc/packages/qt/md/iX86_64.s> $<$:sysc/packages/qt/md/i386.s> $<$:sysc/packages/qt/md/aarch64.s> $<$: sysc/packages/qt/md/powerpc_mach.s sysc/packages/qt/md/powerpc.c> $<$: sysc/packages/qt/md/powerpc_sys5.s sysc/packages/qt/md/powerpc.c> sysc/packages/qt/md/aarch64.h sysc/packages/qt/md/axp.h sysc/packages/qt/md/hppa.h sysc/packages/qt/md/i386.h sysc/packages/qt/md/iX86_64.h sysc/packages/qt/md/ksr1.h sysc/packages/qt/md/m88k.h sysc/packages/qt/md/mips.h sysc/packages/qt/md/powerpc_mach.h sysc/packages/qt/md/powerpc_sys5.h sysc/packages/qt/md/sparc.h sysc/packages/qt/md/vax.h sysc/packages/qt/qt.h sysc/packages/qt/qtmd.h >) add_library (SystemC::systemc ALIAS systemc) target_compile_definitions ( systemc PUBLIC $<$:SC_DISABLE_VIRTUAL_BIND> $<$:WIN32> $<$,$,$>>: SC_WIN_DLL> PRIVATE SC_BUILD SC_INCLUDE_FX $<$:DEBUG_SYSTEMC> $<$:SC_DISABLE_ASYNC_UPDATES> $<$:SC_DISABLE_COPYRIGHT_MESSAGE> $<$:SC_DISABLE_VCD_SCOPES> $<$:SC_ENABLE_ASSERTIONS> $<$:SC_ENABLE_EARLY_MAXTIME_CREATION> $<$: SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS> $<$:SC_ENABLE_SIMULATION_PHASE_CALLBACKS> $<$: SC_ENABLE_SIMULATION_PHASE_CALLBACKS_TRACING> $<$:SC_USE_PTHREADS> $<$: SC_OVERRIDE_DEFAULT_STACK_SIZE=${OVERRIDE_DEFAULT_STACK_SIZE}> $<$,$>:_LIB>) target_compile_options( systemc PUBLIC $<$:/vmg /MP> PRIVATE $<$,$>: -Wall -Wextra -Wno-unused-parameter -Wno-unused-variable> $<$:/W3 /wd4244 /wd4267 /wd4996>) target_include_directories(systemc PUBLIC $ $) if (APPLE) # It's OK that _sc_main is an undefined symbol. set_target_properties (systemc PROPERTIES LINK_FLAGS -Wl,-U,_sc_main) endif (APPLE) target_link_libraries (systemc PUBLIC $<$:Threads::Threads>) set_target_properties (systemc PROPERTIES LINKER_LANGUAGE CXX VERSION ${SystemCLanguage_VERSION} SOVERSION ${SystemCLanguage_SOVERSION} INSTALL_NAME_DIR ${CMAKE_INSTALL_FULL_LIBDIR}) ############################################################################### # Install rules for SystemC library ############################################################################### install (TARGETS systemc EXPORT SystemCLanguageTargets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT lib) # Install the SystemC and TLM headers install (FILES systemc tlm DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT dev) install (DIRECTORY ./ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT dev FILES_MATCHING PATTERN "*.h") install (DIRECTORY ./ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT dev FILES_MATCHING PATTERN "*.hpp") systemc-2.3.3/src/tlm.h0000644000175000017500000000175313360325173014633 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ // kept for backwards compatibility #include "tlm" systemc-2.3.3/src/tlm_core/0000755000175000017500000000000013360325173015464 5ustar carstencarstensystemc-2.3.3/src/tlm_core/Makefile.am0000644000175000017500000001027313360325173017523 0ustar carstencarsten## **************************************************************************** ## ## Licensed to Accellera Systems Initiative Inc. (Accellera) under one or ## more contributor license agreements. See the NOTICE file distributed ## with this work for additional information regarding copyright ownership. ## Accellera licenses this file to you under the Apache License, Version 2.0 ## (the "License"); you may not use this file except in compliance with the ## License. You may obtain a copy of the License at ## ## http://www.apache.org/licenses/LICENSE-2.0 ## ## Unless required by applicable law or agreed to in writing, software ## distributed under the License is distributed on an "AS IS" BASIS, ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or ## implied. See the License for the specific language governing ## permissions and limitations under the License. ## ## **************************************************************************** ## ## src/tlm_core/Makefile.am -- ## Process this file with automake to produce a Makefile.in file. ## ## Original Author: Philipp A. Hartmann, OFFIS, 2013-05-17 ## ## **************************************************************************** ## ## MODIFICATION LOG - modifiers, enter your name, affiliation, date and ## changes you are making here. ## ## Name, Affiliation, Date: ## Description of Modification: ## ## **************************************************************************** include $(top_srcdir)/config/Make-rules.sysc H_FILES = \ tlm_2/tlm_version.h \ tlm_2/tlm_2_interfaces/tlm_2_interfaces.h \ tlm_2/tlm_2_interfaces/tlm_dmi.h \ tlm_2/tlm_2_interfaces/tlm_fw_bw_ifs.h \ \ tlm_2/tlm_generic_payload/tlm_array.h \ tlm_2/tlm_generic_payload/tlm_endian_conv.h \ tlm_2/tlm_generic_payload/tlm_generic_payload.h \ tlm_2/tlm_generic_payload/tlm_gp.h \ tlm_2/tlm_generic_payload/tlm_helpers.h \ tlm_2/tlm_generic_payload/tlm_phase.h \ \ tlm_2/tlm_quantum/tlm_global_quantum.h \ tlm_2/tlm_quantum/tlm_quantum.h \ \ tlm_2/tlm_sockets/tlm_base_socket_if.h \ tlm_2/tlm_sockets/tlm_initiator_socket.h \ tlm_2/tlm_sockets/tlm_sockets.h \ tlm_2/tlm_sockets/tlm_target_socket.h \ \ tlm_1/tlm_analysis/tlm_analysis.h \ tlm_1/tlm_analysis/tlm_analysis_fifo.h \ tlm_1/tlm_analysis/tlm_analysis_if.h \ tlm_1/tlm_analysis/tlm_analysis_port.h \ tlm_1/tlm_analysis/tlm_analysis_triple.h \ tlm_1/tlm_analysis/tlm_write_if.h \ \ tlm_1/tlm_req_rsp/tlm_req_rsp.h \ tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_core_ifs.h \ tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_fifo_ifs.h \ tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_master_slave_ifs.h \ tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_tag.h \ \ tlm_1/tlm_req_rsp/tlm_adapters/tlm_adapters.h \ \ tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/circular_buffer.h \ tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo.h \ tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_peek.h \ tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_put_get.h \ tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_resize.h \ tlm_1/tlm_req_rsp/tlm_channels/tlm_req_rsp_channels/tlm_put_get_imp.h \ tlm_1/tlm_req_rsp/tlm_channels/tlm_req_rsp_channels/tlm_req_rsp_channels.h \ \ tlm_1/tlm_req_rsp/tlm_ports/tlm_event_finder.h \ tlm_1/tlm_req_rsp/tlm_ports/tlm_nonblocking_port.h CXX_FILES = \ tlm_2/tlm_generic_payload/tlm_gp.cpp \ tlm_2/tlm_generic_payload/tlm_phase.cpp \ tlm_2/tlm_quantum/tlm_global_quantum.cpp EXTRA_DIST += \ tlm_1/README.txt \ tlm_2/README.txt INCDIRS = \ tlm_2/tlm_2_interfaces \ tlm_2/tlm_generic_payload \ tlm_2/tlm_quantum \ tlm_2/tlm_sockets \ tlm_2 \ tlm_1/tlm_analysis \ tlm_1/tlm_req_rsp/tlm_1_interfaces \ tlm_1/tlm_req_rsp/tlm_adapters \ tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo \ tlm_1/tlm_req_rsp/tlm_channels/tlm_req_rsp_channels \ tlm_1/tlm_req_rsp/tlm_channels \ tlm_1/tlm_req_rsp/tlm_ports \ tlm_1/tlm_req_rsp \ tlm_1 localincludedir = $(includedir)/tlm_core nobase_localinclude_HEADERS = $(H_FILES) noinst_LTLIBRARIES = libtlm_core.la libtlm_core_la_SOURCES = $(NO_H_FILES) $(CXX_FILES) uninstall-hook: test ! -d "$(localincludedir)" || ( set -e ; cd "$(localincludedir)"; \ for dir in $(INCDIRS) ; do test ! -d $$dir || rmdir $$dir ; done ; \ cd - ; rmdir "$(localincludedir)" ) systemc-2.3.3/src/tlm_core/tlm_2/0000755000175000017500000000000013360325173016501 5ustar carstencarstensystemc-2.3.3/src/tlm_core/tlm_2/README.txt0000644000175000017500000000635313360325173020206 0ustar carstencarstenTLM-2.0 interoperability layer header files =========================================== Dir: include/tlm_core/tlm_2/ SubDirs: tlm_2_interfaces/ tlm_generic_payload/ tlm_quantum/ tlm_sockets Files: README.txt tlm_version.h Comments ======== User code should only #include the tlm or tlm.h header file in the include/ directory and avoid including any of the include files in this directory directly. All objects defined in this file hierarchy are in the tlm namespace. tlm_version.h contains the definitions for the version string and integer values The header files are organizated, by subdirectory, as follows: tlm_2_interfaces/ ----------------- Contains the TLM-2.0 core interfaces Files: tlm_2_interfaces.h (includes the other header files in this directory ) tlm_fw_bw_ifs.h (defines the TLM 2.0 interface API's: tlm_fw_nonblocking_transport_if tlm_bw_nonblocking_transport_if tlm_blocking_transport_if tlm_fw_direct_mem_if tlm_bw_direct_mem_if tlm_transport_dbg_if the enumeration type tlm_sync_enum and the TLM 2.0 standard interfaces using the API's tlm_fw_transport_if tlm_bw_transport_if ) tlm_dmi.h (defines tlm_dmi) tlm_generic_payload/ -------------------- Contains the TLM-2.0 generic payload and associated classes and helper functions Files: tlm_generic_payload.h ( includes the other header files in this directory) tlm_gp.h (defines the TLM 2.0 generic payload classes: tlm_generic_payload tlm_extension tlm_extension_base tlm_mm_interface and the enumeration types tlm_command tlm_response_status ) tlm_array.h (defines array class used by the extention mechanism ) tlm_endian_conv.h (defines the implementation for the endianness helper functions: tlm_to_hostendian_generic() tlm_from_hostendian_generic() tlm_to_hostendian_word() tlm_from_hostendian_word() tlm_to_hostendian_aligned() tlm_from_hostendian_aligned() tlm_to_hostendian_single() tlm_from_hostendian_single() ) tlm_helpers.h (defines the helper functions to determine the hostendianness: get_host_endianness() host_has_little_endianness() has_host_endianness() and defines the enumeration type: tlm_endianness tlm_phase.h (defines tlm_phase as an extendable enum type) tlm_sockets/ ------------ Contains the standard TLM-2.0 initiator and target sockets (which are used as the base classes for the convenience sockets in tlm_utils) Files: tlm_sockets.h (includes the other header files in this directory) tlm_initiator_socket.h (defines the initiator sockets: tlm_initiator_socket_base tlm_initiator_socket_b tlm_initiator_socket tlm_target_socket.h (defines the target sockets: tlm_target_socket_base tlm_target_socket_b tlm_target_socket tlm_quantum/ ------------ This contains the global quantum. (The quantum keeper is in tlm_utils) Files: tlm_quantum.h ( includes the other header file in this directory ) tlm_global_quantum.h ( defines tlm_global_quantum ) systemc-2.3.3/src/tlm_core/tlm_2/tlm_quantum/0000755000175000017500000000000013360325173021047 5ustar carstencarstensystemc-2.3.3/src/tlm_core/tlm_2/tlm_quantum/tlm_global_quantum.cpp0000644000175000017500000000314313360325173025442 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ #include "tlm_core/tlm_2/tlm_quantum/tlm_global_quantum.h" #include "sysc/kernel/sc_simcontext.h" // sc_time_stamp namespace tlm { tlm_global_quantum::tlm_global_quantum() : m_global_quantum(sc_core::SC_ZERO_TIME) {} tlm_global_quantum& tlm_global_quantum::instance() { static tlm_global_quantum instance_; return instance_; } sc_core::sc_time tlm_global_quantum::compute_local_quantum() { if (m_global_quantum != sc_core::SC_ZERO_TIME) { const sc_core::sc_time current = sc_core::sc_time_stamp(); const sc_core::sc_time g_quant = m_global_quantum; return g_quant - (current % g_quant); } else { return sc_core::SC_ZERO_TIME; } } } // namespace tlm systemc-2.3.3/src/tlm_core/tlm_2/tlm_quantum/tlm_global_quantum.h0000644000175000017500000000477313360325173025121 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ #ifndef TLM_CORE_TLM2_TLM_GLOBAL_QUANTUM_H_INCLUDED_ #define TLM_CORE_TLM2_TLM_GLOBAL_QUANTUM_H_INCLUDED_ #include "sysc/kernel/sc_time.h" namespace tlm { // // tlm_global_quantum class // // The global quantum is the maximum time an initiator can run ahead of // SystemC time. All initiators should synchronize on timingpoints that // are multiples of the global quantum value. // // sc_set_time_resolution can only be called before the first // sc_time object is created. This means that after setting the // global quantum it will not be possible to call sc_set_time_resolution. // If sc_set_time_resolution must be called this must be done before // the global quantum is set. // class SC_API tlm_global_quantum { public: // // Returns a reference to the tlm_global_quantum singleton // static tlm_global_quantum& instance(); public: // // Setter/getter for the global quantum // void set(const sc_core::sc_time& t) { m_global_quantum = t; } const sc_core::sc_time& get() const { return m_global_quantum; } // // This function will calculate the maximum value for the next local // quantum for an initiator. All initiators should synchronize on // integer multiples of the global quantum value. The value for the // local quantum of an initiator can be smaller, but should never be // greater than the value returned by this method. // sc_core::sc_time compute_local_quantum(); protected: tlm_global_quantum(); protected: sc_core::sc_time m_global_quantum; }; } // namespace tlm #endif // TLM_CORE_TLM2_TLM_GLOBAL_QUANTUM_H_INCLUDED_ systemc-2.3.3/src/tlm_core/tlm_2/tlm_quantum/tlm_quantum.h0000644000175000017500000000220013360325173023560 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ #ifndef TLM_CORE_TLM2_TLM_QUANTUM_H_INCLUDED_ #define TLM_CORE_TLM2_TLM_QUANTUM_H_INCLUDED_ #include "tlm_core/tlm_2/tlm_quantum/tlm_global_quantum.h" #endif // TLM_CORE_TLM2_TLM_QUANTUM_H_INCLUDED_ systemc-2.3.3/src/tlm_core/tlm_2/tlm_version.h0000644000175000017500000001650613360325173021223 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /* --------------------------------------------------------------------------------------- @file tlm_version.h @brief TLM version header Original Author: Charles Wilson, XtremeEDA Corporation @description This header contains preprocessor and compiler symbols to allow for the determination of the TLM version information. This conforms to IEEE 1666-2005 section 8.5.5 - 8.5.7 . The following are provided: . preprocessor: TLM_VERSION_MAJOR numeric TLM_VERSION_MINOR numeric TLM_VERSION_PATCH numeric TLM_VERSION_ORIGINATOR string ([A-Z][a-z][0-9]_) TLM_VERSION_RELEASE_DATE ISO8601 date (YYYYMMDD) TLM_VERSION_PRERELEASE string ([A-Z][a-z][0-9]_) TLM_IS_PRERELEASE bool (1,0) TLM_VERSION string {2.0.0_DR3-TLMWG} TLM_COPYRIGHT string . compiler: tlm_version_major const unsigned int tlm_version_minor const unsigned int tlm_version_patch const unsigned int tlm_version_originator const std::string tlm_version_release_date const std::string tlm_version_prerelease const std::string tlm_is_prerelease const bool tlm_version const string tlm_copyright const string . accessors: inline const char* tlm_release (void) inline const char* tlm_version (void) inline const char* tlm_copyright (void) --------------------------------------------------------------------------------------- */ #ifndef __TLM_VERSION_H__ #define __TLM_VERSION_H__ namespace tlm { #define TLM_VERSION_MAJOR 2 ///< version major level ( numeric ) #define TLM_VERSION_MINOR 0 ///< version minor level ( numeric ) #define TLM_VERSION_PATCH 5 ///< version patch level ( numeric ) #define TLM_VERSION_ORIGINATOR "Accellera" ///< TLM creator string #define TLM_VERSION_SEPARATOR "." ///< version string separator #define TLM_IS_PRERELEASE 1 ///< pre-release flag ( 1 / 0 ) #if TLM_IS_PRERELEASE # define TLM_VERSION_PRERELEASE "pub_rev" ///< pre-release version string #else # define TLM_VERSION_PRERELEASE "" ///< pre-release version string #endif #define TLM_VERSION_RELEASE_YEAR "2018" ///< release year ( YYYY ) #define TLM_VERSION_RELEASE_MONTH "09" ///< release month ( MM ) #define TLM_VERSION_RELEASE_DAY "04" ///< release day ( DD ) #define TLM_COPYRIGHT \ "Copyright (c) 1996-" TLM_VERSION_RELEASE_YEAR " by all Contributors\n" \ "ALL RIGHTS RESERVED" /************************** do not modify below this line *******************************/ /******************************* preprocessor symbols ***********************************/ #define TLM_VERSION_RELEASE_DATE TLM_VERSION_RELEASE_YEAR \ TLM_VERSION_RELEASE_MONTH \ TLM_VERSION_RELEASE_DAY #define TLM_VERSION_STR(x) TLM_VERSION_STR_HELPER(x) #define TLM_VERSION_STR_HELPER(x) #x #define TLM_VERSION_STRING_MAJOR TLM_VERSION_STR(TLM_VERSION_MAJOR) #define TLM_VERSION_STRING_MINOR TLM_VERSION_STR(TLM_VERSION_MINOR) #define TLM_VERSION_STRING_PATCH TLM_VERSION_STR(TLM_VERSION_PATCH) #define TLM_VERSION_STRING_MMP TLM_VERSION_STRING_MAJOR TLM_VERSION_SEPARATOR \ TLM_VERSION_STRING_MINOR TLM_VERSION_SEPARATOR \ TLM_VERSION_STRING_PATCH #define TLM_VERSION_STRING_PRE_START "_" #define TLM_VERSION_STRING_PRE_END "-" #if ( TLM_IS_PRERELEASE == 1 ) #define TLM_VERSION_STRING_PRERELEASE TLM_VERSION_PRERELEASE #define TLM_VERSION_STRING_RELEASE_DATE "" #else /* TLM_IS_PRERELEASE == 1 */ #define TLM_VERSION_STRING_PRERELEASE "" #define TLM_VERSION_STRING_RELEASE_DATE TLM_VERSION_RELEASE_DATE #endif /* TLM_IS_PRERELEASE == 1 */ #define TLM_VERSION_STRING TLM_VERSION_STRING_MMP \ TLM_VERSION_STRING_PRE_START \ TLM_VERSION_STRING_PRERELEASE \ TLM_VERSION_STRING_PRE_END \ TLM_VERSION_ORIGINATOR #define TLM_VERSION_STRING_2 "TLM " \ TLM_VERSION_STRING_MMP \ " --- " \ TLM_VERSION_RELEASE_YEAR \ "-" \ TLM_VERSION_RELEASE_MONTH \ "-" \ TLM_VERSION_RELEASE_DAY #define TLM_VERSION TLM_VERSION_STRING /********************************* compiler symbols **************************************/ const unsigned int tlm_version_major ( TLM_VERSION_MAJOR ); const unsigned int tlm_version_minor ( TLM_VERSION_MINOR ); const unsigned int tlm_version_patch ( TLM_VERSION_PATCH ); const bool tlm_is_prerelease ( TLM_IS_PRERELEASE ); const std::string tlm_version_string ( TLM_VERSION_STRING ); const std::string tlm_version_originator ( TLM_VERSION_ORIGINATOR ); const std::string tlm_version_prerelease ( TLM_VERSION_PRERELEASE ); const std::string tlm_version_release_date ( TLM_VERSION_STRING_RELEASE_DATE ); const std::string tlm_copyright_string ( TLM_COPYRIGHT ); const std::string tlm_version_string_2 ( TLM_VERSION_STRING_2 ); inline const char* tlm_release ( void ) { return tlm_version_string.c_str (); } inline const char* tlm_version ( void ) { return tlm_version_string_2.c_str (); } inline const char* tlm_copyright ( void ) { return tlm_copyright_string.c_str (); } } // namespace tlm #endif /* __TLM_VERSION_H__ */ systemc-2.3.3/src/tlm_core/tlm_2/tlm_2_interfaces/0000755000175000017500000000000013360325173021721 5ustar carstencarstensystemc-2.3.3/src/tlm_core/tlm_2/tlm_2_interfaces/tlm_dmi.h0000644000175000017500000001172113360325173023521 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ #ifndef __TLM_DMI_H__ #define __TLM_DMI_H__ #include namespace tlm { class tlm_dmi { public: // Enum for indicating the access granted to the initiator. // The initiator uses gp.m_command to indicate it intention (read/write) // The target is allowed to promote DMI_ACCESS_READ or DMI_ACCESS_WRITE // requests to dmi_access_read_write. enum dmi_access_e { DMI_ACCESS_NONE = 0x00 // no access , DMI_ACCESS_READ = 0x01 // read access , DMI_ACCESS_WRITE = 0x02 // write access , DMI_ACCESS_READ_WRITE = DMI_ACCESS_READ | DMI_ACCESS_WRITE // read/write access }; tlm_dmi (void) { init(); } void init (void) { m_dmi_ptr = 0x0; m_dmi_start_address = 0x0; m_dmi_end_address = (sc_dt::uint64)(-1); m_dmi_access = DMI_ACCESS_NONE; m_dmi_read_latency = sc_core::SC_ZERO_TIME; m_dmi_write_latency = sc_core::SC_ZERO_TIME; } unsigned char* get_dmi_ptr (void) const {return m_dmi_ptr;} sc_dt::uint64 get_start_address (void) const {return m_dmi_start_address;} sc_dt::uint64 get_end_address (void) const {return m_dmi_end_address;} sc_core::sc_time get_read_latency (void) const {return m_dmi_read_latency;} sc_core::sc_time get_write_latency (void) const {return m_dmi_write_latency;} dmi_access_e get_granted_access (void) const {return m_dmi_access;} bool is_none_allowed (void) const {return m_dmi_access == DMI_ACCESS_NONE;} bool is_read_allowed (void) const {return (m_dmi_access & DMI_ACCESS_READ) == DMI_ACCESS_READ;} bool is_write_allowed (void) const {return (m_dmi_access & DMI_ACCESS_WRITE) == DMI_ACCESS_WRITE;} bool is_read_write_allowed (void) const {return (m_dmi_access & DMI_ACCESS_READ_WRITE) == DMI_ACCESS_READ_WRITE;} void set_dmi_ptr (unsigned char* p) {m_dmi_ptr = p;} void set_start_address (sc_dt::uint64 addr) {m_dmi_start_address = addr;} void set_end_address (sc_dt::uint64 addr) {m_dmi_end_address = addr;} void set_read_latency (sc_core::sc_time t) {m_dmi_read_latency = t;} void set_write_latency (sc_core::sc_time t) {m_dmi_write_latency = t;} void set_granted_access (dmi_access_e a) {m_dmi_access = a;} void allow_none (void) {m_dmi_access = DMI_ACCESS_NONE;} void allow_read (void) {m_dmi_access = DMI_ACCESS_READ;} void allow_write (void) {m_dmi_access = DMI_ACCESS_WRITE;} void allow_read_write (void) {m_dmi_access = DMI_ACCESS_READ_WRITE;} private: // If the forward call is successful, the target returns the dmi_ptr, // which must point to the data element corresponding to the // dmi_start_address. The data is organized as a byte array with the // endianness of the target (endianness member of the tlm_dmi struct). unsigned char* m_dmi_ptr; // The absolute start and end addresses of the DMI region. If the decoder // logic in the interconnect changes the address field e.g. by masking, the // interconnect is responsible to transform the relative address back to an // absolute address again. sc_dt::uint64 m_dmi_start_address; sc_dt::uint64 m_dmi_end_address; // Granted access dmi_access_e m_dmi_access; // These members define the latency of read/write transactions. The // initiator must initialize these members to zero before requesting a // dmi pointer, because both the interconnect as well as the target can // add to the total transaction latency. // Depending on the 'type' attribute only one, or both of these attributes // will be valid. sc_core::sc_time m_dmi_read_latency; sc_core::sc_time m_dmi_write_latency; }; } // namespace tlm #endif /* TLM_DMI_HEADER */ systemc-2.3.3/src/tlm_core/tlm_2/tlm_2_interfaces/tlm_fw_bw_ifs.h0000644000175000017500000002450713360325173024723 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ #ifndef __TLM_FW_BW_IFS_H__ #define __TLM_FW_BW_IFS_H__ #include #include "tlm_core/tlm_2/tlm_generic_payload/tlm_generic_payload.h" #include "tlm_core/tlm_2/tlm_2_interfaces/tlm_dmi.h" namespace tlm { enum tlm_sync_enum { TLM_ACCEPTED, TLM_UPDATED, TLM_COMPLETED }; //////////////////////////////////////////////////////////////////////////// // Basic interfaces //////////////////////////////////////////////////////////////////////////// template class tlm_fw_nonblocking_transport_if : public virtual sc_core::sc_interface { public: virtual tlm_sync_enum nb_transport_fw(TRANS& trans, PHASE& phase, sc_core::sc_time& t) = 0; }; template class tlm_bw_nonblocking_transport_if : public virtual sc_core::sc_interface { public: virtual tlm_sync_enum nb_transport_bw(TRANS& trans, PHASE& phase, sc_core::sc_time& t) = 0; }; template class tlm_blocking_transport_if : public virtual sc_core::sc_interface { public: virtual void b_transport(TRANS& trans, sc_core::sc_time& t) = 0; }; ////////////////////////////////////////////////////////////////////////// // DMI interfaces for getting and invalidating DMI pointers: ////////////////////////////////////////////////////////////////////////// // The semantics of the forward interface are as follows: // // - An initiator that wants to get direct access to a target's memory region // can call the get_direct_mem_ptr method with the 'trans' parameter set to // the address that it wants to gain access to. It sets the trans.m_command // to specify if the initiator intended use (read or write) // to the target's DMI region. The initiator is responsible for calling the // method with a freshly initialized tlm_dmi object either by using a newly // constructed object, or by calling an existing object's init() method. // - Although a reference to a complete 'TRANS' type is passed to the get_ // direct_mem_ptr call, only the address command, and extension fields are of // interest in most cases. // - Read and write ranges are not necessarily identical. If they are, a target // can specify that the range is valid for all accesses with the tlm_data // m_type attribute in the. // - The interconnect, if any, needs to decode the address and forward the // call to the corresponding target. It needs to handle the address exactly // as the target would expect on a transaction call, e.g. mask the address // according to the target's address width. // - If the target supports DMI access for the given address, it sets the // data fields in the DMI struct and returns true. // - If a target does not support DMI access it needs to return false. // The target can either set the correct address range in the DMI struct // to indicate the memory region where DMI is disallowed, or it can specify // the complete address range if it doesn't know it's memory range. In this // case the interconnect is responsible for clipping the address range to // the correct range that the target serves. // - The interconnect must always translate the addresses to the initiator's // address space. This must be the inverse operation of what the // interconnect needed to do when forwarding the call. In case the // component wants to change any member of the tlm_dmi object, e.g. for // its own latency to the target's latency, it must only do so *after* the // target has been called. The target is always allowed to overwrite all // values in the tlm_dmi object. // - In case the slave returned with an invalid region the bus/interconnect // must fill in the complete address region for the particular slave in the // DMI data structure. // // DMI hint optimization: // // Initiators may use the DMI hint in the tlm_generic_payload to avoid // unnecessary DMI attempts. The recommended sequence of interface // method calls would be: // // - The initiator first tries to check if it has a valid DMI region for the // address that it wants to access next. // - If not, it performs a normal transaction. // - If the DMI hint in this transaction is true, the initiator can try and // get the DMI region. // // Note that the DMI hint optimization is completely optional and every // initiator model is free to ignore the DMI hint. However, a target is // required to set the DMI hint to true if a DMI request on the given address // with the given transaction type (read or write) would have succeeded. template class tlm_fw_direct_mem_if : public virtual sc_core::sc_interface { public: virtual bool get_direct_mem_ptr(TRANS& trans, tlm_dmi& dmi_data) = 0; }; // The semantics of the backwards call is as follows: // // - An interconnect component or a target is required to invalidate all // affected DMI regions whenever any change in the regions take place. // The exact rule is that a component must invalidate all those DMI regions // that it already reported, if it would answer the same DMI request // with any member of the tlm_dmi data structure set differently. // - An interconnect component must forward the invalidate_direct_mem_ptr call // to all initiators that could potentially have a DMI pointer to the region // specified in the method arguments. A safe implementation is to call // every attached initiator. // - An interconnect component must transform the address region of an // incoming invalidate_direct_mem_ptr to the corresponding address space // for the initiators. Basically, this is the same address transformation // that the interconnect does on the DMI ranges on the forward direction. // - Each initiator must check if it has a pointer to the given region and // throw this away. It is recommended that the initiator throws away all DMI // regions that have any overlap with the given regions, but this is not a // hard requirement. // // - A full DMI pointer invalidation, e.g. for a bus remap can be signaled // by setting the range: 0x0 - 0xffffffffffffffffull = (sc_dt::uint64)-1 // - An initiator must throw away all DMI pointers in this case. // // - Under no circumstances a model is allowed to call the get_direct_mem_ptr // from within the invalidate_direct_mem_ptr method, directly or indirectly. // class tlm_bw_direct_mem_if : public virtual sc_core::sc_interface { public: virtual void invalidate_direct_mem_ptr(sc_dt::uint64 start_range, sc_dt::uint64 end_range) = 0; }; ///////////////////////////////////////////////////////////////////// // debug interface for memory access ///////////////////////////////////////////////////////////////////// // // This interface can be used to gain access to a targets memory or registers // in a non-intrusive manner. No side effects, waits or event notifications // must happen in the course of the method. // // Semantics: // - The initiator calls the transport_dbg method with transaction 'trans' as // argument. The commonly used parts of trans for debug are: // . address: The start address that it wants to peek or poke. // . length: The number of bytes that it requests to read or write. // . command: Indicates a read or write access. // . data: A pointer to the initiator-allocated data buffer, which must // be at least num_bytes large. The data is always organized in // the endianness of the machine. // . extensions: Any extension that could affect the transaction. // - The interconnect, if any, will decode the address and forward the call to // the appropriate target. // - The target must return the number of successfully transmitted bytes, where // this number must be <= num_bytes. Thus, a target can safely return 0 if it // does not support debug transactions. // template class tlm_transport_dbg_if : public virtual sc_core::sc_interface { public: // The return value of defines the number of bytes successfully // transferred. virtual unsigned int transport_dbg(TRANS& trans) = 0; }; //////////////////////////////////////////////////////////////////////////// // Combined interfaces //////////////////////////////////////////////////////////////////////////// struct tlm_base_protocol_types { typedef tlm_generic_payload tlm_payload_type; typedef tlm_phase tlm_phase_type; }; // The forward interface: template class tlm_fw_transport_if : public virtual tlm_fw_nonblocking_transport_if , public virtual tlm_blocking_transport_if , public virtual tlm_fw_direct_mem_if , public virtual tlm_transport_dbg_if {}; // The backward interface: template class tlm_bw_transport_if : public virtual tlm_bw_nonblocking_transport_if , public virtual tlm_bw_direct_mem_if {}; } // namespace tlm #endif /* __TLM_FW_BW_IFS_H__ */ systemc-2.3.3/src/tlm_core/tlm_2/tlm_2_interfaces/tlm_2_interfaces.h0000644000175000017500000000215713360325173025317 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ #ifndef __TLM_2_INTERFACES_H__ #define __TLM_2_INTERFACES_H__ #include "tlm_core/tlm_2/tlm_2_interfaces/tlm_dmi.h" #include "tlm_core/tlm_2/tlm_2_interfaces/tlm_fw_bw_ifs.h" #endif systemc-2.3.3/src/tlm_core/tlm_2/tlm_sockets/0000755000175000017500000000000013360325173021030 5ustar carstencarstensystemc-2.3.3/src/tlm_core/tlm_2/tlm_sockets/tlm_base_socket_if.h0000644000175000017500000000376713360325173025032 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ #ifndef TLM_CORE_TLM_BASE_SOCKET_IF_H_INCLUDED_ #define TLM_CORE_TLM_BASE_SOCKET_IF_H_INCLUDED_ #include "sysc/utils/sc_typeindex.h" namespace tlm { enum tlm_socket_category { TLM_UNKNOWN_SOCKET = 0, TLM_INITIATOR_SOCKET = 0x1, TLM_TARGET_SOCKET = 0x2, TLM_MULTI_SOCKET = 0x10, TLM_MULTI_INITIATOR_SOCKET = TLM_INITIATOR_SOCKET | TLM_MULTI_SOCKET, TLM_MULTI_TARGET_SOCKET = TLM_TARGET_SOCKET | TLM_MULTI_SOCKET }; class tlm_base_socket_if { public: virtual sc_core::sc_port_base & get_port_base() = 0; virtual sc_core::sc_port_base const & get_port_base() const = 0; virtual sc_core::sc_export_base & get_export_base() = 0; virtual sc_core::sc_export_base const & get_export_base() const = 0; virtual unsigned int get_bus_width() const = 0; virtual sc_core::sc_type_index get_protocol_types() const = 0; virtual tlm_socket_category get_socket_category() const = 0; protected: virtual ~tlm_base_socket_if() {} }; } // namespace tlm #endif // TLM_CORE_TLM_BASE_SOCKET_IF_H_INCLUDED_ systemc-2.3.3/src/tlm_core/tlm_2/tlm_sockets/tlm_target_socket.h0000644000175000017500000001633713360325173024725 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ #ifndef TLM_CORE_TLM_TARGET_SOCKET_H_INCLUDED_ #define TLM_CORE_TLM_TARGET_SOCKET_H_INCLUDED_ #include "tlm_core/tlm_2/tlm_sockets/tlm_base_socket_if.h" #include "tlm_core/tlm_2/tlm_2_interfaces/tlm_fw_bw_ifs.h" namespace tlm { template , typename BW_IF = tlm_bw_transport_if<> > class tlm_base_target_socket_b { public: virtual ~tlm_base_target_socket_b() {} virtual sc_core::sc_port_b & get_base_port() = 0; virtual sc_core::sc_export & get_base_export() = 0; virtual FW_IF & get_base_interface() = 0; }; template class tlm_base_initiator_socket_b; template class tlm_base_initiator_socket; template , typename BW_IF = tlm_bw_transport_if<>, int N = 1, sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND> class tlm_base_target_socket : public tlm_base_socket_if, public tlm_base_target_socket_b, public sc_core::sc_export { public: typedef FW_IF fw_interface_type; typedef BW_IF bw_interface_type; typedef sc_core::sc_port port_type; typedef sc_core::sc_export export_type; typedef tlm_base_initiator_socket_b base_initiator_socket_type; typedef tlm_base_target_socket_b base_type; template friend class tlm_base_initiator_socket; public: tlm_base_target_socket() : export_type(sc_core::sc_gen_unique_name("tlm_base_target_socket")) , m_port(sc_core::sc_gen_unique_name("tlm_base_target_socket_port")) { } explicit tlm_base_target_socket(const char* name) : export_type(name) , m_port(sc_core::sc_gen_unique_name((std::string(name) + "_port").c_str())) { } virtual const char* kind() const { return "tlm_base_target_socket"; } // // Bind target socket to initiator socket // - Binds the port of the initiator socket to the export of the target // socket // - Binds the port of the target socket to the export of the initiator // socket // virtual void bind(base_initiator_socket_type& s) { // initiator.port -> target.export (s.get_base_port())(get_base_interface()); // target.port -> initiator.export get_base_port()(s.get_base_interface()); } void operator() (base_initiator_socket_type& s) { bind(s); } // // Bind target socket to target socket (hierarchical bind) // - Binds both the export and the port // virtual void bind(base_type& s) { // export (get_base_export())(s.get_base_export()); // port (s.get_base_port())(get_base_port()); } void operator() (base_type& s) { bind(s); } // // Bind interface to socket // - Binds the interface to the export // virtual void bind(fw_interface_type& ifs) { export_type* exp = &get_base_export(); if( this == exp ) { export_type::bind( ifs ); // non-virtual function call } else { exp->bind( ifs ); } } void operator() (fw_interface_type& s) { bind(s); } // // Forward to 'size()' of port class // int size() const { return m_port.size(); } // // Forward to 'operator->()' of port class // bw_interface_type* operator->() { return m_port.operator->(); } // // Forward to 'operator[]()' of port class // bw_interface_type* operator[](int i) { return m_port.operator[](i); } // Implementation of tlm_base_socket_if functions virtual sc_core::sc_port_base & get_port_base() { return m_port; } virtual sc_core::sc_port_base const & get_port_base() const { return m_port; } virtual sc_core::sc_export_base & get_export_base() { return *this; } virtual sc_core::sc_export_base const & get_export_base() const { return *this; } virtual unsigned int get_bus_width() const { return BUSWIDTH; } virtual tlm_socket_category get_socket_category() const { return TLM_TARGET_SOCKET; } // Implementation of tlm_base_target_socket_b functions virtual sc_core::sc_port_b & get_base_port() { return m_port; } virtual sc_core::sc_port_b const & get_base_port() const { return m_port; } virtual FW_IF & get_base_interface() { return *this; } virtual FW_IF const & get_base_interface() const { return *this; } virtual sc_core::sc_export & get_base_export() { return *this; } virtual sc_core::sc_export const & get_base_export() const { return *this; } protected: port_type m_port; }; // // Convenience blocking and non-blocking socket classes // template class tlm_target_socket : public tlm_base_target_socket , tlm_bw_transport_if, N, POL> { public: tlm_target_socket() : tlm_base_target_socket, tlm_bw_transport_if, N, POL>() { } explicit tlm_target_socket(const char* name) : tlm_base_target_socket, tlm_bw_transport_if, N, POL>(name) { } virtual const char* kind() const { return "tlm_target_socket"; } virtual sc_core::sc_type_index get_protocol_types() const { return typeid(TYPES); } }; } // namespace tlm #endif // TLM_CORE_TLM_TARGET_SOCKET_H_INCLUDED_ systemc-2.3.3/src/tlm_core/tlm_2/tlm_sockets/tlm_sockets.h0000644000175000017500000000220313360325173023525 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ #ifndef __TLM_SOCKETS_H__ #define __TLM_SOCKETS_H__ #include "tlm_core/tlm_2/tlm_sockets/tlm_initiator_socket.h" #include "tlm_core/tlm_2/tlm_sockets/tlm_target_socket.h" #endif /* __TLM_SOCKETS_H__ */ systemc-2.3.3/src/tlm_core/tlm_2/tlm_sockets/tlm_initiator_socket.h0000644000175000017500000001666113360325173025441 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ #ifndef TLM_CORE_TLM_INITIATOR_SOCKET_H_INCLUDED_ #define TLM_CORE_TLM_INITIATOR_SOCKET_H_INCLUDED_ #include "tlm_core/tlm_2/tlm_sockets/tlm_base_socket_if.h" #include "tlm_core/tlm_2/tlm_2_interfaces/tlm_fw_bw_ifs.h" #if defined(__clang__) || \ (defined(__GNUC__) && ((__GNUC__ * 1000 + __GNUC_MINOR__) >= 4006)) // ignore warning about deliberately hidden "bind()" overloads #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Woverloaded-virtual" #endif namespace tlm { template , typename BW_IF = tlm_bw_transport_if<> > class tlm_base_initiator_socket_b { public: virtual ~tlm_base_initiator_socket_b() {} virtual sc_core::sc_port_b & get_base_port() = 0; virtual sc_core::sc_port_b const & get_base_port() const = 0; virtual BW_IF & get_base_interface() = 0; virtual BW_IF const & get_base_interface() const = 0; virtual sc_core::sc_export & get_base_export() = 0; virtual sc_core::sc_export const & get_base_export() const = 0; }; template class tlm_base_target_socket_b; template class tlm_base_target_socket; template , typename BW_IF = tlm_bw_transport_if<>, int N = 1, sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND> class tlm_base_initiator_socket : public tlm_base_socket_if, public tlm_base_initiator_socket_b, public sc_core::sc_port { public: typedef FW_IF fw_interface_type; typedef BW_IF bw_interface_type; typedef sc_core::sc_port port_type; typedef sc_core::sc_export export_type; typedef tlm_base_target_socket_b base_target_socket_type; typedef tlm_base_initiator_socket_b base_type; template friend class tlm_base_target_socket; public: tlm_base_initiator_socket() : port_type(sc_core::sc_gen_unique_name("tlm_base_initiator_socket")) , m_export(sc_core::sc_gen_unique_name("tlm_base_initiator_socket_export")) { } explicit tlm_base_initiator_socket(const char* name) : port_type(name) , m_export(sc_core::sc_gen_unique_name((std::string(name) + "_export").c_str())) { } virtual const char* kind() const { return "tlm_base_initiator_socket"; } // // Bind initiator socket to target socket // - Binds the port of the initiator socket to the export of the target // socket // - Binds the port of the target socket to the export of the initiator // socket // virtual void bind(base_target_socket_type& s) { // initiator.port -> target.export (get_base_port())(s.get_base_interface()); // target.port -> initiator.export (s.get_base_port())(get_base_interface()); } void operator() (base_target_socket_type& s) { bind(s); } // // Bind initiator socket to initiator socket (hierarchical bind) // - Binds both the export and the port // virtual void bind(base_type& s) { // port (get_base_port())(s.get_base_port()); // export (s.get_base_export())(get_base_export()); } void operator() (base_type& s) { bind(s); } // // Bind interface to socket // - Binds the interface to the export of this socket // virtual void bind(bw_interface_type& ifs) { (get_base_export())(ifs); } void operator() (bw_interface_type& s) { bind(s); } // Implementation of tlm_base_socket_if functions virtual sc_core::sc_port_base & get_port_base() { return *this; } virtual sc_core::sc_port_base const & get_port_base() const { return *this; } virtual sc_core::sc_export_base & get_export_base() { return m_export; } virtual sc_core::sc_export_base const & get_export_base() const { return m_export; } virtual unsigned int get_bus_width() const { return BUSWIDTH; } virtual tlm_socket_category get_socket_category() const { return TLM_INITIATOR_SOCKET; } // Implementation of tlm_base_target_socket_b functions virtual sc_core::sc_port_b & get_base_port() { return *this; } virtual sc_core::sc_port_b const & get_base_port() const { return *this; } virtual BW_IF & get_base_interface() { return m_export; } virtual BW_IF const & get_base_interface() const { return m_export; } virtual sc_core::sc_export & get_base_export() { return m_export; } virtual sc_core::sc_export const & get_base_export() const { return m_export; } protected: export_type m_export; }; // // Convenience socket classes // template class tlm_initiator_socket : public tlm_base_initiator_socket, tlm_bw_transport_if, N, POL> { public: tlm_initiator_socket() : tlm_base_initiator_socket, tlm_bw_transport_if, N, POL>() { } explicit tlm_initiator_socket(const char* name) : tlm_base_initiator_socket, tlm_bw_transport_if, N, POL>(name) { } virtual const char* kind() const { return "tlm_initiator_socket"; } virtual sc_core::sc_type_index get_protocol_types() const { return typeid(TYPES); } }; } // namespace tlm #if defined(__clang__) || \ (defined(__GNUC__) && ((__GNUC__ * 1000 + __GNUC_MINOR__) >= 4006)) #pragma GCC diagnostic pop #endif #endif // TLM_CORE_TLM_INITIATOR_SOCKET_H_INCLUDED_ systemc-2.3.3/src/tlm_core/tlm_2/tlm_generic_payload/0000755000175000017500000000000013360325173022502 5ustar carstencarstensystemc-2.3.3/src/tlm_core/tlm_2/tlm_generic_payload/tlm_array.h0000644000175000017500000000762613360325173024660 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ #ifndef TLM_CORE_TLM2_TLM_ARRAY_H_INCLUDED_ #define TLM_CORE_TLM2_TLM_ARRAY_H_INCLUDED_ #include #if defined(_MSC_VER) && !defined(SC_WIN_DLL_WARN) #pragma warning(push) #pragma warning(disable: 4251) // DLL import for std::string,vector #endif namespace tlm { // // To the LRM writer: the below class is an artifact of the tlm_generic_payload // implementation and not part of the core TLM standard // // This implements a lean and fast array class that supports array expansion on // request. The class is primarily used in the tlm_generic_payload class for // storing the pointers to the extensions. // // Individual array elements can be accessed through the [] operators, and the // array length is returned by the size() method. // // The size can be dynamically expanded using the expand(uint) method. There // is no shrinking mechanism implemented, because the extension mechanism // does not require this feature. Bear in mind that calling the expand method // may invalidate all direct pointers into the array. //the tlm_array shall always be used with T=tlm_extension_base* template class tlm_array : private std::vector { typedef std::vector base_type; typedef typename base_type::size_type size_type; public: // constructor: tlm_array(size_type size = 0) : base_type(size) , m_entries() { //m_entries.reserve(size); // optional } // copy constructor: // tlm_array(const tlm_array& orig) = default; // destructor: // ~tlm_array() = default; // operators for dereferencing: using base_type::operator[]; // array size: using base_type::size; // expand the array if needed: void expand(size_type new_size) { if (new_size > size()) { base_type::resize(new_size); //m_entries.reserve(new_size); // optional } } static const char* const kind_string; const char* kind() const { return kind_string; } //this function shall get a pointer to a array slot // it stores this slot in a cache of active slots void insert_in_cache(T* p) { //sc_assert( (p-&(*this)[0]) < size() ); m_entries.push_back( p-&(*this)[0] ); } //this functions clears all active slots of the array void free_entire_cache() { while(m_entries.size()) { if ((*this)[m_entries.back()]) //we make sure no one cleared the slot manually (*this)[m_entries.back()]->free();//...and then we call free on the content of the slot (*this)[m_entries.back()]=0; //afterwards we set the slot to NULL m_entries.pop_back(); } } protected: std::vector m_entries; }; template const char* const tlm_array::kind_string = "tlm_array"; #if defined(_MSC_VER) && !defined(SC_WIN_DLL_WARN) #pragma warning(pop) #endif } // namespace tlm #endif /* TLM_CORE_TLM2_TLM_ARRAY_H_INCLUDED_ */ systemc-2.3.3/src/tlm_core/tlm_2/tlm_generic_payload/tlm_phase.h0000644000175000017500000000547313360325173024640 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ #ifndef TLM_CORE_TLM2_TLM_PHASE_H_INCLUDED_ #define TLM_CORE_TLM2_TLM_PHASE_H_INCLUDED_ #include #include #include #include #include "sysc/kernel/sc_cmnhdr.h" // SC_API #include "sysc/kernel/sc_macros.h" // SC_CONCAT_HELPER_, SC_STRINGIFY_HELPER_ namespace tlm { enum SC_API tlm_phase_enum { UNINITIALIZED_PHASE=0, BEGIN_REQ=1, END_REQ, BEGIN_RESP, END_RESP }; class SC_API tlm_phase { public: tlm_phase(); tlm_phase(unsigned int id); // TODO: should be dropped tlm_phase(tlm_phase_enum standard); tlm_phase& operator=(tlm_phase_enum standard); operator unsigned int() const { return m_id; } const char* get_name() const; protected: // register extended phase tlm_phase( const std::type_info & type, const char* name ); private: unsigned int m_id; }; inline tlm_phase::tlm_phase() : m_id( UNINITIALIZED_PHASE ) {} inline tlm_phase::tlm_phase( tlm_phase_enum standard ) : m_id( standard ) {} inline tlm_phase& tlm_phase::operator=( tlm_phase_enum standard ) { m_id = standard; return *this; } inline std::ostream& operator<<(std::ostream& s, const tlm_phase& p) { s << p.get_name(); return s; } #define TLM_DECLARE_EXTENDED_PHASE(name_arg) \ static class SC_CONCAT_HELPER_(tlm_phase_, name_arg) \ : public ::tlm::tlm_phase \ { \ typedef SC_CONCAT_HELPER_(tlm_phase_, name_arg) this_type; \ public: \ SC_CONCAT_HELPER_(tlm_phase_, name_arg)() /* register extended phase */ \ : ::tlm::tlm_phase( typeid(*this), SC_STRINGIFY_HELPER_(name_arg) ) \ {} \ \ static const this_type& get_phase() /* needed only for IEEE 1666-2011 */ \ { static this_type this_; return this_; } \ } \ const name_arg // for backwards-compatibility #define DECLARE_EXTENDED_PHASE( NameArg ) \ TLM_DECLARE_EXTENDED_PHASE( NameArg ) } // namespace tlm #endif /* TLM_CORE_TLM2_TLM_PHASE_H_INCLUDED_ */ // Taf! systemc-2.3.3/src/tlm_core/tlm_2/tlm_generic_payload/tlm_gp.h0000644000175000017500000004271313360325173024144 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ // 12-Jan-2009 John Aynsley Bug fix. has_mm() and get_ref_count() should both be const // 23-Mar-2009 John Aynsley Add method update_original_from() // 20-Apr-2009 John Aynsley Bug fix for 64-bit machines: unsigned long int -> unsigned int // 5-May-2011 JA and Philipp Hartmann Add tlm_gp_option, set_gp_option, get_gp_option // 11-May-2011 John Aynsley Add run-time check to release() #ifndef TLM_CORE_TLM2_TLM_GP_H_INCLUDED_ #define TLM_CORE_TLM2_TLM_GP_H_INCLUDED_ #include "sysc/kernel/sc_cmnhdr.h" // SC_API #include "sysc/utils/sc_report.h" // sc_assert #include "sysc/datatypes/int/sc_nbdefs.h" // sc_dt::uint64 #include "tlm_core/tlm_2/tlm_generic_payload/tlm_array.h" #include // std::type_info namespace tlm { class tlm_generic_payload; class tlm_mm_interface { public: virtual void free(tlm_generic_payload*) = 0; virtual ~tlm_mm_interface() {} }; //--------------------------------------------------------------------------- // Classes and helpers for the extension mechanism //--------------------------------------------------------------------------- // Helper function: SC_API unsigned int max_num_extensions(); // This class can be used for storing pointers to the extension classes, used // in tlm_generic_payload: class SC_API tlm_extension_base { public: virtual tlm_extension_base* clone() const = 0; virtual void free() { delete this; } virtual void copy_from(tlm_extension_base const &) = 0; protected: virtual ~tlm_extension_base() {} static unsigned int register_extension(const std::type_info&); }; // Base class for all extension classes, derive your extension class in // the following way: // class my_extension : public tlm_extension { ... // This triggers proper extension registration during C++ static // contruction time. my_extension::ID will hold the unique index in the // tlm_generic_payload::m_extensions array. template class tlm_extension : public tlm_extension_base { public: virtual tlm_extension_base* clone() const = 0; virtual void copy_from(tlm_extension_base const &ext) = 0; virtual ~tlm_extension() {} const static unsigned int ID; }; template const unsigned int tlm_extension::ID = tlm_extension_base::register_extension(typeid(T)); //--------------------------------------------------------------------------- // enumeration types //--------------------------------------------------------------------------- enum tlm_command { TLM_READ_COMMAND, TLM_WRITE_COMMAND, TLM_IGNORE_COMMAND }; enum tlm_response_status { TLM_OK_RESPONSE = 1, TLM_INCOMPLETE_RESPONSE = 0, TLM_GENERIC_ERROR_RESPONSE = -1, TLM_ADDRESS_ERROR_RESPONSE = -2, TLM_COMMAND_ERROR_RESPONSE = -3, TLM_BURST_ERROR_RESPONSE = -4, TLM_BYTE_ENABLE_ERROR_RESPONSE = -5 }; enum tlm_gp_option { TLM_MIN_PAYLOAD, TLM_FULL_PAYLOAD, TLM_FULL_PAYLOAD_ACCEPTED }; #define TLM_BYTE_DISABLED 0x0 #define TLM_BYTE_ENABLED 0xff //--------------------------------------------------------------------------- // The generic payload class: //--------------------------------------------------------------------------- SC_API_TEMPLATE_DECL_ tlm_array; class SC_API tlm_generic_payload { public: //--------------- // Constructors //--------------- // Default constructor tlm_generic_payload(); explicit tlm_generic_payload(tlm_mm_interface* mm); void acquire() { sc_assert(m_mm != 0); m_ref_count++; } void release() { sc_assert(m_mm != 0 && m_ref_count > 0); if (--m_ref_count==0) m_mm->free(this); } int get_ref_count() const { return m_ref_count; } void set_mm(tlm_mm_interface* mm) { m_mm = mm; } bool has_mm() const { return m_mm != 0; } void reset(); private: //disabled copy ctor and assignment operator. tlm_generic_payload(const tlm_generic_payload& x) /* = delete */; tlm_generic_payload& operator= (const tlm_generic_payload& x) /* = delete */; public: // non-virtual deep-copying of the object void deep_copy_from(const tlm_generic_payload & other); // To update the state of the original generic payload from a deep copy // Assumes that "other" was created from the original by calling deep_copy_from // Argument use_byte_enable_on_read determines whether to use or ignores byte enables // when copying back the data array on a read command void update_original_from(const tlm_generic_payload & other, bool use_byte_enable_on_read = true); void update_extensions_from(const tlm_generic_payload & other); // Free all extensions. Useful when reusing a cloned transaction that doesn't have memory manager. // normal and sticky extensions are freed and extension array cleared. void free_all_extensions(); //-------------- // Destructor //-------------- virtual ~tlm_generic_payload(); //---------------- // API (including setters & getters) //--------------- // Command related method bool is_read() const {return (m_command == TLM_READ_COMMAND);} void set_read() {m_command = TLM_READ_COMMAND;} bool is_write() const {return (m_command == TLM_WRITE_COMMAND);} void set_write() {m_command = TLM_WRITE_COMMAND;} tlm_command get_command() const {return m_command;} void set_command(const tlm_command command) {m_command = command;} // Address related methods sc_dt::uint64 get_address() const {return m_address;} void set_address(const sc_dt::uint64 address) {m_address = address;} // Data related methods unsigned char* get_data_ptr() const {return m_data;} void set_data_ptr(unsigned char* data) {m_data = data;} // Transaction length (in bytes) related methods unsigned int get_data_length() const {return m_length;} void set_data_length(const unsigned int length) {m_length = length;} // Response status related methods bool is_response_ok() const {return (m_response_status > 0);} bool is_response_error() const {return (m_response_status <= 0);} tlm_response_status get_response_status() const {return m_response_status;} void set_response_status(const tlm_response_status response_status) {m_response_status = response_status;} std::string get_response_string() const; // Streaming related methods unsigned int get_streaming_width() const {return m_streaming_width;} void set_streaming_width(const unsigned int streaming_width) {m_streaming_width = streaming_width; } // Byte enable related methods unsigned char* get_byte_enable_ptr() const {return m_byte_enable;} void set_byte_enable_ptr(unsigned char* byte_enable){m_byte_enable = byte_enable;} unsigned int get_byte_enable_length() const {return m_byte_enable_length;} void set_byte_enable_length(const unsigned int byte_enable_length){m_byte_enable_length = byte_enable_length;} // This is the "DMI-hint" a slave can set this to true if it // wants to indicate that a DMI request would be supported: void set_dmi_allowed(bool dmi_allowed) { m_dmi = dmi_allowed; } bool is_dmi_allowed() const { return m_dmi; } // Use full set of attributes in DMI/debug? tlm_gp_option get_gp_option() const { return m_gp_option; } void set_gp_option( const tlm_gp_option gp_opt ) { m_gp_option = gp_opt; } private: /* --------------------------------------------------------------------- */ /* Generic Payload attributes: */ /* --------------------------------------------------------------------- */ /* - m_command : Type of transaction. Three values supported: */ /* - TLM_WRITE_COMMAND */ /* - TLM_READ_COMMAND */ /* - TLM_IGNORE_COMMAND */ /* - m_address : Transaction base address (byte-addressing). */ /* - m_data : When m_command = TLM_WRITE_COMMAND contains a */ /* pointer to the data to be written in the target.*/ /* When m_command = TLM_READ_COMMAND contains a */ /* pointer where to copy the data read from the */ /* target. */ /* - m_length : Total number of bytes of the transaction. */ /* - m_response_status : This attribute indicates whether an error has */ /* occurred during the transaction. */ /* Values supported are: */ /* - TLM_OK_RESP */ /* - TLM_INCOMPLETE_RESP */ /* - TLM_GENERIC_ERROR_RESP */ /* - TLM_ADDRESS_ERROR_RESP */ /* - TLM_COMMAND_ERROR_RESP */ /* - TLM_BURST_ERROR_RESP */ /* - TLM_BYTE_ENABLE_ERROR_RESP */ /* */ /* - m_byte_enable : It can be used to create burst transfers where */ /* the address increment between each beat is greater */ /* than the word length of each beat, or to place */ /* words in selected byte lanes of a bus. */ /* - m_byte_enable_length : For a read or a write command, the target */ /* interpret the byte enable length attribute as the */ /* number of elements in the bytes enable array. */ /* - m_streaming_width : */ /* --------------------------------------------------------------------- */ sc_dt::uint64 m_address; tlm_command m_command; unsigned char* m_data; unsigned int m_length; tlm_response_status m_response_status; bool m_dmi; unsigned char* m_byte_enable; unsigned int m_byte_enable_length; unsigned int m_streaming_width; tlm_gp_option m_gp_option; public: /* --------------------------------------------------------------------- */ /* Dynamic extension mechanism: */ /* --------------------------------------------------------------------- */ /* The extension mechanism is intended to enable initiator modules to */ /* optionally and transparently add data fields to the */ /* tlm_generic_payload. Target modules are free to check for extensions */ /* and may or may not react to the data in the extension fields. The */ /* definition of the extensions' semantics is solely in the */ /* responsibility of the user. */ /* */ /* The following rules apply: */ /* */ /* - Every extension class must be derived from tlm_extension, e.g.: */ /* class my_extension : public tlm_extension { ... } */ /* */ /* - A tlm_generic_payload object should be constructed after C++ */ /* static initialization time. This way it is guaranteed that the */ /* extension array is of sufficient size to hold all possible */ /* extensions. Alternatively, the initiator module can enforce a valid */ /* extension array size by calling the resize_extensions() method */ /* once before the first transaction with the payload object is */ /* initiated. */ /* */ /* - Initiators should use the the set_extension(e) or clear_extension(e)*/ /* methods for manipulating the extension array. The type of the */ /* argument must be a pointer to the specific registered extension */ /* type (my_extension in the above example) and is used to */ /* automatically locate the appropriate index in the array. */ /* */ /* - Targets can check for a specific extension by calling */ /* get_extension(e). e will point to zero if the extension is not */ /* present. */ /* */ /* --------------------------------------------------------------------- */ // Stick the pointer to an extension into the vector, return the // previous value: template T* set_extension(T* ext) { return static_cast(set_extension(T::ID, ext)); } // non-templatized version with manual index: tlm_extension_base* set_extension(unsigned int index, tlm_extension_base* ext); // Stick the pointer to an extension into the vector, return the // previous value and schedule its release template T* set_auto_extension(T* ext) { return static_cast(set_auto_extension(T::ID, ext)); } // non-templatized version with manual index: tlm_extension_base* set_auto_extension(unsigned int index, tlm_extension_base* ext); // Check for an extension, ext will point to 0 if not present template void get_extension(T*& ext) const { ext = get_extension(); } template T* get_extension() const { return static_cast(get_extension(T::ID)); } // Non-templatized version with manual index: tlm_extension_base* get_extension(unsigned int index) const; //this call just removes the extension from the txn but does not // call free() or tells the MM to do so // it return false if there was active MM so you are now in an unsafe situation // recommended use: when 100% sure there is no MM template void clear_extension(const T* ext) { clear_extension(); } //this call just removes the extension from the txn but does not // call free() or tells the MM to do so // it return false if there was active MM so you are now in an unsafe situation // recommended use: when 100% sure there is no MM template void clear_extension() { clear_extension(T::ID); } //this call removes the extension from the txn and does // call free() or tells the MM to do so when the txn is finally done // recommended use: when not sure there is no MM template void release_extension(T* ext) { release_extension(); } //this call removes the extension from the txn and does // call free() or tells the MM to do so when the txn is finally done // recommended use: when not sure there is no MM template void release_extension() { release_extension(T::ID); } private: // Non-templatized version with manual index void clear_extension(unsigned int index); // Non-templatized version with manual index void release_extension(unsigned int index); public: // Make sure the extension array is large enough. Can be called once by // an initiator module (before issuing the first transaction) to make // sure that the extension array is of correct size. This is only needed // if the initiator cannot guarantee that the generic payload object is // allocated after C++ static construction time. void resize_extensions(); private: tlm_array m_extensions; tlm_mm_interface* m_mm; unsigned int m_ref_count; }; } // namespace tlm #endif /* TLM_CORE_TLM2_TLM_GP_H_INCLUDED_ */ systemc-2.3.3/src/tlm_core/tlm_2/tlm_generic_payload/tlm_helpers.h0000644000175000017500000000457313360325173025202 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /* --------------------------------------------------------------------------------------- @file tlm_helpers.h @brief Original Authors: Charles Wilson, ESLX --------------------------------------------------------------------------------------- */ #ifndef __TLM_HELPERS_H__ #define __TLM_HELPERS_H__ //#include //#include namespace tlm { enum tlm_endianness { TLM_UNKNOWN_ENDIAN, TLM_LITTLE_ENDIAN, TLM_BIG_ENDIAN }; inline tlm_endianness get_host_endianness(void) { static tlm_endianness host_endianness = TLM_UNKNOWN_ENDIAN; if (host_endianness == TLM_UNKNOWN_ENDIAN) { unsigned int number = 1; unsigned char *p_msb_or_lsb = (unsigned char*)&number; host_endianness = (p_msb_or_lsb[0] == 0) ? TLM_BIG_ENDIAN : TLM_LITTLE_ENDIAN; } return host_endianness; } inline bool host_has_little_endianness(void) { static tlm_endianness host_endianness = TLM_UNKNOWN_ENDIAN; static bool host_little_endian = false; if (host_endianness == TLM_UNKNOWN_ENDIAN) { unsigned int number = 1; unsigned char *p_msb_or_lsb = (unsigned char*)&number; host_little_endian = (p_msb_or_lsb[0] == 0) ? false : true; } return host_little_endian; } inline bool has_host_endianness(tlm_endianness endianness) { if (host_has_little_endianness()) { return endianness == TLM_LITTLE_ENDIAN; } else { return endianness == TLM_BIG_ENDIAN; } } } // namespace tlm #endif /* __TLM_HELPERS_H__ */ systemc-2.3.3/src/tlm_core/tlm_2/tlm_generic_payload/tlm_phase.cpp0000644000175000017500000000626313360325173025171 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ #include "tlm_core/tlm_2/tlm_generic_payload/tlm_phase.h" #include "sysc/utils/sc_string_view.h" #include "sysc/utils/sc_typeindex.h" #include "sysc/utils/sc_report.h" #include #include using sc_core::sc_string_view; using sc_core::sc_type_index; namespace tlm { /* anonymous */ namespace { struct tlm_phase_registry { typedef unsigned int key_type; static tlm_phase_registry& instance() { static tlm_phase_registry inst; return inst; } unsigned int register_phase(sc_type_index type, sc_string_view name) { type_map::const_iterator it = ids_.find( type ); if( name.empty() ) { SC_REPORT_FATAL( sc_core::SC_ID_INTERNAL_ERROR_, "unexpected empty tlm_phase name" ); return UNINITIALIZED_PHASE; } if( it == ids_.end() ) { // new phase - generate/store ID and name type_map::value_type v( type, static_cast(names_.size()) ); names_.push_back( name_table::value_type(name.data(), name.size()) ); ids_.insert( v ); return v.second; } if( names_[it->second] != name ) { SC_REPORT_FATAL( sc_core::SC_ID_INTERNAL_ERROR_, "tlm_phase registration failed: duplicate type info" ); sc_core::sc_abort(); } return it->second; } const char* get_name( key_type id ) const { sc_assert( id < names_.size() ); return names_[id].c_str(); } private: typedef std::map type_map; typedef std::vector name_table; type_map ids_; name_table names_; tlm_phase_registry() : names_( END_RESP+1 ) { # define BUILTIN_PHASE(phase) \ names_[phase] = #phase BUILTIN_PHASE( UNINITIALIZED_PHASE ); BUILTIN_PHASE( BEGIN_REQ ); BUILTIN_PHASE( END_REQ ); BUILTIN_PHASE( BEGIN_RESP ); BUILTIN_PHASE( END_RESP ); } }; // class tlm_phase_registry } // anonymous namespace tlm_phase::tlm_phase( unsigned int id ) : m_id(id) { // TODO: validate id? // TODO: add deprecation warning? } tlm_phase::tlm_phase( const std::type_info& type, const char* name ) : m_id( tlm_phase_registry::instance().register_phase(type, name) ) {} const char* tlm_phase::get_name() const { return tlm_phase_registry::instance().get_name( m_id ); } } // namespace tlm // Taf! systemc-2.3.3/src/tlm_core/tlm_2/tlm_generic_payload/tlm_endian_conv.h0000644000175000017500000007173513360325173026027 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ #ifndef __TLM_ENDIAN_CONV_H__ #define __TLM_ENDIAN_CONV_H__ #include "tlm_core/tlm_2/tlm_generic_payload/tlm_gp.h" #include // std::memset namespace tlm { /* Tranaction-Level Modelling Endianness Helper Functions DESCRIPTION A set of functions for helping users to get the endianness right in their TLM models of system initiators. These functions are for use within an initiator. They can not be used as-is outside an initiator because the extension used to store context will not work if cascaded, and they do not respect the generic payload mutability rules. However this code may be easily copied and adapted for use in bridges, etc.. These functions are not compulsory. There are other legitimate ways to achieve the same functionality. If extra information is available at compile time about the nature of an initiator's transactions, this can be exploited to accelerate simulations by creating further functions similar to those in this file. In general a functional transaction can be described in more than one way by a TLM-2 GP object. The functions convert the endianness of a GP object, either on request or response. They should only be used when the initiator's endianness does not match the host's endianness. They assume 'arithmetic mode' meaning that within a data word the byte order is always host-endian. For non-arithmetic mode initiators they can be used with a data word size of 1 byte. All the functions are templates, for example: template inline void to_hostendian_generic(tlm_generic_payload *txn, int sizeof_databus) The template parameter provides the data word width. Having this as a class makes it easy to use it for copy and swap operations within the functions. If the assignment operator for this class is overloaded, the endianness conversion function may not have the desired effect. All the functions have the same signature except for different names. The principle is that a function to_hostendian_convtype() is called when the initiator-endian transaction is created, and the matching function from_hostendian_convtype() is called when the transaction is completed, for example before read data can be used. In some cases the from_ function is redundant but an empty function is provided anyway. It is strongly recommended that the from_ function is called, in case it ceases to be redundant in future versions of this code. No context needs to be managed outside the two functions, except that they must be called with the same template parameter and the same bus width. For initiator models that can not easily manage this context information, a single entry point for the from_ function is provided, which will be a little slower than calling the correct from_ function directly, as it can not be inlined. All functions assume power-of-2 bus and data word widths. Functions offered: 0) A pair of functions that work for almost all TLM2 GP transactions. The only limitations are that data and bus widths should be powers of 2, and that the data length should be an integer number of streaming widths and that the streaming width should be an integer number of data words. These functions always allocate new data and byte enable buffers and copy data one byte at a time. tlm_to_hostendian_generic(tlm_generic_payload *txn, int sizeof_databus) tlm_from_hostendian_generic(tlm_generic_payload *txn, int sizeof_databus) 1) A pair of functions that work for all transactions regardless of data and bus data sizes and address alignment except for the the following limitations: - byte-enables are supported only when byte-enable granularity is no finer than the data word (every data word is wholly enabled or wholly disabled) - byte-enable-length is not supported (if byte enables are present, the byte enable length must be equal to the data length). - streaming width is not supported - data word wider than bus word is not supported A new data buffer and a new byte enable buffer are always allocated. Byte enables are assumed to be needed even if not required for the original (unconverted) transaction. Data is copied to the new buffer on request (for writes) or on response (for reads). Copies are done word-by-word where possible. tlm_to_hostendian_word(tlm_generic_payload *txn, int sizeof_databus) tlm_from_hostendian_word(tlm_generic_payload *txn, int sizeof_databus) 2) If the original transaction is both word and bus-aligned then this pair of functions can be used. It will complete faster than the generic function because the data reordering function is much simpler and no address conversion is required. The following limitations apply: - byte-enables are supported only when byte-enable granularity is no finer than the data word (every data word is wholly enabled or wholly disabled) - byte-enable-length is not supported (if byte enables are present, the byte enable length must be equal to the data length). - streaming width is not supported - data word wider than bus word is not supported - the transaction must be an integer number of bus words - the address must be aligned to the bus width tlm_to_hostendian_aligned(tlm_generic_payload *txn, int sizeof_databus) tlm_from_hostendian_aligned(tlm_generic_payload *txn, int sizeof_databus) 3) For single word transactions that don't cross a bus word boundary it is always safe to work in-place and the conversion is very simple. Again, streaming width and byte-enable length are not supported, and byte-enables may not changes within a data word. tlm_to_hostendian_single(tlm_generic_payload *txn, int sizeof_databus) tlm_from_hostendian_single(tlm_generic_payload *txn, int sizeof_databus) 4) A single entry point for accessing the correct from_ function without needing to store context. tlm_from_hostendian(tlm_generic_payload *txn) */ #ifndef uchar #define uchar unsigned char #else #define TLM_END_CONV_DONT_UNDEF_UCHAR #endif /////////////////////////////////////////////////////////////////////////////// // Generic Utilities class tlm_endian_context; class tlm_endian_context_pool { public: tlm_endian_context *first; inline tlm_endian_context_pool(); inline ~tlm_endian_context_pool(); inline tlm_endian_context *pop(); inline void push(tlm_endian_context *c); }; static tlm_endian_context_pool global_tlm_endian_context_pool; // an extension to keep the information needed for reconversion of response class tlm_endian_context : public tlm_extension { public: tlm_endian_context() : dbuf_size(0), bebuf_size(0) {} ~tlm_endian_context() { if(dbuf_size > 0) delete [] new_dbuf; if(bebuf_size > 0) delete [] new_bebuf; } sc_dt::uint64 address; // used by generic, word sc_dt::uint64 new_address; // used by generic uchar *data_ptr; // used by generic, word, aligned uchar *byte_enable; // used by word int length; // used by generic, word int stream_width; // used by generic // used by common entry point on response void (*from_f)(tlm_generic_payload *txn, unsigned int sizeof_databus); int sizeof_databus; // reordering buffers for data and byte-enables uchar *new_dbuf, *new_bebuf; int dbuf_size, bebuf_size; void establish_dbuf(int len) { if(len <= dbuf_size) return; if(dbuf_size > 0) delete [] new_dbuf; new_dbuf = new uchar[len]; dbuf_size = len; } void establish_bebuf(int len) { if(len <= bebuf_size) return; if(bebuf_size > 0) delete [] new_bebuf; new_bebuf = new uchar[len]; bebuf_size = len; } // required for extension management void free() { global_tlm_endian_context_pool.push(this); } tlm_extension_base* clone() const {return 0;} void copy_from(tlm_extension_base const &) {return;} // for pooling tlm_endian_context *next; }; // Assumptions about transaction contexts: // 1) only the address attribute of a transaction // is mutable. all other attributes are unchanged from the request to // response side conversion. // 2) the conversion functions in this file do not respect the mutability // rules and do not put the transaction back into its original state after // completion. so if the initiator has any cleaning up to do (eg of byte // enable buffers), it needs to store its own context. the transaction // returned to the initiator may contain pointers to data and byte enable // that can/must not be deleted. // 3) the conversion functions in this file use an extension to store // context information. they do not remove this extension. the initiator // should not remove it unless it deletes the generic payload // object. inline tlm_endian_context *establish_context(tlm_generic_payload *txn) { tlm_endian_context *tc = txn->get_extension(); if(tc == 0) { tc = global_tlm_endian_context_pool.pop(); txn->set_extension(tc); } return tc; } inline tlm_endian_context_pool::tlm_endian_context_pool() : first(0) {} inline tlm_endian_context_pool::~tlm_endian_context_pool() { while(first != 0) { tlm_endian_context *next = first->next; delete first; first = next; } } tlm_endian_context *tlm_endian_context_pool::pop() { if(first == 0) return new tlm_endian_context; tlm_endian_context *r = first; first = first->next; return r; } void tlm_endian_context_pool::push(tlm_endian_context *c) { c->next = first; first = c; } // a set of constants for efficient filling of byte enables template class tlm_bool { public: static D TLM_TRUE; static D TLM_FALSE; static D make_uchar_array(uchar c) { D d; uchar *tmp = (uchar *)(&d); for(ptrdiff_t i=0; i!=sizeof(D); i++) tmp[i] = c; // 64BITFIX negligable risk but easy fix // return d; } // also provides an syntax-efficient tester, using a // copy constuctor and an implicit cast to boolean tlm_bool(D &d) : b(*((uchar*)&d) != TLM_BYTE_DISABLED) {} operator bool() const {return b;} private: bool b; }; template D tlm_bool::TLM_TRUE = tlm_bool::make_uchar_array(TLM_BYTE_ENABLED); template D tlm_bool::TLM_FALSE = tlm_bool::make_uchar_array(TLM_BYTE_DISABLED); /////////////////////////////////////////////////////////////////////////////// // function set (0): Utilities inline void copy_db0(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { *dest1 = *src1; *dest2 = *src2; } inline void copy_dbtrue0(uchar *src1, uchar * /* src2 */, uchar *dest1, uchar *dest2) { *dest1 = *src1; *dest2 = TLM_BYTE_ENABLED; } inline void copy_btrue0(uchar * /* src1 */, uchar * /* src2 */, uchar * /* dest1 */, uchar *dest2) { *dest2 = TLM_BYTE_ENABLED; } inline void copy_b0(uchar * /* src1 */, uchar *src2, uchar * /* dest1 */, uchar *dest2) { *dest2 = *src2; } inline void copy_dbyb0(uchar *src1, uchar * /* src2 */, uchar *dest1, uchar *dest2) { if(*dest2 == TLM_BYTE_ENABLED) *src1 = *dest1; } template inline void loop_generic0(int new_len, int new_stream_width, int orig_stream_width, int sizeof_databus, sc_dt::uint64 orig_start_address, sc_dt::uint64 new_start_address, int be_length, uchar *ie_data, uchar *ie_be, uchar *he_data, uchar *he_be) { for(int orig_sword = 0, new_sword = 0; new_sword < new_len; new_sword += new_stream_width, orig_sword += orig_stream_width) { sc_dt::uint64 ie_addr = orig_start_address; for(int orig_dword = orig_sword; orig_dword < orig_sword + orig_stream_width; orig_dword += sizeof(D)) { for(int curr_byte = orig_dword + sizeof(D) - 1; curr_byte >= orig_dword; curr_byte--) { ptrdiff_t he_index = ((ie_addr++) ^ (sizeof_databus - 1)) - new_start_address + new_sword; // 64BITFIX // COPY(ie_data+curr_byte, ie_be+(curr_byte % be_length), // 64BITRISK no risk of overflow, always positive // he_data+he_index, he_be+he_index); } } } } /////////////////////////////////////////////////////////////////////////////// // function set (0): Response template inline void tlm_from_hostendian_generic(tlm_generic_payload *txn, unsigned int sizeof_databus) { if(txn->is_read()) { tlm_endian_context *tc = txn->template get_extension(); loop_generic0(txn->get_data_length(), txn->get_streaming_width(), tc->stream_width, sizeof_databus, tc->address, tc->new_address, txn->get_data_length(), tc->data_ptr, 0, txn->get_data_ptr(), txn->get_byte_enable_ptr()); } } /////////////////////////////////////////////////////////////////////////////// // function set (0): Request template inline void tlm_to_hostendian_generic(tlm_generic_payload *txn, unsigned int sizeof_databus) { tlm_endian_context *tc = establish_context(txn); tc->from_f = &(tlm_from_hostendian_generic); tc->sizeof_databus = sizeof_databus; // calculate new size: nr stream words multiplied by big enough stream width int s_width = txn->get_streaming_width(); int length = txn->get_data_length(); if(s_width >= length) s_width = length; int nr_stream_words = length/s_width; // find out in which bus word the stream word starts and ends sc_dt::uint64 new_address = (txn->get_address() & ~(sizeof_databus - 1)); sc_dt::uint64 end_address = ((txn->get_address() + s_width - 1) & ~(sizeof_databus - 1)); int new_stream_width = end_address - new_address + sizeof_databus; int new_length = new_stream_width * nr_stream_words; // store context tc->data_ptr = txn->get_data_ptr(); tc->address = txn->get_address(); tc->new_address = new_address; tc->stream_width = s_width; uchar *orig_be = txn->get_byte_enable_ptr(); int orig_be_length = txn->get_byte_enable_length(); // create data and byte-enable buffers txn->set_address(new_address); tc->establish_dbuf(new_length); txn->set_data_ptr(tc->new_dbuf); tc->establish_bebuf(new_length); txn->set_byte_enable_ptr(tc->new_bebuf); std::memset(txn->get_byte_enable_ptr(), TLM_BYTE_DISABLED, new_length); txn->set_streaming_width(new_stream_width); txn->set_data_length(new_length); txn->set_byte_enable_length(new_length); // copy data and/or byte enables if(txn->is_write()) { if(orig_be == 0) { loop_generic0(new_length, new_stream_width, s_width, sizeof_databus, tc->address, new_address, new_length, tc->data_ptr, 0, txn->get_data_ptr(), txn->get_byte_enable_ptr()); } else { loop_generic0(new_length, new_stream_width, s_width, sizeof_databus, tc->address, new_address, orig_be_length, tc->data_ptr, orig_be, txn->get_data_ptr(), txn->get_byte_enable_ptr()); } } else { // read transaction if(orig_be == 0) { loop_generic0(new_length, new_stream_width, s_width, sizeof_databus, tc->address, new_address, new_length, tc->data_ptr, 0, txn->get_data_ptr(), txn->get_byte_enable_ptr()); } else { loop_generic0(new_length, new_stream_width, s_width, sizeof_databus, tc->address, new_address, orig_be_length, tc->data_ptr, orig_be, txn->get_data_ptr(), txn->get_byte_enable_ptr()); } } } /////////////////////////////////////////////////////////////////////////////// // function set (1): Utilities template inline void copy_d1(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { *((D *)dest1) = *((D *)src1); *((D *)dest2) = tlm_bool::TLM_TRUE; } template inline void copy_db1(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { *((D *)dest1) = *((D *)src1); *((D *)dest2) = *((D *)src2); } template inline void true_b1(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { *((D *)dest2) = tlm_bool::TLM_TRUE; } template inline void copy_b1(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { *((D *)dest2) = *((D *)src2); } template inline void copy_dbyb1(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { if(*src2 != TLM_BYTE_DISABLED) *((D *)src1) = *((D *)dest1); } template inline void copy_dbytrue1(uchar *src1, uchar *src2, uchar *dest1, uchar *dest2) { *((D *)src1) = *((D *)dest1); } template inline void false_b1(uchar *dest1) { *((D *)dest1) = tlm_bool::TLM_FALSE; } template inline void no_b1(uchar *dest1) { } template inline int loop_word1( int bytes_left, int len0, int lenN, int sizeof_databus, uchar *start, uchar *end, uchar *src, uchar *bsrc, uchar *dest, uchar *bdest) { ptrdiff_t d2b_src = bsrc - src; // 64BITFIX was int // ptrdiff_t d2b_dest = bdest - dest; // 64BITFIX was int // uchar *original_dest = dest; while(true) { // len0 bytes at start of a bus word if((src >= start) && (src < end)) { for(int i=0; i= start) && (src < end)) { COPY(src, src+d2b_src, dest, dest+d2b_dest); bytes_left -= sizeof(D); } else { FILLFALSE(dest+d2b_dest); } dest += sizeof(D); if(bytes_left <= 0) return int(dest - original_dest); src -= sizeof(D); } // lenN bytes at end of bus word if((src >= start) && (src < end)) { for(int i=0; i inline void tlm_from_hostendian_word(tlm_generic_payload *txn, unsigned int sizeof_databus) { if(txn->is_read()) { tlm_endian_context *tc = txn->template get_extension(); sc_dt::uint64 b_mask = sizeof_databus - 1; int d_mask = sizeof(DATAWORD) - 1; int a_offset = static_cast(tc->address & b_mask); int len0 = (sizeof_databus - a_offset) & d_mask; int lenN = sizeof(DATAWORD) - len0; uchar *d_start = tc->data_ptr; uchar *d_end = ptrdiff_t(tc->length) + d_start; // 64BITFIX probably redundant // uchar *d = ptrdiff_t(((sizeof_databus - a_offset) & ~d_mask) + lenN) + d_start; // 64BITFIX probably redundant // // iterate over transaction copying data qualified by byte-enables if(tc->byte_enable == 0) { loop_word1, ©_dbytrue1, &no_b1, &no_b1 >( tc->length, len0, lenN, sizeof_databus, d_start, d_end, d, 0, txn->get_data_ptr(), 0); } else { loop_word1, ©_dbyb1, &no_b1, &no_b1 >( tc->length, len0, lenN, sizeof_databus, d_start, d_end, d, tc->byte_enable - d_start + d, txn->get_data_ptr(), 0); } } } /////////////////////////////////////////////////////////////////////////////// // function set (1): Request template inline void tlm_to_hostendian_word(tlm_generic_payload *txn, unsigned int sizeof_databus) { tlm_endian_context *tc = establish_context(txn); tc->from_f = &(tlm_from_hostendian_word); tc->sizeof_databus = sizeof_databus; sc_dt::uint64 b_mask = sizeof_databus - 1; int d_mask = sizeof(DATAWORD) - 1; sc_dt::uint64 a_aligned = txn->get_address() & ~b_mask; int a_offset = static_cast(txn->get_address() & b_mask); int len0 = (sizeof_databus - a_offset) & d_mask; int lenN = sizeof(DATAWORD) - len0; uchar *d_start = txn->get_data_ptr(); uchar *d_end = ptrdiff_t(txn->get_data_length()) + d_start; // 64BITFIX probably redundant // uchar *d = ptrdiff_t(((sizeof_databus - a_offset) & ~d_mask) + lenN) + d_start; // 64BITFIX probably redundant // // create new data and byte enable buffers int long_enough = txn->get_data_length() + 2 * sizeof_databus; tc->establish_dbuf(long_enough); uchar *new_data = tc->new_dbuf; tc->establish_bebuf(long_enough); uchar *new_be = tc->new_bebuf; if(txn->is_read()) { tc->data_ptr = d_start; tc->address = txn->get_address(); tc->byte_enable = txn->get_byte_enable_ptr(); tc->length = txn->get_data_length(); if(txn->get_byte_enable_ptr() == 0) { // iterate over transaction creating new byte enables from all-true txn->set_data_length(loop_word1, &true_b1, &false_b1, &false_b1 >( txn->get_data_length(), len0, lenN, sizeof_databus, d_start, d_end, d, 0, new_data, new_be)); } else { // iterate over transaction copying byte enables txn->set_data_length(loop_word1, ©_b1, &false_b1, &false_b1 >( txn->get_data_length(), len0, lenN, sizeof_databus, d_start, d_end, d, txn->get_byte_enable_ptr() - d_start + d, new_data, new_be)); } } else { // WRITE if(txn->get_byte_enable_ptr() == 0) { // iterate over transaction copying data and creating new byte-enables txn->set_data_length(loop_word1, ©_d1, &false_b1, &false_b1 >( txn->get_data_length(), len0, lenN, sizeof_databus, d_start, d_end, d, 0, new_data, new_be)); } else { // iterate over transaction copying data and byte-enables txn->set_data_length(loop_word1, ©_db1, &false_b1, &false_b1 >( txn->get_data_length(), len0, lenN, sizeof_databus, d_start, d_end, d, txn->get_byte_enable_ptr() - d_start + d, new_data, new_be)); } } txn->set_byte_enable_length(txn->get_data_length()); txn->set_streaming_width(txn->get_data_length()); txn->set_data_ptr(new_data); txn->set_byte_enable_ptr(new_be); txn->set_address(a_aligned); } /////////////////////////////////////////////////////////////////////////////// // function set (2): Utilities template inline void copy_d2(D *src1, D *src2, D *dest1, D *dest2) { *dest1 = *src1; } template inline void copy_db2(D *src1, D *src2, D *dest1, D *dest2) { *dest1 = *src1; *dest2 = *src2; } template inline void copy_dbyb2(D *src1, D *src2, D *dest1, D *dest2) { if(tlm_bool(*src2)) *dest1 = *src1; } template inline void loop_aligned2(D *src1, D *src2, D *dest1, D *dest2, int words, int words_per_bus) { ptrdiff_t src1to2 = (char *)src2 - (char *)src1; // 64BITFIX was int and operands were cast to int // ptrdiff_t dest1to2 = (char *)dest2 - (char *)dest1; // 64BITFIX was int and operands were cast to int // D *done = src1 + ptrdiff_t(words); // 64BITFIX // D *bus_start = src1; src1 += ptrdiff_t(words_per_bus - 1); // 64BITFIX // while(true) { COPY(src1, (D *)(src1to2+(char *)src1), dest1, (D *)(dest1to2+(char *)dest1)); // 64BITFIX // dest1++; if((--src1) < bus_start) { bus_start += ptrdiff_t(words_per_bus); // 64BITFIX // if(bus_start == done) break; src1 = bus_start + ptrdiff_t(words_per_bus - 1); // 64BITFIX // } } } /////////////////////////////////////////////////////////////////////////////// // function set (2): Response template inline void tlm_from_hostendian_aligned(tlm_generic_payload *txn, unsigned int sizeof_databus) { int words_per_bus = sizeof_databus/sizeof(DATAWORD); if(words_per_bus == 1) return; int words = (txn->get_data_length())/sizeof(DATAWORD); tlm_endian_context *tc = txn->template get_extension(); if(txn->get_byte_enable_ptr() == 0) { // no byte enables if(txn->is_read()) { // RD without byte enables. Copy data to original buffer loop_aligned2 >( (DATAWORD *)(txn->get_data_ptr()), 0, (DATAWORD *)(tc->data_ptr), 0, words, words_per_bus); } } else { // byte enables present if(txn->is_read()) { // RD with byte enables. Copy data qualified by byte-enables loop_aligned2 >( (DATAWORD *)(txn->get_data_ptr()), (DATAWORD *)(txn->get_byte_enable_ptr()), (DATAWORD *)(tc->data_ptr), 0, words, words_per_bus); } } } /////////////////////////////////////////////////////////////////////////////// // function set (2): Request template inline void tlm_to_hostendian_aligned(tlm_generic_payload *txn, unsigned int sizeof_databus) { tlm_endian_context *tc = establish_context(txn); tc->from_f = &(tlm_from_hostendian_aligned); tc->sizeof_databus = sizeof_databus; int words_per_bus = sizeof_databus/sizeof(DATAWORD); if(words_per_bus == 1) return; int words = (txn->get_data_length())/sizeof(DATAWORD); DATAWORD *original_be = (DATAWORD *)(txn->get_byte_enable_ptr()); DATAWORD *original_data = (DATAWORD *)(txn->get_data_ptr()); // always allocate a new data buffer tc->establish_dbuf(txn->get_data_length()); txn->set_data_ptr(tc->new_dbuf); if(original_be == 0) { // no byte enables if(txn->is_write()) { // WR no byte enables. Copy data loop_aligned2 >(original_data, 0, (DATAWORD *)(txn->get_data_ptr()), 0, words, words_per_bus); } else { // RD no byte enables. Save original data pointer tc->data_ptr = (uchar *)original_data; } } else { // byte enables present // allocate a new buffer for them tc->establish_bebuf(txn->get_data_length()); txn->set_byte_enable_ptr(tc->new_bebuf); txn->set_byte_enable_length(txn->get_data_length()); if(txn->is_write()) { // WR with byte enables. Copy data and BEs loop_aligned2 >(original_data, original_be, (DATAWORD *)(txn->get_data_ptr()), (DATAWORD *)(txn->get_byte_enable_ptr()), words, words_per_bus); } else { // RD with byte enables. Save original data pointer tc->data_ptr = (uchar *)original_data; // Copy byte enables to new buffer loop_aligned2 >(original_be, 0, (DATAWORD *)(txn->get_byte_enable_ptr()), 0, words, words_per_bus); } } } /////////////////////////////////////////////////////////////////////////////// // function set (3): Response template inline void tlm_from_hostendian_single(tlm_generic_payload *txn, unsigned int sizeof_databus) { // nothing needs to be done here } /////////////////////////////////////////////////////////////////////////////// // function set (3): Request template inline void tlm_to_hostendian_single(tlm_generic_payload *txn, unsigned int sizeof_databus) { tlm_endian_context *tc = establish_context(txn); tc->from_f = &(tlm_from_hostendian_single); tc->sizeof_databus = sizeof_databus; // only need to change the address, always safe to work in-place sc_dt::uint64 mask = sizeof_databus-1; sc_dt::uint64 a = txn->get_address(); txn->set_address((a & ~mask) | (sizeof_databus - (a & mask) - sizeof(DATAWORD))); } /////////////////////////////////////////////////////////////////////////////// // helper function which works for all responses inline void tlm_from_hostendian(tlm_generic_payload *txn) { tlm_endian_context *tc = txn->get_extension(); (*(tc->from_f))(txn, tc->sizeof_databus); } #ifndef TLM_END_CONV_DONT_UNDEF_UCHAR #undef uchar #endif } // namespace tlm #endif // multiple-inclusion protection systemc-2.3.3/src/tlm_core/tlm_2/tlm_generic_payload/tlm_gp.cpp0000644000175000017500000002777013360325173024505 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ #include "tlm_core/tlm_2/tlm_generic_payload/tlm_gp.h" #include "sysc/utils/sc_typeindex.h" // sc_typeindex #include #include // std::memcpy et.al. using sc_core::sc_type_index; namespace tlm { template class SC_API tlm_array; //--------------------------------------------------------------------------- // Classes for the extension mechanism //--------------------------------------------------------------------------- /* anonymous */ namespace { class tlm_extension_registry { typedef unsigned int key_type; typedef std::map type_map; public: static tlm_extension_registry& instance() { if (!instance_) // don't cleanup registry instance_ = new tlm_extension_registry(); return *instance_; } unsigned int register_extension(sc_type_index type) { type_map::const_iterator it = ids_.find( type ); if( it == ids_.end() ) { // new extension - generate/store ID type_map::value_type v( type, static_cast(ids_.size()) ); ids_.insert( v ); return v.second; } return it->second; } static unsigned int max_num_extensions() { return (instance_) ? instance().ids_.size() : 0; } private: static tlm_extension_registry* instance_; type_map ids_; tlm_extension_registry() /* = default */ {} }; // class tlm_extension_registry tlm_extension_registry* tlm_extension_registry::instance_ = NULL; } // anonymous namespace unsigned int max_num_extensions() { return tlm_extension_registry::max_num_extensions(); } unsigned int tlm_extension_base::register_extension(const std::type_info& type) { return tlm_extension_registry::instance().register_extension(type); } //--------------------------------------------------------------------------- // The generic payload class: //--------------------------------------------------------------------------- //--------------- // Constructors //--------------- // Default constructor tlm_generic_payload::tlm_generic_payload() : m_address(0) , m_command(TLM_IGNORE_COMMAND) , m_data(0) , m_length(0) , m_response_status(TLM_INCOMPLETE_RESPONSE) , m_dmi(false) , m_byte_enable(0) , m_byte_enable_length(0) , m_streaming_width(0) , m_gp_option(TLM_MIN_PAYLOAD) , m_extensions(max_num_extensions()) , m_mm(0) , m_ref_count(0) {} tlm_generic_payload::tlm_generic_payload(tlm_mm_interface* mm) : m_address(0) , m_command(TLM_IGNORE_COMMAND) , m_data(0) , m_length(0) , m_response_status(TLM_INCOMPLETE_RESPONSE) , m_dmi(false) , m_byte_enable(0) , m_byte_enable_length(0) , m_streaming_width(0) , m_gp_option(TLM_MIN_PAYLOAD) , m_extensions(max_num_extensions()) , m_mm(mm) , m_ref_count(0) {} void tlm_generic_payload::reset() { //should the other members be reset too? m_gp_option = TLM_MIN_PAYLOAD; m_extensions.free_entire_cache(); }; // non-virtual deep-copying of the object void tlm_generic_payload::deep_copy_from(const tlm_generic_payload & other) { m_command = other.get_command(); m_address = other.get_address(); m_length = other.get_data_length(); m_response_status = other.get_response_status(); m_byte_enable_length = other.get_byte_enable_length(); m_streaming_width = other.get_streaming_width(); m_gp_option = other.get_gp_option(); m_dmi = other.is_dmi_allowed(); // deep copy data // there must be enough space in the target transaction! if(m_data && other.m_data) { std::memcpy(m_data, other.m_data, m_length); } // deep copy byte enables // there must be enough space in the target transaction! if(m_byte_enable && other.m_byte_enable) { std::memcpy(m_byte_enable, other.m_byte_enable, m_byte_enable_length); } // deep copy extensions (sticky and non-sticky) if(m_extensions.size() < other.m_extensions.size()) { m_extensions.expand(other.m_extensions.size()); } for(unsigned int i=0; iclone(); if(ext) //extension may not be clonable. { if(has_mm()) { //mm can take care of removing cloned extensions set_auto_extension(i, ext); } else { // no mm, user will call free_all_extensions(). set_extension(i, ext); } } } else { //We already have such extension. Copy original over it. m_extensions[i]->copy_from(*other.m_extensions[i]); } } } } // To update the state of the original generic payload from a deep copy // Assumes that "other" was created from the original by calling deep_copy_from // Argument use_byte_enable_on_read determines whether to use or ignores byte enables // when copying back the data array on a read command void tlm_generic_payload::update_original_from(const tlm_generic_payload & other, bool use_byte_enable_on_read) { // Copy back extensions that are present on the original update_extensions_from(other); // Copy back the response status and DMI hint attributes m_response_status = other.get_response_status(); m_dmi = other.is_dmi_allowed(); // Copy back the data array for a read command only // deep_copy_from allowed null pointers, and so will we // We assume the arrays are the same size // We test for equal pointers in case the original and the copy share the same array if(is_read() && m_data && other.m_data && m_data != other.m_data) { if (m_byte_enable && use_byte_enable_on_read) { if (m_byte_enable_length == 8 && m_length % 8 == 0 ) { // Optimized implementation copies 64-bit words by masking for (unsigned int i = 0; i < m_length; i += 8) { typedef sc_dt::uint64* u; *reinterpret_cast(&m_data[i]) &= ~*reinterpret_cast(m_byte_enable); *reinterpret_cast(&m_data[i]) |= *reinterpret_cast(&other.m_data[i]) & *reinterpret_cast(m_byte_enable); } } else if (m_byte_enable_length == 4 && m_length % 4 == 0 ) { // Optimized implementation copies 32-bit words by masking for (unsigned int i = 0; i < m_length; i += 4) { typedef unsigned int* u; *reinterpret_cast(&m_data[i]) &= ~*reinterpret_cast(m_byte_enable); *reinterpret_cast(&m_data[i]) |= *reinterpret_cast(&other.m_data[i]) & *reinterpret_cast(m_byte_enable); } } else // Unoptimized implementation for (unsigned int i = 0; i < m_length; i++) if ( m_byte_enable[i % m_byte_enable_length] ) m_data[i] = other.m_data[i]; } else std::memcpy(m_data, other.m_data, m_length); } } void tlm_generic_payload::update_extensions_from(const tlm_generic_payload & other) { // deep copy extensions that are already present sc_assert(m_extensions.size() <= other.m_extensions.size()); for(unsigned int i=0; icopy_from(*other.m_extensions[i]); } } } } // Free all extensions. Useful when reusing a cloned transaction that doesn't have memory manager. // normal and sticky extensions are freed and extension array cleared. void tlm_generic_payload::free_all_extensions() { m_extensions.free_entire_cache(); for(unsigned int i=0; ifree(); m_extensions[i] = 0; } } } //-------------- // Destructor //-------------- tlm_generic_payload::~tlm_generic_payload() { for(unsigned int i=0; ifree(); } //---------------- // API (including setters & getters) //--------------- std::string tlm_generic_payload::get_response_string() const { switch(m_response_status) { case TLM_OK_RESPONSE: return "TLM_OK_RESPONSE"; case TLM_INCOMPLETE_RESPONSE: return "TLM_INCOMPLETE_RESPONSE"; case TLM_GENERIC_ERROR_RESPONSE: return "TLM_GENERIC_ERROR_RESPONSE"; case TLM_ADDRESS_ERROR_RESPONSE: return "TLM_ADDRESS_ERROR_RESPONSE"; case TLM_COMMAND_ERROR_RESPONSE: return "TLM_COMMAND_ERROR_RESPONSE"; case TLM_BURST_ERROR_RESPONSE: return "TLM_BURST_ERROR_RESPONSE"; case TLM_BYTE_ENABLE_ERROR_RESPONSE: return "TLM_BYTE_ENABLE_ERROR_RESPONSE"; } return "TLM_UNKNOWN_RESPONSE"; } /* --------------------------------------------------------------------- */ /* Dynamic extension mechanism: */ /* --------------------------------------------------------------------- */ tlm_extension_base* tlm_generic_payload::set_extension(unsigned int index, tlm_extension_base* ext) { sc_assert(index < m_extensions.size()); tlm_extension_base* tmp = m_extensions[index]; m_extensions[index] = ext; return tmp; } tlm_extension_base* tlm_generic_payload::set_auto_extension(unsigned int index, tlm_extension_base* ext) { sc_assert(index < m_extensions.size()); tlm_extension_base* tmp = m_extensions[index]; m_extensions[index] = ext; if (!tmp) m_extensions.insert_in_cache(&m_extensions[index]); sc_assert(m_mm != 0); return tmp; } tlm_extension_base* tlm_generic_payload::get_extension(unsigned int index) const { sc_assert(index < m_extensions.size()); return m_extensions[index]; } void tlm_generic_payload::clear_extension(unsigned int index) { sc_assert(index < m_extensions.size()); m_extensions[index] = static_cast(0); } void tlm_generic_payload::release_extension(unsigned int index) { sc_assert(index < m_extensions.size()); if (m_mm) { m_extensions.insert_in_cache(&m_extensions[index]); } else { m_extensions[index]->free(); m_extensions[index] = static_cast(0); } } void tlm_generic_payload::resize_extensions() { m_extensions.expand(max_num_extensions()); } } // namespace tlm systemc-2.3.3/src/tlm_core/tlm_2/tlm_generic_payload/tlm_generic_payload.h0000644000175000017500000000236213360325173026657 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ #ifndef __TLM_GENERIC_PAYLOAD_H__ #define __TLM_GENERIC_PAYLOAD_H__ #include "tlm_core/tlm_2/tlm_generic_payload/tlm_helpers.h" #include "tlm_core/tlm_2/tlm_generic_payload/tlm_phase.h" #include "tlm_core/tlm_2/tlm_generic_payload/tlm_gp.h" #include "tlm_core/tlm_2/tlm_generic_payload/tlm_endian_conv.h" #endif systemc-2.3.3/src/tlm_core/tlm_1/0000755000175000017500000000000013360325173016500 5ustar carstencarstensystemc-2.3.3/src/tlm_core/tlm_1/README.txt0000644000175000017500000000633013360325173020200 0ustar carstencarstenTLM-1.0 header files ==================== Dir: include/tlm_core/tlm_1/ SubDirs: tlm_analysis/ tlm_req_rsp/ Files: README.txt Comments ======== User code should only #include the tlm or tlm.h header file in the include/ directory and avoid including any of the include files in this directory directly. All objects defined in this file hierarchy are in the tlm namespace. The header files are organizated, by subdirectory, as follows: tlm_analysis/ -------------- This contains the analysis interfaces, ports, and fifos. These files were not part of the original TLM-1.0 release, but have been grouped with TLM-1.0 in this release of TLM-2.0 Files: tlm_analysis.h (includes the other header files in this directory ) tlm_analysis_fifo.h (defines tlm_analysis_fifo ) tlm_analysis_if.h (defines tlm_analysis_if and tlm_delayed_analysis_if ) tlm_analysis_port.h (defines tlm_analysis_port ) tlm_analysis_triple.h (defines tlm_analysis_triple ) tlm_write_if.h (defines tlm_write_if and tlm_delayed_write_if ) tlm_req_rsp/ ------------ This provides support for TLM modeling based on a request/response pair that are passed by value. This is the original TLM 1.0 standard, with the addition of an overloading of the blocking transport method with pass-by-reference arguments. Files: tlm_req_rsp.h (includes the key header files from the other directories) tlm_1_interfaces/ tlm_core_ifs.h (defines the TLM 1.0 core interfaces: tlm_transport_if tlm_blocking_get_if tlm_blocking_put_if tlm_nonblocking_get_if tlm_nonblocking_put_if tlm_get_if tlm_put_if tlm_blocking_peek_if tlm_nonblocking_peek_if tlm_peek_if tlm_blocking_get_peek_if tlm_nonblocking_get_peek_if tlm_get_peek_if ) tlm_fifo_ifs.h ( defines the TLM1.0 fifo interfaces: tlm_fifo_debug_if tlm_fifo_put_if tlm_fifo_get_if tlm_fifo_config_size_if ) tlm_master_slave_ifs.h ( defines the TLM1.0 master slave interfaces: tlm_blocking_master_if tlm_blocking_slave_if tlm_nonblocking_master_if tlm_nonblocking_slave_if tlm_master_if tlm_slave_if ) tlm_tag.h ( defines tlm_tag ) tlm_ports/ tlm_nonblocking_port.h (defines tlm_nonblocking_put_port, tlm_nonblocking_get_port and tlm_nonblocking_peek_port ) tlm_event_finder.h (defines tlm_event_finder_t ) tlm_channels/ tlm_fifo/ tlm_fifo.h (defines tlm_fifo, includes the other files ) tlm_fifo_peek.h (defines peek and poke interfaces for tlm_fifo ) tlm_fifo_put_get.h (defines put and get interfaces for tlm_fifo ) tlm_fifo_resize.h (defines expand, reduce, bound and unbound interfaces for tlm_fifo ) circular_buffer.h (defines circular buffer used by tlm_fifo ) tlm_req_rsp_channels/ tlm_req_rsp_channels.h (defines tlm_req_rsp_channel and tlm_transport_channel ) tlm_put_get_imp.h (contains implementatins used by the channels) tlm_adapters/ tlm_adapters.h (defines transport_to_master and tlm_slave_to_transport) systemc-2.3.3/src/tlm_core/tlm_1/tlm_analysis/0000755000175000017500000000000013360325173021177 5ustar carstencarstensystemc-2.3.3/src/tlm_core/tlm_1/tlm_analysis/tlm_analysis_triple.h0000644000175000017500000000305113360325173025425 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ #ifndef __TLM_ANALYSIS_TRIPLE_H__ #define __TLM_ANALYSIS_TRIPLE_H__ //#include namespace tlm { template< typename T> struct tlm_analysis_triple { sc_core::sc_time start_time; T transaction; sc_core::sc_time end_time; tlm_analysis_triple() {} tlm_analysis_triple( const tlm_analysis_triple &triple ) { start_time = triple.start_time; transaction = triple.transaction; end_time = triple.end_time; } tlm_analysis_triple( const T &t ) { transaction = t; } operator T() { return transaction; } operator const T &() const { return transaction; } }; } // namespace tlm #endif systemc-2.3.3/src/tlm_core/tlm_1/tlm_analysis/tlm_write_if.h0000644000175000017500000000253513360325173024041 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ #ifndef __TLM_WRITE_IF_H__ #define __TLM_WRITE_IF_H__ #include namespace tlm { template class tlm_write_if : public virtual sc_core::sc_interface { public: virtual void write(const T& t) = 0; }; template class tlm_delayed_write_if : public virtual sc_core::sc_interface { public: virtual void write(const T& t, const sc_core::sc_time& time) = 0; }; } // namespace tlm #endif systemc-2.3.3/src/tlm_core/tlm_1/tlm_analysis/tlm_analysis_port.h0000644000175000017500000000432613360325173025120 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ #ifndef __TLM_ANALYSIS_PORT_H__ #define __TLM_ANALYSIS_PORT_H__ #include "tlm_core/tlm_1/tlm_analysis/tlm_analysis_if.h" #include #include namespace tlm { template < typename T> class tlm_analysis_port : public sc_core::sc_object , public virtual tlm_analysis_if< T > { public: tlm_analysis_port() : sc_core::sc_object() {} tlm_analysis_port( const char *nm ) : sc_core::sc_object( nm ) {} // bind and () work for both interfaces and analysis ports, since // analysis ports implement the analysis interface virtual void bind( tlm_analysis_if &_if ) { m_interfaces.push_back( &_if ); } void operator() ( tlm_analysis_if &_if ) { bind( _if ); } virtual bool unbind( tlm_analysis_if &_if ) { typename std::deque< tlm_analysis_if * >::iterator i = std::remove( m_interfaces.begin(), m_interfaces.end(), &_if ); if( i != m_interfaces.end() ) { m_interfaces.erase(i, m_interfaces.end() ); return 1; } return 0; } void write( const T &t ) { typename std::deque< tlm_analysis_if * >::iterator i; for( i = m_interfaces.begin(); i != m_interfaces.end(); i++ ) { (*i)->write( t ); } } private: std::deque< tlm_analysis_if * > m_interfaces; }; } // namespace tlm #endif systemc-2.3.3/src/tlm_core/tlm_1/tlm_analysis/tlm_analysis_if.h0000644000175000017500000000242113360325173024524 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ #ifndef __TLM_ANALYSIS_IF_H__ #define __TLM_ANALYSIS_IF_H__ #include "tlm_core/tlm_1/tlm_analysis/tlm_write_if.h" namespace tlm { template < typename T > class tlm_analysis_if : public virtual tlm_write_if { }; template < typename T > class tlm_delayed_analysis_if : public virtual tlm_delayed_write_if { }; } // namespace tlm #endif systemc-2.3.3/src/tlm_core/tlm_1/tlm_analysis/tlm_analysis.h0000644000175000017500000000243513360325173024053 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ #ifndef __TLM_ANALYSIS_H__ #define __TLM_ANALYSIS_H__ #include "tlm_core/tlm_1/tlm_analysis/tlm_write_if.h" #include "tlm_core/tlm_1/tlm_analysis/tlm_analysis_if.h" #include "tlm_core/tlm_1/tlm_analysis/tlm_analysis_triple.h" #include "tlm_core/tlm_1/tlm_analysis/tlm_analysis_port.h" #include "tlm_core/tlm_1/tlm_analysis/tlm_analysis_fifo.h" #endif systemc-2.3.3/src/tlm_core/tlm_1/tlm_analysis/tlm_analysis_fifo.h0000644000175000017500000000327313360325173025057 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ #ifndef __TLM_ANALYSIS_FIFO_H__ #define __TLM_ANALYSIS_FIFO_H__ #include "tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo.h" #include "tlm_core/tlm_1/tlm_analysis/tlm_analysis_if.h" #include "tlm_core/tlm_1/tlm_analysis/tlm_analysis_triple.h" namespace tlm { template< typename T > class tlm_analysis_fifo : public tlm_fifo< T > , public virtual tlm_analysis_if< T > , public virtual tlm_analysis_if< tlm_analysis_triple< T > > { public: // analysis fifo is an unbounded tlm_fifo tlm_analysis_fifo( const char *nm ) : tlm_fifo( nm , -16 ) {} tlm_analysis_fifo() : tlm_fifo( -16 ) {} void write( const tlm_analysis_triple &t ) { nb_put( t ); } void write( const T &t ) { nb_put( t ); } }; } // namespace tlm #endif systemc-2.3.3/src/tlm_core/tlm_1/tlm_req_rsp/0000755000175000017500000000000013360325173021027 5ustar carstencarstensystemc-2.3.3/src/tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/0000755000175000017500000000000013360325173024246 5ustar carstencarstensystemc-2.3.3/src/tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_fifo_ifs.h0000644000175000017500000000453313360325173027064 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ // // Note to the LRM writer : These interfaces are channel specific interfaces // useful in the context of tlm_fifo. // #ifndef __TLM_FIFO_IFS_H__ #define __TLM_FIFO_IFS_H__ #include "tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_core_ifs.h" namespace tlm { // // Fifo specific interfaces // // Fifo Debug Interface template< typename T > class tlm_fifo_debug_if : public virtual sc_core::sc_interface { public: virtual int used() const = 0; virtual int size() const = 0; virtual void debug() const = 0; // // non blocking peek and poke - no notification // // n is index of data : // 0 <= n < size(), where 0 is most recently written, and size() - 1 // is oldest ie the one about to be read. // virtual bool nb_peek( T & , int n ) const = 0; virtual bool nb_poke( const T & , int n = 0 ) = 0; }; // fifo interfaces = extended + debug template < typename T > class tlm_fifo_put_if : public virtual tlm_put_if , public virtual tlm_fifo_debug_if {}; template < typename T > class tlm_fifo_get_if : public virtual tlm_get_peek_if , public virtual tlm_fifo_debug_if {}; class tlm_fifo_config_size_if : public virtual sc_core::sc_interface { public: virtual void nb_expand( unsigned int n = 1 ) = 0; virtual void nb_unbound( unsigned int n = 16 ) = 0; virtual bool nb_reduce( unsigned int n = 1 ) = 0; virtual bool nb_bound( unsigned int n ) = 0; }; } // namespace tlm #endif systemc-2.3.3/src/tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_core_ifs.h0000644000175000017500000000763213360325173027074 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ // // Note to the LRM writer : This is the core of the TLM standard // #ifndef __TLM_CORE_IFS_H__ #define __TLM_CORE_IFS_H__ //#include #include "tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_tag.h" namespace tlm { // bidirectional blocking interfaces template < typename REQ , typename RSP > class tlm_transport_if : public virtual sc_core::sc_interface { public: virtual RSP transport( const REQ & ) = 0; virtual void transport( const REQ &req , RSP &rsp ) { rsp = transport( req ); } }; // uni-directional blocking interfaces template < typename T > class tlm_blocking_get_if : public virtual sc_core::sc_interface { public: virtual T get( tlm_tag *t = 0 ) = 0; virtual void get( T &t ) { t = get(); } }; template < typename T > class tlm_blocking_put_if : public virtual sc_core::sc_interface { public: virtual void put( const T &t ) = 0; }; // uni-directional non blocking interfaces template < typename T > class tlm_nonblocking_get_if : public virtual sc_core::sc_interface { public: virtual bool nb_get( T &t ) = 0; virtual bool nb_can_get( tlm_tag *t = 0 ) const = 0; virtual const sc_core::sc_event &ok_to_get( tlm_tag *t = 0 ) const = 0; }; template < typename T > class tlm_nonblocking_put_if : public virtual sc_core::sc_interface { public: virtual bool nb_put( const T &t ) = 0; virtual bool nb_can_put( tlm_tag *t = 0 ) const = 0; virtual const sc_core::sc_event &ok_to_put( tlm_tag *t = 0 ) const = 0; }; // combined uni-directional blocking and non blocking template < typename T > class tlm_get_if : public virtual tlm_blocking_get_if< T > , public virtual tlm_nonblocking_get_if< T > {}; template < typename T > class tlm_put_if : public virtual tlm_blocking_put_if< T > , public virtual tlm_nonblocking_put_if< T > {}; // peek interfaces template < typename T > class tlm_blocking_peek_if : public virtual sc_core::sc_interface { public: virtual T peek( tlm_tag *t = 0 ) const = 0; virtual void peek( T &t ) const { t = peek(); } }; template < typename T > class tlm_nonblocking_peek_if : public virtual sc_core::sc_interface { public: virtual bool nb_peek( T &t ) const = 0; virtual bool nb_can_peek( tlm_tag *t = 0 ) const = 0; virtual const sc_core::sc_event &ok_to_peek( tlm_tag *t = 0 ) const = 0; }; template < typename T > class tlm_peek_if : public virtual tlm_blocking_peek_if< T > , public virtual tlm_nonblocking_peek_if< T > {}; // get_peek interfaces template < typename T > class tlm_blocking_get_peek_if : public virtual tlm_blocking_get_if , public virtual tlm_blocking_peek_if {}; template < typename T > class tlm_nonblocking_get_peek_if : public virtual tlm_nonblocking_get_if , public virtual tlm_nonblocking_peek_if {}; template < typename T > class tlm_get_peek_if : public virtual tlm_get_if , public virtual tlm_peek_if , public virtual tlm_blocking_get_peek_if , public virtual tlm_nonblocking_get_peek_if {}; } // namespace tlm #endif systemc-2.3.3/src/tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_tag.h0000644000175000017500000000215413360325173026050 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ // // Note to the LRM writer : This is part of the core TLM standard // #ifndef __TLM_TAG_H__ #define __TLM_TAG_H__ namespace tlm { template class tlm_tag {}; } #endif systemc-2.3.3/src/tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_master_slave_ifs.h0000644000175000017500000000460013360325173030621 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ #ifndef __TLM_MASTER_SLAVE_IFS_H__ #define __TLM_MASTER_SLAVE_IFS_H__ #include "tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_core_ifs.h" namespace tlm { // // req/rsp combined interfaces // // blocking template < typename REQ , typename RSP> class tlm_blocking_master_if : public virtual tlm_blocking_put_if< REQ > , public virtual tlm_blocking_get_peek_if< RSP > {}; template < typename REQ , typename RSP> class tlm_blocking_slave_if : public virtual tlm_blocking_put_if< RSP > , public virtual tlm_blocking_get_peek_if< REQ > {}; // nonblocking template < typename REQ , typename RSP > class tlm_nonblocking_master_if : public virtual tlm_nonblocking_put_if< REQ > , public virtual tlm_nonblocking_get_peek_if< RSP > {}; template < typename REQ , typename RSP > class tlm_nonblocking_slave_if : public virtual tlm_nonblocking_put_if< RSP > , public virtual tlm_nonblocking_get_peek_if< REQ > {}; // combined template < typename REQ , typename RSP > class tlm_master_if : public virtual tlm_put_if< REQ > , public virtual tlm_get_peek_if< RSP > , public virtual tlm_blocking_master_if< REQ , RSP > , public virtual tlm_nonblocking_master_if< REQ , RSP > {}; template < typename REQ , typename RSP > class tlm_slave_if : public virtual tlm_put_if< RSP > , public virtual tlm_get_peek_if< REQ > , public virtual tlm_blocking_slave_if< REQ , RSP > , public virtual tlm_nonblocking_slave_if< REQ , RSP > {}; } // namespace tlm #endif systemc-2.3.3/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/0000755000175000017500000000000013360325173023476 5ustar carstencarstensystemc-2.3.3/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/0000755000175000017500000000000013360325173025275 5ustar carstencarstensystemc-2.3.3/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_peek.h0000644000175000017500000000373413360325173030260 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ #ifndef __TLM_FIFO_PEEK_H__ #define __TLM_FIFO_PEEK_H__ namespace tlm { template < typename T> inline T tlm_fifo::peek( tlm_tag * ) const { while( is_empty() ) { // call free-standing sc_core::wait(), // since sc_prim_channel::wait(.) is not const sc_core::wait( m_data_written_event ); } return buffer.read_data(); } template < typename T> inline bool tlm_fifo::nb_peek( T &t ) const { if( used() < 1 ) { return false; } t = buffer.peek_data( 0 ); return true; } template < typename T> inline bool tlm_fifo::nb_peek( T &t , int n ) const { if( n >= used() || n < -1 ) { return false; } if( n == -1 ) { n = used() - 1; } t = buffer.peek_data( n ); return true; } template< typename T > inline bool tlm_fifo::nb_can_peek( tlm_tag * ) const { return !is_empty(); } template < typename T> inline bool tlm_fifo::nb_poke( const T &t , int n ) { if( n >= used() || n < 0 ) { return false; } buffer.poke_data( n ) = t; return true; } } // namespace tlm #endif systemc-2.3.3/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_resize.h0000644000175000017500000000372213360325173030632 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ #ifndef __TLM_FIFO_RESIZE_H__ #define __TLM_FIFO_RESIZE_H__ /****************************************************************** // // resize interface // ******************************************************************/ namespace tlm { template < typename T> inline void tlm_fifo::nb_expand( unsigned int n ) { if( m_size >= 0 ) { m_expand = true; m_size += n; request_update(); } } template < typename T> inline void tlm_fifo::nb_unbound( unsigned int n ) { m_expand = true; m_size = -n; if( buffer.size() < static_cast( n ) ) { buffer.resize( n ); } request_update(); } template < typename T> inline bool tlm_fifo::nb_reduce( unsigned int n ) { if( m_size < 0 ) { return false; } return nb_bound( size() - n ); } template < typename T> inline bool tlm_fifo::nb_bound( unsigned int new_size ) { bool ret = true; if( static_cast( new_size ) < used() ) { new_size = used(); ret = false; } m_size = new_size; return ret; } } // namespace tlm #endif systemc-2.3.3/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_put_get.h0000644000175000017500000000501713360325173030777 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ #ifndef __TLM_FIFO_PUT_GET_IF_H__ #define __TLM_FIFO_PUT_GET_IF_H__ namespace tlm { /****************************************************************** // // get interface // ******************************************************************/ template inline T tlm_fifo::get( tlm_tag * ) { while( is_empty() ) { wait( m_data_written_event ); } m_num_read ++; request_update(); return buffer.read(); } // non-blocking read template inline bool tlm_fifo::nb_get( T& val_ ) { if( is_empty() ) { return false; } m_num_read ++; request_update(); val_ = buffer.read(); return true; } template inline bool tlm_fifo::nb_can_get( tlm_tag * ) const { return !is_empty(); } /****************************************************************** // // put interface // ******************************************************************/ template inline void tlm_fifo::put( const T& val_ ) { while( is_full() ) { wait( m_data_read_event ); } if( buffer.is_full() ) { buffer.resize( buffer.size() * 2 ); } m_num_written ++; buffer.write( val_ ); request_update(); } template inline bool tlm_fifo::nb_put( const T& val_ ) { if( is_full() ) { return false; } if( buffer.is_full() ) { buffer.resize( buffer.size() * 2 ); } m_num_written ++; buffer.write( val_ ); request_update(); return true; } template < typename T > inline bool tlm_fifo::nb_can_put( tlm_tag * ) const { return !is_full(); } } // namespace tlm #endif systemc-2.3.3/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/circular_buffer.h0000644000175000017500000001257613360325173030616 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ // // To the LRM writer : this class is purely an artifact of the implementation. // #ifndef __CIRCULAR_BUFFER_H__ #define __CIRCULAR_BUFFER_H__ #include namespace tlm { template < typename T > class circular_buffer { public: explicit circular_buffer( int size = 0 ); ~circular_buffer(); void resize( int size ); void clear(); T read(); void write( const T & ); bool is_empty() const { return used() == 0; } bool is_full() const { return free() == 0; } int size() const { return m_size; } int used() const { return m_used; } int free() const { return m_free; } const T& read_data() const { return buf_read( m_buf, m_ri ); } const T& peek_data( int i ) const { return buf_read( m_buf, (m_ri + i) % size() ); } T & poke_data( int i ) { return buf_read( m_buf , (m_wi + i) % size() ); } void debug() const; private: void increment_write_pos( int i = 1 ); void increment_read_pos( int i = 1 ); void init(); circular_buffer( const circular_buffer &b ); // disabled circular_buffer &operator=( const circular_buffer & ); // disabled void* buf_alloc( int size ); void buf_free( void*& buf ); void buf_write( void* buf, int n, const T & t ); T& buf_read( void* buf, int n ) const; void buf_clear( void* buf, int n ); private: int m_size; // size of the buffer void* m_buf; // the buffer int m_free; // number of free spaces int m_used; // number of used spaces int m_ri; // index of next read int m_wi; // index of next write }; template< typename T > void circular_buffer::debug() const { std::cout << "Buffer debug" << std::endl; std::cout << "Size : " << size() << std::endl; std::cout << "Free/Used " << free() << "/" << used() << std::endl; std::cout << "Indices : r/w = " << m_ri << "/" << m_wi << std::endl; if( is_empty() ) { std::cout << "empty" << std::endl; } if( is_full() ) { std::cout << "full" << std::endl; } std::cout << "Data : " << std::endl; for( int i = 0; i < used(); i++ ) { std::cout << peek_data( i ) << std::endl; } } template < typename T > circular_buffer::circular_buffer( int size ) : m_size(size) , m_buf(0) { init(); } template < typename T > void circular_buffer::clear() { for( int i=0; i < used(); i++ ) { buf_clear( m_buf, (m_ri + i) % m_size ); } m_free = m_size; m_used = m_ri = m_wi = 0; } template < typename T > circular_buffer::~circular_buffer() { clear(); buf_free( m_buf ); } template < typename T > void circular_buffer::resize( int size ) { int i; void * new_buf = buf_alloc(size); for( i = 0; i < size && i < used(); i++ ) { buf_write( new_buf, i, peek_data( i ) ); buf_clear( m_buf, (m_ri + i) % m_size ); } buf_free( m_buf ); m_size = size; m_ri = 0; m_wi = i % m_size; m_used = i; m_free = m_size - m_used; m_buf = new_buf; } template < typename T > void circular_buffer::init() { if( m_size > 0 ) { m_buf = buf_alloc( m_size ); } m_free = m_size; m_used = 0; m_ri = 0; m_wi = 0; } template < typename T > T circular_buffer::read() { T t = read_data(); buf_clear( m_buf, m_ri ); increment_read_pos(); return t; } template < typename T > void circular_buffer::write( const T &t ) { buf_write( m_buf, m_wi, t ); increment_write_pos(); } template < typename T > void circular_buffer::increment_write_pos( int i ) { m_wi = ( m_wi + i ) % m_size; m_used += i; m_free -= i; } template < typename T > void circular_buffer::increment_read_pos( int i ) { m_ri = ( m_ri + i ) % m_size; m_used -= i; m_free += i; } template < typename T > inline void* circular_buffer::buf_alloc( int size ) { return new unsigned char[ size * sizeof(T) ]; } template < typename T > inline void circular_buffer::buf_free( void* & buf ) { delete [] static_cast(buf); buf = 0; } template < typename T > inline void circular_buffer::buf_write( void* buf, int n, const T & t ) { T* p = static_cast(buf) + n; new (p) T(t); } template < typename T > inline T& circular_buffer::buf_read( void* buf, int n ) const { T* p = static_cast(buf) + n; return *p; } template < typename T > inline void circular_buffer::buf_clear( void* buf, int n ) { T* p = static_cast(buf) + n; p->~T(); } } // namespace tlm #endif systemc-2.3.3/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo.h0000644000175000017500000001434313360325173027252 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ #ifndef __TLM_FIFO_H__ #define __TLM_FIFO_H__ // // This implements put, get and peek // // It also implements 0 and infinite size fifos - but the size // zero fifos aren't rendezvous like zero length fifos, they simply are both // full and empty at the same time. // // The size can be dynamically changed using the resize interface // // To get an infinite fifo use a -ve size in the constructor. // The absolute value of the size is taken as the starting size of the // actual physical buffer. // //#include #include "tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_fifo_ifs.h" #include "tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/circular_buffer.h" namespace tlm { template class tlm_fifo : public virtual tlm_fifo_get_if, public virtual tlm_fifo_put_if, public sc_core::sc_prim_channel { public: // constructors explicit tlm_fifo( int size_ = 1 ) : sc_core::sc_prim_channel( sc_core::sc_gen_unique_name( "fifo" ) ) { init( size_ ); } explicit tlm_fifo( const char* name_, int size_ = 1 ) : sc_core::sc_prim_channel( name_ ) { init( size_ ); } // destructor virtual ~tlm_fifo() {} // tlm get interface T get( tlm_tag * = 0 ); bool nb_get( T& ); bool nb_can_get( tlm_tag * = 0 ) const; const sc_core::sc_event &ok_to_get( tlm_tag * = 0 ) const { return m_data_written_event; } // tlm peek interface T peek( tlm_tag * = 0 ) const; bool nb_peek( T& ) const; bool nb_can_peek( tlm_tag * = 0 ) const; const sc_core::sc_event &ok_to_peek( tlm_tag * = 0 ) const { return m_data_written_event; } // tlm put interface void put( const T& ); bool nb_put( const T& ); bool nb_can_put( tlm_tag * = 0 ) const; const sc_core::sc_event& ok_to_put( tlm_tag * = 0 ) const { return m_data_read_event; } // resize if void nb_expand( unsigned int n = 1 ); void nb_unbound( unsigned int n = 16 ); bool nb_reduce( unsigned int n = 1 ); bool nb_bound( unsigned int n ); // debug interface bool nb_peek( T & , int n ) const; bool nb_poke( const T & , int n = 0 ); int used() const { return m_num_readable - m_num_read; } int size() const { return m_size; } void debug() const { if( is_empty() ) std::cout << "empty" << std::endl; if( is_full() ) std::cout << "full" << std::endl; std::cout << "size " << size() << " - " << used() << " used " << std::endl; std::cout << "readable " << m_num_readable << std::endl; std::cout << "written/read " << m_num_written << "/" << m_num_read << std::endl; } // support functions static const char* const kind_string; const char* kind() const { return kind_string; } protected: sc_core::sc_event &read_event( tlm_tag * = 0 ) { return m_data_read_event; } protected: void update(); // support methods void init( int ); protected: circular_buffer buffer; int m_size; // logical size of fifo int m_num_readable; // #samples readable int m_num_read; // #samples read during this delta cycle int m_num_written; // #samples written during this delta cycle bool m_expand; // has an expand occurred during this delta cycle ? int m_num_read_no_notify; // #samples read without notify during this delta cycle sc_core::sc_event m_data_read_event; sc_core::sc_event m_data_written_event; private: // disabled tlm_fifo( const tlm_fifo& ); tlm_fifo& operator = ( const tlm_fifo& ); // // use nb_can_get() and nb_can_put() rather than the following two // private functions // bool is_empty() const { return used() == 0; } bool is_full() const { //return size() == m_num_readable + m_num_written; // Old buggy code if( size() < 0 ) return false; else return size() <= m_num_readable + m_num_written; } }; template const char* const tlm_fifo::kind_string = "tlm_fifo"; /****************************************************************** // // init and update // ******************************************************************/ template< typename T > inline void tlm_fifo::init( int size_ ) { if( size_ > 0 ) { buffer.resize( size_ ); } else if( size_ < 0 ) { buffer.resize( -size_ ); } else { buffer.resize( 16 ); } m_size = size_; m_num_readable = 0; m_num_read = 0; m_num_written = 0; m_expand = false; m_num_read_no_notify = false; } template < typename T> inline void tlm_fifo::update() { if( m_num_read > m_num_read_no_notify || m_expand ) { m_data_read_event.notify( sc_core::SC_ZERO_TIME ); } if( m_num_written > 0 ) { m_data_written_event.notify( sc_core::SC_ZERO_TIME ); } m_expand = false; m_num_read = 0; m_num_written = 0; m_num_readable = buffer.used(); m_num_read_no_notify = 0; } } // namespace tlm #include "tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_put_get.h" #include "tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_peek.h" #include "tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_resize.h" #endif systemc-2.3.3/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_req_rsp_channels/0000755000175000017500000000000013360325173027700 5ustar carstencarsten././@LongLink0000644000000000000000000000014600000000000011604 Lustar rootrootsystemc-2.3.3/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_req_rsp_channels/tlm_req_rsp_channels.hsystemc-2.3.3/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_req_rsp_channels/tlm_req_rsp_channels.0000644000175000017500000001056213360325173034107 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ #ifndef __TLM_REQ_RSP_CHANNELS_H__ #define __TLM_REQ_RSP_CHANNELS_H__ #include "tlm_core/tlm_1/tlm_req_rsp/tlm_adapters/tlm_adapters.h" #include "tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo.h" #include "tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_req_rsp_channels/tlm_put_get_imp.h" namespace tlm { template < typename REQ , typename RSP , typename REQ_CHANNEL = tlm_fifo , typename RSP_CHANNEL = tlm_fifo > class tlm_req_rsp_channel : public sc_core::sc_module { public: // uni-directional slave interface sc_core::sc_export< tlm_fifo_get_if< REQ > > get_request_export; sc_core::sc_export< tlm_fifo_put_if< RSP > > put_response_export; // uni-directional master interface sc_core::sc_export< tlm_fifo_put_if< REQ > > put_request_export; sc_core::sc_export< tlm_fifo_get_if< RSP > > get_response_export; // master / slave interfaces sc_core::sc_export< tlm_master_if< REQ , RSP > > master_export; sc_core::sc_export< tlm_slave_if< REQ , RSP > > slave_export; tlm_req_rsp_channel( int req_size = 1 , int rsp_size = 1 ) : sc_core::sc_module( sc_core::sc_module_name( sc_core::sc_gen_unique_name("tlm_req_rsp_channel") ) ) , request_fifo( req_size ) , response_fifo( rsp_size ) , master( request_fifo , response_fifo ) , slave( request_fifo , response_fifo ) { bind_exports(); } tlm_req_rsp_channel( sc_core::sc_module_name module_name , int req_size = 1 , int rsp_size = 1 ) : sc_core::sc_module( module_name ) , request_fifo( req_size ) , response_fifo( rsp_size ) , master( request_fifo , response_fifo ) , slave( request_fifo , response_fifo ) { bind_exports(); } private: void bind_exports() { put_request_export( request_fifo ); get_request_export( request_fifo ); put_response_export( response_fifo ); get_response_export( response_fifo ); master_export( master ); slave_export( slave ); } protected: REQ_CHANNEL request_fifo; RSP_CHANNEL response_fifo; tlm_master_imp< REQ , RSP > master; tlm_slave_imp< REQ , RSP > slave; }; template < typename REQ , typename RSP , typename REQ_CHANNEL = tlm_fifo , typename RSP_CHANNEL = tlm_fifo > class tlm_transport_channel : public sc_core::sc_module { public: // master transport interface sc_core::sc_export< tlm_transport_if< REQ , RSP > > target_export; // slave interfaces sc_core::sc_export< tlm_fifo_get_if< REQ > > get_request_export; sc_core::sc_export< tlm_fifo_put_if< RSP > > put_response_export; sc_core::sc_export< tlm_slave_if< REQ , RSP > > slave_export; tlm_transport_channel() : sc_core::sc_module( sc_core::sc_module_name( sc_core::sc_gen_unique_name("transport_channel" ) ) ) , target_export("target_export") , req_rsp( "req_rsp" , 1 , 1 ) , t2m("ts2m") { do_binding(); } tlm_transport_channel( sc_core::sc_module_name nm ) : sc_core::sc_module( nm ) , target_export("target_export") , req_rsp( "req_rsp" , 1 , 1 ) , t2m("tsm" ) { do_binding(); } private: void do_binding() { target_export( t2m.target_export ); t2m.master_port( req_rsp.master_export ); get_request_export( req_rsp.get_request_export ); put_response_export( req_rsp.put_response_export ); slave_export( req_rsp.slave_export ); } tlm_req_rsp_channel< REQ , RSP , REQ_CHANNEL , RSP_CHANNEL > req_rsp; tlm_transport_to_master< REQ , RSP > t2m; }; } // namespace tlm #endif systemc-2.3.3/src/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_req_rsp_channels/tlm_put_get_imp.h0000644000175000017500000000636213360325173033250 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ // // To the LRM writer : these classes are purely artifacts of the implementation. // #ifndef __TLM_PUT_GET_IMP_H__ #define __TLM_PUT_GET_IMP_H__ #include "tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_master_slave_ifs.h" namespace tlm { template < typename PUT_DATA , typename GET_DATA> class tlm_put_get_imp : public virtual tlm_put_if< PUT_DATA > , public virtual tlm_get_peek_if< GET_DATA > { public: tlm_put_get_imp( tlm_put_if &p , tlm_get_peek_if &g ) : put_fifo( p ) , get_fifo( g ) {} // put interface void put( const PUT_DATA &t ) { put_fifo.put( t ); } bool nb_put( const PUT_DATA &t ) { return put_fifo.nb_put( t ); } bool nb_can_put( tlm_tag *t = 0 ) const { return put_fifo.nb_can_put( t ); } const sc_core::sc_event &ok_to_put( tlm_tag *t = 0 ) const { return put_fifo.ok_to_put( t ); } // get interface GET_DATA get( tlm_tag * = 0 ) { return get_fifo.get(); } bool nb_get( GET_DATA &t ) { return get_fifo.nb_get( t ); } bool nb_can_get( tlm_tag *t = 0 ) const { return get_fifo.nb_can_get( t ); } virtual const sc_core::sc_event &ok_to_get( tlm_tag *t = 0 ) const { return get_fifo.ok_to_get( t ); } // peek interface GET_DATA peek( tlm_tag * = 0 ) const { return get_fifo.peek(); } bool nb_peek( GET_DATA &t ) const { return get_fifo.nb_peek( t ); } bool nb_can_peek( tlm_tag *t = 0 ) const { return get_fifo.nb_can_peek( t ); } virtual const sc_core::sc_event &ok_to_peek( tlm_tag *t = 0 ) const { return get_fifo.ok_to_peek( t ); } private: tlm_put_if &put_fifo; tlm_get_peek_if &get_fifo; }; template < typename REQ , typename RSP > class tlm_master_imp : private tlm_put_get_imp< REQ , RSP > , public virtual tlm_master_if< REQ , RSP > { public: tlm_master_imp( tlm_put_if &req , tlm_get_peek_if &rsp ) : tlm_put_get_imp( req , rsp ) {} }; template < typename REQ , typename RSP > class tlm_slave_imp : private tlm_put_get_imp< RSP , REQ > , public virtual tlm_slave_if< REQ , RSP > { public: tlm_slave_imp( tlm_get_peek_if &req , tlm_put_if &rsp ) : tlm_put_get_imp( rsp , req ) {} }; } // namespace tlm #endif systemc-2.3.3/src/tlm_core/tlm_1/tlm_req_rsp/tlm_ports/0000755000175000017500000000000013360325173023052 5ustar carstencarstensystemc-2.3.3/src/tlm_core/tlm_1/tlm_req_rsp/tlm_ports/tlm_event_finder.h0000644000175000017500000000471413360325173026555 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ #ifndef TLM_CORE_TLM_EVENT_FINDER_H_INCLUDED_ #define TLM_CORE_TLM_EVENT_FINDER_H_INCLUDED_ #include "tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_tag.h" namespace tlm { template class tlm_event_finder_t : public sc_core::sc_event_finder { public: // constructor tlm_event_finder_t( const sc_core::sc_port_base& port_, const sc_core::sc_event& (IF::*event_method_) ( tlm_tag * ) const ) : sc_core::sc_event_finder( port_ ), m_event_method( event_method_ ) {} // destructor (does nothing) virtual ~tlm_event_finder_t() {} virtual const sc_core::sc_event& find_event( sc_core::sc_interface* if_p = 0 ) const; private: const sc_core::sc_event& (IF::*m_event_method) ( tlm_tag * ) const; private: // disabled tlm_event_finder_t(); tlm_event_finder_t( const tlm_event_finder_t& ); tlm_event_finder_t& operator = ( const tlm_event_finder_t& ); }; template inline const sc_core::sc_event& tlm_event_finder_t::find_event( sc_core::sc_interface* if_p ) const { const IF* iface = ( if_p ) ? dynamic_cast( if_p ) : dynamic_cast( port().get_interface() ); if( iface == 0 ) { report_error( sc_core::SC_ID_FIND_EVENT_, "port is not bound" ); return sc_core::sc_event::none; } return (const_cast( iface )->*m_event_method) ( 0 ); } } // namespace tlm #endif // TLM_CORE_TLM_EVENT_FINDER_H_INCLUDED_ systemc-2.3.3/src/tlm_core/tlm_1/tlm_req_rsp/tlm_ports/tlm_nonblocking_port.h0000644000175000017500000000507013360325173027450 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ #ifndef __TLM_NONBLOCKING_PORT_H__ #define __TLM_NONBLOCKING_PORT_H__ #include "tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_core_ifs.h" #include "tlm_core/tlm_1/tlm_req_rsp/tlm_ports/tlm_event_finder.h" namespace tlm { template < typename T > class tlm_nonblocking_get_port : public sc_core::sc_port< tlm_nonblocking_get_if< T > , 1 > { public: typedef tlm_nonblocking_get_if get_if_type; tlm_nonblocking_get_port( const char *port_name ) : sc_core::sc_port< tlm_nonblocking_get_if< T > , 1 >( port_name ) {} sc_core::sc_event_finder& ok_to_get() const { return *new tlm_event_finder_t< get_if_type , T >( *this, &get_if_type::ok_to_get ); } }; template < typename T > class tlm_nonblocking_peek_port : public sc_core::sc_port< tlm_nonblocking_peek_if< T > , 1 > { public: typedef tlm_nonblocking_peek_if peek_if_type; tlm_nonblocking_peek_port( const char *port_name ) : sc_core::sc_port< tlm_nonblocking_peek_if< T > , 1 >( port_name ) {} sc_core::sc_event_finder& ok_to_peek() const { return *new tlm_event_finder_t< peek_if_type , T >( *this, &peek_if_type::ok_to_peek ); } }; template < typename T > class tlm_nonblocking_put_port : public sc_core::sc_port< tlm_nonblocking_put_if< T > , 1 > { public: typedef tlm_nonblocking_put_if put_if_type; tlm_nonblocking_put_port( const char *port_name ) : sc_core::sc_port< tlm_nonblocking_put_if< T > , 1 >( port_name ) {} sc_core::sc_event_finder& ok_to_put() const { return *new tlm_event_finder_t< put_if_type , T >( *this, &put_if_type::ok_to_put ); } }; } // namespace tlm #endif systemc-2.3.3/src/tlm_core/tlm_1/tlm_req_rsp/tlm_adapters/0000755000175000017500000000000013360325173023506 5ustar carstencarstensystemc-2.3.3/src/tlm_core/tlm_1/tlm_req_rsp/tlm_adapters/tlm_adapters.h0000644000175000017500000000510313360325173026335 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ #ifndef __TLM_ADAPTERS_H__ #define __TLM_ADAPTERS_H__ #include "tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_master_slave_ifs.h" namespace tlm { template< typename REQ , typename RSP > class tlm_transport_to_master : public sc_core::sc_module , public virtual tlm_transport_if< REQ , RSP > { public: sc_core::sc_export< tlm_transport_if< REQ , RSP > > target_export; sc_core::sc_port< tlm_master_if< REQ , RSP > > master_port; tlm_transport_to_master( sc_core::sc_module_name nm ) : sc_core::sc_module( nm ) { target_export( *this ); } tlm_transport_to_master() : sc_core::sc_module( sc_core::sc_module_name( sc_core::sc_gen_unique_name( "transport_to_master" ) ) ){ target_export( *this ); } RSP transport( const REQ &req ) { mutex.lock(); master_port->put( req ); rsp = master_port->get(); mutex.unlock(); return rsp; } private: sc_core::sc_mutex mutex; RSP rsp; }; template< typename REQ , typename RSP > class tlm_slave_to_transport : public sc_core::sc_module { public: SC_HAS_PROCESS( tlm_slave_to_transport ); sc_core::sc_port< tlm_slave_if< REQ , RSP > > slave_port; sc_core::sc_port< tlm_transport_if< REQ , RSP > > initiator_port; tlm_slave_to_transport( sc_core::sc_module_name nm ) : sc_core::sc_module( nm ) {} tlm_slave_to_transport() : sc_core::sc_module( sc_core::sc_module_name( sc_core::sc_gen_unique_name("slave_to_transport") ) ) {} private: void run() { REQ req; RSP rsp; while( true ) { slave_port->get( req ); rsp = initiator_port->transport( req ); slave_port->put( rsp ); } } }; } // namespace tlm #endif systemc-2.3.3/src/tlm_core/tlm_1/tlm_req_rsp/tlm_req_rsp.h0000644000175000017500000000276113360325173023535 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ #ifndef __TLM_REQ_RSP_H__ #define __TLM_REQ_RSP_H__ // The unannotated TLM interfaces #include "tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_core_ifs.h" #include "tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_master_slave_ifs.h" // The channels : tlm_fifo, tlm_transport_channel and tlm_req_rsp_channel #include "tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_req_rsp_channels/tlm_req_rsp_channels.h" // Some non blocking ports to provide static sensitivity #include "tlm_core/tlm_1/tlm_req_rsp/tlm_ports/tlm_nonblocking_port.h" #endif /* __TLM_REQ_RSP_H__ */ systemc-2.3.3/src/tlm_core/Makefile.in0000644000175000017500000006622713360325173017546 0ustar carstencarsten# Makefile.in generated by automake 1.14 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # top-level SystemC include directory is added in Make-rules.{sysc,examples} # build flags VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ DIST_COMMON = $(top_srcdir)/config/Make-rules.sysc \ $(top_srcdir)/config/Make-rules.common $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(top_srcdir)/config/depcomp \ $(nobase_localinclude_HEADERS) @WANT_DEBUG_TRUE@am__append_1 = $(DEBUG_CXXFLAGS) @WANT_DEBUG_TRUE@am__append_2 = $(DEBUG_CXXFLAGS) @WANT_DEBUG_TRUE@am__append_3 = $(DEBUG_CXXFLAGS) @WANT_OPTIMIZE_TRUE@am__append_4 = $(OPT_CXXFLAGS) @WANT_OPTIMIZE_TRUE@am__append_5 = $(OPT_CXXFLAGS) # either for async_update locking or pthread processes @USES_PTHREADS_LIB_TRUE@am__append_6 = $(PTHREAD_CFLAGS) @USES_PTHREADS_LIB_TRUE@am__append_7 = $(PTHREAD_CFLAGS) @USES_PTHREADS_LIB_TRUE@am__append_8 = $(PTHREAD_LIBS) @DISABLE_ASYNC_UPDATES_TRUE@am__append_9 = -DSC_DISABLE_ASYNC_UPDATES @ENABLE_CALLBACKS_TRUE@am__append_10 = -DSC_ENABLE_SIMULATION_PHASE_CALLBACKS @ENABLE_CALLBACKS_TRACING_TRUE@am__append_11 = -DSC_ENABLE_SIMULATION_PHASE_CALLBACKS_TRACING @WANT_PTHREADS_THREADS_TRUE@am__append_12 = -DSC_USE_PTHREADS @DISABLE_VCD_SCOPES_TRUE@am__append_13 = -DSC_DISABLE_VCD_SCOPES subdir = src/tlm_core ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config/ax_check_define.m4 \ $(top_srcdir)/config/ax_pthread.m4 \ $(top_srcdir)/config/libtool.m4 \ $(top_srcdir)/config/ltoptions.m4 \ $(top_srcdir)/config/ltsugar.m4 \ $(top_srcdir)/config/ltversion.m4 \ $(top_srcdir)/config/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libtlm_core_la_LIBADD = am__dirstamp = $(am__leading_dot)dirstamp am__objects_1 = tlm_2/tlm_generic_payload/tlm_gp.lo \ tlm_2/tlm_generic_payload/tlm_phase.lo \ tlm_2/tlm_quantum/tlm_global_quantum.lo am_libtlm_core_la_OBJECTS = $(am__objects_1) libtlm_core_la_OBJECTS = $(am_libtlm_core_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/config/depcomp am__depfiles_maybe = depfiles am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) AM_V_CXX = $(am__v_CXX_@AM_V@) am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) am__v_CXX_0 = @echo " CXX " $@; am__v_CXX_1 = CXXLD = $(CXX) CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = SOURCES = $(libtlm_core_la_SOURCES) DIST_SOURCES = $(libtlm_core_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(localincludedir)" HEADERS = $(nobase_localinclude_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCAS = @CCAS@ CCASDEPMODE = @CCASDEPMODE@ CCASFLAGS = @CCASFLAGS@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEBUG_CXXFLAGS = @DEBUG_CXXFLAGS@ DEFS = $(PKGCONFIG_DEFINES) $(EXTRA_DEFINES) DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXPLICIT_LPTHREAD = @EXPLICIT_LPTHREAD@ EXTRA_ASFLAGS = @EXTRA_ASFLAGS@ EXTRA_CFLAGS = @EXTRA_CFLAGS@ EXTRA_CXXFLAGS = @EXTRA_CXXFLAGS@ EXTRA_LDFLAGS = @EXTRA_LDFLAGS@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LDFLAG_RPATH = @LDFLAG_RPATH@ LIBCONFIG_DEFINES = @LIBCONFIG_DEFINES@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIB_ARCH_SUFFIX = @LIB_ARCH_SUFFIX@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPT_CXXFLAGS = @OPT_CXXFLAGS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKGCONFIG_CFLAGS = @PKGCONFIG_CFLAGS@ PKGCONFIG_DEFINES = @PKGCONFIG_DEFINES@ PKGCONFIG_LDPRIV = @PKGCONFIG_LDPRIV@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ QT_ARCH = @QT_ARCH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TARGET_ARCH = @TARGET_ARCH@ TLM_PACKAGE_VERSION = @TLM_PACKAGE_VERSION@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ ax_pthread_config = @ax_pthread_config@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ examplesdir = @examplesdir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libarchdir = @libarchdir@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ rootdocdir = @rootdocdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src AM_CFLAGS = $(EXTRA_CFLAGS) $(am__append_2) $(am__append_5) \ $(am__append_7) AM_CXXFLAGS = $(EXTRA_CXXFLAGS) $(am__append_1) $(am__append_4) \ $(am__append_6) AM_CCASFLAGS = $(EXTRA_ASFLAGS) $(am__append_3) AM_LDFLAGS = $(EXTRA_LDFLAGS) $(am__append_8) # always add fix-point support EXTRA_DEFINES = -DSC_INCLUDE_FX -DSC_BUILD $(am__append_9) \ $(am__append_10) $(am__append_11) $(am__append_12) \ $(am__append_13) # initialize some useful variables (filled later) CLEANFILES = EXTRA_DIST = tlm_1/README.txt tlm_2/README.txt H_FILES = \ tlm_2/tlm_version.h \ tlm_2/tlm_2_interfaces/tlm_2_interfaces.h \ tlm_2/tlm_2_interfaces/tlm_dmi.h \ tlm_2/tlm_2_interfaces/tlm_fw_bw_ifs.h \ \ tlm_2/tlm_generic_payload/tlm_array.h \ tlm_2/tlm_generic_payload/tlm_endian_conv.h \ tlm_2/tlm_generic_payload/tlm_generic_payload.h \ tlm_2/tlm_generic_payload/tlm_gp.h \ tlm_2/tlm_generic_payload/tlm_helpers.h \ tlm_2/tlm_generic_payload/tlm_phase.h \ \ tlm_2/tlm_quantum/tlm_global_quantum.h \ tlm_2/tlm_quantum/tlm_quantum.h \ \ tlm_2/tlm_sockets/tlm_base_socket_if.h \ tlm_2/tlm_sockets/tlm_initiator_socket.h \ tlm_2/tlm_sockets/tlm_sockets.h \ tlm_2/tlm_sockets/tlm_target_socket.h \ \ tlm_1/tlm_analysis/tlm_analysis.h \ tlm_1/tlm_analysis/tlm_analysis_fifo.h \ tlm_1/tlm_analysis/tlm_analysis_if.h \ tlm_1/tlm_analysis/tlm_analysis_port.h \ tlm_1/tlm_analysis/tlm_analysis_triple.h \ tlm_1/tlm_analysis/tlm_write_if.h \ \ tlm_1/tlm_req_rsp/tlm_req_rsp.h \ tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_core_ifs.h \ tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_fifo_ifs.h \ tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_master_slave_ifs.h \ tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_tag.h \ \ tlm_1/tlm_req_rsp/tlm_adapters/tlm_adapters.h \ \ tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/circular_buffer.h \ tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo.h \ tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_peek.h \ tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_put_get.h \ tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_resize.h \ tlm_1/tlm_req_rsp/tlm_channels/tlm_req_rsp_channels/tlm_put_get_imp.h \ tlm_1/tlm_req_rsp/tlm_channels/tlm_req_rsp_channels/tlm_req_rsp_channels.h \ \ tlm_1/tlm_req_rsp/tlm_ports/tlm_event_finder.h \ tlm_1/tlm_req_rsp/tlm_ports/tlm_nonblocking_port.h CXX_FILES = \ tlm_2/tlm_generic_payload/tlm_gp.cpp \ tlm_2/tlm_generic_payload/tlm_phase.cpp \ tlm_2/tlm_quantum/tlm_global_quantum.cpp INCDIRS = \ tlm_2/tlm_2_interfaces \ tlm_2/tlm_generic_payload \ tlm_2/tlm_quantum \ tlm_2/tlm_sockets \ tlm_2 \ tlm_1/tlm_analysis \ tlm_1/tlm_req_rsp/tlm_1_interfaces \ tlm_1/tlm_req_rsp/tlm_adapters \ tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo \ tlm_1/tlm_req_rsp/tlm_channels/tlm_req_rsp_channels \ tlm_1/tlm_req_rsp/tlm_channels \ tlm_1/tlm_req_rsp/tlm_ports \ tlm_1/tlm_req_rsp \ tlm_1 localincludedir = $(includedir)/tlm_core nobase_localinclude_HEADERS = $(H_FILES) noinst_LTLIBRARIES = libtlm_core.la libtlm_core_la_SOURCES = $(NO_H_FILES) $(CXX_FILES) all: all-am .SUFFIXES: .SUFFIXES: .cpp .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/config/Make-rules.sysc $(top_srcdir)/config/Make-rules.common $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/tlm_core/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/tlm_core/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/config/Make-rules.sysc $(top_srcdir)/config/Make-rules.common: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } tlm_2/tlm_generic_payload/$(am__dirstamp): @$(MKDIR_P) tlm_2/tlm_generic_payload @: > tlm_2/tlm_generic_payload/$(am__dirstamp) tlm_2/tlm_generic_payload/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) tlm_2/tlm_generic_payload/$(DEPDIR) @: > tlm_2/tlm_generic_payload/$(DEPDIR)/$(am__dirstamp) tlm_2/tlm_generic_payload/tlm_gp.lo: \ tlm_2/tlm_generic_payload/$(am__dirstamp) \ tlm_2/tlm_generic_payload/$(DEPDIR)/$(am__dirstamp) tlm_2/tlm_generic_payload/tlm_phase.lo: \ tlm_2/tlm_generic_payload/$(am__dirstamp) \ tlm_2/tlm_generic_payload/$(DEPDIR)/$(am__dirstamp) tlm_2/tlm_quantum/$(am__dirstamp): @$(MKDIR_P) tlm_2/tlm_quantum @: > tlm_2/tlm_quantum/$(am__dirstamp) tlm_2/tlm_quantum/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) tlm_2/tlm_quantum/$(DEPDIR) @: > tlm_2/tlm_quantum/$(DEPDIR)/$(am__dirstamp) tlm_2/tlm_quantum/tlm_global_quantum.lo: \ tlm_2/tlm_quantum/$(am__dirstamp) \ tlm_2/tlm_quantum/$(DEPDIR)/$(am__dirstamp) libtlm_core.la: $(libtlm_core_la_OBJECTS) $(libtlm_core_la_DEPENDENCIES) $(EXTRA_libtlm_core_la_DEPENDENCIES) $(AM_V_CXXLD)$(CXXLINK) $(libtlm_core_la_OBJECTS) $(libtlm_core_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) -rm -f tlm_2/tlm_generic_payload/*.$(OBJEXT) -rm -f tlm_2/tlm_generic_payload/*.lo -rm -f tlm_2/tlm_quantum/*.$(OBJEXT) -rm -f tlm_2/tlm_quantum/*.lo distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@tlm_2/tlm_generic_payload/$(DEPDIR)/tlm_gp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tlm_2/tlm_generic_payload/$(DEPDIR)/tlm_phase.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tlm_2/tlm_quantum/$(DEPDIR)/tlm_global_quantum.Plo@am__quote@ .cpp.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cpp.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cpp.lo: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs -rm -rf tlm_2/tlm_generic_payload/.libs tlm_2/tlm_generic_payload/_libs -rm -rf tlm_2/tlm_quantum/.libs tlm_2/tlm_quantum/_libs install-nobase_localincludeHEADERS: $(nobase_localinclude_HEADERS) @$(NORMAL_INSTALL) @list='$(nobase_localinclude_HEADERS)'; test -n "$(localincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(localincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(localincludedir)" || exit 1; \ fi; \ $(am__nobase_list) | while read dir files; do \ xfiles=; for file in $$files; do \ if test -f "$$file"; then xfiles="$$xfiles $$file"; \ else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ test -z "$$xfiles" || { \ test "x$$dir" = x. || { \ echo " $(MKDIR_P) '$(DESTDIR)$(localincludedir)/$$dir'"; \ $(MKDIR_P) "$(DESTDIR)$(localincludedir)/$$dir"; }; \ echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(localincludedir)/$$dir'"; \ $(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(localincludedir)/$$dir" || exit $$?; }; \ done uninstall-nobase_localincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(nobase_localinclude_HEADERS)'; test -n "$(localincludedir)" || list=; \ $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ dir='$(DESTDIR)$(localincludedir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(localincludedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) -rm -f tlm_2/tlm_generic_payload/$(DEPDIR)/$(am__dirstamp) -rm -f tlm_2/tlm_generic_payload/$(am__dirstamp) -rm -f tlm_2/tlm_quantum/$(DEPDIR)/$(am__dirstamp) -rm -f tlm_2/tlm_quantum/$(am__dirstamp) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -rf tlm_2/tlm_generic_payload/$(DEPDIR) tlm_2/tlm_quantum/$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-nobase_localincludeHEADERS install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf tlm_2/tlm_generic_payload/$(DEPDIR) tlm_2/tlm_quantum/$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-nobase_localincludeHEADERS @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) uninstall-hook .MAKE: install-am install-strip uninstall-am .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-nobase_localincludeHEADERS \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ uninstall-hook uninstall-nobase_localincludeHEADERS uninstall-hook: test ! -d "$(localincludedir)" || ( set -e ; cd "$(localincludedir)"; \ for dir in $(INCDIRS) ; do test ! -d $$dir || rmdir $$dir ; done ; \ cd - ; rmdir "$(localincludedir)" ) # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: systemc-2.3.3/src/tlm_utils/0000755000175000017500000000000013360325173015674 5ustar carstencarstensystemc-2.3.3/src/tlm_utils/README.txt0000644000175000017500000000646613360325173017406 0ustar carstencarsten TLM-2.0 standard utilities ========================== Dir: include/tlm_utils SubDirs: Files: README.txt instance_specific_extensions.h multi_passthrough_initiator_socket.h multi_passthrough_target_socket.h multi_socket_bases.h peq_with_get.h simple_initiator_socket.h simple_target_socket.h peq_with_cb_and_phase.h passthrough_target_socket.h tlm_quantumkeeper.h Comments ======== This directory contains a number of ease-of-use and convenience implementations for the interoperability standard. All objects defined in the header files of this directory are contained in the tlm_util namespace. There is no tlm_utils.h header files containing all includes in order to avoid additional dependencies for TLM 2.0 Files: simple_initiator_socket.h version of an initiator socket that has a default implementation of all interfaces and allows to register an implementation for any of the interfaces to the socket, either unique interfaces or tagged interfaces (carrying an additional id) simple_target_socket.h version of a target socket that has a default implementation of all interfaces and allows to register an implementation for any of the interfaces to the socket, either unique interfaces or tagged interfaces (carrying an additional id) This socket allows to register only 1 of the transport interfaces (blocking or non-blocking) and implements a conversion in case the socket is used on the other interface passthrough_target_socket.h version of a target socket that has a default implementation of all interfaces and allows to register an implementation for any of the interfaces to the socket. multi_passthrough_initiator_socket.h an implementation of a socket that allows to bind multiple targets to the same initiator socket. Implements a mechanism to allow to identify in the backward path through which index of the socket the call passed through multi_passthrough_target_socket.h an implementation of a socket that allows to bind multiple initiators to the same target socket. Implements a mechanism to allow to identify in the forward path through which index of the socket the call passed through multi_socket_bases.h contains base class definitions used by the multi_passthrough sockets peq_with_get.h payload event queue (PEQ) implementation using a pull interface. Has a get_next_transaction API that returns the transaction that is scheduled in the event queue peq_with_cb_and_phase.h another payload event queue, this one with a push interface (callback mechanism ). Allows to register a callback that will be called whenever the event in the event queue is triggered, the callback gets transaction and phase as arguments instance_specific_extensions.h is an implementation for adding extentions in the generic payload that are specific to an instance along the path of a transaction, to allow that extentions of the same type can be used by the different blocks along the path of the transaction tlm_quantumkeeper.h is an convenience object used to keep track of the local time in an initiator (how much it has run ahead of the SystemC time), to synchronize with SystemC time etc. systemc-2.3.3/src/tlm_utils/Makefile.am0000644000175000017500000000432613360325173017735 0ustar carstencarsten## **************************************************************************** ## ## Licensed to Accellera Systems Initiative Inc. (Accellera) under one or ## more contributor license agreements. See the NOTICE file distributed ## with this work for additional information regarding copyright ownership. ## Accellera licenses this file to you under the Apache License, Version 2.0 ## (the "License"); you may not use this file except in compliance with the ## License. You may obtain a copy of the License at ## ## http://www.apache.org/licenses/LICENSE-2.0 ## ## Unless required by applicable law or agreed to in writing, software ## distributed under the License is distributed on an "AS IS" BASIS, ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or ## implied. See the License for the specific language governing ## permissions and limitations under the License. ## ## **************************************************************************** ## ## src/tlm_utils/Makefile.am -- ## Process this file with automake to produce a Makefile.in file. ## ## Original Author: Alan Fitch, Doulos, 2012-03-10 ## ## **************************************************************************** ## ## MODIFICATION LOG - modifiers, enter your name, affiliation, date and ## changes you are making here. ## ## Name, Affiliation, Date: ## Description of Modification: ## ## **************************************************************************** include $(top_srcdir)/config/Make-rules.sysc H_FILES = \ convenience_socket_bases.h \ instance_specific_extensions.h \ instance_specific_extensions_int.h \ multi_passthrough_initiator_socket.h \ multi_passthrough_target_socket.h \ multi_socket_bases.h \ passthrough_target_socket.h \ peq_with_cb_and_phase.h \ peq_with_get.h \ simple_initiator_socket.h \ simple_target_socket.h \ tlm_quantumkeeper.h CXX_FILES = \ convenience_socket_bases.cpp \ instance_specific_extensions.cpp EXTRA_DIST += \ README.txt localincludedir = $(includedir)/tlm_utils nobase_localinclude_HEADERS = $(H_FILES) noinst_LTLIBRARIES = libtlm_utils.la libtlm_utils_la_SOURCES = $(NO_H_FILES) $(CXX_FILES) uninstall-hook: test ! -d "$(localincludedir)" || rmdir "$(localincludedir)" systemc-2.3.3/src/tlm_utils/passthrough_target_socket.h0000644000175000017500000003741113360325173023340 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ #ifndef TLM_UTILS_PASSTHROUGH_TARGET_SOCKET_H_INCLUDED_ #define TLM_UTILS_PASSTHROUGH_TARGET_SOCKET_H_INCLUDED_ #include #include "tlm_utils/convenience_socket_bases.h" namespace tlm_utils { template< typename MODULE, unsigned int BUSWIDTH, typename TYPES , sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND > class passthrough_target_socket_b : public tlm::tlm_target_socket , protected passthrough_socket_base { public: typedef typename TYPES::tlm_payload_type transaction_type; typedef typename TYPES::tlm_phase_type phase_type; typedef tlm::tlm_sync_enum sync_enum_type; typedef tlm::tlm_fw_transport_if fw_interface_type; typedef tlm::tlm_bw_transport_if bw_interface_type; typedef tlm::tlm_target_socket base_type; public: static const char* default_name() { return sc_core::sc_gen_unique_name("passthrough_target_socket"); } explicit passthrough_target_socket_b(const char* n = default_name()) : base_type(n) , m_process(this) { bind(m_process); } using base_type::bind; // REGISTER_XXX void register_nb_transport_fw(MODULE* mod, sync_enum_type (MODULE::*cb)(transaction_type&, phase_type&, sc_core::sc_time&)) { m_process.set_nb_transport_ptr(mod, cb); } void register_b_transport(MODULE* mod, void (MODULE::*cb)(transaction_type&, sc_core::sc_time&)) { m_process.set_b_transport_ptr(mod, cb); } void register_transport_dbg(MODULE* mod, unsigned int (MODULE::*cb)(transaction_type&)) { m_process.set_transport_dbg_ptr(mod, cb); } void register_get_direct_mem_ptr(MODULE* mod, bool (MODULE::*cb)(transaction_type&, tlm::tlm_dmi&)) { m_process.set_get_direct_mem_ptr(mod, cb); } private: class process : public tlm::tlm_fw_transport_if , protected convenience_socket_cb_holder { public: typedef sync_enum_type (MODULE::*NBTransportPtr)(transaction_type&, phase_type&, sc_core::sc_time&); typedef void (MODULE::*BTransportPtr)(transaction_type&, sc_core::sc_time&); typedef unsigned int (MODULE::*TransportDbgPtr)(transaction_type&); typedef bool (MODULE::*GetDirectMem_ptr)(transaction_type&, tlm::tlm_dmi&); explicit process(passthrough_socket_base* owner) : convenience_socket_cb_holder(owner), m_mod(0) , m_nb_transport_ptr(0) , m_b_transport_ptr(0) , m_transport_dbg_ptr(0) , m_get_direct_mem_ptr(0) { } void set_nb_transport_ptr(MODULE* mod, NBTransportPtr p) { if (m_nb_transport_ptr) { display_warning("non-blocking callback already registered"); return; } sc_assert(!m_mod || m_mod == mod); m_mod = mod; m_nb_transport_ptr = p; } void set_b_transport_ptr(MODULE* mod, BTransportPtr p) { if (m_b_transport_ptr) { display_warning("blocking callback already registered"); return; } sc_assert(!m_mod || m_mod == mod); m_mod = mod; m_b_transport_ptr = p; } void set_transport_dbg_ptr(MODULE* mod, TransportDbgPtr p) { if (m_transport_dbg_ptr) { display_warning("debug callback already registered"); return; } sc_assert(!m_mod || m_mod == mod); m_mod = mod; m_transport_dbg_ptr = p; } void set_get_direct_mem_ptr(MODULE* mod, GetDirectMem_ptr p) { if (m_get_direct_mem_ptr) { display_warning("get DMI pointer callback already registered"); return; } sc_assert(!m_mod || m_mod == mod); m_mod = mod; m_get_direct_mem_ptr = p; } sync_enum_type nb_transport_fw(transaction_type& trans, phase_type& phase, sc_core::sc_time& t) { if (m_nb_transport_ptr) { // forward call sc_assert(m_mod); return (m_mod->*m_nb_transport_ptr)(trans, phase, t); } display_error("no non-blocking callback registered"); return tlm::TLM_COMPLETED; } void b_transport(transaction_type& trans, sc_core::sc_time& t) { if (m_b_transport_ptr) { // forward call sc_assert(m_mod); return (m_mod->*m_b_transport_ptr)(trans, t); } display_error("no blocking callback registered"); } unsigned int transport_dbg(transaction_type& trans) { if (m_transport_dbg_ptr) { // forward call sc_assert(m_mod); return (m_mod->*m_transport_dbg_ptr)(trans); } // No debug support return 0; } bool get_direct_mem_ptr(transaction_type& trans, tlm::tlm_dmi& dmi_data) { if (m_get_direct_mem_ptr) { // forward call sc_assert(m_mod); return (m_mod->*m_get_direct_mem_ptr)(trans, dmi_data); } // No DMI support dmi_data.allow_read_write(); dmi_data.set_start_address(0x0); dmi_data.set_end_address((sc_dt::uint64)-1); return false; } private: MODULE* m_mod; NBTransportPtr m_nb_transport_ptr; BTransportPtr m_b_transport_ptr; TransportDbgPtr m_transport_dbg_ptr; GetDirectMem_ptr m_get_direct_mem_ptr; }; private: const sc_core::sc_object* get_socket() const { return this; } private: process m_process; }; template< typename MODULE, unsigned int BUSWIDTH = 32 , typename TYPES = tlm::tlm_base_protocol_types > class passthrough_target_socket : public passthrough_target_socket_b { typedef passthrough_target_socket_b socket_b; public: passthrough_target_socket() : socket_b() {} explicit passthrough_target_socket(const char* name) : socket_b(name) {} }; template< typename MODULE, unsigned int BUSWIDTH = 32 , typename TYPES = tlm::tlm_base_protocol_types > class passthrough_target_socket_optional : public passthrough_target_socket_b { typedef passthrough_target_socket_b socket_b; public: passthrough_target_socket_optional() : socket_b() {} explicit passthrough_target_socket_optional(const char* name) : socket_b(name) {} }; //ID Tagged version template< typename MODULE, unsigned int BUSWIDTH, typename TYPES , sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND > class passthrough_target_socket_tagged_b : public tlm::tlm_target_socket , protected passthrough_socket_base { public: typedef typename TYPES::tlm_payload_type transaction_type; typedef typename TYPES::tlm_phase_type phase_type; typedef tlm::tlm_sync_enum sync_enum_type; typedef tlm::tlm_fw_transport_if fw_interface_type; typedef tlm::tlm_bw_transport_if bw_interface_type; typedef tlm::tlm_target_socket base_type; static const char* default_name() { return sc_core::sc_gen_unique_name("passthrough_target_socket_tagged"); } public: explicit passthrough_target_socket_tagged_b(const char* n = default_name()) : base_type(n) , m_process(this) { bind(m_process); } using base_type::bind; // REGISTER_XXX void register_nb_transport_fw(MODULE* mod, sync_enum_type (MODULE::*cb)(int id, transaction_type&, phase_type&, sc_core::sc_time&), int id) { m_process.set_nb_transport_ptr(mod, cb); m_process.set_nb_transport_user_id(id); } void register_b_transport(MODULE* mod, void (MODULE::*cb)(int id, transaction_type&, sc_core::sc_time&), int id) { m_process.set_b_transport_ptr(mod, cb); m_process.set_b_transport_user_id(id); } void register_transport_dbg(MODULE* mod, unsigned int (MODULE::*cb)(int id, transaction_type&), int id) { m_process.set_transport_dbg_ptr(mod, cb); m_process.set_transport_dbg_user_id(id); } void register_get_direct_mem_ptr(MODULE* mod, bool (MODULE::*cb)(int id, transaction_type&, tlm::tlm_dmi&), int id) { m_process.set_get_direct_mem_ptr(mod, cb); m_process.set_get_dmi_user_id(id); } private: class process : public tlm::tlm_fw_transport_if , protected convenience_socket_cb_holder { public: typedef sync_enum_type (MODULE::*NBTransportPtr)(int id, transaction_type&, phase_type&, sc_core::sc_time&); typedef void (MODULE::*BTransportPtr)(int id, transaction_type&, sc_core::sc_time&); typedef unsigned int (MODULE::*TransportDbgPtr)(int id, transaction_type&); typedef bool (MODULE::*GetDirectMem_ptr)(int id, transaction_type&, tlm::tlm_dmi&); process(passthrough_socket_base* owner) : convenience_socket_cb_holder(owner), m_mod(0) , m_nb_transport_ptr(0) , m_b_transport_ptr(0) , m_transport_dbg_ptr(0) , m_get_direct_mem_ptr(0) , m_nb_transport_user_id(0) , m_b_transport_user_id(0) , m_transport_dbg_user_id(0) , m_get_dmi_user_id(0) { } void set_nb_transport_user_id(int id) { m_nb_transport_user_id = id; } void set_b_transport_user_id(int id) { m_b_transport_user_id = id; } void set_transport_dbg_user_id(int id) { m_transport_dbg_user_id = id; } void set_get_dmi_user_id(int id) { m_get_dmi_user_id = id; } void set_nb_transport_ptr(MODULE* mod, NBTransportPtr p) { if (m_nb_transport_ptr) { display_warning("non-blocking callback already registered"); return; } sc_assert(!m_mod || m_mod == mod); m_mod = mod; m_nb_transport_ptr = p; } void set_b_transport_ptr(MODULE* mod, BTransportPtr p) { if (m_b_transport_ptr) { display_warning("blocking callback already registered"); return; } sc_assert(!m_mod || m_mod == mod); m_mod = mod; m_b_transport_ptr = p; } void set_transport_dbg_ptr(MODULE* mod, TransportDbgPtr p) { if (m_transport_dbg_ptr) { display_warning("debug callback already registered"); return; } sc_assert(!m_mod || m_mod == mod); m_mod = mod; m_transport_dbg_ptr = p; } void set_get_direct_mem_ptr(MODULE* mod, GetDirectMem_ptr p) { if (m_get_direct_mem_ptr) { display_warning("get DMI pointer callback already registered"); return; } sc_assert(!m_mod || m_mod == mod); m_mod = mod; m_get_direct_mem_ptr = p; } sync_enum_type nb_transport_fw(transaction_type& trans, phase_type& phase, sc_core::sc_time& t) { if (m_nb_transport_ptr) { // forward call sc_assert(m_mod); return (m_mod->*m_nb_transport_ptr)(m_nb_transport_user_id, trans, phase, t); } display_error("no non-blocking callback registered"); return tlm::TLM_COMPLETED; } void b_transport(transaction_type& trans, sc_core::sc_time& t) { if (m_b_transport_ptr) { // forward call sc_assert(m_mod); return (m_mod->*m_b_transport_ptr)(m_b_transport_user_id, trans, t); } display_error("no blocking callback registered"); } unsigned int transport_dbg(transaction_type& trans) { if (m_transport_dbg_ptr) { // forward call sc_assert(m_mod); return (m_mod->*m_transport_dbg_ptr)(m_transport_dbg_user_id, trans); } // No debug support return 0; } bool get_direct_mem_ptr(transaction_type& trans, tlm::tlm_dmi& dmi_data) { if (m_get_direct_mem_ptr) { // forward call sc_assert(m_mod); return (m_mod->*m_get_direct_mem_ptr)(m_get_dmi_user_id, trans, dmi_data); } // No DMI support dmi_data.allow_read_write(); dmi_data.set_start_address(0x0); dmi_data.set_end_address((sc_dt::uint64)-1); return false; } private: MODULE* m_mod; NBTransportPtr m_nb_transport_ptr; BTransportPtr m_b_transport_ptr; TransportDbgPtr m_transport_dbg_ptr; GetDirectMem_ptr m_get_direct_mem_ptr; int m_nb_transport_user_id; int m_b_transport_user_id; int m_transport_dbg_user_id; int m_get_dmi_user_id; }; private: const sc_core::sc_object* get_socket() const { return this; } private: process m_process; }; template< typename MODULE, unsigned int BUSWIDTH = 32 , typename TYPES = tlm::tlm_base_protocol_types > class passthrough_target_socket_tagged : public passthrough_target_socket_tagged_b { typedef passthrough_target_socket_tagged_b socket_b; public: passthrough_target_socket_tagged() : socket_b() {} explicit passthrough_target_socket_tagged(const char* name) : socket_b(name) {} }; template< typename MODULE, unsigned int BUSWIDTH = 32 , typename TYPES = tlm::tlm_base_protocol_types > class passthrough_target_socket_tagged_optional : public passthrough_target_socket_tagged_b { typedef passthrough_target_socket_tagged_b socket_b; public: passthrough_target_socket_tagged_optional() : socket_b() {} explicit passthrough_target_socket_tagged_optional(const char* name) : socket_b(name) {} }; } // namespace tlm_utils #endif // TLM_UTILS_PASSTHROUGH_TARGET_SOCKET_H_INCLUDED_ systemc-2.3.3/src/tlm_utils/convenience_socket_bases.h0000644000175000017500000000505413360325173023072 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ #ifndef TLM_UTILS_CONVENIENCE_SOCKET_BASES_H_INCLUDED_ #define TLM_UTILS_CONVENIENCE_SOCKET_BASES_H_INCLUDED_ #include namespace sc_core { class SC_API sc_object; } namespace tlm_utils { // implementation-defined base class helper for convenience sockets class SC_API convenience_socket_base { public: void display_warning(const char* msg) const; void display_error(const char* msg) const; protected: virtual ~convenience_socket_base(){} private: virtual const char* get_report_type() const = 0; virtual const sc_core::sc_object* get_socket() const = 0; }; // implementation-defined base class helper for simple sockets class SC_API simple_socket_base : public convenience_socket_base { virtual const char* get_report_type() const; protected: void elaboration_check(const char* action) const; }; // implementation-defined base class helper for passthrough sockets class SC_API passthrough_socket_base : public convenience_socket_base { virtual const char* get_report_type() const; }; // implementation-defined base class helper for multi sockets class SC_API multi_socket_base : public convenience_socket_base { virtual const char* get_report_type() const; }; // implementation-defined base class for callback helpers class SC_API convenience_socket_cb_holder { public: void display_warning(const char* msg) const; void display_error(const char* msg) const; protected: explicit convenience_socket_cb_holder(convenience_socket_base* owner) : m_owner(owner) {} private: convenience_socket_base* m_owner; }; } // namespace tlm_utils #endif // TLM_UTILS_CONVENIENCE_SOCKET_BASES_H_INCLUDED_ systemc-2.3.3/src/tlm_utils/multi_passthrough_initiator_socket.h0000644000175000017500000002641213360325173025265 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ #ifndef TLM_UTILS_MULTI_PASSTHROUGH_INITIATOR_SOCKET_H_INCLUDED_ #define TLM_UTILS_MULTI_PASSTHROUGH_INITIATOR_SOCKET_H_INCLUDED_ #include "multi_socket_bases.h" namespace tlm_utils { /* This class implements a trivial multi initiator socket. The triviality refers to the fact that the socket does not do blocking to non-blocking or non-blocking to blocking conversions. It allows to connect multiple targets to this socket. The user has to register callbacks for the bw interface methods he likes to use. The callbacks are basically equal to the bw interface methods but carry an additional integer that indicates to which index of this socket the calling target is connected. */ template class multi_passthrough_initiator_socket : public multi_init_base< BUSWIDTH, TYPES, N, POL> { public: //typedefs // tlm 2.0 types for nb_transport typedef typename TYPES::tlm_payload_type transaction_type; typedef typename TYPES::tlm_phase_type phase_type; typedef tlm::tlm_sync_enum sync_enum_type; // typedefs to keep the fn ptr notations short typedef sync_enum_type (MODULE::*nb_cb)(int, transaction_type&, phase_type&, sc_core::sc_time&); typedef void (MODULE::*dmi_cb)(int, sc_dt::uint64, sc_dt::uint64); typedef multi_init_base base_type; typedef typename base_type::base_target_socket_type base_target_socket_type; static const char* default_name() { return sc_core::sc_gen_unique_name("multi_passthrough_initiator_socket"); } //CTOR explicit multi_passthrough_initiator_socket(const char* name = default_name()) : base_type(name) , m_hierarch_bind(0) , m_beoe_disabled(false) , m_dummy(this,42) { } ~multi_passthrough_initiator_socket(){ //clean up everything allocated by 'new' for (unsigned int i=0; i& get_base_interface() { m_binders.push_back(new callback_binder_bw(this, m_binders.size())); return *m_binders[m_binders.size()-1]; } // const overload not allowed for multi-sockets virtual const tlm::tlm_bw_transport_if& get_base_interface() const { display_error("'get_base_interface()' const not allowed for multi-sockets."); return base_type::get_base_interface(); } //Override virtual functions of the tlm_initiator_socket: // this function is called whenever an sc_export (as part of a initiator socket) // wants to bind to the export of the underlying tlm_initiator_socket // i.e. a hierarchical bind takes place virtual sc_core::sc_export >& get_base_export() { if (!m_beoe_disabled) //we are not bound hierarchically base_type::m_export.bind(m_dummy); //so we bind the dummy to avoid a SystemC error return base_type::get_base_export(); //and then return our own export so that the hierarchical binding is set up properly } virtual const sc_core::sc_export >& get_base_export() const { return base_type::get_base_export(); } //bind against a target socket virtual void bind(base_target_socket_type& s) { //error if this socket is already bound hierarchically if (m_hierarch_bind) { display_error("Already hierarchically bound."); return; } base_type::bind(s); //satisfy systemC, leads to a call to get_base_interface() //try to cast the target socket into a fw interface sc_core::sc_export >* p_ex_s=dynamic_cast >*>(&s); if (!p_ex_s) { display_error("Multi socket not bound to tlm_socket."); return; } //try a cast into a multi sockets multi_to_multi_bind_base* test=dynamic_cast*> (p_ex_s); if (test) //did we just do a multi-multi bind?? //if that is the case the multi target socket must have just created a callback binder // which we want to get from it. //Moreover, we also just created one, which we will pass to it. m_sockets.push_back(test->get_last_binder(m_binders[m_binders.size()-1])); else{ // if not just bind normally sc_core::sc_export >& ex_s=*p_ex_s; m_sockets.push_back(&((tlm::tlm_fw_transport_if&)ex_s)); //store the interface we are bound against } } //operator notation for direct bind void operator() (base_target_socket_type& s) { bind(s); } //SystemC standard callback before end of elaboration void before_end_of_elaboration(){ //if our export hasn't been bound yet (due to a hierarch binding) // we bind it now to avoid a SystemC error. //We must do that, because it is legal not to register a callback on this socket // as the user might only use b_transport if (!base_type::m_export.get_interface()){ base_type::m_export.bind(m_dummy); } //'break' here if the socket was told not to do callback binding if (m_beoe_disabled) return; //get the callback binders of the top of the hierachical bind chain // NOTE: this could be the same socket if there is no hierachical bind std::vector* >& binders=get_hierarch_bind()->get_binders(); //get the interfaces bound to the top of the hierachical bind chain // NOTE: this could be the same socket if there is no hierachical bind m_used_sockets=get_hierarch_bind()->get_sockets(); //register the callbacks of this socket with the callback binders // we just got from the top of the hierachical bind chain for (unsigned int i=0; iset_callbacks(m_nb_f, m_dmi_f); } } // // Bind multi initiator socket to multi initiator socket (hierarchical bind) // virtual void bind(base_type& s) { if (m_binders.size()) { //a multi socket is either bound hierarchically or directly display_error("Socket already directly bound."); return; } if (m_hierarch_bind){ display_warning("Socket already bound hierarchically. Bind attempt ignored."); return; } //remember to which socket we are hierarchically bound and disable it, // so that it won't try to register callbacks itself s.disable_cb_bind(); m_hierarch_bind=&s; base_type::bind(s); //satisfy SystemC } //operator notation for hierarchical bind void operator() (base_type& s) { bind(s); } //get access to sub port tlm::tlm_fw_transport_if* operator[](int i){return m_used_sockets[i];} //get the number of bound targets // NOTE: this is only valid at end of elaboration! unsigned int size() {return get_hierarch_bind()->get_sockets().size();} protected: using base_type::display_warning; using base_type::display_error; //implementation of base class interface base_type* get_hierarch_bind(){if (m_hierarch_bind) return m_hierarch_bind->get_hierarch_bind(); else return this;} void disable_cb_bind(){ m_beoe_disabled=true;} std::vector* >& get_binders(){return m_binders;} std::vector*>& get_sockets(){return m_sockets;} //vector of connected sockets std::vector*> m_sockets; std::vector*> m_used_sockets; //vector of binders that convert untagged interface into tagged interface std::vector*> m_binders; base_type* m_hierarch_bind; //pointer to hierarchical bound multi port bool m_beoe_disabled; // bool that remembers whether this socket shall bind callbacks or not callback_binder_bw m_dummy; //a callback binder that is bound to the underlying export // in case there was no real bind //callbacks as functors // (allows to pass the callback to another socket that does not know the type of the module that owns // the callbacks) typename callback_binder_bw::nb_func_type m_nb_f; typename callback_binder_bw::dmi_func_type m_dmi_f; }; template class multi_passthrough_initiator_socket_optional : public multi_passthrough_initiator_socket { typedef multi_passthrough_initiator_socket socket_b; public: multi_passthrough_initiator_socket_optional() : socket_b() {} explicit multi_passthrough_initiator_socket_optional(const char* name) : socket_b(name) {} }; } // namespace tlm_utils #endif // TLM_UTILS_MULTI_PASSTHROUGH_INITIATOR_SOCKET_H_INCLUDED_ systemc-2.3.3/src/tlm_utils/peq_with_get.h0000644000175000017500000000513113360325173020524 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ // 12-Jan-2009 John Aynsley Bug fix. sc_time argument to notify should be const // 20-Mar-2009 John Aynsley Add cancel_all() method #ifndef __PEQ_WITH_GET_H__ #define __PEQ_WITH_GET_H__ #include //#include #include namespace tlm_utils { template class peq_with_get : public sc_core::sc_object { public: typedef PAYLOAD transaction_type; typedef std::pair pair_type; public: peq_with_get(const char* name) : sc_core::sc_object(name) { } void notify(transaction_type& trans, const sc_core::sc_time& t) { m_scheduled_events.insert(pair_type(t + sc_core::sc_time_stamp(), &trans)); m_event.notify(t); } void notify(transaction_type& trans) { m_scheduled_events.insert(pair_type(sc_core::sc_time_stamp(), &trans)); m_event.notify(); // immediate notification } // needs to be called until it returns 0 transaction_type* get_next_transaction() { if (m_scheduled_events.empty()) { return 0; } sc_core::sc_time now = sc_core::sc_time_stamp(); if (m_scheduled_events.begin()->first <= now) { transaction_type* trans = m_scheduled_events.begin()->second; m_scheduled_events.erase(m_scheduled_events.begin()); return trans; } m_event.notify(m_scheduled_events.begin()->first - now); return 0; } sc_core::sc_event& get_event() { return m_event; } // Cancel all events from the event queue void cancel_all() { m_scheduled_events.clear(); m_event.cancel(); } private: std::multimap m_scheduled_events; sc_core::sc_event m_event; }; } #endif systemc-2.3.3/src/tlm_utils/convenience_socket_bases.cpp0000644000175000017500000000460113360325173023422 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ #include "tlm_utils/convenience_socket_bases.h" #include "sysc/kernel/sc_object.h" #include "sysc/kernel/sc_simcontext.h" #include "sysc/utils/sc_report.h" #include namespace tlm_utils { void convenience_socket_base::display_warning(const char* text) const { std::stringstream s; s << get_socket()->name() << ": " << text; SC_REPORT_WARNING(get_report_type(), s.str().c_str()); } void convenience_socket_base::display_error(const char* text) const { std::stringstream s; s << get_socket()->name() << ": " << text; SC_REPORT_ERROR(get_report_type(), s.str().c_str()); } //simple helpers for warnings an errors to shorten in code notation void convenience_socket_cb_holder::display_warning(const char* msg) const { m_owner->display_warning(msg); } void convenience_socket_cb_holder::display_error(const char* msg) const { m_owner->display_error(msg); } const char* simple_socket_base::get_report_type() const { return "/OSCI_TLM-2/simple_socket"; } void simple_socket_base::elaboration_check(const char* action) const { if (sc_core::sc_get_curr_simcontext()->elaboration_done()) { std::stringstream s; s << " elaboration completed, " << action << " not allowed"; display_error(s.str().c_str()); } } const char* passthrough_socket_base::get_report_type() const { return "/OSCI_TLM-2/passthrough_socket"; } const char* multi_socket_base::get_report_type() const { return "/OSCI_TLM-2/multi_socket"; } } // namespace tlm_utils systemc-2.3.3/src/tlm_utils/instance_specific_extensions_int.h0000644000175000017500000001431413360325173024652 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ #ifndef TLM_UTILS_INSTANCE_SPECIFIC_EXTENSIONS_INT_H_INCLUDED_ #define TLM_UTILS_INSTANCE_SPECIFIC_EXTENSIONS_INT_H_INCLUDED_ #ifndef SC_BUILD // incluce full TLM, when not building the library #include #else #include "tlm_core/tlm_2/tlm_generic_payload/tlm_gp.h" #endif // SC_BUILD namespace tlm_utils { class SC_API ispex_base; class SC_API instance_specific_extension_accessor; class SC_API instance_specific_extension_container; class instance_specific_extension_carrier; class instance_specific_extension_container_pool; } namespace tlm { SC_API_TEMPLATE_DECL_ tlm_array; } // namespace tlm namespace tlm_utils { //The private extension base. Similar to normal extension base, but without clone and free class SC_API ispex_base { friend class tlm::tlm_array; void free() {} // needed for explicit tlm_array instantiation public: virtual ~ispex_base() {} protected: static unsigned int register_private_extension(const std::type_info&); }; //this thing is basically a snippet of the generic_payload // it contains all the extension specific code (the extension API so to speak) // the differences are: // - it calls back to its owner whenever a real (==non-NULL) extension gets set for the first time // - it calls back to its owner whenever a living (==non-NULL) extension gets cleared class SC_API instance_specific_extensions_per_accessor { public: typedef instance_specific_extension_container container_type; explicit instance_specific_extensions_per_accessor(container_type* container) : m_container(container) {} template T* set_extension(T* ext) { return static_cast( set_extension(T::priv_id, ext) ); } // non-templatized version with manual index: ispex_base* set_extension(unsigned int index, ispex_base* ext); // Check for an extension, ext will point to 0 if not present template void get_extension(T*& ext) const { ext = static_cast(get_extension(T::priv_id)); } // Non-templatized version: ispex_base* get_extension(unsigned int index) const; // Clear extension, the argument is needed to find the right index: template void clear_extension(const T*) { clear_extension(T::priv_id); } // Non-templatized version with manual index void clear_extension(unsigned int index); // Make sure the extension array is large enough. Can be called once by // an initiator module (before issuing the first transaction) to make // sure that the extension array is of correct size. This is only needed // if the initiator cannot guarantee that the generic payload object is // allocated after C++ static construction time. void resize_extensions(); private: tlm::tlm_array m_extensions; container_type* m_container; }; // class instance_specific_extensions_per_accessor #if defined(_MSC_VER) && !defined(SC_WIN_DLL_WARN) #pragma warning(push) #pragma warning(disable: 4251) // DLL import for vector #endif //this thing contains the vector of extensions per accessor //which can be really large so this one should be pool allocated // therefore it keeps a use_count of itself to automatically free itself // - to this end it provides callbacks to the extensions per accessor // to increment and decrement the use_count class SC_API instance_specific_extension_container { friend class instance_specific_extension_accessor; friend class instance_specific_extension_carrier; friend class instance_specific_extension_container_pool; friend class instance_specific_extensions_per_accessor; typedef void release_fn(instance_specific_extension_carrier*,void*); instance_specific_extension_container(); ~instance_specific_extension_container(); void resize(); void inc_use_count(); void dec_use_count(); static instance_specific_extension_container* create(); void attach_carrier(instance_specific_extension_carrier*, void* txn, release_fn*); instance_specific_extensions_per_accessor* get_accessor(unsigned int index); std::vector m_ispex_per_accessor; unsigned int use_count; void* m_txn; release_fn* m_release_fn; instance_specific_extension_carrier* m_carrier; instance_specific_extension_container* next; //for pooling }; // class instance_specific_extension_container #if defined(_MSC_VER) && !defined(SC_WIN_DLL_WARN) #pragma warning(pop) #endif // ---------------------------------------------------------------------------- //This class 'hides' all the instance specific extension stuff from the user // he instantiates one of those (e.g. instance_specific_extension_accessor extAcc;) and can then access // the private extensions // extAcc(txn).extensionAPIFnCall() // where extensionAPIFnCall is set_extension, get_extension, clear_extension,... class SC_API instance_specific_extension_accessor { public: instance_specific_extension_accessor(); template // implementation in instance_specific_extensions.h inline instance_specific_extensions_per_accessor& operator()(T& txn); protected: template static void release_carrier(instance_specific_extension_carrier*, void* txn); unsigned int m_index; }; // class instance_specific_extension_accessor } // namespace tlm_utils #endif // TLM_UTILS_INSTANCE_SPECIFIC_EXTENSIONS_INT_H_INCLUDED_ systemc-2.3.3/src/tlm_utils/Makefile.in0000644000175000017500000005700013360325173017743 0ustar carstencarsten# Makefile.in generated by automake 1.14 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # top-level SystemC include directory is added in Make-rules.{sysc,examples} # build flags VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ DIST_COMMON = $(top_srcdir)/config/Make-rules.sysc \ $(top_srcdir)/config/Make-rules.common $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(top_srcdir)/config/depcomp \ $(nobase_localinclude_HEADERS) @WANT_DEBUG_TRUE@am__append_1 = $(DEBUG_CXXFLAGS) @WANT_DEBUG_TRUE@am__append_2 = $(DEBUG_CXXFLAGS) @WANT_DEBUG_TRUE@am__append_3 = $(DEBUG_CXXFLAGS) @WANT_OPTIMIZE_TRUE@am__append_4 = $(OPT_CXXFLAGS) @WANT_OPTIMIZE_TRUE@am__append_5 = $(OPT_CXXFLAGS) # either for async_update locking or pthread processes @USES_PTHREADS_LIB_TRUE@am__append_6 = $(PTHREAD_CFLAGS) @USES_PTHREADS_LIB_TRUE@am__append_7 = $(PTHREAD_CFLAGS) @USES_PTHREADS_LIB_TRUE@am__append_8 = $(PTHREAD_LIBS) @DISABLE_ASYNC_UPDATES_TRUE@am__append_9 = -DSC_DISABLE_ASYNC_UPDATES @ENABLE_CALLBACKS_TRUE@am__append_10 = -DSC_ENABLE_SIMULATION_PHASE_CALLBACKS @ENABLE_CALLBACKS_TRACING_TRUE@am__append_11 = -DSC_ENABLE_SIMULATION_PHASE_CALLBACKS_TRACING @WANT_PTHREADS_THREADS_TRUE@am__append_12 = -DSC_USE_PTHREADS @DISABLE_VCD_SCOPES_TRUE@am__append_13 = -DSC_DISABLE_VCD_SCOPES subdir = src/tlm_utils ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config/ax_check_define.m4 \ $(top_srcdir)/config/ax_pthread.m4 \ $(top_srcdir)/config/libtool.m4 \ $(top_srcdir)/config/ltoptions.m4 \ $(top_srcdir)/config/ltsugar.m4 \ $(top_srcdir)/config/ltversion.m4 \ $(top_srcdir)/config/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libtlm_utils_la_LIBADD = am__objects_1 = convenience_socket_bases.lo \ instance_specific_extensions.lo am_libtlm_utils_la_OBJECTS = $(am__objects_1) libtlm_utils_la_OBJECTS = $(am_libtlm_utils_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/config/depcomp am__depfiles_maybe = depfiles am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) AM_V_CXX = $(am__v_CXX_@AM_V@) am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) am__v_CXX_0 = @echo " CXX " $@; am__v_CXX_1 = CXXLD = $(CXX) CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = SOURCES = $(libtlm_utils_la_SOURCES) DIST_SOURCES = $(libtlm_utils_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(localincludedir)" HEADERS = $(nobase_localinclude_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCAS = @CCAS@ CCASDEPMODE = @CCASDEPMODE@ CCASFLAGS = @CCASFLAGS@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DEBUG_CXXFLAGS = @DEBUG_CXXFLAGS@ DEFS = $(PKGCONFIG_DEFINES) $(EXTRA_DEFINES) DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ EXPLICIT_LPTHREAD = @EXPLICIT_LPTHREAD@ EXTRA_ASFLAGS = @EXTRA_ASFLAGS@ EXTRA_CFLAGS = @EXTRA_CFLAGS@ EXTRA_CXXFLAGS = @EXTRA_CXXFLAGS@ EXTRA_LDFLAGS = @EXTRA_LDFLAGS@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LDFLAG_RPATH = @LDFLAG_RPATH@ LIBCONFIG_DEFINES = @LIBCONFIG_DEFINES@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIB_ARCH_SUFFIX = @LIB_ARCH_SUFFIX@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPT_CXXFLAGS = @OPT_CXXFLAGS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKGCONFIG_CFLAGS = @PKGCONFIG_CFLAGS@ PKGCONFIG_DEFINES = @PKGCONFIG_DEFINES@ PKGCONFIG_LDPRIV = @PKGCONFIG_LDPRIV@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ QT_ARCH = @QT_ARCH@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TARGET_ARCH = @TARGET_ARCH@ TLM_PACKAGE_VERSION = @TLM_PACKAGE_VERSION@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ ax_pthread_config = @ax_pthread_config@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ examplesdir = @examplesdir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libarchdir = @libarchdir@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ rootdocdir = @rootdocdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CPPFLAGS = -I$(top_srcdir)/src AM_CFLAGS = $(EXTRA_CFLAGS) $(am__append_2) $(am__append_5) \ $(am__append_7) AM_CXXFLAGS = $(EXTRA_CXXFLAGS) $(am__append_1) $(am__append_4) \ $(am__append_6) AM_CCASFLAGS = $(EXTRA_ASFLAGS) $(am__append_3) AM_LDFLAGS = $(EXTRA_LDFLAGS) $(am__append_8) # always add fix-point support EXTRA_DEFINES = -DSC_INCLUDE_FX -DSC_BUILD $(am__append_9) \ $(am__append_10) $(am__append_11) $(am__append_12) \ $(am__append_13) # initialize some useful variables (filled later) CLEANFILES = EXTRA_DIST = README.txt H_FILES = \ convenience_socket_bases.h \ instance_specific_extensions.h \ instance_specific_extensions_int.h \ multi_passthrough_initiator_socket.h \ multi_passthrough_target_socket.h \ multi_socket_bases.h \ passthrough_target_socket.h \ peq_with_cb_and_phase.h \ peq_with_get.h \ simple_initiator_socket.h \ simple_target_socket.h \ tlm_quantumkeeper.h CXX_FILES = \ convenience_socket_bases.cpp \ instance_specific_extensions.cpp localincludedir = $(includedir)/tlm_utils nobase_localinclude_HEADERS = $(H_FILES) noinst_LTLIBRARIES = libtlm_utils.la libtlm_utils_la_SOURCES = $(NO_H_FILES) $(CXX_FILES) all: all-am .SUFFIXES: .SUFFIXES: .cpp .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/config/Make-rules.sysc $(top_srcdir)/config/Make-rules.common $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/tlm_utils/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign src/tlm_utils/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_srcdir)/config/Make-rules.sysc $(top_srcdir)/config/Make-rules.common: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libtlm_utils.la: $(libtlm_utils_la_OBJECTS) $(libtlm_utils_la_DEPENDENCIES) $(EXTRA_libtlm_utils_la_DEPENDENCIES) $(AM_V_CXXLD)$(CXXLINK) $(libtlm_utils_la_OBJECTS) $(libtlm_utils_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/convenience_socket_bases.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/instance_specific_extensions.Plo@am__quote@ .cpp.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cpp.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cpp.lo: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-nobase_localincludeHEADERS: $(nobase_localinclude_HEADERS) @$(NORMAL_INSTALL) @list='$(nobase_localinclude_HEADERS)'; test -n "$(localincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(localincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(localincludedir)" || exit 1; \ fi; \ $(am__nobase_list) | while read dir files; do \ xfiles=; for file in $$files; do \ if test -f "$$file"; then xfiles="$$xfiles $$file"; \ else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ test -z "$$xfiles" || { \ test "x$$dir" = x. || { \ echo " $(MKDIR_P) '$(DESTDIR)$(localincludedir)/$$dir'"; \ $(MKDIR_P) "$(DESTDIR)$(localincludedir)/$$dir"; }; \ echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(localincludedir)/$$dir'"; \ $(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(localincludedir)/$$dir" || exit $$?; }; \ done uninstall-nobase_localincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(nobase_localinclude_HEADERS)'; test -n "$(localincludedir)" || list=; \ $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ dir='$(DESTDIR)$(localincludedir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(localincludedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-nobase_localincludeHEADERS install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-nobase_localincludeHEADERS @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) uninstall-hook .MAKE: install-am install-strip uninstall-am .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-nobase_localincludeHEADERS \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ uninstall-hook uninstall-nobase_localincludeHEADERS uninstall-hook: test ! -d "$(localincludedir)" || rmdir "$(localincludedir)" # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: systemc-2.3.3/src/tlm_utils/instance_specific_extensions.h0000644000175000017500000001121313360325173023773 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /* Instance specific extensions, are extension that only a single instance of a module may access. They are invisible to all other modules; they are private to this instance so to speak. As they are only of value to a certain instance, this instance knows very well when it needs them and when it does not need them any longer (usually when a transaction passes through a module for the last time). It does not have to care if anyone else in the system may still have a reference to the transaction as this one is not able to access the extension anyway. Therefore the instance is obliged to call set_extension when it wants to add a private extension and clear_extension when it does not need it any more. To get access to an instance specifc extension the module must own a so called instance_specific_extension_accessor that provides the exclusive access rights. Assuming the instance_specific_extension_accessor of a given module is called m_accessor and the transaction of which the private extension is about to be accessed is called txn, then the calls have to be m_accessor(txn).set_extension(...); or m_accessor(txn).clear_extension(...); The owner of the private extension is responsible to allocate/deallocate the extension before/after setting/clearing the extension. */ #ifndef TLM_UTILS_INSTANCE_SPECIFIC_EXTENSIONS_H_INCLUDED_ #define TLM_UTILS_INSTANCE_SPECIFIC_EXTENSIONS_H_INCLUDED_ #include "tlm_utils/instance_specific_extensions_int.h" namespace tlm_utils { //The templated private extension. Similar to normal extension template class instance_specific_extension : public ispex_base { public: virtual ~instance_specific_extension() {} const static unsigned int priv_id; }; template const unsigned int instance_specific_extension::priv_id = ispex_base::register_private_extension(typeid(T)); // ---------------------------------------------------------------------------- // This is the class that actually sits in the extension array // - we keep this small since that one gets allocated and deallocated all the times // - we keep the implementation in the header to avoid registration // of the extension itself unless used in the model class instance_specific_extension_carrier : public tlm::tlm_extension { friend class instance_specific_extension_accessor; public: instance_specific_extension_carrier() : m_container() {} virtual tlm::tlm_extension_base* clone() const { //we don't clone since private info is instance specific and associated to a given txn (the original) //so the deep copied txn will be virgin in terms of private info return NULL; } void copy_from(tlm::tlm_extension_base const &) { return; } void free() { return; } private: instance_specific_extension_container* m_container; }; // ---------------------------------------------------------------------------- template instance_specific_extensions_per_accessor& instance_specific_extension_accessor::operator()(T& txn) { instance_specific_extension_carrier* carrier = NULL; txn.get_extension(carrier); if (!carrier) { carrier = new instance_specific_extension_carrier(); carrier->m_container = instance_specific_extension_container::create(); carrier->m_container->attach_carrier(carrier, &txn, &release_carrier); txn.set_extension(carrier); } return *carrier->m_container->get_accessor(m_index); } template void instance_specific_extension_accessor:: release_carrier(instance_specific_extension_carrier* carrier, void* txn) { T* typed_txn = static_cast(txn); typed_txn->clear_extension(carrier); delete carrier; } } // namespace tlm_utils #endif // TLM_UTILS_INSTANCE_SPECIFIC_EXTENSIONS_H_INCLUDED_ systemc-2.3.3/src/tlm_utils/multi_socket_bases.h0000644000175000017500000003636013360325173021734 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ #ifndef TLM_UTILS_MULTI_SOCKET_BASES_H_INCLUDED_ #define TLM_UTILS_MULTI_SOCKET_BASES_H_INCLUDED_ #include #include "tlm_utils/convenience_socket_bases.h" #include namespace tlm_utils { template struct fn_container{ signature function; }; #define TLM_DEFINE_FUNCTOR(name) \ template \ inline TLM_RET_VAL static_##name( void* mod \ , void* fn \ , int index \ , TLM_FULL_ARG_LIST) \ { \ typedef fn_container fn_container_type; \ MODULE* tmp_mod=static_cast(mod); \ fn_container_type* tmp_cb =static_cast (fn); \ return (tmp_mod->*(tmp_cb->function))(index, TLM_ARG_LIST_WITHOUT_TYPES); \ }\ \ template \ inline void delete_fn_container_of_##name(void* fn) \ { \ typedef fn_container fn_container_type; \ fn_container_type* tmp_cb =static_cast (fn); \ if (tmp_cb) delete tmp_cb;\ } \ \ template \ class name##_functor{ \ public: \ typedef typename TRAITS::tlm_payload_type payload_type; \ typedef typename TRAITS::tlm_phase_type phase_type; \ typedef TLM_RET_VAL (*call_fn)(void*,void*, int, TLM_FULL_ARG_LIST); \ typedef void (*del_fn)(void*); \ \ name##_functor(): m_fn(0), m_del_fn(0), m_mod(0), m_mem_fn(0){} \ ~name##_functor(){if (m_del_fn) (*m_del_fn)(m_mem_fn);} \ \ template \ void set_function(MODULE* mod, TLM_RET_VAL (MODULE::*cb)(int, TLM_FULL_ARG_LIST)){ \ typedef fn_container fn_container_type; \ m_fn=&static_##name;\ m_del_fn=&delete_fn_container_of_##name;\ m_del_fn(m_mem_fn); \ fn_container_type* tmp= new fn_container_type(); \ tmp->function=cb; \ m_mod=static_cast(mod); \ m_mem_fn=static_cast(tmp); \ } \ \ TLM_RET_VAL operator()(int index, TLM_FULL_ARG_LIST){ \ return m_fn(m_mod,m_mem_fn, index, TLM_ARG_LIST_WITHOUT_TYPES); \ } \ \ bool is_valid(){return (m_mod!=0 && m_mem_fn!=0 && m_fn!=0);}\ \ protected: \ call_fn m_fn;\ del_fn m_del_fn; \ void* m_mod; \ void* m_mem_fn; \ private: \ name##_functor& operator=(const name##_functor&); \ } #define TLM_RET_VAL tlm::tlm_sync_enum #define TLM_FULL_ARG_LIST typename TRAITS::tlm_payload_type& txn, typename TRAITS::tlm_phase_type& ph, sc_core::sc_time& t #define TLM_ARG_LIST_WITHOUT_TYPES txn,ph,t TLM_DEFINE_FUNCTOR(nb_transport); #undef TLM_RET_VAL #undef TLM_FULL_ARG_LIST #undef TLM_ARG_LIST_WITHOUT_TYPES #define TLM_RET_VAL void #define TLM_FULL_ARG_LIST typename TRAITS::tlm_payload_type& txn, sc_core::sc_time& t #define TLM_ARG_LIST_WITHOUT_TYPES txn,t TLM_DEFINE_FUNCTOR(b_transport); #undef TLM_RET_VAL #undef TLM_FULL_ARG_LIST #undef TLM_ARG_LIST_WITHOUT_TYPES #define TLM_RET_VAL unsigned int #define TLM_FULL_ARG_LIST typename TRAITS::tlm_payload_type& txn #define TLM_ARG_LIST_WITHOUT_TYPES txn TLM_DEFINE_FUNCTOR(debug_transport); #undef TLM_RET_VAL #undef TLM_FULL_ARG_LIST #undef TLM_ARG_LIST_WITHOUT_TYPES #define TLM_RET_VAL bool #define TLM_FULL_ARG_LIST typename TRAITS::tlm_payload_type& txn, tlm::tlm_dmi& dmi #define TLM_ARG_LIST_WITHOUT_TYPES txn,dmi TLM_DEFINE_FUNCTOR(get_dmi_ptr); #undef TLM_RET_VAL #undef TLM_FULL_ARG_LIST #undef TLM_ARG_LIST_WITHOUT_TYPES #define TLM_RET_VAL void #define TLM_FULL_ARG_LIST sc_dt::uint64 l, sc_dt::uint64 u #define TLM_ARG_LIST_WITHOUT_TYPES l,u TLM_DEFINE_FUNCTOR(invalidate_dmi); #undef TLM_RET_VAL #undef TLM_FULL_ARG_LIST #undef TLM_ARG_LIST_WITHOUT_TYPES #undef TLM_DEFINE_FUNCTOR /* This class implements the fw interface. It allows to register a callback for each of the fw interface methods. The callbacks simply forward the fw interface call, but add the id (an int) of the callback binder to the signature of the call. */ template class callback_binder_fw : public tlm::tlm_fw_transport_if , protected convenience_socket_cb_holder { public: //typedefs according to the used TYPES class typedef typename TYPES::tlm_payload_type transaction_type; typedef typename TYPES::tlm_phase_type phase_type; typedef tlm::tlm_sync_enum sync_enum_type; //typedefs for the callbacks typedef nb_transport_functor nb_func_type; typedef b_transport_functor b_func_type; typedef debug_transport_functor debug_func_type; typedef get_dmi_ptr_functor dmi_func_type; //ctor: an ID is needed to create a callback binder callback_binder_fw(multi_socket_base* owner, int id) : convenience_socket_cb_holder(owner), m_id(id) , m_nb_f(0), m_b_f(0), m_dbg_f(0), m_dmi_f(0) , m_caller_port(0) {} //the nb_transport method of the fw interface sync_enum_type nb_transport_fw(transaction_type& txn, phase_type& p, sc_core::sc_time& t){ //check if a callback is registered if (m_nb_f && m_nb_f->is_valid()) { return (*m_nb_f)(m_id, txn, p, t); //do the callback } display_error("Call to nb_transport_fw without a registered callback for nb_transport_fw."); return tlm::TLM_COMPLETED; } //the b_transport method of the fw interface void b_transport(transaction_type& trans,sc_core::sc_time& t){ //check if a callback is registered if (m_b_f && m_b_f->is_valid()) { (*m_b_f)(m_id, trans,t); //do the callback return; } display_error("Call to b_transport without a registered callback for b_transport."); } //the DMI method of the fw interface bool get_direct_mem_ptr(transaction_type& trans, tlm::tlm_dmi& dmi_data){ //check if a callback is registered if (m_dmi_f && m_dmi_f->is_valid()) { return (*m_dmi_f)(m_id, trans,dmi_data); //do the callback } dmi_data.allow_none(); dmi_data.set_start_address(0x0); dmi_data.set_end_address((sc_dt::uint64)-1); return false; } //the debug method of the fw interface unsigned int transport_dbg(transaction_type& trans){ //check if a callback is registered if (m_dbg_f && m_dbg_f->is_valid()) { return (*m_dbg_f)(m_id, trans); //do the callback } return 0; } //the SystemC standard callback register_port: // - called when a port if bound to the interface // - allowd to find out who is bound to that callback binder void register_port(sc_core::sc_port_base& b, const char* /*name*/){ m_caller_port=&b; } //register callbacks for all fw interface methods at once void set_callbacks(nb_func_type& cb1, b_func_type& cb2, dmi_func_type& cb3, debug_func_type& cb4){ m_nb_f=&cb1; m_b_f=&cb2; m_dmi_f=&cb3; m_dbg_f=&cb4; } //getter method to get the port that is bound to that callback binder // NOTE: this will only return a valid value at end of elaboration // (but not before end of elaboration!) sc_core::sc_port_base* get_other_side(){return m_caller_port;} private: //the ID of the callback binder int m_id; //the callbacks nb_func_type* m_nb_f; b_func_type* m_b_f; debug_func_type* m_dbg_f; dmi_func_type* m_dmi_f; //the port bound to that callback binder sc_core::sc_port_base* m_caller_port; }; /* This class implements the bw interface. It allows to register a callback for each of the bw interface methods. The callbacks simply forward the bw interface call, but add the id (an int) of the callback binder to the signature of the call. */ template class callback_binder_bw : public tlm::tlm_bw_transport_if , protected convenience_socket_cb_holder { public: //typedefs according to the used TYPES class typedef typename TYPES::tlm_payload_type transaction_type; typedef typename TYPES::tlm_phase_type phase_type; typedef tlm::tlm_sync_enum sync_enum_type; //typedefs for the callbacks typedef nb_transport_functor nb_func_type; typedef invalidate_dmi_functor dmi_func_type; //ctor: an ID is needed to create a callback binder callback_binder_bw(multi_socket_base* owner, int id) : convenience_socket_cb_holder(owner), m_id(id) , m_nb_f(0), m_dmi_f(0) {} //the nb_transport method of the bw interface sync_enum_type nb_transport_bw(transaction_type& txn, phase_type& p, sc_core::sc_time& t){ //check if a callback is registered if (m_nb_f && m_nb_f->is_valid()) { return (*m_nb_f)(m_id, txn, p, t); //do the callback } display_error("Call to nb_transport_bw without a registered callback for nb_transport_bw"); return tlm::TLM_COMPLETED; } //the DMI method of the bw interface void invalidate_direct_mem_ptr(sc_dt::uint64 l, sc_dt::uint64 u){ //check if a callback is registered if (m_dmi_f && m_dmi_f->is_valid()) { (*m_dmi_f)(m_id,l,u); //do the callback } } //register callbacks for all bw interface methods at once void set_callbacks(nb_func_type& cb1, dmi_func_type& cb2){ m_nb_f=&cb1; m_dmi_f=&cb2; } private: //the ID of the callback binder int m_id; //the callbacks nb_func_type* m_nb_f; dmi_func_type* m_dmi_f; }; /* This class forms the base for multi initiator sockets, with fewer template parameters than the multi_init_base. This class is implementation-defined. */ template class multi_init_base_if { public: //this method shall return a vector of the callback binders of multi initiator socket virtual std::vector* >& get_binders()=0; //this method shall return a vector of all target interfaces bound to this multi init socket virtual std::vector*>& get_sockets()=0; protected: virtual ~multi_init_base_if() {} }; /* This class forms the base for multi initiator sockets. It enforces a multi initiator socket to implement all functions needed to do hierarchical bindings. */ template class multi_init_base : public tlm::tlm_initiator_socket , public multi_init_base_if , protected multi_socket_base { public: //typedef for the base type: the standard tlm initiator socket typedef tlm::tlm_initiator_socket base_type; //this method shall disable the code that does the callback binding // that registers callbacks to binders virtual void disable_cb_bind()=0; //this method shall return the multi_init_base to which the // multi_init_base is bound hierarchically // If the base is not bound hierarchically it shall return a pointer to itself virtual multi_init_base* get_hierarch_bind()=0; virtual tlm::tlm_socket_category get_socket_category() const { return tlm::TLM_MULTI_INITIATOR_SOCKET; } //ctor and dtor virtual ~multi_init_base(){} multi_init_base():base_type(sc_core::sc_gen_unique_name("multi_init_base")){} multi_init_base(const char* name):base_type(name){} private: const sc_core::sc_object* get_socket() const { return this; } }; /* This class forms the base for multi target sockets, with fewer template parameters than the multi_target_base. This class is implementation-defined. */ template class multi_target_base_if { public: //this method shall return a vector of the callback binders of multi initiator socket virtual std::vector* >& get_binders()=0; //this method shall return a map of all multi initiator sockets that are // bound to this multi target the key of the map is the index at which the // multi initiator i bound, while the value is the interface of the multi // initiator socket that is bound at that index virtual std::map*>& get_multi_binds()=0; protected: virtual ~multi_target_base_if() {} }; /* This class forms the base for multi target sockets. It enforces a multi target socket to implement all functions needed to do hierarchical bindings. */ template class multi_target_base : public tlm::tlm_target_socket , public multi_target_base_if , protected multi_socket_base { public: //typedef for the base type: the standard tlm target socket typedef tlm::tlm_target_socket base_type; //this method shall return the multi_init_base to which the // multi_init_base is bound hierarchically // If the base is not bound hierarchically it shall return a pointer to itself virtual multi_target_base* get_hierarch_bind()=0; //this method shall inform the multi target socket that it is bound // hierarchically and to which other multi target socket it is bound hierarchically virtual void set_hierarch_bind(multi_target_base*)=0; virtual tlm::tlm_socket_category get_socket_category() const { return tlm::TLM_MULTI_TARGET_SOCKET; } //ctor and dtor virtual ~multi_target_base(){} multi_target_base():base_type(sc_core::sc_gen_unique_name("multi_target_base")){} multi_target_base(const char* name):base_type(name){} private: const sc_core::sc_object* get_socket() const { return this; } }; /* All multi sockets must additionally derive from this class. It enforces a multi socket to implement a function needed to do multi init to multi target bindings. */ template class multi_to_multi_bind_base{ public: virtual ~multi_to_multi_bind_base(){} virtual tlm::tlm_fw_transport_if* get_last_binder(tlm::tlm_bw_transport_if*)=0; }; } // namespace tlm_utils #endif // TLM_UTILS_MULTI_SOCKET_BASES_H_INCLUDED_ systemc-2.3.3/src/tlm_utils/simple_initiator_socket.h0000644000175000017500000002565413360325173023004 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ #ifndef TLM_UTILS_SIMPLE_INITIATOR_SOCKET_H_INCLUDED_ #define TLM_UTILS_SIMPLE_INITIATOR_SOCKET_H_INCLUDED_ #include #include "tlm_utils/convenience_socket_bases.h" namespace tlm_utils { template< typename MODULE, unsigned int BUSWIDTH, typename TYPES , sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND > class simple_initiator_socket_b : public tlm::tlm_initiator_socket , protected simple_socket_base { public: typedef typename TYPES::tlm_payload_type transaction_type; typedef typename TYPES::tlm_phase_type phase_type; typedef tlm::tlm_sync_enum sync_enum_type; typedef tlm::tlm_fw_transport_if fw_interface_type; typedef tlm::tlm_bw_transport_if bw_interface_type; typedef tlm::tlm_initiator_socket base_type; public: static const char* default_name() { return sc_core::sc_gen_unique_name("simple_initiator_socket"); } explicit simple_initiator_socket_b(const char* n = default_name()) : base_type(n) , m_process(this) { this->m_export.bind(m_process); } void register_nb_transport_bw(MODULE* mod, sync_enum_type (MODULE::*cb)(transaction_type&, phase_type&, sc_core::sc_time&)) { m_process.set_transport_ptr(mod, cb); } void register_invalidate_direct_mem_ptr(MODULE* mod, void (MODULE::*cb)(sc_dt::uint64, sc_dt::uint64)) { m_process.set_invalidate_direct_mem_ptr(mod, cb); } private: class process : public tlm::tlm_bw_transport_if , protected convenience_socket_cb_holder { public: typedef sync_enum_type (MODULE::*TransportPtr)(transaction_type&, phase_type&, sc_core::sc_time&); typedef void (MODULE::*InvalidateDirectMemPtr)(sc_dt::uint64, sc_dt::uint64); explicit process(simple_socket_base* owner) : convenience_socket_cb_holder(owner), m_mod(0) , m_transport_ptr(0) , m_invalidate_direct_mem_ptr(0) { } void set_transport_ptr(MODULE* mod, TransportPtr p) { if (m_transport_ptr) { display_warning("non-blocking callback already registered"); return; } sc_assert(!m_mod || m_mod == mod); m_mod = mod; m_transport_ptr = p; } void set_invalidate_direct_mem_ptr(MODULE* mod, InvalidateDirectMemPtr p) { if (m_invalidate_direct_mem_ptr) { display_warning("invalidate DMI callback already registered"); return; } sc_assert(!m_mod || m_mod == mod); m_mod = mod; m_invalidate_direct_mem_ptr = p; } sync_enum_type nb_transport_bw(transaction_type& trans, phase_type& phase, sc_core::sc_time& t) { if (m_transport_ptr) { // forward call sc_assert(m_mod); return (m_mod->*m_transport_ptr)(trans, phase, t); } display_error("no transport callback registered"); return tlm::TLM_COMPLETED; } void invalidate_direct_mem_ptr(sc_dt::uint64 start_range, sc_dt::uint64 end_range) { if (m_invalidate_direct_mem_ptr) { // forward call sc_assert(m_mod); (m_mod->*m_invalidate_direct_mem_ptr)(start_range, end_range); } } private: MODULE* m_mod; TransportPtr m_transport_ptr; InvalidateDirectMemPtr m_invalidate_direct_mem_ptr; }; private: const sc_core::sc_object* get_socket() const { return this; } private: process m_process; }; template< typename MODULE, unsigned int BUSWIDTH = 32 , typename TYPES = tlm::tlm_base_protocol_types > class simple_initiator_socket : public simple_initiator_socket_b { typedef simple_initiator_socket_b socket_b; public: simple_initiator_socket() : socket_b() {} explicit simple_initiator_socket(const char* name) : socket_b(name) {} }; template< typename MODULE, unsigned int BUSWIDTH = 32 , typename TYPES = tlm::tlm_base_protocol_types > class simple_initiator_socket_optional : public simple_initiator_socket_b { typedef simple_initiator_socket_b socket_b; public: simple_initiator_socket_optional() : socket_b() {} explicit simple_initiator_socket_optional(const char* name) : socket_b(name) {} }; // Tagged version template< typename MODULE, unsigned int BUSWIDTH, typename TYPES , sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND > class simple_initiator_socket_tagged_b : public tlm::tlm_initiator_socket , protected simple_socket_base { public: typedef typename TYPES::tlm_payload_type transaction_type; typedef typename TYPES::tlm_phase_type phase_type; typedef tlm::tlm_sync_enum sync_enum_type; typedef tlm::tlm_fw_transport_if fw_interface_type; typedef tlm::tlm_bw_transport_if bw_interface_type; typedef tlm::tlm_initiator_socket base_type; public: static const char* default_name() { return sc_core::sc_gen_unique_name("simple_initiator_socket_tagged"); } explicit simple_initiator_socket_tagged_b(const char* n = default_name()) : base_type(n) , m_process(this) { this->m_export.bind(m_process); } void register_nb_transport_bw(MODULE* mod, sync_enum_type (MODULE::*cb)(int, transaction_type&, phase_type&, sc_core::sc_time&), int id) { m_process.set_transport_ptr(mod, cb); m_process.set_transport_user_id(id); } void register_invalidate_direct_mem_ptr(MODULE* mod, void (MODULE::*cb)(int, sc_dt::uint64, sc_dt::uint64), int id) { m_process.set_invalidate_direct_mem_ptr(mod, cb); m_process.set_invalidate_dmi_user_id(id); } private: class process : public tlm::tlm_bw_transport_if , protected convenience_socket_cb_holder { public: typedef sync_enum_type (MODULE::*TransportPtr)(int, transaction_type&, phase_type&, sc_core::sc_time&); typedef void (MODULE::*InvalidateDirectMemPtr)(int, sc_dt::uint64, sc_dt::uint64); explicit process(simple_socket_base* owner) : convenience_socket_cb_holder(owner), m_mod(0) , m_transport_ptr(0) , m_invalidate_direct_mem_ptr(0) , m_transport_user_id(0) , m_invalidate_direct_mem_user_id(0) { } void set_transport_user_id(int id) { m_transport_user_id = id; } void set_invalidate_dmi_user_id(int id) { m_invalidate_direct_mem_user_id = id; } void set_transport_ptr(MODULE* mod, TransportPtr p) { if (m_transport_ptr) { display_warning("non-blocking callback already registered"); return; } sc_assert(!m_mod || m_mod == mod); m_mod = mod; m_transport_ptr = p; } void set_invalidate_direct_mem_ptr(MODULE* mod, InvalidateDirectMemPtr p) { if (m_invalidate_direct_mem_ptr) { display_warning("invalidate DMI callback already registered"); return; } sc_assert(!m_mod || m_mod == mod); m_mod = mod; m_invalidate_direct_mem_ptr = p; } sync_enum_type nb_transport_bw(transaction_type& trans, phase_type& phase, sc_core::sc_time& t) { if (m_transport_ptr) { // forward call sc_assert(m_mod); return (m_mod->*m_transport_ptr)(m_transport_user_id, trans, phase, t); } display_error("no transport callback registered"); return tlm::TLM_COMPLETED; } void invalidate_direct_mem_ptr(sc_dt::uint64 start_range, sc_dt::uint64 end_range) { if (m_invalidate_direct_mem_ptr) { // forward call sc_assert(m_mod); (m_mod->*m_invalidate_direct_mem_ptr)(m_invalidate_direct_mem_user_id, start_range, end_range); } } private: MODULE* m_mod; TransportPtr m_transport_ptr; InvalidateDirectMemPtr m_invalidate_direct_mem_ptr; int m_transport_user_id; int m_invalidate_direct_mem_user_id; }; private: const sc_core::sc_object* get_socket() const { return this; } private: process m_process; }; template< typename MODULE, unsigned int BUSWIDTH = 32 , typename TYPES = tlm::tlm_base_protocol_types > class simple_initiator_socket_tagged : public simple_initiator_socket_tagged_b { typedef simple_initiator_socket_tagged_b socket_b; public: simple_initiator_socket_tagged() : socket_b() {} explicit simple_initiator_socket_tagged(const char* name) : socket_b(name) {} }; template< typename MODULE, unsigned int BUSWIDTH = 32 , typename TYPES = tlm::tlm_base_protocol_types > class simple_initiator_socket_tagged_optional : public simple_initiator_socket_tagged_b { typedef simple_initiator_socket_tagged_b socket_b; public: simple_initiator_socket_tagged_optional() : socket_b() {} explicit simple_initiator_socket_tagged_optional(const char* name) : socket_b(name) {} }; } // namespace tlm_utils #endif // TLM_UTILS_SIMPLE_INITIATOR_SOCKET_H_INCLUDED_ systemc-2.3.3/src/tlm_utils/peq_with_cb_and_phase.h0000644000175000017500000001707613360325173022346 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ // 12-Jan-2009 John Aynsley Bug fix. Phase argument to notify should be const // 20-Mar-2009 John Aynsley Add cancel_all() method #ifndef __PEQ_WITH_CB_AND_PHASE_H__ #define __PEQ_WITH_CB_AND_PHASE_H__ #ifndef SC_INCLUDE_DYNAMIC_PROCESSES // needed for sc_spawn # define SC_INCLUDE_DYNAMIC_PROCESSES #endif #include #include #include namespace tlm_utils { template class time_ordered_list { public: struct element { struct element *next; PAYLOAD p; sc_core::sc_time t; sc_dt::uint64 d; element(PAYLOAD& p, sc_core::sc_time t, sc_dt::uint64 d): p(p),t(t),d(d) {} element(){} }; element *nill; element *empties; element *list; unsigned int size; time_ordered_list() : nill(new element()), empties(NULL), list(nill), size(0) { } ~time_ordered_list() { reset(); while(empties){ struct element *e=empties->next; delete empties; empties=e; } delete nill; } void reset() { while(size) { delete_top(); } } void insert(const PAYLOAD& p, sc_core::sc_time t) { if (!empties) { empties=new struct element(); empties->next=NULL; } struct element *e=empties; empties=empties->next; e->p=p; e->t=t; e->d=sc_core::sc_delta_count(); struct element * ancestor=nill; struct element * iterator=list; while (iterator!=nill && iterator->t<=t){ ancestor=iterator; iterator=iterator->next; } if (ancestor==nill){ e->next=list; list=e; } else { e->next=iterator; ancestor->next=e; } size++; } void delete_top(){ if (list != nill) { struct element *e=list; list=list->next; e->next=empties; empties=e; size--; } } unsigned int get_size() { return size; } PAYLOAD &top() { return list->p; } sc_core::sc_time top_time() { return list->t; } sc_dt::uint64& top_delta() { return list->d; } sc_core::sc_time next_time() { return list->next->t; } }; //--------------------------------------------------------------------------- /** * An event queue that can contain any number of pending * notifications. Each notification have an associate payload. */ //--------------------------------------------------------------------------- template class peq_with_cb_and_phase: public sc_core::sc_object { typedef typename TYPES::tlm_payload_type tlm_payload_type; typedef typename TYPES::tlm_phase_type tlm_phase_type; typedef std::pair PAYLOAD; typedef void (OWNER::*cb)(tlm_payload_type&, const tlm_phase_type&); class delta_list{ public: delta_list(){ reset(); entries.resize(100); } inline void insert(const PAYLOAD& p){ if (size==entries.size()){ entries.resize(entries.size()*2); } entries[size++]=p; } inline PAYLOAD& get(){ return entries[out++]; } inline bool next(){ return out entries; unsigned int out; }; public: peq_with_cb_and_phase(OWNER* _owner, cb _cb) :sc_core::sc_object( sc_core::sc_gen_unique_name( "peq_with_cb_and_phase" ) ) ,m_owner(_owner) ,m_cb(_cb) { sc_core::sc_spawn_options opts; opts.spawn_method(); opts.set_sensitivity(&m_e); opts.dont_initialize(); sc_core::sc_spawn(sc_bind(&peq_with_cb_and_phase::fec, this), sc_core::sc_gen_unique_name("fec"), &opts); } peq_with_cb_and_phase(const char* _name, OWNER* _owner,cb _cb) : sc_core::sc_object( _name ) ,m_owner(_owner) ,m_cb(_cb) { sc_core::sc_spawn_options opts; opts.spawn_method(); opts.set_sensitivity(&m_e); opts.dont_initialize(); sc_core::sc_spawn(sc_bind(&peq_with_cb_and_phase::fec, this), sc_core::sc_gen_unique_name("fec"), &opts); } ~peq_with_cb_and_phase(){} void notify (tlm_payload_type& t, const tlm_phase_type& p, const sc_core::sc_time& when){ //t.aquire(); if (when==sc_core::SC_ZERO_TIME) { if (sc_core::sc_delta_count() & (sc_dt::uint64)0x1) //uneven delta cycle so delta delay is for even cylce m_even_delta.insert(PAYLOAD(&t,p)); else m_uneven_delta.insert(PAYLOAD(&t,p)); //even delta cycle so delta delay is for uneven delta m_e.notify(sc_core::SC_ZERO_TIME); } else { m_ppq.insert(PAYLOAD(&t,p), when + sc_core::sc_time_stamp() ); m_e.notify(when); // note, this will only over-right the "newest" event. } } void notify (tlm_payload_type& t, const tlm_phase_type& p){ m_immediate_yield.insert(PAYLOAD(&t,p)); m_e.notify(); // immediate notification } // Cancel all events from the event queue void cancel_all() { m_ppq.reset(); m_uneven_delta.reset(); m_even_delta.reset(); m_immediate_yield.reset(); m_e.cancel(); } private: void fec(){ //immediate yield notifications while(m_immediate_yield.next()) {PAYLOAD& tmp=m_immediate_yield.get(); (m_owner->*m_cb)(*tmp.first, tmp.second);} //tmp.first->release();} m_immediate_yield.reset(); //delta notifications if (sc_core::sc_delta_count() & (sc_dt::uint64) 0x1) {//uneven delta so put out all payloads for uneven delta while (m_uneven_delta.next()) {PAYLOAD& tmp=m_uneven_delta.get(); (m_owner->*m_cb)(*tmp.first, tmp.second);} //tmp.first->release();} m_uneven_delta.reset(); if (m_even_delta.size) m_e.notify(sc_core::SC_ZERO_TIME); } else { while (m_even_delta.next()) {PAYLOAD& tmp=m_even_delta.get(); (m_owner->*m_cb)(*tmp.first, tmp.second);} //tmp.first->release();} m_even_delta.reset(); if (m_uneven_delta.size) m_e.notify(sc_core::SC_ZERO_TIME); } if (!m_ppq.get_size()) return; //there were only delta notification //timed notifications const sc_core::sc_time now=sc_core::sc_time_stamp(); sc_core::sc_time top=m_ppq.top_time(); while(m_ppq.get_size() && top==now) { // push all active ones into target PAYLOAD& tmp=m_ppq.top(); (m_owner->*m_cb)(*tmp.first, tmp.second); //tmp.first->release();} m_ppq.delete_top(); top=m_ppq.top_time(); } if ( m_ppq.get_size()) { m_e.notify( top - now) ; } } OWNER* m_owner; cb m_cb; time_ordered_list m_ppq; delta_list m_uneven_delta; delta_list m_even_delta; delta_list m_immediate_yield; sc_core::sc_event m_e; // default event }; } #endif // __PEQ_WITH_CB_AND_PHASE_H__ systemc-2.3.3/src/tlm_utils/instance_specific_extensions.cpp0000644000175000017500000001515513360325173024337 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ #include "tlm_utils/instance_specific_extensions_int.h" #include "sysc/utils/sc_typeindex.h" // sc_typeindex #include #include namespace tlm { template class SC_API tlm_array; } // namespace tlm namespace tlm_utils { /* anonymous */ namespace { class ispex_registry // copied from tlm_gp.cpp { typedef unsigned int key_type; typedef std::map type_map; public: static ispex_registry& instance() { if (!instance_) // don't cleanup registry instance_ = new ispex_registry(); return *instance_; } unsigned int register_extension(sc_core::sc_type_index type) { type_map::const_iterator it = ids_.find( type ); if( it == ids_.end() ) { // new extension - generate/store ID type_map::value_type v( type, static_cast(ids_.size()) ); ids_.insert( v ); return v.second; } return it->second; } static unsigned int max_num_extensions() { return (instance_) ? instance().ids_.size() : 0; } private: static ispex_registry* instance_; type_map ids_; ispex_registry() /* = default */ {} }; // class ispex_registry ispex_registry* ispex_registry::instance_ = NULL; } // anonymous namespace unsigned int ispex_base::register_private_extension(const std::type_info& type) { return ispex_registry::instance().register_extension(type); } //Helper to do the numbering of private extension accessors static unsigned int max_num_ispex_accessors(bool increment=false) { static unsigned int max_num = 0; if (increment) ++max_num; return max_num; } // ---------------------------------------------------------------------------- //the pool for the container, plain as can be class instance_specific_extension_container_pool { instance_specific_extension_container_pool() : unused(NULL){} ~instance_specific_extension_container_pool(); public: static instance_specific_extension_container_pool& instance() { static instance_specific_extension_container_pool inst; return inst; } instance_specific_extension_container* create(); void free(instance_specific_extension_container*); private: instance_specific_extension_container* unused; }; // class instance_specific_extension_container_pool instance_specific_extension_container* instance_specific_extension_container_pool::create() { if (!unused) { unused =new instance_specific_extension_container(); } instance_specific_extension_container* tmp = unused; unused = unused->next; return tmp; } void instance_specific_extension_container_pool:: free(instance_specific_extension_container* cont) { cont->next=unused; unused=cont; } instance_specific_extension_container_pool:: ~instance_specific_extension_container_pool() { while(unused) { instance_specific_extension_container* tmp = unused; unused=unused->next; delete tmp; } } // ---------------------------------------------------------------------------- instance_specific_extension_container* instance_specific_extension_container::create() { return instance_specific_extension_container_pool::instance().create(); } instance_specific_extension_container::instance_specific_extension_container() : use_count(0) , m_txn(NULL) , m_release_fn(NULL) , m_carrier(NULL) , next(NULL) { resize(); } void instance_specific_extension_container:: attach_carrier(instance_specific_extension_carrier* carrier, void* txn, release_fn* rel_fn) { m_txn = txn; m_release_fn = rel_fn; m_carrier = carrier; } void instance_specific_extension_container::resize() { m_ispex_per_accessor.resize( max_num_ispex_accessors() ); for (unsigned int i=0; i < m_ispex_per_accessor.size(); ++i) { m_ispex_per_accessor[i] = new instance_specific_extensions_per_accessor(this); m_ispex_per_accessor[i]->resize_extensions(); } } instance_specific_extension_container:: ~instance_specific_extension_container() { for (unsigned int i=0; iinc_use_count(); return tmp; } ispex_base* instance_specific_extensions_per_accessor:: get_extension(unsigned int index) const { return (index < m_extensions.size()) ? m_extensions[index] : NULL; } void instance_specific_extensions_per_accessor:: clear_extension(unsigned int index) { if (index < m_extensions.size()) { if (m_extensions[index]) m_container->dec_use_count(); m_extensions[index] = static_cast(0); } } void instance_specific_extensions_per_accessor::resize_extensions() { m_extensions.expand(ispex_registry::max_num_extensions()); } // ---------------------------------------------------------------------------- instance_specific_extension_accessor::instance_specific_extension_accessor() : m_index(max_num_ispex_accessors(true)-1) {} } // namespace tlm_utils systemc-2.3.3/src/tlm_utils/simple_target_socket.h0000644000175000017500000010704413360325173022262 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ // ***************************************************************************** // Modified by John Aynsley, Doulos, Feb 2009, // Fix a bug in simple_target_socket and simple_target_socket_tagged // with the addition of one new line of code in each: wait(*e); // ***************************************************************************** // ***************************************************************************** // Modified by John Aynsley on behalf of Robert Guenzel, May 2011, // Fix a bug in simple_target_socket and simple_target_socket_tagged // with the addition of one new line of code in each: wait(t); // ***************************************************************************** #ifndef TLM_UTILS_SIMPLE_TARGET_SOCKET_H_INCLUDED_ #define TLM_UTILS_SIMPLE_TARGET_SOCKET_H_INCLUDED_ #ifndef SC_INCLUDE_DYNAMIC_PROCESSES // needed for sc_spawn # define SC_INCLUDE_DYNAMIC_PROCESSES #endif #include #include #include "tlm_utils/convenience_socket_bases.h" #include "tlm_utils/peq_with_get.h" namespace tlm_utils { template< typename MODULE, unsigned int BUSWIDTH, typename TYPES , sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND > class simple_target_socket_b : public tlm::tlm_target_socket , protected simple_socket_base { friend class fw_process; friend class bw_process; public: typedef typename TYPES::tlm_payload_type transaction_type; typedef typename TYPES::tlm_phase_type phase_type; typedef tlm::tlm_sync_enum sync_enum_type; typedef tlm::tlm_fw_transport_if fw_interface_type; typedef tlm::tlm_bw_transport_if bw_interface_type; typedef tlm::tlm_target_socket base_type; public: static const char* default_name() { return sc_core::sc_gen_unique_name("simple_target_socket"); } explicit simple_target_socket_b(const char* n = default_name()) : base_type(n) , m_fw_process(this) , m_bw_process(this) { bind(m_fw_process); } using base_type::bind; // bw transport must come thru us. tlm::tlm_bw_transport_if * operator ->() {return &m_bw_process;} // REGISTER_XXX void register_nb_transport_fw(MODULE* mod, sync_enum_type (MODULE::*cb)(transaction_type&, phase_type&, sc_core::sc_time&)) { elaboration_check("register_nb_transport_fw"); m_fw_process.set_nb_transport_ptr(mod, cb); } void register_b_transport(MODULE* mod, void (MODULE::*cb)(transaction_type&, sc_core::sc_time&)) { elaboration_check("register_b_transport"); m_fw_process.set_b_transport_ptr(mod, cb); } void register_transport_dbg(MODULE* mod, unsigned int (MODULE::*cb)(transaction_type&)) { elaboration_check("register_transport_dbg"); m_fw_process.set_transport_dbg_ptr(mod, cb); } void register_get_direct_mem_ptr(MODULE* mod, bool (MODULE::*cb)(transaction_type&, tlm::tlm_dmi&)) { elaboration_check("register_get_direct_mem_ptr"); m_fw_process.set_get_direct_mem_ptr(mod, cb); } protected: void start_of_simulation() { base_type::start_of_simulation(); m_fw_process.start_of_simulation(); } private: //make call on bw path. sync_enum_type bw_nb_transport(transaction_type &trans, phase_type &phase, sc_core::sc_time &t) { return base_type::operator ->()->nb_transport_bw(trans, phase, t); } void bw_invalidate_direct_mem_ptr(sc_dt::uint64 s,sc_dt::uint64 e) { base_type::operator ->()->invalidate_direct_mem_ptr(s, e); } //Helper class to handle bw path calls // Needed to detect transaction end when called from b_transport. class bw_process : public tlm::tlm_bw_transport_if { public: bw_process(simple_target_socket_b *p_own) : m_owner(p_own) { } sync_enum_type nb_transport_bw(transaction_type &trans, phase_type &phase, sc_core::sc_time &t) { typename std::map::iterator it = m_owner->m_pending_trans.find(&trans); if(it == m_owner->m_pending_trans.end()) { // Not a blocking call, forward. return m_owner->bw_nb_transport(trans, phase, t); } if (phase == tlm::END_REQ) { m_owner->m_end_request.notify(sc_core::SC_ZERO_TIME); return tlm::TLM_ACCEPTED; } if (phase == tlm::BEGIN_RESP) { if (m_owner->m_current_transaction == &trans) { m_owner->m_end_request.notify(sc_core::SC_ZERO_TIME); } //TODO: add response-accept delay? it->second->notify(t); m_owner->m_pending_trans.erase(it); return tlm::TLM_COMPLETED; } m_owner->display_error("invalid phase received"); return tlm::TLM_COMPLETED; } void invalidate_direct_mem_ptr(sc_dt::uint64 s,sc_dt::uint64 e) { return m_owner->bw_invalidate_direct_mem_ptr(s, e); } private: simple_target_socket_b *m_owner; }; class fw_process : public tlm::tlm_fw_transport_if, public tlm::tlm_mm_interface { public: typedef sync_enum_type (MODULE::*NBTransportPtr)(transaction_type&, phase_type&, sc_core::sc_time&); typedef void (MODULE::*BTransportPtr)(transaction_type&, sc_core::sc_time&); typedef unsigned int (MODULE::*TransportDbgPtr)(transaction_type&); typedef bool (MODULE::*GetDirectMemPtr)(transaction_type&, tlm::tlm_dmi&); fw_process(simple_target_socket_b *p_own) : m_owner(p_own), m_mod(0), m_nb_transport_ptr(0), m_b_transport_ptr(0), m_transport_dbg_ptr(0), m_get_direct_mem_ptr(0), m_peq(sc_core::sc_gen_unique_name("m_peq")), m_response_in_progress(false) {} void start_of_simulation() { if (!m_b_transport_ptr && m_nb_transport_ptr) { // only spawn b2nb_thread, if needed sc_core::sc_spawn_options opts; opts.set_sensitivity(&m_peq.get_event()); opts.dont_initialize(); sc_core::sc_spawn(sc_bind(&fw_process::b2nb_thread, this), sc_core::sc_gen_unique_name("b2nb_thread"), &opts); } } void set_nb_transport_ptr(MODULE* mod, NBTransportPtr p) { if (m_nb_transport_ptr) { m_owner->display_warning("non-blocking callback already registered"); return; } sc_assert(!m_mod || m_mod == mod); m_mod = mod; m_nb_transport_ptr = p; } void set_b_transport_ptr(MODULE* mod, BTransportPtr p) { if (m_b_transport_ptr) { m_owner->display_warning("blocking callback already registered"); return; } sc_assert(!m_mod || m_mod == mod); m_mod = mod; m_b_transport_ptr = p; } void set_transport_dbg_ptr(MODULE* mod, TransportDbgPtr p) { if (m_transport_dbg_ptr) { m_owner->display_warning("debug callback already registered"); return; } sc_assert(!m_mod || m_mod == mod); m_mod = mod; m_transport_dbg_ptr = p; } void set_get_direct_mem_ptr(MODULE* mod, GetDirectMemPtr p) { if (m_get_direct_mem_ptr) { m_owner->display_warning("get DMI pointer callback already registered"); return; } sc_assert(!m_mod || m_mod == mod); m_mod = mod; m_get_direct_mem_ptr = p; } // Interface implementation sync_enum_type nb_transport_fw(transaction_type& trans, phase_type& phase, sc_core::sc_time& t) { if (m_nb_transport_ptr) { // forward call sc_assert(m_mod); return (m_mod->*m_nb_transport_ptr)(trans, phase, t); } // nb->b conversion if (m_b_transport_ptr) { if (phase == tlm::BEGIN_REQ) { // prepare thread to do blocking call process_handle_class * ph = m_process_handle.get_handle(&trans); if (!ph) { // create new dynamic process ph = new process_handle_class(&trans); m_process_handle.put_handle(ph); sc_core::sc_spawn_options opts; opts.dont_initialize(); opts.set_sensitivity(&ph->m_e); sc_core::sc_spawn(sc_bind(&fw_process::nb2b_thread,this, ph), sc_core::sc_gen_unique_name("nb2b_thread"), &opts); } ph->m_e.notify(t); return tlm::TLM_ACCEPTED; } if (phase == tlm::END_RESP) { m_response_in_progress = false; m_end_response.notify(t); return tlm::TLM_COMPLETED; } m_owner->display_error("invalid phase received"); return tlm::TLM_COMPLETED; } m_owner->display_error("no non-blocking transport callback registered"); return tlm::TLM_COMPLETED; } void b_transport(transaction_type& trans, sc_core::sc_time& t) { if (m_b_transport_ptr) { // forward call sc_assert(m_mod); (m_mod->*m_b_transport_ptr)(trans, t); return; } // b->nb conversion if (m_nb_transport_ptr) { m_peq.notify(trans, t); t = sc_core::SC_ZERO_TIME; mm_end_event_ext mm_ext; const bool mm_added = !trans.has_mm(); if (mm_added) { trans.set_mm(this); trans.set_auto_extension(&mm_ext); trans.acquire(); } // wait until transaction is finished sc_core::sc_event end_event; m_owner->m_pending_trans[&trans] = &end_event; sc_core::wait(end_event); if (mm_added) { // release will not delete the transaction, it will notify mm_ext.done trans.release(); if (trans.get_ref_count()) { sc_core::wait(mm_ext.done); } trans.set_mm(0); } return; } // should not be reached m_owner->display_error("no blocking transport callback registered"); } unsigned int transport_dbg(transaction_type& trans) { if (m_transport_dbg_ptr) { // forward call sc_assert(m_mod); return (m_mod->*m_transport_dbg_ptr)(trans); } // No debug support return 0; } bool get_direct_mem_ptr(transaction_type& trans, tlm::tlm_dmi& dmi_data) { if (m_get_direct_mem_ptr) { // forward call sc_assert(m_mod); return (m_mod->*m_get_direct_mem_ptr)(trans, dmi_data); } // No DMI support dmi_data.allow_read_write(); dmi_data.set_start_address(0x0); dmi_data.set_end_address((sc_dt::uint64)-1); return false; } private: // dynamic process handler for nb2b conversion class process_handle_class { public: explicit process_handle_class(transaction_type * trans) : m_trans(trans),m_suspend(false) {} transaction_type* m_trans; sc_core::sc_event m_e; bool m_suspend; }; class process_handle_list { public: process_handle_list() {} ~process_handle_list() { for( typename std::vector::iterator it=v.begin(), end = v.end(); it != end; ++it ) delete *it; } process_handle_class* get_handle(transaction_type *trans) { typename std::vector::iterator it; for(it = v.begin(); it != v.end(); it++) { if ((*it)->m_suspend) { // found suspended dynamic process, re-use it (*it)->m_trans = trans; // replace to new one (*it)->m_suspend = false; return *it; } } return NULL; // no suspended process } void put_handle(process_handle_class* ph) { v.push_back(ph); } private: std::vector v; }; process_handle_list m_process_handle; void nb2b_thread(process_handle_class* h) { while(1) { transaction_type *trans = h->m_trans; sc_core::sc_time t = sc_core::SC_ZERO_TIME; // forward call sc_assert(m_mod); (m_mod->*m_b_transport_ptr)(*trans, t); sc_core::wait(t); // return path while (m_response_in_progress) { sc_core::wait(m_end_response); } t = sc_core::SC_ZERO_TIME; phase_type phase = tlm::BEGIN_RESP; sync_enum_type sync = m_owner->bw_nb_transport(*trans, phase, t); if ( !(sync == tlm::TLM_COMPLETED || (sync == tlm::TLM_UPDATED && phase == tlm::END_RESP)) ) { m_response_in_progress = true; } // suspend until next transaction h->m_suspend = true; sc_core::wait(); } } void b2nb_thread() { while (true) { transaction_type* trans; while ((trans = m_peq.get_next_transaction())!=0) { sc_assert(m_mod); sc_assert(m_nb_transport_ptr); phase_type phase = tlm::BEGIN_REQ; sc_core::sc_time t = sc_core::SC_ZERO_TIME; switch ((m_mod->*m_nb_transport_ptr)(*trans, phase, t)) { case tlm::TLM_COMPLETED: { // notify transaction is finished typename std::map::iterator it = m_owner->m_pending_trans.find(trans); sc_assert(it != m_owner->m_pending_trans.end()); it->second->notify(t); m_owner->m_pending_trans.erase(it); break; } case tlm::TLM_ACCEPTED: case tlm::TLM_UPDATED: switch (phase) { case tlm::BEGIN_REQ: m_owner->m_current_transaction = trans; sc_core::wait(m_owner->m_end_request); m_owner->m_current_transaction = 0; break; case tlm::END_REQ: sc_core::wait(t); break; case tlm::BEGIN_RESP: { phase = tlm::END_RESP; sc_core::wait(t); // This line is a bug fix added in TLM-2.0.2 t = sc_core::SC_ZERO_TIME; (m_mod->*m_nb_transport_ptr)(*trans, phase, t); // notify transaction is finished typename std::map::iterator it = m_owner->m_pending_trans.find(trans); sc_assert(it != m_owner->m_pending_trans.end()); it->second->notify(t); m_owner->m_pending_trans.erase(it); break; } default: m_owner->display_error("invalid phase received"); } break; default: m_owner->display_error("invalid sync value received"); } } sc_core::wait(); } } void free(tlm::tlm_generic_payload* trans) { mm_end_event_ext* ext = trans->template get_extension(); sc_assert(ext); // notif event first before freeing extensions (reset) ext->done.notify(); trans->reset(); } private: struct mm_end_event_ext : public tlm::tlm_extension { tlm::tlm_extension_base* clone() const { return NULL; } void free() {} void copy_from(tlm::tlm_extension_base const &) {} sc_core::sc_event done; }; private: simple_target_socket_b *m_owner; MODULE* m_mod; NBTransportPtr m_nb_transport_ptr; BTransportPtr m_b_transport_ptr; TransportDbgPtr m_transport_dbg_ptr; GetDirectMemPtr m_get_direct_mem_ptr; peq_with_get m_peq; bool m_response_in_progress; sc_core::sc_event m_end_response; }; private: const sc_core::sc_object* get_socket() const { return this; } private: fw_process m_fw_process; bw_process m_bw_process; std::map m_pending_trans; sc_core::sc_event m_end_request; transaction_type* m_current_transaction; }; template< typename MODULE, unsigned int BUSWIDTH = 32 , typename TYPES = tlm::tlm_base_protocol_types > class simple_target_socket : public simple_target_socket_b { typedef simple_target_socket_b socket_b; public: simple_target_socket() : socket_b() {} explicit simple_target_socket(const char* name) : socket_b(name) {} }; template< typename MODULE, unsigned int BUSWIDTH = 32 , typename TYPES = tlm::tlm_base_protocol_types > class simple_target_socket_optional : public simple_target_socket_b { typedef simple_target_socket_b socket_b; public: simple_target_socket_optional() : socket_b() {} explicit simple_target_socket_optional(const char* name) : socket_b(name) {} }; //ID Tagged version template< typename MODULE, unsigned int BUSWIDTH, typename TYPES , sc_core::sc_port_policy POL = sc_core::SC_ONE_OR_MORE_BOUND > class simple_target_socket_tagged_b : public tlm::tlm_target_socket , protected simple_socket_base { friend class fw_process; friend class bw_process; public: typedef typename TYPES::tlm_payload_type transaction_type; typedef typename TYPES::tlm_phase_type phase_type; typedef tlm::tlm_sync_enum sync_enum_type; typedef tlm::tlm_fw_transport_if fw_interface_type; typedef tlm::tlm_bw_transport_if bw_interface_type; typedef tlm::tlm_target_socket base_type; public: static const char* default_name() { return sc_core::sc_gen_unique_name("simple_target_socket_tagged"); } explicit simple_target_socket_tagged_b(const char* n = default_name()) : base_type(n) , m_fw_process(this) , m_bw_process(this) { bind(m_fw_process); } using base_type::bind; // bw transport must come thru us. tlm::tlm_bw_transport_if * operator ->() {return &m_bw_process;} // REGISTER_XXX void register_nb_transport_fw(MODULE* mod, sync_enum_type (MODULE::*cb)(int id, transaction_type&, phase_type&, sc_core::sc_time&), int id) { elaboration_check("register_nb_transport_fw"); m_fw_process.set_nb_transport_ptr(mod, cb); m_fw_process.set_nb_transport_user_id(id); } void register_b_transport(MODULE* mod, void (MODULE::*cb)(int id, transaction_type&, sc_core::sc_time&), int id) { elaboration_check("register_b_transport"); m_fw_process.set_b_transport_ptr(mod, cb); m_fw_process.set_b_transport_user_id(id); } void register_transport_dbg(MODULE* mod, unsigned int (MODULE::*cb)(int id, transaction_type&), int id) { elaboration_check("register_transport_dbg"); m_fw_process.set_transport_dbg_ptr(mod, cb); m_fw_process.set_transport_dbg_user_id(id); } void register_get_direct_mem_ptr(MODULE* mod, bool (MODULE::*cb)(int id, transaction_type&, tlm::tlm_dmi&), int id) { elaboration_check("register_get_direct_mem_ptr"); m_fw_process.set_get_direct_mem_ptr(mod, cb); m_fw_process.set_get_dmi_user_id(id); } protected: void start_of_simulation() { base_type::start_of_simulation(); m_fw_process.start_of_simulation(); } private: //make call on bw path. sync_enum_type bw_nb_transport(transaction_type &trans, phase_type &phase, sc_core::sc_time &t) { return base_type::operator ->()->nb_transport_bw(trans, phase, t); } void bw_invalidate_direct_mem_ptr(sc_dt::uint64 s,sc_dt::uint64 e) { base_type::operator ->()->invalidate_direct_mem_ptr(s, e); } //Helper class to handle bw path calls // Needed to detect transaction end when called from b_transport. class bw_process : public tlm::tlm_bw_transport_if { public: bw_process(simple_target_socket_tagged_b *p_own) : m_owner(p_own) { } sync_enum_type nb_transport_bw(transaction_type &trans, phase_type &phase, sc_core::sc_time &t) { typename std::map::iterator it = m_owner->m_pending_trans.find(&trans); if(it == m_owner->m_pending_trans.end()) { // Not a blocking call, forward. return m_owner->bw_nb_transport(trans, phase, t); } if (phase == tlm::END_REQ) { m_owner->m_end_request.notify(sc_core::SC_ZERO_TIME); return tlm::TLM_ACCEPTED; } if (phase == tlm::BEGIN_RESP) { if (m_owner->m_current_transaction == &trans) { m_owner->m_end_request.notify(sc_core::SC_ZERO_TIME); } //TODO: add response-accept delay? it->second->notify(t); m_owner->m_pending_trans.erase(it); return tlm::TLM_COMPLETED; } m_owner->display_error("invalid phase received"); return tlm::TLM_COMPLETED; } void invalidate_direct_mem_ptr(sc_dt::uint64 s,sc_dt::uint64 e) { return m_owner->bw_invalidate_direct_mem_ptr(s, e); } private: simple_target_socket_tagged_b *m_owner; }; class fw_process : public tlm::tlm_fw_transport_if, public tlm::tlm_mm_interface { public: typedef sync_enum_type (MODULE::*NBTransportPtr)(int id, transaction_type&, phase_type&, sc_core::sc_time&); typedef void (MODULE::*BTransportPtr)(int id, transaction_type&, sc_core::sc_time&); typedef unsigned int (MODULE::*TransportDbgPtr)(int id, transaction_type&); typedef bool (MODULE::*GetDirectMemPtr)(int id, transaction_type&, tlm::tlm_dmi&); fw_process(simple_target_socket_tagged_b *p_own) : m_owner(p_own), m_mod(0), m_nb_transport_ptr(0), m_b_transport_ptr(0), m_transport_dbg_ptr(0), m_get_direct_mem_ptr(0), m_nb_transport_user_id(0), m_b_transport_user_id(0), m_transport_dbg_user_id(0), m_get_dmi_user_id(0), m_peq(sc_core::sc_gen_unique_name("m_peq")), m_response_in_progress(false) {} void start_of_simulation() { if (!m_b_transport_ptr && m_nb_transport_ptr) { // only spawn b2nb_thread, if needed sc_core::sc_spawn_options opts; opts.set_sensitivity(&m_peq.get_event()); opts.dont_initialize(); sc_core::sc_spawn(sc_bind(&fw_process::b2nb_thread, this), sc_core::sc_gen_unique_name("b2nb_thread"), &opts); } } void set_nb_transport_user_id(int id) { m_nb_transport_user_id = id; } void set_b_transport_user_id(int id) { m_b_transport_user_id = id; } void set_transport_dbg_user_id(int id) { m_transport_dbg_user_id = id; } void set_get_dmi_user_id(int id) { m_get_dmi_user_id = id; } void set_nb_transport_ptr(MODULE* mod, NBTransportPtr p) { if (m_nb_transport_ptr) { m_owner->display_warning("non-blocking callback already registered"); return; } sc_assert(!m_mod || m_mod == mod); m_mod = mod; m_nb_transport_ptr = p; } void set_b_transport_ptr(MODULE* mod, BTransportPtr p) { if (m_b_transport_ptr) { m_owner->display_warning("blocking callback already registered"); return; } sc_assert(!m_mod || m_mod == mod); m_mod = mod; m_b_transport_ptr = p; } void set_transport_dbg_ptr(MODULE* mod, TransportDbgPtr p) { if (m_transport_dbg_ptr) { m_owner->display_warning("debug callback already registered"); return; } sc_assert(!m_mod || m_mod == mod); m_mod = mod; m_transport_dbg_ptr = p; } void set_get_direct_mem_ptr(MODULE* mod, GetDirectMemPtr p) { if (m_get_direct_mem_ptr) { m_owner->display_warning("get DMI pointer callback already registered"); } sc_assert(!m_mod || m_mod == mod); m_mod = mod; m_get_direct_mem_ptr = p; } // Interface implementation sync_enum_type nb_transport_fw(transaction_type& trans, phase_type& phase, sc_core::sc_time& t) { if (m_nb_transport_ptr) { // forward call sc_assert(m_mod); return (m_mod->*m_nb_transport_ptr)(m_nb_transport_user_id, trans, phase, t); } // nb->b conversion if (m_b_transport_ptr) { if (phase == tlm::BEGIN_REQ) { // prepare thread to do blocking call process_handle_class * ph = m_process_handle.get_handle(&trans); if (!ph) { // create new dynamic process ph = new process_handle_class(&trans); m_process_handle.put_handle(ph); sc_core::sc_spawn_options opts; opts.dont_initialize(); opts.set_sensitivity(&ph->m_e); sc_core::sc_spawn(sc_bind(&fw_process::nb2b_thread, this, ph), sc_core::sc_gen_unique_name("nb2b_thread"), &opts); } ph->m_e.notify(t); return tlm::TLM_ACCEPTED; } if (phase == tlm::END_RESP) { m_response_in_progress = false; m_end_response.notify(t); return tlm::TLM_COMPLETED; } m_owner->display_error("invalid phase"); return tlm::TLM_COMPLETED; } m_owner->display_error("no non-blocking transport callback registered"); return tlm::TLM_COMPLETED; } void b_transport(transaction_type& trans, sc_core::sc_time& t) { if (m_b_transport_ptr) { // forward call sc_assert(m_mod); (m_mod->*m_b_transport_ptr)(m_b_transport_user_id, trans, t); return; } // b->nb conversion if (m_nb_transport_ptr) { m_peq.notify(trans, t); t = sc_core::SC_ZERO_TIME; mm_end_event_ext mm_ext; const bool mm_added = !trans.has_mm(); if (mm_added){ trans.set_mm(this); trans.set_auto_extension(&mm_ext); trans.acquire(); } // wait until transaction is finished sc_core::sc_event end_event; m_owner->m_pending_trans[&trans] = &end_event; sc_core::wait(end_event); if (mm_added) { // release will not delete the transaction, it will notify mm_ext.done trans.release(); if (trans.get_ref_count()) { sc_core::wait(mm_ext.done); } trans.set_mm(0); } return; } m_owner->display_error("no transport callback registered"); } unsigned int transport_dbg(transaction_type& trans) { if (m_transport_dbg_ptr) { // forward call sc_assert(m_mod); return (m_mod->*m_transport_dbg_ptr)(m_transport_dbg_user_id, trans); } // No debug support return 0; } bool get_direct_mem_ptr(transaction_type& trans, tlm::tlm_dmi& dmi_data) { if (m_get_direct_mem_ptr) { // forward call sc_assert(m_mod); return (m_mod->*m_get_direct_mem_ptr)(m_get_dmi_user_id, trans, dmi_data); } // No DMI support dmi_data.allow_read_write(); dmi_data.set_start_address(0x0); dmi_data.set_end_address((sc_dt::uint64)-1); return false; } private: // dynamic process handler for nb2b conversion class process_handle_class { public: explicit process_handle_class(transaction_type * trans) : m_trans(trans),m_suspend(false){} transaction_type* m_trans; sc_core::sc_event m_e; bool m_suspend; }; class process_handle_list { public: process_handle_list() {} ~process_handle_list() { for( typename std::vector::iterator it=v.begin(), end = v.end(); it != end; ++it ) delete *it; } process_handle_class* get_handle(transaction_type *trans) { typename std::vector::iterator it; for(it = v.begin(); it != v.end(); it++) { if ((*it)->m_suspend) { // found suspended dynamic process, re-use it (*it)->m_trans = trans; // replace to new one (*it)->m_suspend = false; return *it; } } return NULL; // no suspended process } void put_handle(process_handle_class* ph) { v.push_back(ph); } private: std::vector v; }; process_handle_list m_process_handle; void nb2b_thread(process_handle_class* h) { while(1) { transaction_type * trans = h->m_trans; sc_core::sc_time t = sc_core::SC_ZERO_TIME; // forward call sc_assert(m_mod); (m_mod->*m_b_transport_ptr)(m_b_transport_user_id, *trans, t); sc_core::wait(t); // return path while (m_response_in_progress) { sc_core::wait(m_end_response); } t = sc_core::SC_ZERO_TIME; phase_type phase = tlm::BEGIN_RESP; sync_enum_type sync = m_owner->bw_nb_transport(*trans, phase, t); if ( !(sync == tlm::TLM_COMPLETED || (sync == tlm::TLM_UPDATED && phase == tlm::END_RESP)) ) { m_response_in_progress = true; } // suspend until next transaction h->m_suspend = true; sc_core::wait(); } } void b2nb_thread() { while (true) { transaction_type* trans; while ((trans = m_peq.get_next_transaction())!=0) { sc_assert(m_mod); sc_assert(m_nb_transport_ptr); phase_type phase = tlm::BEGIN_REQ; sc_core::sc_time t = sc_core::SC_ZERO_TIME; switch ((m_mod->*m_nb_transport_ptr)(m_nb_transport_user_id, *trans, phase, t)) { case tlm::TLM_COMPLETED: { // notify transaction is finished typename std::map::iterator it = m_owner->m_pending_trans.find(trans); sc_assert(it != m_owner->m_pending_trans.end()); it->second->notify(t); m_owner->m_pending_trans.erase(it); break; } case tlm::TLM_ACCEPTED: case tlm::TLM_UPDATED: switch (phase) { case tlm::BEGIN_REQ: m_owner->m_current_transaction = trans; sc_core::wait(m_owner->m_end_request); m_owner->m_current_transaction = 0; break; case tlm::END_REQ: sc_core::wait(t); break; case tlm::BEGIN_RESP: { phase = tlm::END_RESP; sc_core::wait(t); // This line is a bug fix added in TLM-2.0.2 t = sc_core::SC_ZERO_TIME; (m_mod->*m_nb_transport_ptr)(m_nb_transport_user_id, *trans, phase, t); // notify transaction is finished typename std::map::iterator it = m_owner->m_pending_trans.find(trans); sc_assert(it != m_owner->m_pending_trans.end()); it->second->notify(t); m_owner->m_pending_trans.erase(it); break; } default: m_owner->display_error("invalid phase received"); }; break; default: m_owner->display_error("invalid sync value received"); } } sc_core::wait(); } } void free(tlm::tlm_generic_payload* trans) { mm_end_event_ext* ext = trans->template get_extension(); sc_assert(ext); // notif event first before freeing extensions (reset) ext->done.notify(); trans->reset(); } private: struct mm_end_event_ext : public tlm::tlm_extension { tlm::tlm_extension_base* clone() const { return NULL; } void free() {} void copy_from(tlm::tlm_extension_base const &) {} sc_core::sc_event done; }; private: simple_target_socket_tagged_b *m_owner; MODULE* m_mod; NBTransportPtr m_nb_transport_ptr; BTransportPtr m_b_transport_ptr; TransportDbgPtr m_transport_dbg_ptr; GetDirectMemPtr m_get_direct_mem_ptr; int m_nb_transport_user_id; int m_b_transport_user_id; int m_transport_dbg_user_id; int m_get_dmi_user_id; peq_with_get m_peq; bool m_response_in_progress; sc_core::sc_event m_end_response; }; private: const sc_core::sc_object* get_socket() const { return this; } private: fw_process m_fw_process; bw_process m_bw_process; std::map m_pending_trans; sc_core::sc_event m_end_request; transaction_type* m_current_transaction; }; template< typename MODULE, unsigned int BUSWIDTH = 32 , typename TYPES = tlm::tlm_base_protocol_types > class simple_target_socket_tagged : public simple_target_socket_tagged_b { typedef simple_target_socket_tagged_b socket_b; public: simple_target_socket_tagged() : socket_b() {} explicit simple_target_socket_tagged(const char* name) : socket_b(name) {} }; template< typename MODULE, unsigned int BUSWIDTH = 32 , typename TYPES = tlm::tlm_base_protocol_types > class simple_target_socket_tagged_optional : public simple_target_socket_tagged_b { typedef simple_target_socket_tagged_b socket_b; public: simple_target_socket_tagged_optional() : socket_b() {} explicit simple_target_socket_tagged_optional(const char* name) : socket_b(name) {} }; } // namespace tlm_utils #endif // TLM_UTILS_SIMPLE_TARGET_SOCKET_H_INCLUDED_ systemc-2.3.3/src/tlm_utils/multi_passthrough_target_socket.h0000644000175000017500000003005713360325173024551 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ #ifndef TLM_UTILS_MULTI_PASSTHROUGH_TARGET_SOCKET_H_INCLUDED_ #define TLM_UTILS_MULTI_PASSTHROUGH_TARGET_SOCKET_H_INCLUDED_ #include "tlm_utils/multi_socket_bases.h" namespace tlm_utils { /* This class implements a trivial multi target socket. The triviality refers to the fact that the socket does not do blocking to non-blocking or non-blocking to blocking conversions. It allows to connect multiple initiators to this socket. The user has to register callbacks for the fw interface methods he likes to use. The callbacks are basically equal to the fw interface methods but carry an additional integer that indicates to which index of this socket the calling initiator is connected. */ template class multi_passthrough_target_socket : public multi_target_base< BUSWIDTH, TYPES, N, POL> , public multi_to_multi_bind_base { public: //typedefs // tlm 2.0 types for nb_transport typedef typename TYPES::tlm_payload_type transaction_type; typedef typename TYPES::tlm_phase_type phase_type; typedef tlm::tlm_sync_enum sync_enum_type; // typedefs to keep the fn ptr notations short typedef sync_enum_type (MODULE::*nb_cb)(int, transaction_type&, phase_type&, sc_core::sc_time&); typedef void (MODULE::*b_cb)(int, transaction_type&, sc_core::sc_time&); typedef unsigned int (MODULE::*dbg_cb)(int, transaction_type& txn); typedef bool (MODULE::*dmi_cb)(int, transaction_type& txn, tlm::tlm_dmi& dmi); typedef multi_target_base base_type; typedef typename base_type::base_initiator_socket_type base_initiator_socket_type; static const char* default_name() { return sc_core::sc_gen_unique_name("multi_passthrough_target_socket"); } //CTOR explicit multi_passthrough_target_socket(const char* name = default_name()) : base_type(name) , m_hierarch_bind(0) , m_eoe_disabled(false) , m_export_callback_created(false) { } ~multi_passthrough_target_socket(){ //clean up everything allocated by 'new' for (unsigned int i=0; i >::get_interface()) { // We bind to a callback_binder that will be used as the first interface // i.e. calls to the sc_export will have the same ID as calls from the first initator // socket bound callback_binder_fw * binder; if (m_binders.size() == 0) { binder = new callback_binder_fw(this, m_binders.size()); m_binders.push_back(binder); m_export_callback_created = true; } else { binder = m_binders[0]; } sc_core::sc_export >::bind(*binder); } } //register callback for nb transport of fw interface void register_nb_transport_fw(MODULE* mod, nb_cb cb) { check_export_binding(); //warn if there already is a callback if (m_nb_f.is_valid()){ display_warning("NBTransport_bw callback already registered."); return; } //set the functor m_nb_f.set_function(mod, cb); } //register callback for b transport of fw interface void register_b_transport(MODULE* mod, b_cb cb) { check_export_binding(); //warn if there already is a callback if (m_b_f.is_valid()){ display_warning("BTransport callback already registered."); return; } //set the functor m_b_f.set_function(mod, cb); } //register callback for debug transport of fw interface void register_transport_dbg(MODULE* mod, dbg_cb cb) { check_export_binding(); //warn if there already is a callback if (m_dbg_f.is_valid()){ display_warning("DebugTransport callback already registered."); return; } //set the functor m_dbg_f.set_function(mod, cb); } //register callback for DMI of fw interface void register_get_direct_mem_ptr(MODULE* mod, dmi_cb cb) { check_export_binding(); //warn if there already is a callback if (m_dmi_f.is_valid()){ display_warning("DMI callback already registered."); return; } //set the functor m_dmi_f.set_function(mod, cb); } //Override virtual functions of the tlm_target_socket: // this function is called whenever an sc_port (as part of a init socket) // wants to bind to the export of the underlying tlm_target_socket //At this time a callback binder is created an returned to the sc_port // of the init socket, so that it binds to the callback binder virtual tlm::tlm_fw_transport_if& get_base_interface() { //error if this socket is already bound hierarchically if (m_hierarch_bind) display_error("Socket already bound hierarchically."); if (m_export_callback_created) { // consume binder created from the callback registration m_export_callback_created = false; } else { m_binders.push_back(new callback_binder_fw(this, m_binders.size())); } return *m_binders[m_binders.size()-1]; } // const overload not allowed for multi-sockets virtual const tlm::tlm_fw_transport_if& get_base_interface() const { display_error("'get_base_interface() const' not allowed for multi-sockets."); return base_type::get_base_interface(); } //just return the export of the underlying tlm_target_socket in case of a hierarchical bind virtual sc_core::sc_export >& get_base_export() { return *this; } //just return the export of the underlying tlm_target_socket in case of a hierarchical bind virtual const sc_core::sc_export >& get_base_export() const { return base_type::get_base_export(); } //the standard end of elaboration callback void end_of_elaboration(){ //'break' here if the socket was told not to do callback binding if (m_eoe_disabled) return; //get the callback binders and the multi binds of the top of the hierachical bind chain // NOTE: this could be the same socket if there is no hierachical bind std::vector* >& binders=get_hierarch_bind()->get_binders(); std::map*>& multi_binds=get_hierarch_bind()->get_multi_binds(); // complete binding only if there has been a real bind bool locally_unbound = (binders.size() == 1 && m_export_callback_created); // no call to get_base_interface has consumed the export - ignore if (locally_unbound && !m_hierarch_bind) return; // iterate over all binders for (unsigned int i=0; iset_callbacks(m_nb_f, m_b_f, m_dmi_f, m_dbg_f); //set the callbacks for the binder if (multi_binds.find(i)!=multi_binds.end()) //check if this connection is multi-multi //if so remember the interface m_sockets.push_back(multi_binds[i]); else{ //if we are bound to a normal socket //get the calling port and try to cast it into a tlm socket base base_initiator_socket_type* test=dynamic_cast(binders[i]->get_other_side()); if (!test){display_error("Not bound to tlm_socket.");} m_sockets.push_back(&test->get_base_interface()); //remember the interface } } } // // Bind multi target socket to multi target socket (hierarchical bind) // virtual void bind(base_type& s) { //warn if already bound hierarchically if (m_eoe_disabled){ display_warning("Socket already bound hierarchically. Bind attempt ignored."); return; } //disable our own end of elaboration call disable_cb_bind(); //inform the bound target socket that it is bound hierarchically now s.set_hierarch_bind((base_type*)this); base_type::bind(s); //satisfy SystemC } //operator notation for hierarchical bind void operator() (base_type& s) { bind(s); } //get access to sub port tlm::tlm_bw_transport_if* operator[](int i){return m_sockets[i];} //get number of bound initiators // NOTE: this is only valid at end of elaboration! unsigned int size(){return get_hierarch_bind()->get_binders().size();} protected: using base_type::display_warning; using base_type::display_error; //implementation of base class interface base_type* get_hierarch_bind(){if (m_hierarch_bind) return m_hierarch_bind->get_hierarch_bind(); else return this;} std::map*>& get_multi_binds(){return m_multi_binds;} void set_hierarch_bind(base_type* h){m_hierarch_bind=h;} tlm::tlm_fw_transport_if* get_last_binder(tlm::tlm_bw_transport_if* other){ m_multi_binds[m_binders.size()-1]=other; return m_binders[m_binders.size()-1]; } //map that stores to which index a multi init socket is connected // and the interface of the multi init socket std::map*> m_multi_binds; void disable_cb_bind(){ m_eoe_disabled=true;} std::vector* >& get_binders(){return m_binders;} //vector of connected sockets std::vector*> m_sockets; //vector of binders that convert untagged interface into tagged interface std::vector*> m_binders; base_type* m_hierarch_bind; //pointer to hierarchical bound multi port bool m_eoe_disabled; //bool that disables callback bindings at end of elaboration bool m_export_callback_created; //bool that indicates that a binder has been created from a callback registration //callbacks as functors // (allows to pass the callback to another socket that does not know the type of the module that owns // the callbacks) typename callback_binder_fw::nb_func_type m_nb_f; typename callback_binder_fw::b_func_type m_b_f; typename callback_binder_fw::debug_func_type m_dbg_f; typename callback_binder_fw::dmi_func_type m_dmi_f; }; template class multi_passthrough_target_socket_optional : public multi_passthrough_target_socket { typedef multi_passthrough_target_socket socket_b; public: multi_passthrough_target_socket_optional() : socket_b() {} explicit multi_passthrough_target_socket_optional(const char* name) : socket_b(name) {} }; } // namespace tlm_utils #endif // TLM_UTILS_MULTI_PASSTHROUGH_TARGET_SOCKET_H_INCLUDED_ systemc-2.3.3/src/tlm_utils/tlm_quantumkeeper.h0000644000175000017500000001236513360325173021616 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ // 20-Mar-2009 John Aynsley Add set_and_sync() method #ifndef __TLM_QUANTUMKEEPER_H__ #define __TLM_QUANTUMKEEPER_H__ #include "tlm_core/tlm_2/tlm_quantum/tlm_global_quantum.h" namespace tlm_utils { // // tlm_quantumkeeper class // // The tlm_quantumkeeper class is used to keep track of the local time in // an initiator (how much it has run ahead of the SystemC time), to // synchronize with SystemC time etc. // class tlm_quantumkeeper { public: // // Static setters/getters for the global quantum value. // // The global quantum is the maximum time an initiator can run ahead of // systemC time. All initiators will synchronize on timingpoints that are // multiples of the global quantum value. // static void set_global_quantum(const sc_core::sc_time& t) { tlm::tlm_global_quantum::instance().set(t); } static const sc_core::sc_time& get_global_quantum() { return tlm::tlm_global_quantum::instance().get(); } public: tlm_quantumkeeper() : m_next_sync_point(sc_core::SC_ZERO_TIME), m_local_time(sc_core::SC_ZERO_TIME) { } virtual ~tlm_quantumkeeper() {} // // Increment the local time (the time the initiator is ahead of the // systemC time) After incrementing the local time an initiator should // check (with the need_sync method) if a sync is required. // virtual void inc(const sc_core::sc_time& t) { m_local_time += t; } // // Sets the local time (the time the initiator is ahead of the // systemC time) After changing the local time an initiator should // check (with the need_sync method) if a sync is required. // virtual void set(const sc_core::sc_time& t) { m_local_time = t; } // // Checks if a sync to systemC is required for this initiator. This will // be the case if the local time becomes greater than the local (current) // quantum value for this initiator. // virtual bool need_sync() const { return sc_core::sc_time_stamp() + m_local_time >= m_next_sync_point; } // // Synchronize to systemC. This call will do a wait for the time the // initiator was running ahead of systemC time and reset the // tlm_quantumkeeper. // virtual void sync() { sc_core::wait(m_local_time); reset(); } // // Non-virtual convenience method to set the local time and sync only if needed // void set_and_sync(const sc_core::sc_time& t) { set(t); if (need_sync()) sync(); } // // Resets the local time to SC_ZERO_TIME and computes the value of the // next local quantum. This method should be called by an initiator after // a wait because of a synchronization request by a target (TLM_ACCEPTED, // or TLM_UPDATED). // virtual void reset() { m_local_time = sc_core::SC_ZERO_TIME; m_next_sync_point = sc_core::sc_time_stamp() + compute_local_quantum(); } // // Helper function to get the current systemC time, taken the local time // into account. The current systemC time is calculated as the time // returned by sc_time_stamp incremeneted with the time the initiator is // running ahead. // virtual sc_core::sc_time get_current_time() const { return sc_core::sc_time_stamp() + m_local_time; } // // Helper functions to get the time the initiator is running ahead of // systenC (local time). This time should be passed to a target in the // nb_transport call // virtual sc_core::sc_time get_local_time() const { return m_local_time; } protected: // // Calculate the next local quantum for this initiator. // // The method can be overloaded in a derived object if an initiator wants // to use another local quantum. This derived object should also take the // global quantum into account. It's local quantum should not be set to a // value that is larger than the quantum returned by the // compute_local_quantum of the tlm_global_quantum singleton. // virtual sc_core::sc_time compute_local_quantum() { return tlm::tlm_global_quantum::instance().compute_local_quantum(); } protected: sc_core::sc_time m_next_sync_point; sc_core::sc_time m_local_time; }; } // namespace tlm #endif systemc-2.3.3/src/sysc/0000755000175000017500000000000013360325173014641 5ustar carstencarstensystemc-2.3.3/src/sysc/Makefile.am0000644000175000017500000000453413360325173016703 0ustar carstencarsten## **************************************************************************** ## ## Licensed to Accellera Systems Initiative Inc. (Accellera) under one or ## more contributor license agreements. See the NOTICE file distributed ## with this work for additional information regarding copyright ownership. ## Accellera licenses this file to you under the Apache License, Version 2.0 ## (the "License"); you may not use this file except in compliance with the ## License. You may obtain a copy of the License at ## ## http://www.apache.org/licenses/LICENSE-2.0 ## ## Unless required by applicable law or agreed to in writing, software ## distributed under the License is distributed on an "AS IS" BASIS, ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or ## implied. See the License for the specific language governing ## permissions and limitations under the License. ## ## **************************************************************************** ## ## src/sysc/Makefile.am -- ## Process this file with automake to produce a Makefile.in file. ## ## Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 ## ## **************************************************************************** ## ## MODIFICATION LOG - modifiers, enter your name, affiliation, date and ## changes you are making here. ## ## Name, Affiliation, Date: ## Description of Modification: ## ## **************************************************************************** include $(top_srcdir)/config/Make-rules.sysc if WANT_QT_THREADS QT_LIB = packages/qt/libqt.la QT_SUBDIR = packages/qt endif # only build external packages separately SUBDIRS = \ packages/boost \ $(QT_SUBDIR) H_FILES = NO_H_FILES = CXX_FILES = INCDIRS = # include file lists for sub-directories include kernel/files.am include communication/files.am include datatypes/files.am include tracing/files.am include utils/files.am localincludedir = $(includedir)/sysc nobase_localinclude_HEADERS = $(H_FILES) noinst_LTLIBRARIES = libsysc.la libsysc_la_SOURCES = $(NO_H_FILES) $(CXX_FILES) # add dependent (package) libraries libsysc_la_LIBADD = \ $(QT_LIB) INCDIRS += \ packages uninstall-hook: test ! -d "$(localincludedir)" || ( set -e ; cd "$(localincludedir)"; \ for dir in $(INCDIRS) ; do test ! -d $$dir || rmdir $$dir ; done ; \ cd - ; rmdir "$(localincludedir)" ) ## Taf! systemc-2.3.3/src/sysc/kernel/0000755000175000017500000000000013360325173016121 5ustar carstencarstensystemc-2.3.3/src/sysc/kernel/sc_cor_fiber.h0000644000175000017500000001107013360325173020710 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_cor_fiber.h -- Coroutine implementation with fibers. Original Author: Martin Janssen, Synopsys, Inc., 2001-12-18 CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #ifndef SC_COR_FIBER_H #define SC_COR_FIBER_H #if defined(_WIN32) || defined(WIN32) || defined(WIN64) #include "sysc/kernel/sc_cor.h" #include "sysc/kernel/sc_cmnhdr.h" #if defined(__GNUC__) && __USING_SJLJ_EXCEPTIONS__ // _Unwind_SjLj_Register() & _Unwind_SjLj_Unregister() only need first field. struct SjLj_Function_Context { struct SjLj_Function_Context *prev; }; #endif namespace sc_core { class sc_cor_pkg_fiber; typedef sc_cor_pkg_fiber sc_cor_pkg_t; #if( defined(_MSC_VER) && _MSC_VER >= 1300 ) typedef std::size_t size_t; #endif // ---------------------------------------------------------------------------- // CLASS : sc_cor_fiber // // Coroutine class implemented with QuickThreads. // ---------------------------------------------------------------------------- class sc_cor_fiber : public sc_cor { public: // constructor sc_cor_fiber() : m_stack_size( 0 ), m_fiber( 0 ), m_pkg( 0 ) { # if defined(__GNUC__) && __USING_SJLJ_EXCEPTIONS__ m_eh.prev = 0; # endif } // destructor virtual ~sc_cor_fiber(); public: std::size_t m_stack_size; // stack size void* m_fiber; // fiber sc_cor_pkg_fiber* m_pkg; // the creating coroutine package #if defined(__GNUC__) && __USING_SJLJ_EXCEPTIONS__ struct SjLj_Function_Context m_eh; // the exception handling context #endif private: // disabled sc_cor_fiber( const sc_cor_fiber& ); sc_cor_fiber& operator = ( const sc_cor_fiber& ); }; // ---------------------------------------------------------------------------- // CLASS : sc_cor_pkg_fiber // // Coroutine package class implemented with QuickThreads. // ---------------------------------------------------------------------------- class SC_API sc_cor_pkg_fiber : public sc_cor_pkg { public: // constructor sc_cor_pkg_fiber( sc_simcontext* simc ); // destructor virtual ~sc_cor_pkg_fiber(); // create a new coroutine virtual sc_cor* create( std::size_t stack_size, sc_cor_fn* fn, void* arg ); // yield to the next coroutine virtual void yield( sc_cor* next_cor ); // abort the current coroutine (and resume the next coroutine) virtual void abort( sc_cor* next_cor ); // get the main coroutine virtual sc_cor* get_main(); private: static int instance_count; private: // disabled sc_cor_pkg_fiber(); sc_cor_pkg_fiber( const sc_cor_pkg_fiber& ); sc_cor_pkg_fiber& operator = ( const sc_cor_pkg_fiber& ); }; } // namespace sc_core #endif // WIN32 // $Log: sc_cor_fiber.h,v $ // Revision 1.6 2011/08/26 20:46:09 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.5 2011/06/25 17:08:39 acg // Andy Goodrich: Jerome Cornet's changes to use libtool to build the // library. // // Revision 1.4 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.3 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.2 2008/05/22 17:06:25 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.3 2006/01/13 18:44:29 acg // Added $Log to record CVS changes into the source. // #endif // Taf! systemc-2.3.3/src/sysc/kernel/sc_attribute.h0000644000175000017500000001330013360325173020757 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_attribute.h -- Attribute classes. Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #ifndef SC_ATTRIBUTE_H #define SC_ATTRIBUTE_H #include #include #include "sysc/kernel/sc_cmnhdr.h" #if defined(_MSC_VER) && !defined(SC_WIN_DLL_WARN) #pragma warning(push) #pragma warning(disable: 4251) // DLL import for std::string,vector #endif namespace sc_core { // ---------------------------------------------------------------------------- // CLASS : sc_attr_base // // Attribute base class. // ---------------------------------------------------------------------------- class SC_API sc_attr_base { public: // constructors sc_attr_base( const std::string& name_ ); sc_attr_base( const sc_attr_base& ); // destructor (does nothing) virtual ~sc_attr_base(); // get the name const std::string& name() const; private: std::string m_name; private: // disabled sc_attr_base(); sc_attr_base& operator = ( const sc_attr_base& ); }; // ---------------------------------------------------------------------------- // CLASS : sc_attr_cltn // // Attribute collection class. Stores pointers to attributes. // Note: iterate over the collection by using iterators. // ---------------------------------------------------------------------------- class SC_API sc_attr_cltn { public: // typedefs typedef sc_attr_base* elem_type; typedef std::vector::iterator iterator; typedef std::vector::const_iterator const_iterator; // constructors sc_attr_cltn(); sc_attr_cltn( const sc_attr_cltn& ); // destructor ~sc_attr_cltn(); // add attribute to the collection. // returns 'true' if the name of the attribute is unique, // returns 'false' otherwise (attribute is not added). bool push_back( sc_attr_base* ); // get attribute by name. // returns pointer to attribute, or 0 if name does not exist. sc_attr_base* operator [] ( const std::string& name_ ); const sc_attr_base* operator [] ( const std::string& name_ ) const; // remove attribute by name. // returns pointer to attribute, or 0 if name does not exist. sc_attr_base* remove( const std::string& name_ ); // remove all attributes void remove_all(); // get the size of the collection int size() const { return static_cast(m_cltn.size()); } // get the begin iterator iterator begin() { return m_cltn.begin(); } const_iterator begin() const { return m_cltn.begin(); } // get the end iterator iterator end() { return m_cltn.end(); } const_iterator end() const { return m_cltn.end(); } private: std::vector m_cltn; private: // disabled sc_attr_cltn& operator = ( const sc_attr_cltn& ); }; // ---------------------------------------------------------------------------- // CLASS : sc_attribute // // Attribute class. // Note: T must have a default constructor and copy constructor. // ---------------------------------------------------------------------------- template class sc_attribute : public sc_attr_base { public: // constructors sc_attribute( const std::string& name_ ) : sc_attr_base( name_ ), value() {} sc_attribute( const std::string& name_, const T& value_ ) : sc_attr_base( name_ ), value( value_ ) {} sc_attribute( const sc_attribute& a ) : sc_attr_base( a.name() ), value( a.value ) {} // destructor (does nothing) virtual ~sc_attribute() {} public: // public data member; for easy access T value; private: // disabled sc_attribute(); sc_attribute& operator = ( const sc_attribute& ); }; } // namespace sc_core #if defined(_MSC_VER) && !defined(SC_WIN_DLL_WARN) #pragma warning(pop) #endif // $Log: sc_attribute.h,v $ // Revision 1.6 2011/08/26 20:46:08 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.5 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.4 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.3 2010/07/22 20:02:33 acg // Andy Goodrich: bug fixes. // // Revision 1.2 2008/05/22 17:06:24 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.3 2006/01/13 18:44:29 acg // Added $Log to record CVS changes into the source. // #endif // Taf! systemc-2.3.3/src/sysc/kernel/sc_cor_pthread.cpp0000644000175000017500000002333313360325173021610 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_cor_pthread.cpp -- Coroutine implementation with pthreads. Original Author: Andy Goodrich, Forte Design Systems, 2002-11-10 CHANGE LOG APPEARS AT THE END OF THE FILE *****************************************************************************/ #if !defined(_WIN32) && !defined(WIN32) && defined(SC_USE_PTHREADS) // ORDER OF THE INCLUDES AND namespace sc_core IS IMPORTANT!!! #include "sysc/kernel/sc_cor_pthread.h" #include "sysc/kernel/sc_simcontext.h" using namespace std; namespace sc_core { // MAKE SURE WE HAVE A NULL THAT WILL WORK: #if defined(__hpux) # define PTHREAD_NULL cma_c_null #else // !defined(__hpux) # define PTHREAD_NULL NULL #endif // !defined(__hpux) #define DEBUGF \ if (0) std::cout << "sc_cor_pthread.cpp(" << __LINE__ << ") " // ---------------------------------------------------------------------------- // File static variables. // // (1) The thread creation mutex and the creation condition are used to // suspend the thread creating another one until the created thread // reaches its invoke_module_method. This allows us to get control of // thread scheduling away from the pthread package. // ---------------------------------------------------------------------------- static sc_cor_pthread* active_cor_p=0; // Active co-routine. static pthread_cond_t create_condition; // See note 1 above. static pthread_mutex_t create_mutex; // See note 1 above. static sc_cor_pthread main_cor; // Main coroutine. // ---------------------------------------------------------------------------- // CLASS : sc_cor_pthread // // Coroutine class implemented with Posix Threads. // ---------------------------------------------------------------------------- // constructor sc_cor_pthread::sc_cor_pthread() : m_cor_fn_arg( 0 ), m_pkg_p( 0 ) { DEBUGF << this << ": sc_cor_pthread::sc_cor_pthread()" << std::endl; pthread_cond_init( &m_pt_condition, PTHREAD_NULL ); pthread_mutex_init( &m_mutex, PTHREAD_NULL ); } // destructor sc_cor_pthread::~sc_cor_pthread() { DEBUGF << this << ": sc_cor_pthread::~sc_cor_pthread()" << std::endl; pthread_cond_destroy( &m_pt_condition); pthread_mutex_destroy( &m_mutex ); } // This static method is a Posix Threads helper callback and invokes a thread // for the first time. It performs some synchronization and then invokes the // actual sc_cor helper function. // context_p -> thread to invoke module method of. // Result is 0 and ignored. void* sc_cor_pthread::invoke_module_method(void* context_p) { sc_cor_pthread* p = (sc_cor_pthread*)context_p; DEBUGF << p << ": sc_cor_pthread::invoke_module_method()" << std::endl; // SUSPEND THE THREAD SO WE CAN GAIN CONTROL FROM THE PTHREAD PACKAGE: // // Since pthread_create schedules each thread behind our back for its // initial execution we immediately suspend a newly created thread // here so we can control when its execution will occur. We also wake // up the main thread which is waiting for this thread to execute to this // wait point. pthread_mutex_lock( &create_mutex ); DEBUGF << p << ": child signalling main thread " << endl; pthread_cond_signal( &create_condition ); pthread_mutex_lock( &p->m_mutex ); pthread_mutex_unlock( &create_mutex ); pthread_cond_wait( &p->m_pt_condition, &p->m_mutex ); pthread_mutex_unlock( &p->m_mutex ); // CALL THE SYSTEMC CODE THAT WILL ACTUALLY START THE THREAD OFF: active_cor_p = p; DEBUGF << p << ": about to invoke real method " << active_cor_p << std::endl; (p->m_cor_fn)(p->m_cor_fn_arg); return 0; } // ---------------------------------------------------------------------------- // CLASS : sc_cor_pkg_pthread // // Coroutine package class implemented with Posix Threads. // ---------------------------------------------------------------------------- int sc_cor_pkg_pthread::instance_count = 0; // constructor sc_cor_pkg_pthread::sc_cor_pkg_pthread( sc_simcontext* simc ) : sc_cor_pkg( simc ) { // initialize the current coroutine if( ++ instance_count == 1 ) { pthread_cond_init( &create_condition, PTHREAD_NULL ); pthread_mutex_init( &create_mutex, PTHREAD_NULL ); sc_assert( active_cor_p == 0 ); main_cor.m_pkg_p = this; DEBUGF << &main_cor << ": is main co-routine" << std::endl; active_cor_p = &main_cor; } } // destructor sc_cor_pkg_pthread::~sc_cor_pkg_pthread() { if( -- instance_count == 0 ) { // cleanup the main coroutine } } // create a new coroutine sc_cor* sc_cor_pkg_pthread::create( std::size_t stack_size, sc_cor_fn* fn, void* arg ) { sc_cor_pthread* cor_p = new sc_cor_pthread; DEBUGF << &main_cor << ": sc_cor_pkg_pthread::create(" << cor_p << ")" << std::endl; // INITIALIZE OBJECT'S FIELDS FROM ARGUMENT LIST: cor_p->m_pkg_p = this; cor_p->m_cor_fn = fn; cor_p->m_cor_fn_arg = arg; // SET UP THREAD CREATION ATTRIBUTES: // // Use default values except for stack size. If stack size is non-zero // set it. pthread_attr_t attr; pthread_attr_init( &attr ); pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED ); if ( stack_size != 0 ) { pthread_attr_setstacksize( &attr, stack_size ); } // ALLOCATE THE POSIX THREAD TO USE AND FORCE SEQUENTIAL EXECUTION: // // Because pthread_create causes the created thread to be executed, // we need to let it run until we can block in the invoke_module_method. // So we: // (1) Lock the creation mutex before creating the new thread. // (2) Sleep on the creation condition, which will be signalled by // the newly created thread just before it goes to sleep in // invoke_module_method. // This scheme results in the newly created thread being dormant before // the main thread continues execution. pthread_mutex_lock( &create_mutex ); DEBUGF << &main_cor << ": about to create actual thread " << cor_p << std::endl; if ( pthread_create( &cor_p->m_thread, &attr, &sc_cor_pthread::invoke_module_method, (void*)cor_p ) ) { std::fprintf(stderr, "ERROR - could not create thread\n"); } DEBUGF << &main_cor << ": main thread waiting for signal from " << cor_p << std::endl; pthread_cond_wait( &create_condition, &create_mutex ); DEBUGF << &main_cor << ": main thread signaled by " << cor_p << endl; pthread_attr_destroy( &attr ); pthread_mutex_unlock( &create_mutex ); DEBUGF << &main_cor << ": exiting sc_cor_pkg_pthread::create(" << cor_p << ")" << std::endl; return cor_p; } // yield to the next coroutine // // We don't do anything after the p_thread_cond_wait since it won't // happen until the thread wakes up again! void sc_cor_pkg_pthread::yield( sc_cor* next_cor_p ) { sc_cor_pthread* from_p = active_cor_p; sc_cor_pthread* to_p = (sc_cor_pthread*)next_cor_p; DEBUGF << from_p << ": switch to " << to_p << std::endl; if ( to_p != from_p ) { pthread_mutex_lock( &to_p->m_mutex ); pthread_cond_signal( &to_p->m_pt_condition ); pthread_mutex_lock( &from_p->m_mutex ); pthread_mutex_unlock( &to_p->m_mutex ); pthread_cond_wait( &from_p->m_pt_condition, &from_p->m_mutex ); pthread_mutex_unlock( &from_p->m_mutex ); } active_cor_p = from_p; // When we come out of wait make ourselves active. DEBUGF << from_p << " restarting after yield to " << to_p << std::endl; } // abort the current coroutine (and resume the next coroutine) void sc_cor_pkg_pthread::abort( sc_cor* next_cor_p ) { sc_cor_pthread* n_p = (sc_cor_pthread*)next_cor_p; DEBUGF << active_cor_p << ": aborting, switching to " << n_p << std::endl; pthread_mutex_lock( &n_p->m_mutex ); pthread_cond_signal( &n_p->m_pt_condition ); pthread_mutex_unlock( &n_p->m_mutex ); } // get the main coroutine sc_cor* sc_cor_pkg_pthread::get_main() { return &main_cor; } } // namespace sc_core #endif // !defined(_WIN32) && !defined(WIN32) && defined(SC_USE_PTHREADS) // $Log: sc_cor_pthread.cpp,v $ // Revision 1.6 2011/08/30 21:51:04 acg // Jerome Cornet: auto processing of pthread configurations. // // Revision 1.5 2011/08/26 20:46:09 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.4 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.3 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.2 2008/05/22 17:06:25 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.3 2006/01/13 18:44:29 acg // Added $Log to record CVS changes into the source. // // Taf! systemc-2.3.3/src/sysc/kernel/sc_cor_pthread.h0000644000175000017500000001107713360325173021257 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_cor_pthread.h -- Coroutine implementation with pthreads. Original Author: Andy Goodrich, Forte Design Systems, 2002-11-10 CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #ifndef SC_COR_PTHREAD_H #define SC_COR_PTHREAD_H #if defined(SC_USE_PTHREADS) #include "sysc/kernel/sc_cor.h" #include "sysc/kernel/sc_cmnhdr.h" #include namespace sc_core { class sc_cor_pkg_pthread; typedef sc_cor_pkg_pthread sc_cor_pkg_t; // ---------------------------------------------------------------------------- // CLASS : sc_cor_pthread // // Coroutine class implemented with Posix Threads. // // Notes: // (1) The thread creation mutex and the creation condition are used to // suspend the thread creating another one until the created thread // reaches its invoke_module_method. This allows us to get control of // thread scheduling away from the pthread package. // ---------------------------------------------------------------------------- class sc_cor_pthread : public sc_cor { public: // constructor sc_cor_pthread(); // destructor virtual ~sc_cor_pthread(); // module method invocator (starts thread execution) static void* invoke_module_method( void* context_p ); public: static sc_cor_pthread* m_active_cor_p; // Active coroutine. public: sc_cor_fn* m_cor_fn; // Core function. void* m_cor_fn_arg; // Core function argument. pthread_mutex_t m_mutex; // Mutex to suspend thread on. sc_cor_pkg_pthread* m_pkg_p; // the creating coroutine package pthread_cond_t m_pt_condition; // Condition waiting for. pthread_t m_thread; // Our pthread storage. private: // disabled sc_cor_pthread( const sc_cor_pthread& ); sc_cor_pthread& operator = ( const sc_cor_pthread& ); }; // ---------------------------------------------------------------------------- // CLASS : sc_cor_pkg_pthread // // Coroutine package class implemented with Posix Threads. // ---------------------------------------------------------------------------- class sc_cor_pkg_pthread : public sc_cor_pkg { public: // constructor sc_cor_pkg_pthread( sc_simcontext* simc ); // destructor virtual ~sc_cor_pkg_pthread(); // create a new coroutine virtual sc_cor* create( std::size_t stack_size, sc_cor_fn* fn, void* arg ); // yield to the next coroutine virtual void yield( sc_cor* next_cor ); // abort the current coroutine (and resume the next coroutine) virtual void abort( sc_cor* next_cor ); // get the main coroutine virtual sc_cor* get_main(); private: static int instance_count; private: // disabled sc_cor_pkg_pthread(); sc_cor_pkg_pthread( const sc_cor_pkg_pthread& ); sc_cor_pkg_pthread& operator = ( const sc_cor_pkg_pthread& ); }; } // namespace sc_core #endif // $Log: sc_cor_pthread.h,v $ // Revision 1.5 2011/08/26 20:46:09 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.4 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.3 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.2 2008/05/22 17:06:25 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.3 2006/01/13 18:44:29 acg // Added $Log to record CVS changes into the source. // #endif // defined(SC_USE_PTHREADS) // Taf! systemc-2.3.3/src/sysc/kernel/files.am0000644000175000017500000000742313360325173017550 0ustar carstencarsten## **************************************************************************** ## ## Licensed to Accellera Systems Initiative Inc. (Accellera) under one or ## more contributor license agreements. See the NOTICE file distributed ## with this work for additional information regarding copyright ownership. ## Accellera licenses this file to you under the Apache License, Version 2.0 ## (the "License"); you may not use this file except in compliance with the ## License. You may obtain a copy of the License at ## ## http://www.apache.org/licenses/LICENSE-2.0 ## ## Unless required by applicable law or agreed to in writing, software ## distributed under the License is distributed on an "AS IS" BASIS, ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or ## implied. See the License for the specific language governing ## permissions and limitations under the License. ## ## **************************************************************************** ## ## src/sysc/kernel/files.am -- ## Included from a Makefile.am to provide directory-specific information ## ## Original Author: Philipp A. Hartmann, Intel, 2015-11-24 ## ## **************************************************************************** ## ## MODIFICATION LOG - modifiers, enter your name, affiliation, date and ## changes you are making here. ## ## Name, Affiliation, Date: ## Description of Modification: ## ## **************************************************************************** ## Generic directory setup ## (should be kept in sync among all files.am files) ## ## Note: Recent Automake versions (>1.13) support relative placeholders for ## included files (%D%,%C%). To support older versions, use explicit ## names for now. ## ## Local values: ## %D%: kernel ## %C%: kernel H_FILES += \ kernel/sc_attribute.h \ kernel/sc_cmnhdr.h \ kernel/sc_constants.h \ kernel/sc_cor.h \ kernel/sc_dynamic_processes.h \ kernel/sc_event.h \ kernel/sc_except.h \ kernel/sc_externs.h \ kernel/sc_join.h \ kernel/sc_kernel_ids.h \ kernel/sc_macros.h \ kernel/sc_module.h \ kernel/sc_module_name.h \ kernel/sc_object.h \ kernel/sc_process.h \ kernel/sc_process_handle.h \ kernel/sc_runnable.h \ kernel/sc_sensitive.h \ kernel/sc_spawn.h \ kernel/sc_spawn_options.h \ kernel/sc_status.h \ kernel/sc_simcontext.h \ kernel/sc_time.h \ kernel/sc_ver.h \ kernel/sc_wait.h \ kernel/sc_wait_cthread.h NO_H_FILES += \ kernel/sc_cor_fiber.h \ kernel/sc_cor_pthread.h \ kernel/sc_cor_qt.h \ kernel/sc_cthread_process.h \ kernel/sc_method_process.h \ kernel/sc_module_registry.h \ kernel/sc_name_gen.h \ kernel/sc_object_int.h \ kernel/sc_object_manager.h \ kernel/sc_phase_callback_registry.h \ kernel/sc_reset.h \ kernel/sc_runnable_int.h \ kernel/sc_simcontext_int.h \ kernel/sc_thread_process.h CXX_FILES += \ kernel/sc_attribute.cpp \ $(CXX_COR_FILES) \ kernel/sc_cthread_process.cpp \ kernel/sc_event.cpp \ kernel/sc_except.cpp \ kernel/sc_join.cpp \ kernel/sc_main.cpp \ kernel/sc_main_main.cpp \ kernel/sc_method_process.cpp \ kernel/sc_module.cpp \ kernel/sc_module_name.cpp \ kernel/sc_module_registry.cpp \ kernel/sc_name_gen.cpp \ kernel/sc_object.cpp \ kernel/sc_object_manager.cpp \ kernel/sc_phase_callback_registry.cpp \ kernel/sc_process.cpp \ kernel/sc_reset.cpp \ kernel/sc_sensitive.cpp \ kernel/sc_simcontext.cpp \ kernel/sc_spawn_options.cpp \ kernel/sc_thread_process.cpp \ kernel/sc_time.cpp \ kernel/sc_ver.cpp \ kernel/sc_wait.cpp \ kernel/sc_wait_cthread.cpp # co-routine implementation if WANT_QT_THREADS CXX_COR_FILES = kernel/sc_cor_qt.cpp else if WANT_PTHREADS_THREADS CXX_COR_FILES = kernel/sc_cor_pthread.cpp else CXX_COR_FILES = kernel/sc_cor_fiber.cpp endif endif # co-routine implementation INCDIRS += \ kernel ## Taf! ## :vim:ft=automake: systemc-2.3.3/src/sysc/kernel/sc_spawn.h0000644000175000017500000002756213360325173020123 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_spawn.h -- Process spawning support. Original Authors: Andy Goodrich, Forte Design Systems, 17 June 2003 Stuart Swan, Cadence, Bishnupriya Bhattacharya, Cadence Design Systems, 25 August, 2003 CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #if !defined(sc_spawn_h_INCLUDED) #define sc_spawn_h_INCLUDED #include "sysc/kernel/sc_process_handle.h" #include "sysc/kernel/sc_spawn_options.h" namespace sc_core { class sc_event; class sc_port_base; class sc_interface; class sc_event_finder; class sc_process_b; //============================================================================= // CLASS sc_spawn_object // // This templated helper class allows an object to provide the execution // semantics for a process via its () operator. An instance of the supplied // execution object will be kept to provide the semantics when the process is // scheduled for execution. The () operator does not return a value. An example // of an object that might be used for this helper function would be void // sc_bind bound function or method. // // This class is derived from sc_process_host and overloads // sc_process_host::semantics to provide the actual semantic content. // // sc_spawn_object(T object, const char* name, const sc_spawn_options* opt_p) // This is the object instance constructor for this class. It makes a // copy of the supplied object. The tp_call constructor is called // with an indication that this object instance should be reclaimed when // execution completes. // object = object whose () operator will be called to provide // the process semantics. // name_p = optional name for object instance, or zero. // opt_p -> spawn options or zero. // // virtual void semantics() // This virtual method provides the execution semantics for its process. // It performs a () operation on m_object. //============================================================================= template class sc_spawn_object : public sc_process_host { public: sc_spawn_object( T object) : m_object(object) { } virtual void semantics() { m_object(); } protected: T m_object; }; //------------------------------------------------------------------------------ //"sc_spawn - semantic object with no return value" // // This inline function spawns a process for execution. The execution semantics // for the process being spawned will be provided by the supplied object // instance via its () operator. (E.g., an sc_bind bound function) // After creating the process it is registered with the simulator. // object = object instance providing the execution semantics via its // () operator. // name_p = optional name for object instance, or zero. // opt_p -> optional spawn options for process, or zero for the default. //------------------------------------------------------------------------------ template inline sc_process_handle sc_spawn( T object, const char* name_p = 0, const sc_spawn_options* opt_p = 0) { sc_simcontext* context_p; sc_spawn_object* spawn_p; context_p = sc_get_curr_simcontext(); spawn_p = new sc_spawn_object(object); if ( !opt_p || !opt_p->is_method() ) { sc_process_handle thread_handle = context_p->create_thread_process( name_p, true, SC_MAKE_FUNC_PTR(sc_spawn_object,semantics), spawn_p, opt_p ); return thread_handle; } else { sc_process_handle method_handle = context_p->create_method_process( name_p, true, SC_MAKE_FUNC_PTR(sc_spawn_object,semantics), spawn_p, opt_p ); return method_handle; } } //============================================================================= // CLASS sc_spawn_object_v for all compilers except HP aCC // or // CLASS sc_spawn_object_v for HP aCC which tries to match this // one template argument class when the sc_spawn() declared above is // invoked with 3 arguments or 2 arguments, and generates compiler errors. // // This templated helper class allows an object to provide the execution // semantics for a process via its () operator. An instance of the supplied // object will be kept to provide the semantics when the process is scheduled // for execution. The () operator returns a value, which will be stored at the // location specified by the supplied pointer. An example of an object that // might be used for this helper function would be valued sc_bind bound // function or method. // // sc_spawn_object_v( typename F::result_type* r_p, T f, const char* name_p, // const sc_spawn_options* opt_p ) // r_p -> where to place the result of the function invocation. // f = information to be executed. // name_p = optional name for object instance, or zero. // opt_p -> optional spawn options for process, or zero for the default // This is the object instance constructor for this class. It makes a // copy of the supplied object. The tp_call constructor is called // with an indication that this object instance should be reclaimed when // execution completes. // result_p -> where to place the value of the () operator. // object = object whose () operator will be called to provide // the process semantics. // // virtual void semantics() // This virtual method provides the execution semantics for its process. // It performs a () operation on m_object, placing the result at m_result_p. //============================================================================= //------------------------------------------------------------------------------ //"sc_spawn_object_v - semantic object with return value" // // This inline function spawns a process for execution. The execution semantics // for the process being spawned will be provided by the supplied object // instance via its () operator. (E.g., an sc_bind bound function) That // operator returns a value, which will be placed in the supplied return // location. // After creating the process it is registered with the simulator. // object = object instance providing the execution semantics via its () // operator. // r_p -> where to place the value of the () operator. // name_p = optional name for object instance, or zero. // opt_p -> optional spawn options for process, or zero for the default. //------------------------------------------------------------------------------ #if !defined (__HP_aCC) template class sc_spawn_object_v : public sc_process_host { public: sc_spawn_object_v( typename T::result_type* r_p, T object ) : m_object(object), m_result_p(r_p) { } virtual void semantics() { *m_result_p = m_object(); } protected: T m_object; typename T::result_type* m_result_p; }; template inline sc_process_handle sc_spawn( typename T::result_type* r_p, T object, const char* name_p = 0, const sc_spawn_options* opt_p = 0) { sc_simcontext* context_p; sc_spawn_object_v* spawn_p; context_p = sc_get_curr_simcontext(); spawn_p = new sc_spawn_object_v(r_p, object); if ( !opt_p || !opt_p->is_method() ) { sc_process_handle thread_handle = context_p->create_thread_process( name_p, true, SC_MAKE_FUNC_PTR(sc_spawn_object_v,semantics), spawn_p, opt_p ); return thread_handle; } else { sc_process_handle method_handle = context_p->create_method_process( name_p, true, SC_MAKE_FUNC_PTR(sc_spawn_object_v,semantics), spawn_p, opt_p ); return method_handle; } } #else // for HP aCC template class sc_spawn_object_v : public sc_process_host { public: sc_spawn_object_v( R* r_p, T object) : m_object(object), m_result_p(r_p) { } virtual void semantics() { *m_result_p = m_object(); } protected: T m_object; R* m_result_p; }; template inline sc_process_handle sc_spawn( R* r_p, T object, const char* name_p = 0, const sc_spawn_options* opt_p = 0) { sc_simcontext* context_p; sc_spawn_object_v* spawn_p; context_p = sc_get_curr_simcontext(); spawn_p = new sc_spawn_object_v(r_p, object); if ( !opt_p || !opt_p->is_method() ) { sc_process_handle thread_handle = context_p->create_thread_process( name_p, true, static_cast( &sc_spawn_object_v::semantics), spawn_p, opt_p ); return thread_handle; } else { sc_process_handle method_handle = context_p->create_method_process( name_p, true, static_cast( &sc_spawn_object_v::semantics), spawn_p, opt_p ); return method_handle; } } #endif // HP } // namespace sc_core // $Log: sc_spawn.h,v $ // Revision 1.7 2011/08/26 20:46:11 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.6 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.5 2011/02/13 21:47:38 acg // Andy Goodrich: update copyright notice. // // Revision 1.4 2011/02/01 21:14:02 acg // Andy Goodrich: formatting. // // Revision 1.3 2009/07/28 01:10:53 acg // Andy Goodrich: updates for 2.3 release candidate. // // Revision 1.2 2008/05/22 17:06:26 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.6 2006/05/26 20:33:16 acg // Andy Goodrich: changes required by additional platform compilers (i.e., // Microsoft VC++, Sun Forte, HP aCC). // // Revision 1.5 2006/05/08 18:01:44 acg // Andy Goodrich: changed the HP-specific implementations of sc_spawn() to // use a static_cast to create their entry functions rather than the // SC_MAKE_FUNC_PTR macro. The HP preprocessor does not parse template // arguments that contain a comma properly. // // Revision 1.4 2006/04/11 23:13:21 acg // Andy Goodrich: Changes for reduced reset support that only includes // sc_cthread, but has preliminary hooks for expanding to method and thread // processes also. // // Revision 1.3 2006/01/13 18:44:30 acg // Added $Log to record CVS changes into the source. #endif // !defined(sc_spawn_h_INCLUDED) systemc-2.3.3/src/sysc/kernel/sc_object_int.h0000644000175000017500000000537613360325173021112 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_object_int.h -- For inline definitions of some utility functions. DO NOT EXPORT THIS INCLUDE FILE. Original Author: Philipp A. Hartmann, OFFIS, 2013-02-10 *****************************************************************************/ #ifndef SC_OBJECT_INT_H_INCLUDED_ #define SC_OBJECT_INT_H_INCLUDED_ #include "sysc/kernel/sc_object.h" #include "sysc/kernel/sc_module.h" #include "sysc/kernel/sc_simcontext_int.h" #include "sysc/kernel/sc_phase_callback_registry.h" namespace sc_core { class sc_object::hierarchy_scope { public: explicit hierarchy_scope(sc_object* obj); explicit hierarchy_scope(sc_module* mod); ~hierarchy_scope(); private: sc_module * scope_; private: hierarchy_scope( hierarchy_scope const & other ) /* = delete */; hierarchy_scope& operator=(hierarchy_scope const&) /* = delete */; }; inline sc_object::hierarchy_scope::hierarchy_scope( sc_object* obj ) : scope_(0) { if( !obj ) return; scope_ = dynamic_cast(obj); if( !scope_ ) scope_ = dynamic_cast(obj->get_parent_object()); if( scope_ ) scope_->simcontext()->hierarchy_push(scope_); } inline sc_object::hierarchy_scope::hierarchy_scope( sc_module* mod ) : scope_(mod) { if( scope_ ) scope_->simcontext()->hierarchy_push(scope_); } inline sc_object::hierarchy_scope::~hierarchy_scope() { if( scope_ ) scope_->simcontext()->hierarchy_pop(); } // ----------------------------------------------------------------------- inline void sc_object::do_simulation_phase_callback() { simulation_phase_callback(); } // ----------------------------------------------------------------------- } // namespace sc_core #endif // SC_OBJECT_INT_H_INCLUDED_ // Taf! systemc-2.3.3/src/sysc/kernel/sc_simcontext.h0000644000175000017500000007130513360325173021162 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_simcontext.h -- Definition of the simulation context class. Original Author: Stan Y. Liao, Synopsys, Inc. Martin Janssen, Synopsys, Inc. CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #ifndef SC_SIMCONTEXT_H #define SC_SIMCONTEXT_H #include "sysc/kernel/sc_cmnhdr.h" #include "sysc/kernel/sc_process.h" #include "sysc/kernel/sc_status.h" #include "sysc/kernel/sc_time.h" #include "sysc/utils/sc_hash.h" #include "sysc/utils/sc_pq.h" #if defined(_MSC_VER) && !defined(SC_WIN_DLL_WARN) #pragma warning(push) #pragma warning(disable: 4251) // DLL import for std::vector #endif namespace sc_core { // forward declarations class sc_cor; class sc_cor_pkg; class sc_event; class sc_event_timed; class sc_export_registry; class sc_module; class sc_module_name; class sc_module_registry; class sc_name_gen; class sc_object; class sc_object_manager; class sc_phase_callback_registry; class sc_process_handle; class sc_port_registry; class sc_prim_channel_registry; class sc_process_table; class sc_signal_bool_deval; class sc_trace_file; class sc_runnable; class sc_process_host; class sc_method_process; class sc_cthread_process; class sc_thread_process; class sc_reset_finder; template< typename > class sc_plist; typedef sc_plist< sc_process_b* > sc_process_list; struct SC_API sc_curr_proc_info { sc_process_b* process_handle; sc_curr_proc_kind kind; sc_curr_proc_info() : process_handle( 0 ), kind( SC_NO_PROC_ ) {} }; typedef const sc_curr_proc_info* sc_curr_proc_handle; enum sc_stop_mode { // sc_stop modes: SC_STOP_FINISH_DELTA, SC_STOP_IMMEDIATE }; extern SC_API void sc_set_stop_mode( sc_stop_mode mode ); extern SC_API sc_stop_mode sc_get_stop_mode(); enum sc_starvation_policy { SC_EXIT_ON_STARVATION, SC_RUN_TO_TIME }; extern SC_API void sc_start(); extern SC_API void sc_start( const sc_time& duration, sc_starvation_policy p=SC_RUN_TO_TIME ); inline void sc_start( int duration, sc_time_unit unit, sc_starvation_policy p=SC_RUN_TO_TIME ) { sc_start( sc_time((double)duration,unit), p ); } inline void sc_start( double duration, sc_time_unit unit, sc_starvation_policy p=SC_RUN_TO_TIME ) { sc_start( sc_time(duration,unit), p ); } extern SC_API void sc_stop(); // friend function declarations SC_API sc_dt::uint64 sc_delta_count(); SC_API sc_dt::uint64 sc_delta_count_at_current_time(); SC_API const std::vector& sc_get_top_level_events( const sc_simcontext* simc_p); SC_API const std::vector& sc_get_top_level_objects( const sc_simcontext* simc_p); SC_API bool sc_is_running( const sc_simcontext* simc_p ); SC_API void sc_pause(); SC_API bool sc_end_of_simulation_invoked(); SC_API void sc_start( const sc_time&, sc_starvation_policy ); SC_API bool sc_start_of_simulation_invoked(); SC_API void sc_set_time_resolution( double, sc_time_unit ); SC_API sc_time sc_get_time_resolution(); SC_API void sc_set_default_time_unit( double, sc_time_unit ); SC_API sc_time sc_get_default_time_unit(); SC_API bool sc_pending_activity_at_current_time( const sc_simcontext* ); SC_API bool sc_pending_activity_at_future_time( const sc_simcontext* ); SC_API sc_time sc_time_to_pending_activity( const sc_simcontext* ); struct sc_invoke_method; // ---------------------------------------------------------------------------- // CLASS : sc_simcontext // // The simulation context. // ---------------------------------------------------------------------------- class SC_API sc_simcontext { friend struct sc_invoke_method; friend class sc_event; friend class sc_module; friend class sc_object; friend class sc_time; friend class sc_time_tuple; friend class sc_clock; friend class sc_method_process; friend class sc_phase_callback_registry; friend class sc_process_b; friend class sc_process_handle; friend class sc_prim_channel; friend class sc_cthread_process; friend class sc_thread_process; friend SC_API sc_dt::uint64 sc_delta_count(); friend SC_API const std::vector& sc_get_top_level_events( const sc_simcontext* simc_p); friend SC_API const std::vector& sc_get_top_level_objects( const sc_simcontext* simc_p); friend SC_API bool sc_is_running( const sc_simcontext* simc_p ); friend SC_API void sc_pause(); friend SC_API bool sc_end_of_simulation_invoked(); friend SC_API void sc_start( const sc_time&, sc_starvation_policy ); friend SC_API bool sc_start_of_simulation_invoked(); friend void sc_thread_cor_fn(void*); friend SC_API sc_time sc_time_to_pending_activity( const sc_simcontext* ); friend SC_API bool sc_pending_activity_at_current_time( const sc_simcontext* ); friend SC_API bool sc_pending_activity_at_future_time( const sc_simcontext* ); enum sc_signal_write_check { SC_SIGNAL_WRITE_CHECK_DISABLE_ = 0x0, // no multiple writer checks SC_SIGNAL_WRITE_CHECK_DEFAULT_ = 0x1, // default IEEE-1666 writer checks SC_SIGNAL_WRITE_CHECK_CONFLICT_ = 0x2 // only check for conflicting writes }; void init(); void clean(); public: sc_simcontext(); ~sc_simcontext(); void initialize( bool = false ); void cycle( const sc_time& ); void simulate( const sc_time& duration ); void stop(); void end(); void reset(); int sim_status() const; bool elaboration_done() const; std::vector& get_active_invokers(); sc_object_manager* get_object_manager(); inline sc_status get_status() const; sc_object* active_object(); void hierarchy_push( sc_module* ); sc_module* hierarchy_pop(); sc_module* hierarchy_curr() const; sc_object* first_object(); sc_object* next_object(); sc_object* find_object( const char* name ); sc_module_registry* get_module_registry(); sc_port_registry* get_port_registry(); sc_export_registry* get_export_registry(); sc_prim_channel_registry* get_prim_channel_registry(); std::string construct_hierarchical_name(const sc_object* parent, const std::string& name); bool register_hierarchical_name(const sc_object* parent, const std::string& name); bool unregister_hierarchical_name(const sc_object* parent, const std::string& name); bool hierarchical_name_exists(const sc_object* parent, const std::string& name); const char* get_hierarchical_name(const sc_object* parent, const std::string& name); // to generate unique names for objects in an MT-Safe way const char* gen_unique_name( const char* basename_, bool preserve_first = false ); // process creation sc_process_handle create_cthread_process( const char* name_p, bool free_host, SC_ENTRY_FUNC method_p, sc_process_host* host_p, const sc_spawn_options* opt_p ); sc_process_handle create_method_process( const char* name_p, bool free_host, SC_ENTRY_FUNC method_p, sc_process_host* host_p, const sc_spawn_options* opt_p ); sc_process_handle create_thread_process( const char* name_p, bool free_host, SC_ENTRY_FUNC method_p, sc_process_host* host_p, const sc_spawn_options* opt_p ); sc_curr_proc_handle get_curr_proc_info(); sc_process_b* get_current_writer() const; bool write_check() const; bool write_check_conflicts_only() const; void set_curr_proc( sc_process_b* ); void reset_curr_proc(); int next_proc_id(); void add_trace_file( sc_trace_file* ); void remove_trace_file( sc_trace_file* ); friend SC_API void sc_set_time_resolution( double, sc_time_unit ); friend SC_API sc_time sc_get_time_resolution(); friend SC_API void sc_set_default_time_unit( double, sc_time_unit ); friend SC_API sc_time sc_get_default_time_unit(); const sc_time& max_time() const; const sc_time& time_stamp() const; sc_dt::uint64 change_stamp() const; sc_dt::uint64 delta_count() const; sc_dt::uint64 delta_count_at_current_time() const; bool event_occurred( sc_dt::uint64 last_change_count ) const; bool evaluation_phase() const; bool is_running() const; bool update_phase() const; bool notify_phase() const; bool get_error(); void set_error( sc_report* ); sc_cor_pkg* cor_pkg() { return m_cor_pkg; } sc_cor* next_cor(); void add_reset_finder( sc_reset_finder* ); const ::std::vector& get_child_objects() const; void elaborate(); void prepare_to_simulate(); inline void initial_crunch( bool no_crunch ); bool next_time( sc_time& t ) const; bool pending_activity_at_current_time() const; private: void add_child_event( sc_event* ); void add_child_object( sc_object* ); void remove_child_event( sc_event* ); void remove_child_object( sc_object* ); void crunch( bool once=false ); int add_delta_event( sc_event* ); void remove_delta_event( sc_event* ); void add_timed_event( sc_event_timed* ); void trace_cycle( bool delta_cycle ); void execute_method_next( sc_method_handle ); void execute_thread_next( sc_thread_handle ); sc_method_handle pop_runnable_method(); sc_thread_handle pop_runnable_thread(); void preempt_with( sc_method_handle ); inline void preempt_with( sc_thread_handle ); void push_runnable_method( sc_method_handle ); void push_runnable_thread( sc_thread_handle ); void push_runnable_method_front( sc_method_handle ); void push_runnable_thread_front( sc_thread_handle ); void remove_runnable_method( sc_method_handle ); void remove_runnable_thread( sc_thread_handle ); void requeue_current_process(); void suspend_current_process(); void do_sc_stop_action(); void do_timestep( const sc_time& ); void mark_to_collect_process( sc_process_b* zombie_p ); void do_collect_processes(); sc_method_handle remove_process( sc_method_handle ); sc_thread_handle remove_process( sc_thread_handle ); private: enum execution_phases { phase_initialize = 0, phase_evaluate, phase_update, phase_notify }; sc_object_manager* m_object_manager; sc_module_registry* m_module_registry; sc_port_registry* m_port_registry; sc_export_registry* m_export_registry; sc_prim_channel_registry* m_prim_channel_registry; sc_phase_callback_registry* m_phase_cb_registry; sc_name_gen* m_name_gen; sc_process_table* m_process_table; sc_curr_proc_info m_curr_proc_info; sc_process_b* m_current_writer; sc_signal_write_check m_write_check; int m_next_proc_id; std::vector m_active_invokers; std::vector m_child_events; std::vector m_child_objects; std::vector m_delta_events; sc_ppq* m_timed_events; std::vector m_trace_files; bool m_something_to_trace; sc_runnable* m_runnable; sc_process_list* m_collectable; sc_time_params* m_time_params; sc_time m_curr_time; mutable sc_time m_max_time; sc_invoke_method* m_method_invoker_p; sc_dt::uint64 m_change_stamp; // "time" change occurred. sc_dt::uint64 m_delta_count; sc_dt::uint64 m_initial_delta_count_at_current_time; bool m_forced_stop; bool m_paused; bool m_ready_to_simulate; bool m_elaboration_done; execution_phases m_execution_phase; sc_report* m_error; bool m_in_simulator_control; bool m_end_of_simulation_called; sc_status m_simulation_status; bool m_start_of_simulation_called; sc_cor_pkg* m_cor_pkg; // the simcontext's coroutine package sc_cor* m_cor; // the simcontext's coroutine sc_reset_finder* m_reset_finder_q; // Q of reset finders to reconcile. private: // disabled sc_simcontext( const sc_simcontext& ); sc_simcontext& operator = ( const sc_simcontext& ); }; // IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII // Not MT safe. #if 1 extern SC_API sc_simcontext* sc_curr_simcontext; extern SC_API sc_simcontext* sc_default_global_context; inline sc_simcontext* sc_get_curr_simcontext() { if( sc_curr_simcontext == 0 ) { sc_default_global_context = new sc_simcontext; sc_curr_simcontext = sc_default_global_context; } return sc_curr_simcontext; } #else extern SC_API sc_simcontext* sc_get_curr_simcontext(); #endif // 0 inline sc_status sc_get_status() { return sc_get_curr_simcontext()->get_status(); } // IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII inline bool sc_simcontext::elaboration_done() const { return m_elaboration_done; } inline sc_status sc_simcontext::get_status() const { return m_simulation_status != SC_RUNNING ? m_simulation_status : (m_in_simulator_control ? SC_RUNNING : SC_PAUSED); } inline int sc_simcontext::sim_status() const { if( m_error ) { return SC_SIM_ERROR; } if( m_forced_stop ) { return SC_SIM_USER_STOP; } return SC_SIM_OK; } inline sc_object_manager* sc_simcontext::get_object_manager() { return m_object_manager; } inline sc_module_registry* sc_simcontext::get_module_registry() { return m_module_registry; } inline sc_port_registry* sc_simcontext::get_port_registry() { return m_port_registry; } inline sc_export_registry* sc_simcontext::get_export_registry() { return m_export_registry; } inline sc_prim_channel_registry* sc_simcontext::get_prim_channel_registry() { return m_prim_channel_registry; } inline sc_curr_proc_handle sc_simcontext::get_curr_proc_info() { return &m_curr_proc_info; } inline int sc_simcontext::next_proc_id() { return ( ++ m_next_proc_id ); } inline const sc_time& sc_simcontext::max_time() const { if ( m_max_time == SC_ZERO_TIME ) { m_max_time = sc_time::from_value( ~sc_dt::UINT64_ZERO ); } return m_max_time; } inline sc_dt::uint64 sc_simcontext::change_stamp() const { return m_change_stamp; } inline sc_dt::uint64 sc_simcontext::delta_count_at_current_time() const { return m_delta_count - m_initial_delta_count_at_current_time; } inline const sc_time& sc_simcontext::time_stamp() const { return m_curr_time; } inline bool sc_simcontext::event_occurred(sc_dt::uint64 last_change_stamp) const { return m_change_stamp == last_change_stamp; } inline bool sc_simcontext::evaluation_phase() const { return (m_execution_phase == phase_evaluate) && m_ready_to_simulate; } inline bool sc_simcontext::update_phase() const { return m_execution_phase == phase_update; } inline bool sc_simcontext::notify_phase() const { return m_execution_phase == phase_notify; } inline void sc_simcontext::set_error( sc_report* err ) { delete m_error; m_error = err; } inline bool sc_simcontext::get_error() { return m_error != NULL; } inline int sc_simcontext::add_delta_event( sc_event* e ) { m_delta_events.push_back( 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 ); } // ---------------------------------------------------------------------------- inline sc_process_b* sc_simcontext::get_current_writer() const { return m_current_writer; } inline bool sc_simcontext::write_check() const { return m_write_check != SC_SIGNAL_WRITE_CHECK_DISABLE_; } // ---------------------------------------------------------------------------- class sc_process_handle; SC_API sc_process_handle sc_get_current_process_handle(); // Get the current object hierarchy context // // Returns a pointer the the sc_object (module or process) that // would become the parent object of a newly created element // of the SystemC object hierarchy, or NULL. // inline sc_object* sc_get_current_object() { return sc_get_curr_simcontext()->active_object(); } inline sc_process_b* sc_get_current_process_b() { return sc_get_curr_simcontext()->get_curr_proc_info()->process_handle; } // THE FOLLOWING FUNCTION IS DEPRECATED IN 2.1 extern SC_API sc_process_b* sc_get_curr_process_handle(); inline sc_curr_proc_kind sc_get_curr_process_kind() { return sc_get_curr_simcontext()->get_curr_proc_info()->kind; } inline int sc_get_simulator_status() { return sc_get_curr_simcontext()->sim_status(); } // Generates unique names within each module. extern SC_API const char* sc_gen_unique_name( const char* basename_, bool preserve_first = false ); // Set the random seed for controlled randomization -- not yet implemented extern SC_API void sc_set_random_seed( unsigned int seed_ ); extern SC_API void sc_initialize(); extern SC_API const sc_time& sc_max_time(); // Get maximum time value. extern SC_API const sc_time& sc_time_stamp(); // Current simulation time. extern SC_API double sc_simulation_time(); // Current time in default time units. inline const std::vector& sc_get_top_level_events( const sc_simcontext* simc_p = sc_get_curr_simcontext() ) { return simc_p->m_child_events; } inline const std::vector& sc_get_top_level_objects( const sc_simcontext* simc_p = sc_get_curr_simcontext() ) { return simc_p->m_child_objects; } extern SC_API sc_event* sc_find_event( const char* name ); extern SC_API sc_object* sc_find_object( const char* name ); inline sc_dt::uint64 sc_delta_count() { return sc_get_curr_simcontext()->m_delta_count; } inline sc_dt::uint64 sc_delta_count_at_current_time() { return sc_get_curr_simcontext()->delta_count_at_current_time(); } inline bool sc_is_running( const sc_simcontext* simc_p = sc_get_curr_simcontext() ) { return simc_p->m_ready_to_simulate; } SC_API bool sc_is_unwinding(); inline void sc_pause() { sc_get_curr_simcontext()->m_paused = true; } // Return indication if there are more processes to execute in this delta phase inline bool sc_pending_activity_at_current_time ( const sc_simcontext* simc_p = sc_get_curr_simcontext() ) { return simc_p->pending_activity_at_current_time(); } // Return indication if there are timed notifications in the future inline bool sc_pending_activity_at_future_time ( const sc_simcontext* simc_p = sc_get_curr_simcontext() ) { sc_time ignored; return simc_p->next_time( ignored ); } // Return indication if there are processes to run, // or notifications in the future inline bool sc_pending_activity ( const sc_simcontext* simc_p = sc_get_curr_simcontext() ) { return sc_pending_activity_at_current_time( simc_p ) || sc_pending_activity_at_future_time( simc_p ); } SC_API sc_time sc_time_to_pending_activity ( const sc_simcontext* simc_p = sc_get_curr_simcontext() ); inline bool sc_end_of_simulation_invoked() { return sc_get_curr_simcontext()->m_end_of_simulation_called; } inline bool sc_hierarchical_name_exists( const char* name ) { return sc_get_curr_simcontext()->hierarchical_name_exists(NULL, name); } inline bool sc_hierarchical_name_exists( const sc_object* parent, const char* name ) { return sc_get_curr_simcontext()->hierarchical_name_exists(parent, name); } inline const char* sc_get_hierarchical_name(const char* name) { return sc_get_curr_simcontext()->get_hierarchical_name(NULL, name); } inline const char* sc_get_hierarchical_name(const sc_object* parent, const char* name) { return sc_get_curr_simcontext()->get_hierarchical_name(parent, name); } inline bool sc_register_hierarchical_name(const char* name) { return sc_get_curr_simcontext()->register_hierarchical_name(NULL, name); } inline bool sc_register_hierarchical_name(const sc_object* parent, const char* name) { return sc_get_curr_simcontext()->register_hierarchical_name(parent, name); } inline bool sc_unregister_hierarchical_name(const char* name) { return sc_get_curr_simcontext()->unregister_hierarchical_name(NULL, name); } inline bool sc_unregister_hierarchical_name(const sc_object* parent, const char* name) { return sc_get_curr_simcontext()->unregister_hierarchical_name(parent, name); } inline bool sc_start_of_simulation_invoked() { return sc_get_curr_simcontext()->m_start_of_simulation_called; } // The following variable controls whether process control corners should // be considered errors or not. See sc_simcontext.cpp for details on what // happens if this value is set to true. extern SC_API bool sc_allow_process_control_corners; } // namespace sc_core #if defined(_MSC_VER) && !defined(SC_WIN_DLL_WARN) #pragma warning(pop) #endif /***************************************************************************** MODIFICATION LOG - modifiers, enter your name, affiliation, date and changes you are making here. Name, Affiliation, Date: Andy Goodrich, Forte Design Systems 20 May 2003 Description of Modification: - phase callbacks - sc_stop mode Name, Affiliation, Date: Bishnupriya Bhattacharya, Cadence Design Systems, 25 August, 2003 Description of Modification: - support for dynamic process - support for sc export registry - new member methods elaborate(), prepare_to_simulate(), and initial_crunch() that are invoked by initialize() in that order - add sc_get_last_created_process_handle() for use before simulation starts Name, Affiliation, Date: Bishnupriya Bhattacharya, Cadence Design Systems, 3 March, 2004 Description of Modification: add sc_get_curr_process_kind() Name, Affiliation, Date: Description of Modification: *****************************************************************************/ // $Log: sc_simcontext.h,v $ // Revision 1.26 2011/09/05 21:20:22 acg // Andy Goodrich: result of automake invocation. // // Revision 1.25 2011/09/01 15:28:10 acg // Andy Goodrich: the aftermath of automake. // // Revision 1.24 2011/08/29 18:04:32 acg // Philipp A. Hartmann: miscellaneous clean ups. // // Revision 1.23 2011/08/26 20:46:10 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.22 2011/08/24 22:05:51 acg // Torsten Maehne: initialization changes to remove warnings. // // Revision 1.21 2011/05/09 04:07:49 acg // Philipp A. Hartmann: // (1) Restore hierarchy in all phase callbacks. // (2) Ensure calls to before_end_of_elaboration. // // Revision 1.20 2011/04/08 18:26:07 acg // Andy Goodrich: added execute_method_next() to handle method dispatch // for asynchronous notifications that occur outside the evaluation phase. // // Revision 1.19 2011/04/05 20:50:57 acg // Andy Goodrich: // (1) changes to make sure that event(), posedge() and negedge() only // return true if the clock has not moved. // (2) fixes for method self-resumes. // (3) added SC_PRERELEASE_VERSION // (4) removed kernel events from the object hierarchy, added // sc_hierarchical_name_exists(). // // Revision 1.18 2011/03/20 13:43:23 acg // Andy Goodrich: added async_signal_is() plus suspend() as a corner case. // // Revision 1.17 2011/03/07 18:25:19 acg // Andy Goodrich: tightening of check for resume on a disabled process to // only produce an error if it is ready to run. // // Revision 1.16 2011/03/06 15:58:50 acg // Andy Goodrich: added escape to turn off process control corner case // checks. // // Revision 1.15 2011/03/05 04:45:16 acg // Andy Goodrich: moved active process calculation to the sc_simcontext class. // // Revision 1.14 2011/03/05 01:39:21 acg // Andy Goodrich: changes for named events. // // Revision 1.13 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.12 2011/02/13 21:47:38 acg // Andy Goodrich: update copyright notice. // // Revision 1.11 2011/02/13 21:34:35 acg // Andy Goodrich: added SC_UNITIALIZED enum value to process status so // its possible to detect throws before initialization. // // Revision 1.10 2011/02/11 13:25:24 acg // Andy Goodrich: Philipp A. Hartmann's changes: // (1) Removal of SC_CTHREAD method overloads. // (2) New exception processing code. // // Revision 1.9 2011/02/01 21:18:56 acg // Andy Goodrich: addition of new preempt_with() method used to immediately // throw exceptions from threads. // // Revision 1.8 2011/01/25 20:50:37 acg // Andy Goodrich: changes for IEEE 1666 2011. // // Revision 1.7 2011/01/19 23:21:50 acg // Andy Goodrich: changes for IEEE 1666 2011 // // Revision 1.6 2011/01/18 20:10:45 acg // Andy Goodrich: changes for IEEE1666_2011 semantics. // // Revision 1.5 2010/07/22 20:02:33 acg // Andy Goodrich: bug fixes. // // Revision 1.4 2009/05/22 16:06:29 acg // Andy Goodrich: process control updates. // // Revision 1.3 2008/05/22 17:06:26 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.2 2007/09/20 20:32:35 acg // Andy Goodrich: changes to the semantics of throw_it() to match the // specification. A call to throw_it() will immediately suspend the calling // thread until all the throwees have executed. At that point the calling // thread will be restarted before the execution of any other threads. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.13 2006/05/08 18:00:06 acg // Andy Goodrich: added David Long's forward declarations for friend // functions, methods, and operators to keep the Microsoft compiler happy. // // Revision 1.11 2006/04/11 23:13:21 acg // Andy Goodrich: Changes for reduced reset support that only includes // sc_cthread, but has preliminary hooks for expanding to method and thread // processes also. // // Revision 1.10 2006/03/21 00:00:34 acg // Andy Goodrich: changed name of sc_get_current_process_base() to be // sc_get_current_process_b() since its returning an sc_process_b instance. // // Revision 1.9 2006/01/26 21:04:54 acg // Andy Goodrich: deprecation message changes and additional messages. // // Revision 1.8 2006/01/24 20:49:05 acg // Andy Goodrich: changes to remove the use of deprecated features within the // simulator, and to issue warning messages when deprecated features are used. // // Revision 1.7 2006/01/19 00:29:52 acg // Andy Goodrich: Yet another implementation for signal write checking. This // one uses an environment variable SC_SIGNAL_WRITE_CHECK, that when set to // DISABLE will disable write checking on signals. // // Revision 1.6 2006/01/18 21:42:37 acg // Andy Goodrich: Changes for check writer support. // // Revision 1.5 2006/01/13 18:44:30 acg // Added $Log to record CVS changes into the source. // // Revision 1.4 2006/01/03 23:18:44 acg // Changed copyright to include 2006. // // Revision 1.3 2005/12/20 22:11:10 acg // Fixed $Log lines. // // Revision 1.2 2005/12/20 22:02:30 acg // Changed where delta cycles are incremented to match IEEE 1666. Added the // event_occurred() method to hide how delta cycle comparisions are done within // sc_simcontext. Changed the boolean update_phase to an enum that shows all // the phases. #endif systemc-2.3.3/src/sysc/kernel/sc_object.cpp0000644000175000017500000003636013360325173020570 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_object.cpp -- Abstract base class of all SystemC objects. Original Author: Stan Y. Liao, Synopsys, Inc. CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #include #include #include #include #include #include #include "sysc/kernel/sc_externs.h" #include "sysc/kernel/sc_kernel_ids.h" #include "sysc/kernel/sc_module.h" #include "sysc/kernel/sc_object.h" #include "sysc/kernel/sc_object_manager.h" #include "sysc/kernel/sc_phase_callback_registry.h" #include "sysc/kernel/sc_process_handle.h" #include "sysc/kernel/sc_simcontext.h" #include "sysc/kernel/sc_event.h" #include "sysc/utils/sc_hash.h" #include "sysc/utils/sc_list.h" #include "sysc/utils/sc_utils_ids.h" #include "sysc/utils/sc_mempool.h" namespace sc_core { typedef int (*STRCMP)(const void*, const void*); const char SC_HIERARCHY_CHAR = '.'; /* This will be gotten rid after multiple-processes are implemented. This is to fix some regression problems. */ bool sc_enable_name_checking = true; // ---------------------------------------------------------------------------- // CLASS : sc_object // // Abstract base class of all SystemC `simulation' objects. // ---------------------------------------------------------------------------- void sc_object::add_child_event( sc_event* event_p ) { // no check if event_p is already in the set m_child_events.push_back( event_p ); } void sc_object::add_child_object( sc_object* object_ ) { // no check if object_ is already in the set m_child_objects.push_back( object_ ); } const char* sc_object::basename() const { std::size_t pos; // position of last SC_HIERARCHY_CHAR. pos = m_name.rfind( (char)SC_HIERARCHY_CHAR ); return ( pos == m_name.npos ) ? m_name.c_str() : &(m_name.c_str()[pos+1]); } void sc_object::print(::std::ostream& os) const { os << name(); } void sc_object::dump(::std::ostream& os) const { os << "name = " << name() << "\n"; os << "kind = " << kind() << "\n"; } // +---------------------------------------------------------------------------- // |"sc_object::remove_child_event" // | // | This virtual method removes the supplied event from the list of child // | events if it is present. // | // | Arguments: // | event_p -> event to be removed. // | Returns true if the event was present, false if not. // +---------------------------------------------------------------------------- bool sc_object::remove_child_event( sc_event* event_p ) { int size = m_child_events.size(); for( int i = 0; i < size; ++ i ) { if( event_p == m_child_events[i] ) { m_child_events[i] = m_child_events[size - 1]; m_child_events.pop_back(); return true; } } return false; } // +---------------------------------------------------------------------------- // |"sc_object::remove_child_object" // | // | This virtual method removes the supplied object from the list of child // | objects if it is present. // | // | Arguments: // | object_p -> object to be removed. // | Returns true if the object was present, false if not. // +---------------------------------------------------------------------------- bool sc_object::remove_child_object( sc_object* object_p ) { int size = m_child_objects.size(); for( int i = 0; i < size; ++ i ) { if( object_p == m_child_objects[i] ) { m_child_objects[i] = m_child_objects[size - 1]; m_child_objects.pop_back(); object_p->m_parent = NULL; return true; } } return false; } // +---------------------------------------------------------------------------- // |"sc_object::sc_object_init" // | // | This method initializes this object instance and places it in to the // | object hierarchy. // | // | Arguments: // | nm = leaf name for the object. // +---------------------------------------------------------------------------- void sc_object::sc_object_init(const char* nm) { // SET UP POINTERS TO OBJECT MANAGER, PARENT, AND SIMULATION CONTEXT: // // Make the current simcontext the simcontext for this object m_simc = sc_get_curr_simcontext(); m_attr_cltn_p = 0; sc_object_manager* object_manager = m_simc->get_object_manager(); m_parent = m_simc->active_object(); // CONSTRUCT PATHNAME TO OBJECT BEING CREATED: sc_assert( nm ); m_name = object_manager->create_name(nm); // PLACE THE OBJECT INTO THE HIERARCHY object_manager->insert_object(m_name, this); if ( m_parent ) m_parent->add_child_object( this ); else m_simc->add_child_object( this ); } sc_object::sc_object() : m_attr_cltn_p(0), m_child_events(), m_child_objects(), m_name(), m_parent(0), m_simc(0) { sc_object_init( sc_gen_unique_name("object") ); } sc_object::sc_object( const sc_object& that ) : m_attr_cltn_p(0), m_child_events(), m_child_objects(), m_name(), m_parent(0), m_simc(0) { sc_object_init( sc_gen_unique_name( that.basename() ) ); } static bool object_name_illegal_char(char ch) { return (ch == SC_HIERARCHY_CHAR) || std::isspace(ch); } sc_object::sc_object(const char* nm) : m_attr_cltn_p(0), m_child_events(), m_child_objects(), m_name(), m_parent(0), m_simc(0) { int namebuf_alloc = 0; char* namebuf = 0; const char* p; // null name or "" uses machine generated name. if ( !nm || !*nm ) nm = sc_gen_unique_name("object"); p = nm; if (nm && sc_enable_name_checking) { namebuf_alloc = 1 + std::strlen(nm); namebuf = (char*) sc_mempool::allocate(namebuf_alloc); char* q = namebuf; const char* r = nm; bool has_illegal_char = false; while (*r) { if (object_name_illegal_char(*r)) { has_illegal_char = true; *q = '_'; } else { *q = *r; } r++; q++; } *q = '\0'; p = namebuf; if (has_illegal_char) { std::string message = nm; message += " substituted by "; message += namebuf; SC_REPORT_WARNING( SC_ID_ILLEGAL_CHARACTERS_, message.c_str()); } } sc_object_init(p); sc_mempool::release( namebuf, namebuf_alloc ); } sc_object::~sc_object() { #if SC_HAS_PHASE_CALLBACKS_ unregister_simulation_phase_callback( SC_STATUS_ANY ); #endif detach(); delete m_attr_cltn_p; } //------------------------------------------------------------------------------ //"sc_object::detach" // // This method detaches this object instance from the object hierarchy. // It is called in two places: ~sc_object() and sc_process_b::kill_process(). //------------------------------------------------------------------------------ void sc_object::detach() { if (m_simc) { // REMOVE OBJECT FROM THE OBJECT MANAGER: sc_object_manager* object_manager = m_simc->get_object_manager(); object_manager->remove_object(m_name); // REMOVE OBJECT FROM PARENT'S LIST OF OBJECTS: if ( m_parent ) m_parent->remove_child_object( this ); else m_simc->remove_child_object( this ); // ORPHAN THIS OBJECT'S CHILDREN: #if 0 // #### ::std:: children_p = &get_child_objects(); int child_n = children_p->size(); sc_object* parent_p; for ( int child_i = 0; child_i < child_n; child_i++ ) { (*children_p)[child_i]->m_parent = 0; } #endif } } // +---------------------------------------------------------------------------- // |"sc_object::orphan_child_events" // | // | This method moves the children of this object instance to be children // | of the simulator. // +---------------------------------------------------------------------------- void sc_object::orphan_child_events() { std::vector< sc_event* > const & events = get_child_events(); std::vector< sc_event* >::const_iterator it = events.begin(), end = events.end(); for( ; it != end; ++it ) { (*it)->m_parent_p = NULL; simcontext()->add_child_event(*it); } } // +---------------------------------------------------------------------------- // |"sc_object::orphan_child_objects" // | // | This method moves the children of this object instance to be children // | of the simulator. // +---------------------------------------------------------------------------- void sc_object::orphan_child_objects() { std::vector< sc_object* > const & children = get_child_objects(); std::vector< sc_object* >::const_iterator it = children.begin(), end = children.end(); for( ; it != end; ++it ) { (*it)->m_parent = NULL; simcontext()->add_child_object(*it); } } void sc_object::trace( sc_trace_file * /* unused */) const { /* This space is intentionally left blank */ } // add attribute bool sc_object::add_attribute( sc_attr_base& attribute_ ) { if ( !m_attr_cltn_p ) m_attr_cltn_p = new sc_attr_cltn; return ( m_attr_cltn_p->push_back( &attribute_ ) ); } // get attribute by name sc_attr_base* sc_object::get_attribute( const std::string& name_ ) { if ( !m_attr_cltn_p ) m_attr_cltn_p = new sc_attr_cltn; return ( (*m_attr_cltn_p)[name_] ); } const sc_attr_base* sc_object::get_attribute( const std::string& name_ ) const { if ( !m_attr_cltn_p ) m_attr_cltn_p = new sc_attr_cltn; return ( (*m_attr_cltn_p)[name_] ); } // remove attribute by name sc_attr_base* sc_object::remove_attribute( const std::string& name_ ) { if ( m_attr_cltn_p ) return ( m_attr_cltn_p->remove( name_ ) ); else return 0; } // remove all attributes void sc_object::remove_all_attributes() { if ( m_attr_cltn_p ) m_attr_cltn_p->remove_all(); } // get the number of attributes int sc_object::num_attributes() const { if ( m_attr_cltn_p ) return ( m_attr_cltn_p->size() ); else return 0; } // get the attribute collection sc_attr_cltn& sc_object::attr_cltn() { if ( !m_attr_cltn_p ) m_attr_cltn_p = new sc_attr_cltn; return *m_attr_cltn_p; } const sc_attr_cltn& sc_object::attr_cltn() const { if ( !m_attr_cltn_p ) m_attr_cltn_p = new sc_attr_cltn; return *m_attr_cltn_p; } sc_object* sc_object::get_parent() const { static bool warn_sc_get_parent_deprecated=true; if ( warn_sc_get_parent_deprecated ) { warn_sc_get_parent_deprecated=false; SC_REPORT_INFO(sc_core::SC_ID_IEEE_1666_DEPRECATION_, "sc_object::get_parent() is deprecated, " "use get_parent_object() instead"); } return get_parent_object(); } // ---------------------------------------------------------------------------- // simulation phase callbacks sc_object::phase_cb_mask sc_object::register_simulation_phase_callback( phase_cb_mask mask ) { mask = simcontext()->m_phase_cb_registry ->register_callback(*this, mask); return mask; } sc_object::phase_cb_mask sc_object::unregister_simulation_phase_callback( phase_cb_mask mask ) { mask = simcontext()->m_phase_cb_registry ->unregister_callback(*this, mask); return mask; } void sc_object::simulation_phase_callback() { SC_REPORT_WARNING( SC_ID_PHASE_CALLBACK_NOT_IMPLEMENTED_, name() ); } } // namespace sc_core /***************************************************************************** MODIFICATION LOG - modifiers, enter your name, affiliation, date and changes you are making here. Name, Affiliation, Date: Bishnupriya Bhattacharya, Cadence Design Systems, 25 August, 2003 Description of Modification: if module name hierarchy is empty, sc_object ctor assumes the currently executing process as the parent object to support dynamic process creation similar to other sc_objects Name, Affiliation, Date: Andy Goodrich, Forte Design Systems 5 September 2003 Description of Modification: - Made creation of attributes structure conditional on its being used. This eliminates 100 bytes of storage for each normal sc_object. *****************************************************************************/ // $Log: sc_object.cpp,v $ // Revision 1.16 2011/08/29 18:04:32 acg // Philipp A. Hartmann: miscellaneous clean ups. // // Revision 1.15 2011/08/26 20:46:10 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.14 2011/08/24 22:05:51 acg // Torsten Maehne: initialization changes to remove warnings. // // Revision 1.13 2011/04/01 21:24:57 acg // Andy Goodrich: removed unused code. // // Revision 1.12 2011/03/06 15:55:11 acg // Andy Goodrich: Changes for named events. // // Revision 1.11 2011/03/05 19:44:20 acg // Andy Goodrich: changes for object and event naming and structures. // // Revision 1.10 2011/03/05 04:45:16 acg // Andy Goodrich: moved active process calculation to the sc_simcontext class. // // Revision 1.9 2011/03/05 01:39:21 acg // Andy Goodrich: changes for named events. // // Revision 1.8 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.7 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.6 2011/01/25 20:50:37 acg // Andy Goodrich: changes for IEEE 1666 2011. // // Revision 1.5 2011/01/18 20:10:44 acg // Andy Goodrich: changes for IEEE1666_2011 semantics. // // Revision 1.4 2010/08/03 17:02:39 acg // Andy Goodrich: formatting changes. // // Revision 1.3 2009/02/28 00:26:58 acg // Andy Goodrich: changed boost name space to sc_boost to allow use with // full boost library applications. // // Revision 1.2 2008/05/22 17:06:26 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.5 2006/04/20 17:08:17 acg // Andy Goodrich: 3.0 style process changes. // // Revision 1.4 2006/03/21 00:00:34 acg // Andy Goodrich: changed name of sc_get_current_process_base() to be // sc_get_current_process_b() since its returning an sc_process_b instance. // // Revision 1.3 2006/01/13 18:44:30 acg // Added $Log to record CVS changes into the source. // systemc-2.3.3/src/sysc/kernel/sc_module_name.cpp0000644000175000017500000001045513360325173021604 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_module_name.cpp -- An object used to help manage object names and hierarchy Original Author: Stan Y. Liao, Synopsys, Inc. CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #include #include "sysc/kernel/sc_kernel_ids.h" #include "sysc/kernel/sc_module.h" #include "sysc/kernel/sc_module_name.h" #include "sysc/kernel/sc_object_manager.h" #include "sysc/kernel/sc_simcontext.h" namespace sc_core { sc_module_name::sc_module_name( const char* name_ ) : m_name( name_ ), m_module_p( 0 ), m_next( 0 ), m_simc( sc_get_curr_simcontext() ), m_pushed( true ) { m_simc->get_object_manager()->push_module_name( this ); } sc_module_name::sc_module_name( const sc_module_name& name_ ) : m_name( name_.m_name ), m_module_p( 0 ), m_next( 0 ), m_simc( name_.m_simc ), m_pushed( false ) {} sc_module_name::~sc_module_name() { if( m_pushed ) { sc_module_name* smn = m_simc->get_object_manager()->pop_module_name(); if( this != smn ) { SC_REPORT_ERROR( SC_ID_SC_MODULE_NAME_USE_, 0 ); } if ( m_module_p ) m_module_p->end_module(); } } sc_module_name::operator const char*() const { return m_name; } } // namespace sc_core // $Log: sc_module_name.cpp,v $ // Revision 1.5 2011/08/26 20:46:10 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.4 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.3 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.2 2008/05/22 17:06:26 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.4 2006/03/14 23:56:58 acg // Andy Goodrich: This fixes a bug when an exception is thrown in // sc_module::sc_module() for a dynamically allocated sc_module // object. We are calling sc_module::end_module() on a module that has // already been deleted. The scenario runs like this: // // a) the sc_module constructor is entered // b) the exception is thrown // c) the exception processor deletes the storage for the sc_module // d) the stack is unrolled causing the sc_module_name instance to be deleted // e) ~sc_module_name() calls end_module() with its pointer to the sc_module // f) because the sc_module has been deleted its storage is corrupted, // either by linking it to a free space chain, or by reuse of some sort // g) the m_simc field is garbage // h) the m_object_manager field is also garbage // i) an exception occurs // // This does not happen for automatic sc_module instances since the // storage for the module is not reclaimed its just part of the stack. // // I am fixing this by having the destructor for sc_module clear the // module pointer in its sc_module_name instance. That cuts things at // step (e) above, since the pointer will be null if the module has // already been deleted. To make sure the module stack is okay, I call // end-module() in ~sc_module in the case where there is an // sc_module_name pointer lying around. // // Revision 1.3 2006/01/13 18:44:30 acg // Added $Log to record CVS changes into the source. // systemc-2.3.3/src/sysc/kernel/sc_event.cpp0000644000175000017500000005651513360325173020447 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_event.cpp -- Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 CHANGE LOG APPEARS AT THE END OF THE FILE *****************************************************************************/ #include #include #include "sysc/kernel/sc_event.h" #include "sysc/kernel/sc_kernel_ids.h" #include "sysc/kernel/sc_phase_callback_registry.h" #include "sysc/kernel/sc_process.h" #include "sysc/kernel/sc_process_handle.h" #include "sysc/kernel/sc_simcontext_int.h" #include "sysc/kernel/sc_object_manager.h" #include "sysc/utils/sc_utils_ids.h" #include namespace sc_core { using std::malloc; using std::strrchr; using std::strncmp; // ---------------------------------------------------------------------------- // CLASS : sc_event // // The event class. // ---------------------------------------------------------------------------- // kernel-internal event, that is never notified const sc_event sc_event::none( kernel_event, "none" ); const char* sc_event::basename() const { const char* p = strrchr( m_name.c_str(), SC_HIERARCHY_CHAR ); return p ? (p + 1) : m_name.c_str(); } void sc_event::cancel() { // cancel a delta or timed notification switch( m_notify_type ) { case DELTA: { // remove this event from the delta events set m_simc->remove_delta_event( this ); m_notify_type = NONE; break; } case TIMED: { // remove this event from the timed events set sc_assert( m_timed != 0 ); m_timed->m_event = 0; m_timed = 0; m_notify_type = NONE; break; } default: ; } } void sc_event::notify() { // immediate notification if( !m_simc->evaluation_phase() ) // coming from // * elaboration // * sc_prim_channel::update // * phase callbacks { SC_REPORT_ERROR( SC_ID_IMMEDIATE_NOTIFICATION_, "" ); return; } cancel(); trigger(); } void sc_event::notify( const sc_time& t ) { if( m_notify_type == DELTA ) { return; } if( t == SC_ZERO_TIME ) { # if SC_HAS_PHASE_CALLBACKS_ if( SC_UNLIKELY_( m_simc->get_status() & (SC_END_OF_UPDATE|SC_BEFORE_TIMESTEP) ) ) { std::stringstream msg; msg << m_simc->get_status() << ":\n\t delta notification of `" << name() << "' ignored"; SC_REPORT_WARNING( SC_ID_PHASE_CALLBACK_FORBIDDEN_ , msg.str().c_str() ); return; } # endif 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; } // add this event to the delta events set m_delta_event_index = m_simc->add_delta_event( this ); m_notify_type = DELTA; return; } # if SC_HAS_PHASE_CALLBACKS_ if( SC_UNLIKELY_( m_simc->get_status() & (SC_END_OF_UPDATE|SC_BEFORE_TIMESTEP) ) ) { std::stringstream msg; msg << m_simc->get_status() << ":\n\t timed notification of `" << name() << "' ignored"; SC_REPORT_WARNING( SC_ID_PHASE_CALLBACK_FORBIDDEN_ , msg.str().c_str() ); return; } # endif if( m_notify_type == TIMED ) { sc_assert( m_timed != 0 ); if( m_timed->m_notify_time <= m_simc->time_stamp() + t ) { return; } // remove this event from the timed events set m_timed->m_event = 0; m_timed = 0; } // 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; } static void sc_warn_notify_delayed() { static bool warn_notify_delayed=true; if ( warn_notify_delayed ) { warn_notify_delayed = false; SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, "notify_delayed(...) is deprecated, use notify(sc_time) instead" ); } } void sc_event::notify_delayed() { sc_warn_notify_delayed(); if( m_notify_type != NONE ) { SC_REPORT_ERROR( SC_ID_NOTIFY_DELAYED_, 0 ); } // add this event to the delta events set m_delta_event_index = m_simc->add_delta_event( this ); m_notify_type = DELTA; } void sc_event::notify_delayed( const sc_time& t ) { sc_warn_notify_delayed(); if( m_notify_type != NONE ) { SC_REPORT_ERROR( SC_ID_NOTIFY_DELAYED_, 0 ); } if( t == SC_ZERO_TIME ) { // add this event to the delta events set m_delta_event_index = m_simc->add_delta_event( this ); 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; } } #define SC_KERNEL_EVENT_PREFIX "$$$$kernel_event$$$$_" sc_event::kernel_tag sc_event::kernel_event; // +---------------------------------------------------------------------------- // |"sc_event::register_event" // | // | This method sets the name of this object instance and optionally adds // | it to the object manager's hierarchy. The object instance will be // | inserted into the object manager's hierarchy if one of the following is // | true: // | (a) the leaf name is non-null and is_kernel_event == false // | (b) the event is being created before the start of simulation. // | // | Arguments: // | leaf_name = leaf name of the object or NULL. // +---------------------------------------------------------------------------- void sc_event::register_event( const char* leaf_name, bool is_kernel_event /* = false */ ) { sc_object_manager* object_manager = m_simc->get_object_manager(); m_parent_p = m_simc->active_object(); // No name provided, if we are not executing then create a name: if( !leaf_name || !leaf_name[0] ) { if ( sc_is_running( m_simc ) ) return; leaf_name = sc_gen_unique_name ( is_kernel_event ? SC_KERNEL_EVENT_PREFIX : "event" ); } // prepend kernel events with internal prefix else if ( is_kernel_event ) { m_name = SC_KERNEL_EVENT_PREFIX; m_name.append( leaf_name ); leaf_name = m_name.c_str(); } // Create a hierarchichal name and place it into the object manager if // its not a kernel event: object_manager->create_name( leaf_name ).swap( m_name ); if ( !is_kernel_event ) { object_manager->insert_event(m_name, this); if ( m_parent_p ) m_parent_p->add_child_event( this ); else m_simc->add_child_event( this ); } } void sc_event::reset() { m_notify_type = NONE; m_delta_event_index = -1; m_timed = 0; // clear the dynamic sensitive methods m_methods_dynamic.resize(0); // clear the dynamic sensitive threads m_threads_dynamic.resize(0); } // +---------------------------------------------------------------------------- // |"sc_event::sc_event(name)" // | // | This is the object instance constructor for named sc_event instances. // | If the name is non-null or this is during elaboration add the // | event to the object hierarchy. // | // | Arguments: // | name = name of the event. // +---------------------------------------------------------------------------- sc_event::sc_event( const char* name ) : m_name(), m_parent_p(NULL), m_simc( sc_get_curr_simcontext() ), m_trigger_stamp( ~sc_dt::UINT64_ZERO ), m_notify_type( NONE ), m_delta_event_index( -1 ), m_timed( 0 ), m_methods_static(), m_methods_dynamic(), m_threads_static(), m_threads_dynamic() { register_event( name ); } // +---------------------------------------------------------------------------- // |"sc_event::sc_event()" // | // | This is the object instance constructor for non-named sc_event instances. // | If this is during elaboration create a name and add it to the object // | hierarchy. // +---------------------------------------------------------------------------- sc_event::sc_event() : m_name(), m_parent_p(NULL), m_simc( sc_get_curr_simcontext() ), m_trigger_stamp( ~sc_dt::UINT64_ZERO ), m_notify_type( NONE ), m_delta_event_index( -1 ), m_timed( 0 ), m_methods_static(), m_methods_dynamic(), m_threads_static(), m_threads_dynamic() { register_event( NULL ); } // +---------------------------------------------------------------------------- // |"sc_event::sc_event(kernel_event, name)" // | // | This is the object instance constructor for kernel sc_event instances. // | If this is during elaboration create an implementation-defined name and // | do NOT add it to the object hierarchy. // +---------------------------------------------------------------------------- sc_event::sc_event( kernel_tag, const char* name ) : m_name(), m_parent_p(NULL), m_simc( sc_get_curr_simcontext() ), m_trigger_stamp( ~sc_dt::UINT64_ZERO ), m_notify_type( NONE ), m_delta_event_index( -1 ), m_timed( 0 ), m_methods_static(), m_methods_dynamic(), m_threads_static(), m_threads_dynamic() { register_event( name, /* is_kernel_event = */ true ); } // +---------------------------------------------------------------------------- // |"sc_event::~sc_event" // | // | This is the object instance destructor for this class. It cancels any // | outstanding waits and removes the event from the object manager's // | instance table if it has a name. // +---------------------------------------------------------------------------- sc_event::~sc_event() { cancel(); if ( m_name.length() != 0 ) { sc_object_manager* object_manager_p = m_simc->get_object_manager(); object_manager_p->remove_event( m_name ); } for(size_t i = 0; i < m_threads_dynamic.size(); ++i ) { if( m_threads_dynamic[i]->m_event_p == this ) m_threads_dynamic[i]->m_event_p = 0; } for(size_t i = 0; i < m_methods_dynamic.size(); ++i ) { if( m_methods_dynamic[i]->m_event_p == this ) m_methods_dynamic[i]->m_event_p = 0; } } // +---------------------------------------------------------------------------- // |"sc_event::trigger" // | // | This method "triggers" this object instance. This consists of scheduling // | for execution all the processes that are schedulable and waiting on this // | event. // +---------------------------------------------------------------------------- void sc_event::trigger() { m_trigger_stamp = m_simc->change_stamp(); m_notify_type = NONE; m_delta_event_index = -1; m_timed = 0; int last_i; // index of last element in vector now accessing. int size; // size of vector now accessing. // trigger the static sensitive methods if( ( size = m_methods_static.size() ) != 0 ) { sc_method_handle* l_methods_static = &m_methods_static[0]; int i = size - 1; do { sc_method_handle method_h = l_methods_static[i]; method_h->trigger_static(); } while( -- i >= 0 ); } // trigger the dynamic sensitive methods if( ( size = m_methods_dynamic.size() ) != 0 ) { last_i = size - 1; sc_method_handle* l_methods_dynamic = &m_methods_dynamic[0]; for ( int i = 0; i <= last_i; i++ ) { sc_method_handle method_h = l_methods_dynamic[i]; if ( method_h->trigger_dynamic( this ) ) { l_methods_dynamic[i] = l_methods_dynamic[last_i]; last_i--; i--; } } m_methods_dynamic.resize(last_i+1); } // trigger the static sensitive threads if( ( size = m_threads_static.size() ) != 0 ) { sc_thread_handle* l_threads_static = &m_threads_static[0]; int i = size - 1; do { sc_thread_handle thread_h = l_threads_static[i]; thread_h->trigger_static(); } while( -- i >= 0 ); } // trigger the dynamic sensitive threads if( ( size = m_threads_dynamic.size() ) != 0 ) { last_i = size - 1; sc_thread_handle* l_threads_dynamic = &m_threads_dynamic[0]; for ( int i = 0; i <= last_i; i++ ) { sc_thread_handle thread_h = l_threads_dynamic[i]; if ( thread_h->trigger_dynamic( this ) ) { l_threads_dynamic[i] = l_threads_dynamic[last_i]; i--; last_i--; } } m_threads_dynamic.resize(last_i+1); } } bool sc_event::triggered() const { return m_trigger_stamp == m_simc->change_stamp(); } bool sc_event::remove_static( sc_method_handle method_h_ ) const { int size; if ( ( size = m_methods_static.size() ) != 0 ) { sc_method_handle* l_methods_static = &m_methods_static[0]; for( int i = size - 1; i >= 0; -- i ) { if( l_methods_static[i] == method_h_ ) { l_methods_static[i] = l_methods_static[size - 1]; m_methods_static.resize(size-1); return true; } } } return false; } bool sc_event::remove_static( sc_thread_handle thread_h_ ) const { int size; if ( ( size = m_threads_static.size() ) != 0 ) { sc_thread_handle* l_threads_static = &m_threads_static[0]; for( int i = size - 1; i >= 0; -- i ) { if( l_threads_static[i] == thread_h_ ) { l_threads_static[i] = l_threads_static[size - 1]; m_threads_static.resize(size-1); return true; } } } return false; } bool sc_event::remove_dynamic( sc_method_handle method_h_ ) const { int size; if ( ( size = m_methods_dynamic.size() ) != 0 ) { sc_method_handle* l_methods_dynamic = &m_methods_dynamic[0]; for( int i = size - 1; i >= 0; -- i ) { if( l_methods_dynamic[i] == method_h_ ) { l_methods_dynamic[i] = l_methods_dynamic[size - 1]; m_methods_dynamic.resize(size-1); return true; } } } return false; } bool sc_event::remove_dynamic( sc_thread_handle thread_h_ ) const { int size; if ( ( size= m_threads_dynamic.size() ) != 0 ) { sc_thread_handle* l_threads_dynamic = &m_threads_dynamic[0]; for( int i = size - 1; i >= 0; -- i ) { if( l_threads_dynamic[i] == thread_h_ ) { l_threads_dynamic[i] = l_threads_dynamic[size - 1]; m_threads_dynamic.resize(size-1); return true; } } } return false; } // ---------------------------------------------------------------------------- // CLASS : sc_event_timed // // Class for storing the time to notify a timed event. // ---------------------------------------------------------------------------- // dedicated memory management; not MT-Safe union sc_event_timed_u { sc_event_timed_u* next; char dummy[sizeof( sc_event_timed )]; }; static sc_event_timed_u* free_list = 0; void* sc_event_timed::allocate() { const int ALLOC_SIZE = 64; if( free_list == 0 ) { free_list = (sc_event_timed_u*) malloc( ALLOC_SIZE * sizeof( sc_event_timed_u ) ); int i = 0; for( ; i < ALLOC_SIZE - 1; ++ i ) { free_list[i].next = &free_list[i + 1]; } free_list[i].next = 0; } sc_event_timed_u* q = free_list; free_list = free_list->next; return q; } void sc_event_timed::deallocate( void* p ) { if( p != 0 ) { sc_event_timed_u* q = reinterpret_cast( p ); q->next = free_list; free_list = q; } } // ---------------------------------------------------------------------------- // CLASS : sc_event_list // // Base class for lists of events. // ---------------------------------------------------------------------------- void sc_event_list::push_back( const sc_event& e ) { // make sure e is not already in the list if ( m_events.size() != 0 ) { const sc_event** l_events = &m_events[0]; for( int i = m_events.size() - 1; i >= 0; -- i ) { if( &e == l_events[i] ) { // event already in the list; ignore return; } } } m_events.push_back( &e ); } void sc_event_list::push_back( const sc_event_list& el ) { m_events.reserve( size() + el.size() ); for ( int i = el.m_events.size() - 1; i >= 0; --i ) { push_back( *el.m_events[i] ); } el.auto_delete(); } void sc_event_list::add_dynamic( sc_method_handle method_h ) const { m_busy++; if ( m_events.size() != 0 ) { const sc_event* const * l_events = &m_events[0]; for( int i = m_events.size() - 1; i >= 0; -- i ) { l_events[i]->add_dynamic( method_h ); } } } void sc_event_list::add_dynamic( sc_thread_handle thread_h ) const { m_busy++; if ( m_events.size() != 0 ) { const sc_event* const* l_events = &m_events[0]; for( int i = m_events.size() - 1; i >= 0; -- i ) { l_events[i]->add_dynamic( thread_h ); } } } void sc_event_list::remove_dynamic( sc_method_handle method_h, const sc_event* e_not ) const { if ( m_events.size() != 0 ) { const sc_event* const* l_events = &m_events[0]; for( int i = m_events.size() - 1; i >= 0; -- i ) { const sc_event* e = l_events[i]; if( e != e_not ) { e->remove_dynamic( method_h ); } } } } void sc_event_list::remove_dynamic( sc_thread_handle thread_h, const sc_event* e_not ) const { if ( m_events.size() != 0 ) { const sc_event* const* l_events = &m_events[0]; for( int i = m_events.size() - 1; i >= 0; -- i ) { const sc_event* e = l_events[i]; if( e != e_not ) { e->remove_dynamic( thread_h ); } } } } void sc_event_list::report_premature_destruction() const { // TDB: reliably detect premature destruction // // If an event list is used as a member of a module, // its lifetime may (correctly) end, although there // are processes currently waiting for it. // // Detecting (and ignoring) this corner-case is quite // difficult for similar reasons to the sc_is_running() // return value during the destruction of the module // hierarchy. // // Ignoring the lifetime checks for now, if no process // is currently running (which is only part of the story): if( sc_get_current_process_handle().valid() ) { // called from a destructor, can't throw SC_REPORT_FATAL( SC_ID_EVENT_LIST_FAILED_ , "list prematurely destroyed" ); sc_abort(); } } void sc_event_list::report_invalid_modification() const { SC_REPORT_ERROR( SC_ID_EVENT_LIST_FAILED_ , "list modified while being waited on" ); // may continue, if suppressed } // ---------------------------------------------------------------------------- // Deprecated functional notation for notifying events. // ---------------------------------------------------------------------------- static void sc_warn_notify() { static bool warn_notify=true; if ( warn_notify ) { SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, "the notify() function is deprecated use sc_event::notify()" ); warn_notify = false; } } void notify( sc_event& e ) { sc_warn_notify(); e.notify(); } void notify( const sc_time& t, sc_event& e ) { sc_warn_notify(); e.notify( t ); } void notify( double v, sc_time_unit tu, sc_event& e ) { sc_warn_notify(); e.notify( v, tu ); } } // namespace sc_core // $Log: sc_event.cpp,v $ // Revision 1.17 2011/08/26 20:46:09 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.16 2011/08/24 22:05:50 acg // Torsten Maehne: initialization changes to remove warnings. // // Revision 1.15 2011/03/12 21:07:51 acg // Andy Goodrich: changes to kernel generated event support. // // Revision 1.14 2011/03/06 15:55:52 acg // Andy Goodrich: changes for named events. // // Revision 1.13 2011/03/05 01:39:21 acg // Andy Goodrich: changes for named events. // // Revision 1.12 2011/02/19 08:33:25 acg // Andy Goodrich: remove }'s that should have been removed before. // // Revision 1.11 2011/02/19 08:30:53 acg // Andy Goodrich: Moved process queueing into trigger_static from // sc_event::notify. // // Revision 1.10 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.9 2011/02/17 19:49:51 acg // Andy Goodrich: // (1) Changed signature of trigger_dynamic() to return a bool again. // (2) Moved process run queue processing into trigger_dynamic(). // // Revision 1.8 2011/02/16 22:37:30 acg // Andy Goodrich: clean up to remove need for ps_disable_pending. // // Revision 1.7 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.6 2011/02/01 21:02:28 acg // Andy Goodrich: new return code for trigger_dynamic() calls. // // Revision 1.5 2011/01/18 20:10:44 acg // Andy Goodrich: changes for IEEE1666_2011 semantics. // // Revision 1.4 2011/01/06 18:04:05 acg // Andy Goodrich: added code to leave disabled processes on the dynamic // method and thread queues. // // Revision 1.3 2008/05/22 17:06:25 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.2 2007/01/17 22:44:30 acg // Andy Goodrich: fix for Microsoft compiler. // // Revision 1.7 2006/04/11 23:13:20 acg // Andy Goodrich: Changes for reduced reset support that only includes // sc_cthread, but has preliminary hooks for expanding to method and thread // processes also. // // Revision 1.6 2006/01/25 00:31:19 acg // Andy Goodrich: Changed over to use a standard message id of // SC_ID_IEEE_1666_DEPRECATION for all deprecation messages. // // Revision 1.5 2006/01/24 20:59:11 acg // Andy Goodrich: fix up of CVS comments, new version roll. // // Revision 1.4 2006/01/24 20:48:14 acg // Andy Goodrich: added deprecation warnings for notify_delayed(). Added two // new implementation-dependent methods, notify_next_delta() & notify_internal() // to replace calls to notify_delayed() from within the simulator. These two // new methods are simpler than notify_delayed() and should speed up simulations // // Revision 1.3 2006/01/13 18:44:29 acg // Added $Log to record CVS changes into the source. // Taf! systemc-2.3.3/src/sysc/kernel/sc_module_registry.cpp0000644000175000017500000001172513360325173022535 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_module_registry.cpp -- Registry for all modules. FOR INTERNAL USE ONLY. Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #include "sysc/kernel/sc_kernel_ids.h" #include "sysc/kernel/sc_module.h" #include "sysc/kernel/sc_module_registry.h" #include "sysc/kernel/sc_simcontext.h" namespace sc_core { // ---------------------------------------------------------------------------- // CLASS : sc_module_registry // // Registry for all modules. // FOR INTERNAL USE ONLY! // ---------------------------------------------------------------------------- void sc_module_registry::insert( sc_module& module_ ) { if( sc_is_running() ) { SC_REPORT_ERROR( SC_ID_INSERT_MODULE_, "simulation running" ); return; } if( m_simc->elaboration_done() ) { SC_REPORT_ERROR( SC_ID_INSERT_MODULE_, "elaboration done" ); return; } #ifdef DEBUG_SYSTEMC // check if module_ is already inserted for( int i = size() - 1; i >= 0; -- i ) { if( &module_ == m_module_vec[i] ) { SC_REPORT_ERROR( SC_ID_INSERT_MODULE_, "already inserted" ); return; } } #endif // insert m_module_vec.push_back( &module_ ); } void sc_module_registry::remove( sc_module& module_ ) { int i; for( i = 0; i < size(); ++ i ) { if( &module_ == m_module_vec[i] ) { break; } } if( i == size() ) { SC_REPORT_ERROR( SC_ID_REMOVE_MODULE_, 0 ); return; } // remove m_module_vec[i] = m_module_vec.back(); m_module_vec.pop_back(); } // constructor sc_module_registry::sc_module_registry( sc_simcontext& simc_ ) : m_construction_done(0), m_module_vec(), m_simc( &simc_ ) {} // destructor sc_module_registry::~sc_module_registry() {} // called when construction is done bool sc_module_registry::construction_done() { if( size() == m_construction_done ) // nothing has been updated return true; for( ; m_construction_done < size(); ++m_construction_done ) { m_module_vec[m_construction_done]->construction_done(); } return false; } // called when elaboration is done void sc_module_registry::elaboration_done() { bool error = false; for( int i = 0; i < size(); ++ i ) { m_module_vec[i]->elaboration_done( error ); } } // called before simulation begins void sc_module_registry::start_simulation() { for( int i = 0; i < size(); ++ i ) { m_module_vec[i]->start_simulation(); } } // called after simulation ends void sc_module_registry::simulation_done() { for( int i = 0; i < size(); ++ i ) { m_module_vec[i]->simulation_done(); } } } // namespace sc_core // $Log: sc_module_registry.cpp,v $ // Revision 1.8 2011/08/26 20:46:10 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.7 2011/08/24 22:05:51 acg // Torsten Maehne: initialization changes to remove warnings. // // Revision 1.6 2011/05/09 04:07:49 acg // Philipp A. Hartmann: // (1) Restore hierarchy in all phase callbacks. // (2) Ensure calls to before_end_of_elaboration. // // Revision 1.5 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.4 2011/02/14 17:51:40 acg // Andy Goodrich: proper pushing an poppping of the module hierarchy for // start_of_simulation() and end_of_simulation. // // Revision 1.3 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.2 2008/05/22 17:06:26 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.4 2006/01/26 21:04:54 acg // Andy Goodrich: deprecation message changes and additional messages. // // Revision 1.3 2006/01/13 18:44:30 acg // Added $Log to record CVS changes into the source. // // Taf! systemc-2.3.3/src/sysc/kernel/sc_object_manager.h0000644000175000017500000001136413360325173021724 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_object_manager.h -- Manager of objects (naming, &c.) Original Author: Stan Y. Liao, Synopsys, Inc. CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #ifndef SC_OBJECT_MANAGER_H #define SC_OBJECT_MANAGER_H #include #include namespace sc_core { class sc_event; class sc_object; class sc_module_name; // ---------------------------------------------------------------------------- // CLASS : sc_object_manager // // Manager of objects. // ---------------------------------------------------------------------------- class sc_object_manager { friend class sc_event; friend class sc_object; friend class sc_simcontext; protected: enum sc_name_origin { SC_NAME_NONE, SC_NAME_OBJECT, SC_NAME_EVENT, SC_NAME_EXTERNAL }; struct table_entry { table_entry() : m_element_p(NULL), m_name_origin(SC_NAME_NONE) {} void* m_element_p; // can be an sc_object or an sc_event sc_name_origin m_name_origin; }; public: typedef std::map instance_table_t; typedef std::vector object_vector_t; sc_object_manager(); ~sc_object_manager(); bool name_exists(const std::string& name); const char* get_name(const std::string& name); sc_event* find_event(const char* name); sc_object* find_object(const char* name); sc_object* first_object(); sc_object* next_object(); void hierarchy_push(sc_object* mdl); sc_object* hierarchy_pop(); sc_object* hierarchy_curr(); int hierarchy_size(); void push_module_name(sc_module_name* mod_name); sc_module_name* pop_module_name(); sc_module_name* top_of_module_name_stack(); private: std::string create_name( const char* leaf_name ); void insert_event(const std::string& name, sc_event* obj); void insert_object(const std::string& name, sc_object* obj); bool insert_external_name(const std::string& name); void remove_event(const std::string& name); void remove_object(const std::string& name); bool remove_external_name(const std::string& name); private: instance_table_t::iterator m_event_it; // event instance iterator. bool m_event_walk_ok; // true if can walk events. instance_table_t m_instance_table; // table of instances. sc_module_name* m_module_name_stack; // sc_module_name stack. instance_table_t::iterator m_object_it; // object instance iterator. object_vector_t m_object_stack; // sc_object stack. bool m_object_walk_ok; // true if can walk objects. }; } // namespace sc_core // $Log: sc_object_manager.h,v $ // Revision 1.9 2011/08/26 20:46:10 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.8 2011/03/06 15:55:11 acg // Andy Goodrich: Changes for named events. // // Revision 1.7 2011/03/05 19:44:20 acg // Andy Goodrich: changes for object and event naming and structures. // // Revision 1.6 2011/03/05 01:39:21 acg // Andy Goodrich: changes for named events. // // Revision 1.5 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.4 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.3 2010/07/22 20:02:33 acg // Andy Goodrich: bug fixes. // // Revision 1.2 2008/05/22 17:06:26 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.3 2006/01/13 18:44:30 acg // Added $Log to record CVS changes into the source. #endif systemc-2.3.3/src/sysc/kernel/sc_thread_process.h0000644000175000017500000005210713360325173021771 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_thread_process.h -- Thread process declarations Original Author: Andy Goodrich, Forte Design Systems, 4 August 2005 CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #if !defined(sc_thread_process_h_INCLUDED) #define sc_thread_process_h_INCLUDED #include "sysc/kernel/sc_spawn_options.h" #include "sysc/kernel/sc_process.h" #include "sysc/kernel/sc_cor.h" #include "sysc/kernel/sc_event.h" #include "sysc/kernel/sc_except.h" #include "sysc/kernel/sc_reset.h" // DEBUGGING MACROS: // // DEBUG_MSG(NAME,P,MSG) // MSG = message to print // NAME = name that must match the process for the message to print, or // null if the message should be printed unconditionally. // P = pointer to process message is for, or NULL in which case the // message will not print. #if 0 # include # define DEBUG_NAME "" # define DEBUG_MSG(NAME,P,MSG) \ { \ if ( P && ( (std::strlen(NAME)==0) || !std::strcmp(NAME,P->name())) ) \ std::cout << "**** " << sc_time_stamp() << " (" \ << sc_get_current_process_name("** NONE **") << "): " << MSG \ << " - " << P->name() << std::endl; \ } #else # define DEBUG_MSG(NAME,P,MSG) #endif namespace sc_core { // forward references: class sc_event_and_list; class sc_event_or_list; class sc_reset; void sc_thread_cor_fn( void* ); SC_API void sc_set_stack_size( sc_thread_handle, std::size_t ); class sc_event; class sc_join; class sc_module; class sc_process_handle; class sc_process_table; class sc_simcontext; class sc_runnable; sc_cor* get_cor_pointer( sc_process_b* process_p ); SC_API void sc_set_stack_size( sc_thread_handle thread_h, std::size_t size ); SC_API void wait( int, sc_simcontext* ); SC_API void wait( sc_simcontext* ); SC_API void wait( const sc_event&, sc_simcontext* ); SC_API void wait( const sc_event_or_list&, sc_simcontext* ); SC_API void wait( const sc_event_and_list&, sc_simcontext* ); SC_API void wait( const sc_time&, sc_simcontext* ); SC_API void wait( const sc_time&, const sc_event&, sc_simcontext* ); SC_API void wait( const sc_time&, const sc_event_or_list&, sc_simcontext* ); SC_API void wait( const sc_time&, const sc_event_and_list&, sc_simcontext* ); //============================================================================== // sc_thread_process - // //============================================================================== class sc_thread_process : public sc_process_b { friend void sc_thread_cor_fn( void* ); friend void sc_set_stack_size( sc_thread_handle, std::size_t ); friend class sc_event; friend class sc_join; friend class sc_module; friend class sc_process_b; friend class sc_process_handle; friend class sc_process_table; friend class sc_simcontext; friend class sc_runnable; friend sc_cor* get_cor_pointer( sc_process_b* process_p ); friend void wait( int, sc_simcontext* ); friend void wait( sc_simcontext* ); friend void wait( const sc_event&, sc_simcontext* ); friend void wait( const sc_event_or_list&, sc_simcontext* ); friend void wait( const sc_event_and_list&, sc_simcontext* ); friend void wait( const sc_time&, sc_simcontext* ); friend void wait( const sc_time&, const sc_event&, sc_simcontext* ); friend void wait( const sc_time&, const sc_event_or_list&, sc_simcontext* ); friend void wait( const sc_time&, const sc_event_and_list&, sc_simcontext*); public: sc_thread_process( const char* name_p, bool free_host, SC_ENTRY_FUNC method_p, sc_process_host* host_p, const sc_spawn_options* opt_p ); virtual const char* kind() const { return "sc_thread_process"; } protected: // may not be deleted manually (called from sc_process_b) virtual ~sc_thread_process(); virtual void disable_process( sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); virtual void enable_process( sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); virtual void kill_process( sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); sc_thread_handle next_exist(); sc_thread_handle next_runnable(); virtual void prepare_for_simulation(); virtual void resume_process( sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); void set_next_exist( sc_thread_handle next_p ); void set_next_runnable( sc_thread_handle next_p ); void set_stack_size( std::size_t size ); inline void suspend_me(); virtual void suspend_process( sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); virtual void throw_reset( bool async ); virtual void throw_user( const sc_throw_it_helper& helper, sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); bool trigger_dynamic( sc_event* ); inline void trigger_static(); void wait( const sc_event& ); void wait( const sc_event_or_list& ); void wait( const sc_event_and_list& ); void wait( const sc_time& ); void wait( const sc_time&, const sc_event& ); void wait( const sc_time&, const sc_event_or_list& ); void wait( const sc_time&, const sc_event_and_list& ); void wait_cycles( int n=1 ); protected: void add_monitor( sc_process_monitor* monitor_p ); void remove_monitor( sc_process_monitor* monitor_p); void signal_monitors( int type = 0 ); protected: sc_cor* m_cor_p; // Thread's coroutine. std::vector m_monitor_q; // Thread monitors. std::size_t m_stack_size; // Thread stack size. int m_wait_cycle_n; // # of waits to be done. private: // disabled sc_thread_process( const sc_thread_process& ); const sc_thread_process& operator = ( const sc_thread_process& ); }; //------------------------------------------------------------------------------ //"sc_thread_process::set_stack_size" // //------------------------------------------------------------------------------ inline void sc_thread_process::set_stack_size( std::size_t size ) { sc_assert( size ); m_stack_size = size; } //------------------------------------------------------------------------------ //"sc_thread_process::suspend_me" // // This method suspends this object instance in favor of the next runnable // process. Upon awakening we check to see if an exception should be thrown. // There are two types of exceptions that can be thrown, synchronous reset // and asynchronous reset. At a future time there may be more asynchronous // exceptions. If an asynchronous reset is seen and there is not static reset // specified, or the static reset is not active then clear the throw // type for the next time this method is called. // // Notes: // (1) For an explanation of how the reset mechanism works see the top of // the file sc_reset.cpp. // (2) The m_sticky_reset field is used to handle synchronous resets that // are enabled via the sc_process_handle::sync_reset_on() method. These // resets are not generated by a signal, but rather are modal by // method call: sync_reset_on() - sync_reset_off(). //------------------------------------------------------------------------------ inline void sc_thread_process::suspend_me() { // remember, if we're currently unwinding bool unwinding_preempted = m_unwinding; sc_simcontext* simc_p = simcontext(); sc_cor* cor_p = simc_p->next_cor(); // do not switch, if we're about to execute next (e.g. suicide) if( m_cor_p != cor_p ) { DEBUG_MSG( DEBUG_NAME , this, "suspending thread"); simc_p->cor_pkg()->yield( cor_p ); DEBUG_MSG( DEBUG_NAME , this, "resuming thread"); } // IF THERE IS A THROW TO BE DONE FOR THIS PROCESS DO IT NOW: // // (1) Optimize THROW_NONE for speed as it is the normal case. // (2) If this thread is already unwinding then suspend_me() was // called from the catch clause to throw an exception on another // process, so just go back to the catch clause. if ( m_throw_status == THROW_NONE ) return; if ( m_unwinding ) return; switch( m_throw_status ) { case THROW_ASYNC_RESET: case THROW_SYNC_RESET: DEBUG_MSG( DEBUG_NAME , this, "throwing reset for"); if ( m_reset_event_p ) m_reset_event_p->notify(); throw sc_unwind_exception( this, true ); case THROW_USER: DEBUG_MSG( DEBUG_NAME, this, "invoking throw_it for"); m_throw_status = m_active_areset_n ? THROW_ASYNC_RESET : (m_active_reset_n ? THROW_SYNC_RESET : THROW_NONE); m_throw_helper_p->throw_it(); break; case THROW_KILL: DEBUG_MSG( DEBUG_NAME, this, "throwing kill for"); throw sc_unwind_exception( this, false ); default: // THROWING_NOW if( !unwinding_preempted ) SC_REPORT_FATAL( SC_ID_INTERNAL_ERROR_ , "unexpected unwinding/throw status" ); // may continue, if suppressed m_throw_status = THROW_NONE; DEBUG_MSG( DEBUG_NAME, this, "restarting thread"); break; } } //------------------------------------------------------------------------------ //"sc_thread_process::wait" // //------------------------------------------------------------------------------ inline void sc_thread_process::wait( const sc_event& e ) { if( m_unwinding ) SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() ); m_event_p = &e; // for cleanup. e.add_dynamic( this ); m_trigger_type = EVENT; suspend_me(); } inline void sc_thread_process::wait( const sc_event_or_list& el ) { if( m_unwinding ) SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() ); el.add_dynamic( this ); m_event_list_p = ⪙ m_trigger_type = OR_LIST; suspend_me(); } inline void sc_thread_process::wait( const sc_event_and_list& el ) { if( m_unwinding ) SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() ); el.add_dynamic( this ); m_event_list_p = ⪙ m_event_count = el.size(); m_trigger_type = AND_LIST; suspend_me(); } inline void sc_thread_process::wait( const sc_time& t ) { if( m_unwinding ) SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() ); m_timeout_event_p->notify_internal( t ); m_timeout_event_p->add_dynamic( this ); m_trigger_type = TIMEOUT; suspend_me(); } inline void sc_thread_process::wait( const sc_time& t, const sc_event& e ) { if( m_unwinding ) SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() ); m_timeout_event_p->notify_internal( t ); m_timeout_event_p->add_dynamic( this ); e.add_dynamic( this ); m_event_p = &e; m_trigger_type = EVENT_TIMEOUT; suspend_me(); } inline void sc_thread_process::wait( const sc_time& t, const sc_event_or_list& el ) { if( m_unwinding ) SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() ); m_timeout_event_p->notify_internal( t ); m_timeout_event_p->add_dynamic( this ); el.add_dynamic( this ); m_event_list_p = ⪙ m_trigger_type = OR_LIST_TIMEOUT; suspend_me(); } inline void sc_thread_process::wait( const sc_time& t, const sc_event_and_list& el ) { if( m_unwinding ) SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() ); m_timeout_event_p->notify_internal( t ); m_timeout_event_p->add_dynamic( this ); el.add_dynamic( this ); m_event_list_p = ⪙ m_event_count = el.size(); m_trigger_type = AND_LIST_TIMEOUT; suspend_me(); } //------------------------------------------------------------------------------ //"sc_thread_process::wait_cycles" // // This method suspends this object instance for the specified number of cycles. // A cycle is defined as the event the thread is set up to staticly wait on. // The field m_wait_cycle_n is set to one less than the number of cycles to // be waited for, since the value is tested before being decremented in // the simulation kernel. //------------------------------------------------------------------------------ inline void sc_thread_process::wait_cycles( int n ) { if( m_unwinding ) SC_REPORT_ERROR( SC_ID_WAIT_DURING_UNWINDING_, name() ); if( n <= 0 ) SC_REPORT_ERROR( SC_ID_WAIT_NEGATIVE_CYCLES_, name() ); m_wait_cycle_n = n-1; suspend_me(); } //------------------------------------------------------------------------------ //"sc_thread_process::miscellaneous support" // //------------------------------------------------------------------------------ inline void sc_thread_process::add_monitor(sc_process_monitor* monitor_p) { m_monitor_q.push_back(monitor_p); } inline void sc_thread_process::remove_monitor(sc_process_monitor* monitor_p) { int mon_n = m_monitor_q.size(); for ( int mon_i = 0; mon_i < mon_n; mon_i++ ) { if ( m_monitor_q[mon_i] == monitor_p ) { m_monitor_q[mon_i] = m_monitor_q[mon_n-1]; m_monitor_q.resize(mon_n-1); } } } inline void sc_thread_process::set_next_exist(sc_thread_handle next_p) { m_exist_p = next_p; } inline sc_thread_handle sc_thread_process::next_exist() { return (sc_thread_handle)m_exist_p; } inline void sc_thread_process::set_next_runnable(sc_thread_handle next_p) { m_runnable_p = next_p; } inline sc_thread_handle sc_thread_process::next_runnable() { return (sc_thread_handle)m_runnable_p; } inline sc_cor* get_cor_pointer( sc_process_b* process_p ) { sc_thread_handle thread_p = dynamic_cast(process_p); return thread_p->m_cor_p; } //------------------------------------------------------------------------------ //"sc_thread_process::trigger_static" // // This inline method adds the current thread to the queue of runnable // processes if required. This is the case if the following criteria // are met: // (1) The process is in a runnable state. // (2) The process is not already on the run queue. // (3) The process is expecting a static trigger, // dynamic event waits take priority. // (4) The process' static wait count is zero. // // If the triggering process is the same process, the trigger is // ignored as well, unless SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS // is defined. //------------------------------------------------------------------------------ inline void sc_thread_process::trigger_static() { // No need to try queueing this thread if one of the following is true: // (a) it is disabled // (b) it is already queued for execution // (c) it is waiting on a dynamic event // (d) its wait count is not satisfied and it is not currently in reset if ( (m_state & ps_bit_disabled) || is_runnable() || m_trigger_type != STATIC ) return; #if ! defined( SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS ) if( SC_UNLIKELY_( sc_get_current_process_b() == this ) ) { report_immediate_self_notification(); return; } #endif // SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS if ( m_wait_cycle_n > 0 && THROW_NONE == m_throw_status ) { --m_wait_cycle_n; return; } // If we get here, then the thread has satisfied its wait criteria. If it is // suspended, then mark its state as ready to run. If it is not suspended, // then push it onto the runnable queue. if ( m_state & ps_bit_suspended ) { m_state = m_state | ps_bit_ready_to_run; return; } simcontext()->push_runnable_thread(this); } #undef DEBUG_MSG #undef DEBUG_NAME } // namespace sc_core // $Log: sc_thread_process.h,v $ // Revision 1.30 2011/08/26 20:46:11 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.29 2011/08/24 23:36:12 acg // Andy Goodrich: removed break statements that can never be reached and // which causes warnings in the Greenhills C++ compiler. // // Revision 1.28 2011/04/14 22:34:27 acg // Andy Goodrich: removed dead code. // // Revision 1.27 2011/04/13 05:02:18 acg // Andy Goodrich: added missing check to the wake up code in suspend_me() // so that we just return if the call to suspend_me() was issued from a // stack unwinding. // // Revision 1.26 2011/04/13 02:44:26 acg // Andy Goodrich: added m_unwinding flag in place of THROW_NOW because the // throw status will be set back to THROW_*_RESET if reset is active and // the check for an unwind being complete was expecting THROW_NONE as the // clearing of THROW_NOW. // // Revision 1.25 2011/04/11 22:05:14 acg // Andy Goodrich: use the DEBUG_NAME macro in DEBUG_MSG invocations. // // Revision 1.24 2011/04/10 22:12:32 acg // Andy Goodrich: adding debugging macros. // // Revision 1.23 2011/04/08 22:41:28 acg // Andy Goodrich: added comment pointing to the description of the reset // mechanism in sc_reset.cpp. // // Revision 1.22 2011/04/08 18:27:33 acg // Andy Goodrich: added check to make sure we don't schedule a running process // because of it issues a notify() it is sensitive to. // // Revision 1.21 2011/04/05 06:22:38 acg // Andy Goodrich: expanded comment for trigger_static() initial vetting. // // Revision 1.20 2011/04/01 21:24:57 acg // Andy Goodrich: removed unused code. // // Revision 1.19 2011/02/19 08:30:53 acg // Andy Goodrich: Moved process queueing into trigger_static from // sc_event::notify. // // Revision 1.18 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.17 2011/02/17 19:55:58 acg // Andy Goodrich: // (1) Changed signature of trigger_dynamic() back to a bool. // (2) Simplified process control usage. // (3) Changed trigger_static() to recognize process controls and to // do the down-count on wait(N), allowing the elimination of // ready_to_run(). // // Revision 1.16 2011/02/16 22:37:31 acg // Andy Goodrich: clean up to remove need for ps_disable_pending. // // Revision 1.15 2011/02/13 21:47:38 acg // Andy Goodrich: update copyright notice. // // Revision 1.14 2011/02/13 21:35:54 acg // Andy Goodrich: added error for performing a wait() during unwinding. // // Revision 1.13 2011/02/11 13:25:24 acg // Andy Goodrich: Philipp A. Hartmann's changes: // (1) Removal of SC_CTHREAD method overloads. // (2) New exception processing code. // // Revision 1.12 2011/02/01 23:01:53 acg // Andy Goodrich: removed dead code. // // Revision 1.11 2011/02/01 21:18:01 acg // Andy Goodrich: // (1) Changes in throw processing for new process control rules. // (2) Support of new process_state enum values. // // Revision 1.10 2011/01/25 20:50:37 acg // Andy Goodrich: changes for IEEE 1666 2011. // // Revision 1.9 2011/01/19 23:21:50 acg // Andy Goodrich: changes for IEEE 1666 2011 // // Revision 1.8 2011/01/18 20:10:45 acg // Andy Goodrich: changes for IEEE1666_2011 semantics. // // Revision 1.7 2011/01/06 17:59:58 acg // Andy Goodrich: removed debugging output. // // Revision 1.6 2010/07/22 20:02:33 acg // Andy Goodrich: bug fixes. // // Revision 1.5 2009/07/28 01:10:53 acg // Andy Goodrich: updates for 2.3 release candidate. // // Revision 1.4 2009/05/22 16:06:29 acg // Andy Goodrich: process control updates. // // Revision 1.3 2009/03/12 22:59:58 acg // Andy Goodrich: updates for 2.4 stuff. // // Revision 1.2 2008/05/22 17:06:06 acg // Andy Goodrich: formatting and comments. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.7 2006/05/08 17:57:13 acg // Andy Goodrich: Added David Long's forward declarations for friend functions // to keep the Microsoft C++ compiler happy. // // Revision 1.6 2006/04/20 17:08:17 acg // Andy Goodrich: 3.0 style process changes. // // Revision 1.5 2006/04/11 23:13:21 acg // Andy Goodrich: Changes for reduced reset support that only includes // sc_cthread, but has preliminary hooks for expanding to method and thread // processes also. // // Revision 1.4 2006/01/24 20:49:05 acg // Andy Goodrich: changes to remove the use of deprecated features within the // simulator, and to issue warning messages when deprecated features are used. // // Revision 1.3 2006/01/13 18:44:30 acg // Added $Log to record CVS changes into the source. #endif // !defined(sc_thread_process_h_INCLUDED) systemc-2.3.3/src/sysc/kernel/sc_process_handle.h0000644000175000017500000005137613360325173021764 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_process_handle.h -- Process access support. Original Author: Andy Goodrich, Forte Design Systems, 17 June 2003 CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ // $Log: sc_process_handle.h,v $ // Revision 1.21 2011/08/26 21:54:04 acg // Torsten Maehne: Simplify use of dynamic_cast<> for initializing m_target. // // Revision 1.20 2011/08/26 20:46:10 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // #if !defined(sc_process_handle_h_INCLUDED) #define sc_process_handle_h_INCLUDED #include "sysc/kernel/sc_module.h" #if defined(_MSC_VER) && !defined(SC_WIN_DLL_WARN) #pragma warning(push) #pragma warning(disable: 4251) // DLL import for std::vector #endif namespace sc_core { // forward operator declarations: class sc_process_handle; bool operator == ( const sc_process_handle& left, const sc_process_handle& right ); bool operator != ( const sc_process_handle& left, const sc_process_handle& right ); bool operator < ( const sc_process_handle& left, const sc_process_handle& right ); //============================================================================= // CLASS sc_process_handle // // This class provides access to an sc_process_b object instance in a // manner which allows some persistence after the deletion of the actual // process. //============================================================================= class sc_simcontext; class SC_API sc_process_handle { typedef sc_process_handle this_type; friend bool operator == ( const this_type& left, const this_type& right ); friend bool operator != ( const this_type& left, const this_type& right ); friend bool operator < ( const this_type& left, const this_type& right ); friend class sc_object; friend class sc_join; friend class sc_module; friend class sc_reset; friend class sc_sensitive; friend class sc_sensitive_pos; friend class sc_sensitive_neg; friend class sc_thread_process; public: inline sc_process_handle(); inline explicit sc_process_handle( sc_object* object_p ); inline explicit sc_process_handle( sc_process_b* process_p ); inline sc_process_handle( const sc_process_handle& orig ); inline ~sc_process_handle(); inline sc_process_handle& operator = ( sc_process_handle src ); inline void swap( sc_process_handle& other ); public: inline void disable( sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS ); inline bool dynamic() const; inline void enable( sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS ); inline const std::vector& get_child_events() const; inline const std::vector& get_child_objects() const; inline sc_object* get_parent_object() const; inline sc_object* get_process_object() const; inline bool is_unwinding() const; inline void kill( sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS ); inline const char* name() const; inline const char* basename() const; inline sc_curr_proc_kind proc_kind() const; inline void reset( sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS ); inline sc_event& reset_event() const; inline void resume( sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS ); inline void suspend( sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS ); inline void sync_reset_off( sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS ); inline void sync_reset_on( sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS ); inline sc_event& terminated_event(); inline bool terminated() const; template inline void throw_it( const EXCEPT& exception, sc_descendant_inclusion_info descendants=SC_NO_DESCENDANTS ); inline bool valid() const; public: // implementation specific methods: inline std::string dump_state() const; protected: inline bool dont_initialize() const { return m_target_p ? m_target_p->dont_initialize() : false; } inline void dont_initialize( bool dont ); public: operator sc_process_b* () { return m_target_p; } operator sc_cthread_handle (); operator sc_method_handle (); operator sc_thread_handle (); protected: sc_process_b* m_target_p; // Target for this object instance. protected: static std::vector empty_event_vector; // If m_target_p == 0. static std::vector empty_object_vector; // If m_target_p == 0. static sc_event non_event; // If m_target_p == 0. }; inline bool operator == ( const sc_process_handle& left, const sc_process_handle& right ) { return (left.m_target_p != 0) && (right.m_target_p != 0) && (left.m_target_p == right.m_target_p); } inline bool operator != ( const sc_process_handle& left, const sc_process_handle& right ) { return (left.m_target_p == 0) || (right.m_target_p == 0) || (left.m_target_p != right.m_target_p); } inline bool operator < ( const sc_process_handle& left, const sc_process_handle& right ) { return left.m_target_p < right.m_target_p; } //------------------------------------------------------------------------------ //"sc_process_handle::sc_process_handle - non-pointer constructor" // // This version of the object instance constructor for this class creates // an object instance whose target needs to be supplied via an assignment. //------------------------------------------------------------------------------ inline sc_process_handle::sc_process_handle() : m_target_p(0) { } //------------------------------------------------------------------------------ //"sc_process_handle::sc_process_handle - pointer constructor" // // This version of the object instance constructor for this class creates // an object instance whose target is the supplied sc_object instance. // The supplied sc_object must in fact be an sc_process_b instance. // object_p -> sc_object instance this is handle for. //------------------------------------------------------------------------------ inline sc_process_handle::sc_process_handle( sc_object* object_p ) : m_target_p(dynamic_cast(object_p)) { if ( m_target_p ) m_target_p->reference_increment(); } //------------------------------------------------------------------------------ //"sc_process_handle::sc_process_handle - pointer constructor" // // This version of the object instance constructor for this class creates // an object instance whose target is the supplied sc_process_b instance. // This saves a dynamic cast compared to the sc_object* case. // process_p -> process instance this is handle for. //------------------------------------------------------------------------------ inline sc_process_handle::sc_process_handle( sc_process_b* process_p ) : m_target_p(process_p) { if ( m_target_p ) m_target_p->reference_increment(); } //------------------------------------------------------------------------------ //"sc_process_handle::sc_process_handle - copy constructor" // // This version of the object instance constructor for this class provides // the copy constructor for the class. It clones the supplied original // handle and increments the references to its target. // orig = sc_process_handle object instance to be copied from. //------------------------------------------------------------------------------ inline sc_process_handle::sc_process_handle( const sc_process_handle& orig ) : m_target_p(orig.m_target_p) { if ( m_target_p ) m_target_p->reference_increment(); } //------------------------------------------------------------------------------ //"sc_process_handle::operator =" // // This assignment operator signature is call by value rather than reference. // This means that an sc_process_handle instance will be created and the // target for that instance will be incremented before the assignment is done. // The assignment is done using the swap() method, which simply swaps the // targets of 'orig' and this object instance. We don't need to increment // the reference count for our new target since that was done when 'orig' // was created. Our old target's reference count will be decremented when // 'orig' is deleted. // orig = sc_process_handle object instance to be copied from. // Result is a reference for this object instance. //------------------------------------------------------------------------------ inline sc_process_handle& sc_process_handle::operator = ( sc_process_handle orig ) { swap( orig ); return *this; } //------------------------------------------------------------------------------ //"sc_process_handle::~sc_process_handle" // // This is the object instance destructor for this class. It decrements // the reference count for its target. //------------------------------------------------------------------------------ inline sc_process_handle::~sc_process_handle() { if ( m_target_p ) m_target_p->reference_decrement(); } //------------------------------------------------------------------------------ //"sc_process_handle::inline methods" // // These are short inline methods. //------------------------------------------------------------------------------ // disable this object instance's target. inline void sc_process_handle::disable(sc_descendant_inclusion_info descendants) { if ( m_target_p ) m_target_p->disable_process(descendants); else SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "disable()"); } // call dont_initialize() on this object instance's target. inline void sc_process_handle::dont_initialize( bool dont ) { if ( m_target_p ) m_target_p->dont_initialize( dont ); else SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "dont_initialize()"); } // dump the status of this object instance's target: inline std::string sc_process_handle::dump_state() const { return m_target_p ? m_target_p->dump_state() : std::string("NO TARGET"); } // return whether this object instance's target is dynamic or not. inline bool sc_process_handle::dynamic() const { return m_target_p ? m_target_p->dynamic() : false; } // enable this object instance's target. inline void sc_process_handle::enable(sc_descendant_inclusion_info descendants) { if ( m_target_p ) m_target_p->enable_process(descendants); else SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "enable()"); } // return the child objects for this object instance's target. inline const std::vector& sc_process_handle::get_child_events() const { return m_target_p ? m_target_p->get_child_events() : empty_event_vector; } // return the child objects for this object instance's target. inline const std::vector& sc_process_handle::get_child_objects() const { return m_target_p ? m_target_p->get_child_objects() : empty_object_vector; } // return the parent object for this object instance's target. inline sc_object* sc_process_handle::get_parent_object() const { return m_target_p ? m_target_p->get_parent_object() : NULL; } // return this object instance's target. inline sc_object* sc_process_handle::get_process_object() const { return m_target_p; } // return whether this object instance is unwinding or not. inline bool sc_process_handle::is_unwinding() const { if ( m_target_p ) return m_target_p->is_unwinding(); else { SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "is_unwinding()"); return false; } } // kill this object instance's target. inline void sc_process_handle::kill( sc_descendant_inclusion_info descendants ) { if ( m_target_p ) m_target_p->kill_process( descendants ); else SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "kill()"); } // return the name of this object instance's target. inline const char* sc_process_handle::name() const { return m_target_p ? m_target_p->name() : ""; } // return the basename of this object instance's target. inline const char* sc_process_handle::basename() const { return m_target_p ? m_target_p->basename() : ""; } // return the process kind for this object instance's target. inline sc_curr_proc_kind sc_process_handle::proc_kind() const { return m_target_p ? m_target_p->proc_kind() : SC_NO_PROC_; } // reset this object instance's target. inline void sc_process_handle::reset( sc_descendant_inclusion_info descendants ) { if ( m_target_p ) m_target_p->reset_process( sc_process_b::reset_asynchronous, descendants ); else SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "reset()"); } // return the reset event for this object instance's target. inline sc_event& sc_process_handle::reset_event() const { if ( m_target_p ) return m_target_p->reset_event(); else { SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "reset()"); return sc_process_handle::non_event; } } // resume this object instance's target. inline void sc_process_handle::resume(sc_descendant_inclusion_info descendants) { if ( m_target_p ) m_target_p->resume_process(descendants); else SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "resume()"); } // suspend this object instance's target. inline void sc_process_handle::suspend(sc_descendant_inclusion_info descendants) { if ( m_target_p ) m_target_p->suspend_process(descendants); else SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "suspend()"); } // swap targets of this process handle with the supplied one. inline void sc_process_handle::swap( sc_process_handle& other ) { sc_process_b* tmp = m_target_p; m_target_p = other.m_target_p; other.m_target_p = tmp; } // turn sync_reset off for this object instance's target. inline void sc_process_handle::sync_reset_off( sc_descendant_inclusion_info descendants) { if ( m_target_p ) m_target_p->reset_process( sc_process_b::reset_synchronous_off, descendants); else SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "sync_reset_off()"); } // turn sync_reset on for this object instance's target. inline void sc_process_handle::sync_reset_on( sc_descendant_inclusion_info descendants) { if ( m_target_p ) { m_target_p->reset_process(sc_process_b::reset_synchronous_on, descendants); } else { SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "sync_reset_on()"); } } // terminate this object instance's target. inline bool sc_process_handle::terminated() const { return m_target_p ? m_target_p->terminated() : false; } // return the termination event for this object instance's target. inline sc_event& sc_process_handle::terminated_event() { if ( m_target_p ) return m_target_p->terminated_event(); else { SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "terminated_event()"); return sc_process_handle::non_event; } } // return true if this object instance has a target, false it not. inline bool sc_process_handle::valid() const { return m_target_p ? true : false; } //------------------------------------------------------------------------------ //"sc_process_handle::sc_throw_it" // // This method throws the supplied exception to the process whose handle this // object instance is, and optionally to the process' descendants. Once the // exception is thrown the currently executed process will suspend to allow // the exception to be propagated. Once the propagation has occurred the // current process will be resumed. // // Notes: // (1) We allocate the helper function on the stack, see the description of // sc_throw_it, in sc_process.h, for why. // // Arguments: // exception = exception to be thrown // descendants = indication of whether descendant processes should also // receive the throw. //------------------------------------------------------------------------------ template inline void sc_process_handle::throw_it( const EXCEPT& exception, sc_descendant_inclusion_info descendants) { sc_throw_it helper(exception); // helper to throw the exception. if ( !m_target_p ) { SC_REPORT_WARNING( SC_ID_EMPTY_PROCESS_HANDLE_, "throw_it()"); return; } m_target_p->throw_user(helper, descendants); } //------------------------------------------------------------------------------ //"sc_process_b::last_created_process_handle" // // This method returns the kind of this process. //------------------------------------------------------------------------------ inline sc_process_handle sc_process_b::last_created_process_handle() { return sc_process_handle(m_last_created_process_p); } inline sc_process_handle sc_get_last_created_process_handle() { return sc_process_b::last_created_process_handle(); } } // namespace sc_core #if defined(_MSC_VER) && !defined(SC_WIN_DLL_WARN) #pragma warning(pop) #endif // Revision 1.19 2011/08/24 22:05:51 acg // Torsten Maehne: initialization changes to remove warnings. // // Revision 1.18 2011/04/01 22:08:26 acg // Andy Goodrich: remove unused variable. // // Revision 1.17 2011/03/12 21:07:51 acg // Andy Goodrich: changes to kernel generated event support. // // Revision 1.16 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.15 2011/02/17 19:53:03 acg // Andy Goodrich: changed dump_status() to dump_state() with new signature. // // Revision 1.14 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.13 2011/02/13 21:33:30 acg // Andy Goodrich: added dump_status() to allow the dumping of the status // of a process handle's target. // // Revision 1.12 2011/02/01 23:01:53 acg // Andy Goodrich: removed dead code. // // Revision 1.11 2011/02/01 21:07:36 acg // Andy Goodrich: defering of run queue manipulations to the // sc_thread_process::throw_it() method. // // Revision 1.10 2011/01/25 20:50:37 acg // Andy Goodrich: changes for IEEE 1666 2011. // // Revision 1.9 2011/01/20 16:52:20 acg // Andy Goodrich: changes for IEEE 1666 2011. // // Revision 1.8 2011/01/19 23:21:50 acg // Andy Goodrich: changes for IEEE 1666 2011 // // Revision 1.7 2011/01/18 20:10:45 acg // Andy Goodrich: changes for IEEE1666_2011 semantics. // // Revision 1.6 2010/07/30 05:21:22 acg // Andy Goodrich: release 2.3 fixes. // // Revision 1.5 2010/07/22 20:02:33 acg // Andy Goodrich: bug fixes. // // Revision 1.4 2009/05/22 16:06:29 acg // Andy Goodrich: process control updates. // // Revision 1.3 2008/05/22 17:06:26 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.2 2007/09/20 20:32:35 acg // Andy Goodrich: changes to the semantics of throw_it() to match the // specification. A call to throw_it() will immediately suspend the calling // thread until all the throwees have executed. At that point the calling // thread will be restarted before the execution of any other threads. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.7 2006/05/08 17:58:24 acg // Andy Goodrich: added David Long's forward declarations for friend // functions, methods, and operators to keep the Microsoft compiler happy. // // Revision 1.6 2006/04/20 17:08:17 acg // Andy Goodrich: 3.0 style process changes. // // Revision 1.5 2006/04/11 23:13:21 acg // Andy Goodrich: Changes for reduced reset support that only includes // sc_cthread, but has preliminary hooks for expanding to method and thread // processes also. // // Revision 1.4 2006/01/24 20:49:05 acg // Andy Goodrich: changes to remove the use of deprecated features within the // simulator, and to issue warning messages when deprecated features are used. // // Revision 1.3 2006/01/13 18:44:30 acg // Added $Log to record CVS changes into the source. #endif // !defined(sc_spawn_h_INCLUDED) systemc-2.3.3/src/sysc/kernel/sc_dynamic_processes.h0000644000175000017500000000765513360325173022506 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_dynamic_process.h -- Dynamic Process Package Definitions Original Author: Andy Goodrich, Forte Design Systems, 5 May 2003 CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #ifndef SC_DYNAMIC_PROCESSES_H #define SC_DYNAMIC_PROCESSES_H #include "sysc/kernel/sc_cmnhdr.h" #include "sysc/kernel/sc_except.h" #include "sysc/kernel/sc_spawn.h" #include "sysc/kernel/sc_join.h" #if SC_CPLUSPLUS >= 201103L // C++11 or later has std::bind # include namespace sc_unnamed { using namespace std::placeholders; } // namespace sc_unnamed namespace sc_core { template auto sc_bind( F&& f, Args&&... args ) # if SC_CPLUSPLUS < 201402L // explicit return type needed before C++14 -> decltype( std::bind(std::forward(f), std::forward(args)...) ) # endif { return std::bind( std::forward(f), std::forward(args)... ); } template auto sc_ref( T&& v ) # if SC_CPLUSPLUS < 201402L // explicit return type needed before C++14 -> decltype( std::ref(std::forward(v) ) ) # endif { return std::ref( std::forward(v) ); } template auto sc_cref( T&& v ) # if SC_CPLUSPLUS < 201402L // explicit return type needed before C++14 -> decltype( std::cref(std::forward(v) ) ) # endif { return std::cref( std::forward(v) ); } } // namespace sc_core // bring sc_bind, sc_ref, sc_cref into global namespace - unless asked not to // TODO: invert default for IEEE 1666-202x #if ! (defined(SC_BIND_IN_GLOBAL_NAMESPACE) && SC_BIND_IN_GLOBAL_NAMESPACE == 0) using sc_core::sc_bind; using sc_core::sc_ref; using sc_core::sc_cref; #endif // SC_BIND_IN_GLOBAL_NAMESPACE #else // use Boost implementation # include "sysc/packages/boost/bind.hpp" # include "sysc/packages/boost/ref.hpp" # define sc_bind sc_boost::bind # define sc_ref(r) sc_boost::ref(r) # define sc_cref(r) sc_boost::cref(r) #endif // C++11 implementation // $Log: sc_dynamic_processes.h,v $ // Revision 1.5 2011/08/26 20:46:09 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.4 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.3 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.2 2008/05/22 17:06:25 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.5 2006/04/20 17:08:16 acg // Andy Goodrich: 3.0 style process changes. // // Revision 1.4 2006/04/11 23:13:20 acg // Andy Goodrich: Changes for reduced reset support that only includes // sc_cthread, but has preliminary hooks for expanding to method and thread // processes also. // // Revision 1.3 2006/01/13 18:44:29 acg // Added $Log to record CVS changes into the source. // #endif // SC_DYNAMIC_PROCESSES_H systemc-2.3.3/src/sysc/kernel/sc_time.cpp0000644000175000017500000003562213360325173020260 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_time.cpp -- Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #include "sysc/kernel/sc_time.h" #include "sysc/kernel/sc_kernel_ids.h" #include "sysc/kernel/sc_simcontext.h" #include "sysc/utils/sc_utils_ids.h" #include #include #include #include #include #ifdef SC_ENABLE_EARLY_MAXTIME_CREATION # define SC_MAXTIME_ALLOWED_ 1 #else # define SC_MAXTIME_ALLOWED_ 0 #endif namespace sc_core { static double time_values[] = { 1, // fs 1e3, // ps 1e6, // ns 1e9, // us 1e12, // ms 1e15 // s }; static const char* time_units[] = { "fs", "ps", "ns", "us", "ms", "s" }; static const char* time_units_sc[] = { "SC_FS", "SC_PS", "SC_NS", "SC_US", "SC_MS", "SC_SEC" }; // ---------------------------------------------------------------------------- // CLASS : sc_time_tuple // // The time tuple helper class. // ---------------------------------------------------------------------------- void sc_time_tuple::init( value_type val ) { sc_time_params* time_params = sc_get_curr_simcontext()->m_time_params; # if SC_MAXTIME_ALLOWED_ time_params->time_resolution_fixed = true; # endif // SC_MAXTIME_ALLOWED_ value_type tr = static_cast( time_params->time_resolution ); unsigned scale = 0; while( ( tr % 10 ) == 0 ) { tr /= 10; scale++; } sc_assert( tr == 1 ); unsigned tu = scale / 3; while( tu < SC_SEC && ( val % 10 ) == 0 ) { val /= 10; scale++; tu += ( 0 == ( scale % 3 ) ); } m_value = val; m_unit = static_cast( tu ); m_offset = 1; for( scale %= 3; scale != 0 ; scale-- ) m_offset *= 10; } bool sc_time_tuple::has_value() const { return ( m_value < ( (~sc_dt::UINT64_ZERO) / m_offset ) ); } sc_time::value_type sc_time_tuple::value() const { if( !has_value() ) SC_REPORT_ERROR( SC_ID_TIME_CONVERSION_FAILED_ , "sc_time_tuple value overflow" ); return m_value * m_offset; } const char * sc_time_tuple::unit_symbol() const { return time_units[m_unit]; } std::string sc_time_tuple::to_string() const { std::ostringstream oss; if ( !m_value ) { oss << "0 s"; } else { oss << m_value; for( unsigned zeros = m_offset; zeros > 1; zeros /= 10 ) { oss << '0'; } oss << ' ' << time_units[m_unit]; } return oss.str(); } // ---------------------------------------------------------------------------- // CLASS : sc_time // // The time class. // ---------------------------------------------------------------------------- // constructors namespace /* anonymous */ { static sc_time::value_type from_value_and_unit( double v, sc_time_unit tu, sc_time_params* tp ) { sc_time::value_type t = 0; if( v != 0 ) { double scale_fac = time_values[tu] / tp->time_resolution; // linux bug workaround; don't change next two lines volatile double tmp = v * scale_fac + 0.5; t = static_cast( tmp ); tp->time_resolution_fixed = true; } return t; } } /* anonymous namespace */ sc_time::sc_time( double v, sc_time_unit tu ) : m_value ( from_value_and_unit( v, tu, sc_get_curr_simcontext()->m_time_params ) ) {} sc_time::sc_time( double v, sc_time_unit tu, sc_simcontext* simc ) : m_value( from_value_and_unit( v, tu, simc->m_time_params ) ) {} sc_time::sc_time( double v, bool scale ) : m_value( 0 ) { static bool warn_constructor=true; if ( warn_constructor ) { warn_constructor=false; SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, "deprecated constructor: sc_time(double,bool)"); } if( v != 0 ) { sc_time_params* time_params = sc_get_curr_simcontext()->m_time_params; if( scale ) { double scale_fac = sc_dt::uint64_to_double( time_params->default_time_unit ); // linux bug workaround; don't change next two lines volatile double tmp = v * scale_fac + 0.5; m_value = static_cast( tmp ); } else { // linux bug workaround; don't change next two lines volatile double tmp = v + 0.5; m_value = static_cast( tmp ); } time_params->time_resolution_fixed = true; } } sc_time::sc_time( value_type v, bool scale ) : m_value( 0 ) { static bool warn_constructor=true; if ( warn_constructor ) { warn_constructor=false; SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, "deprecated constructor: sc_time(uint64,bool)"); } if( v != 0 ) { sc_time_params* time_params = sc_get_curr_simcontext()->m_time_params; if( scale ) { double scale_fac = sc_dt::uint64_to_double( time_params->default_time_unit ); // linux bug workaround; don't change next two lines volatile double tmp = sc_dt::uint64_to_double( v ) * scale_fac + 0.5; m_value = static_cast( tmp ); } else { m_value = v; } time_params->time_resolution_fixed = true; } } sc_time sc_time::from_value( value_type v ) { sc_time t; if( v != 0 && !(SC_MAXTIME_ALLOWED_ && v == ~sc_dt::UINT64_ZERO) ) { sc_time_params* time_params = sc_get_curr_simcontext()->m_time_params; time_params->time_resolution_fixed = true; } t.m_value = v; return t; } namespace /* anonymous */ { static sc_time::value_type from_value_and_unit_symbol( double v, const char* unit, sc_time_params* tp ) { sc_time::value_type t = 0; if( !unit || !*unit ) { SC_REPORT_ERROR( SC_ID_TIME_CONVERSION_FAILED_, "no time unit given" ); return t; } unsigned tu = SC_FS; while( tu <= SC_SEC && std::strcmp( unit, time_units[tu] ) != 0 && std::strcmp( unit, time_units_sc[tu] ) != 0 ) { ++tu; } if( tu > SC_SEC ) { SC_REPORT_ERROR( SC_ID_TIME_CONVERSION_FAILED_, "invalid unit given" ); return t; } return from_value_and_unit( v, static_cast(tu), tp ); } } /* anonymous namespace */ sc_time::sc_time( double v, const char* unit ) : m_value ( from_value_and_unit_symbol( v, unit, sc_get_curr_simcontext()->m_time_params ) ) {} sc_time::sc_time( double v, const char* unit, sc_simcontext* simc ) : m_value( from_value_and_unit_symbol( v, unit, simc->m_time_params ) ) {} sc_time sc_time::from_string( const char * str ) { char * endptr = NULL; double v = str ? std::strtod( str, &endptr ) : 0.0; if( str == endptr || v < 0.0 ) { SC_REPORT_ERROR( SC_ID_TIME_CONVERSION_FAILED_, "invalid value given" ); return SC_ZERO_TIME; } while( *endptr && std::isspace( *endptr ) ) ++endptr; // skip whitespace return sc_time( v, endptr ); } // conversion functions double sc_time::to_default_time_units() const { sc_time_params* time_params = sc_get_curr_simcontext()->m_time_params; # if SC_MAXTIME_ALLOWED_ if( m_value == 0 ) return 0.0; time_params->time_resolution_fixed = true; # endif // SC_MAXTIME_ALLOWED_ return ( sc_dt::uint64_to_double( m_value ) / sc_dt::uint64_to_double( time_params->default_time_unit ) ); } double sc_time::to_seconds() const { sc_time_params* time_params = sc_get_curr_simcontext()->m_time_params; # if SC_MAXTIME_ALLOWED_ if( m_value == 0 ) return 0.0; time_params->time_resolution_fixed = true; # endif // SC_MAXTIME_ALLOWED_ return ( sc_dt::uint64_to_double( m_value ) * time_params->time_resolution * 1e-15 ); } // print function void sc_time::print( ::std::ostream& os ) const { os << to_string(); } // ---------------------------------------------------------------------------- // STRUCT : sc_time_params // // Struct that holds the time resolution and default time unit. // ---------------------------------------------------------------------------- sc_time_params::sc_time_params() : time_resolution( 1000 ), // default 1 ps time_resolution_specified( false ), time_resolution_fixed( false ), default_time_unit( 1000 ), // default 1 ns default_time_unit_specified( false ) {} sc_time_params::~sc_time_params() {} // ---------------------------------------------------------------------------- // functions for accessing the time resolution and default time unit void sc_set_time_resolution( double v, sc_time_unit tu ) { // first perform the necessary checks // must be positive if( v < 0.0 ) { SC_REPORT_ERROR( SC_ID_SET_TIME_RESOLUTION_, "value not positive" ); } // must be a power of ten double dummy; #if defined( __HP_aCC ) || defined(__ppc__) // aCC seems to have a bug in modf() if( modf( log10( v < 1.0 ? 1.0/v : v ), &dummy ) != 0.0 ) { #else if( modf( log10( v ), &dummy ) != 0.0 ) { #endif SC_REPORT_ERROR( SC_ID_SET_TIME_RESOLUTION_, "value not a power of ten" ); } sc_simcontext* simc = sc_get_curr_simcontext(); // can only be specified during elaboration if( sc_is_running() ) { SC_REPORT_ERROR( SC_ID_SET_TIME_RESOLUTION_, "simulation running" ); } sc_time_params* time_params = simc->m_time_params; // can be specified only once if( time_params->time_resolution_specified ) { SC_REPORT_ERROR( SC_ID_SET_TIME_RESOLUTION_, "already specified" ); } // can only be specified before any sc_time is constructed if( time_params->time_resolution_fixed ) { SC_REPORT_ERROR( SC_ID_SET_TIME_RESOLUTION_, "sc_time object(s) constructed" ); } // must be larger than or equal to 1 fs volatile double resolution = v * time_values[tu]; if( resolution < 1.0 ) { SC_REPORT_ERROR( SC_ID_SET_TIME_RESOLUTION_, "value smaller than 1 fs" ); } // recalculate the default time unit volatile double time_unit = sc_dt::uint64_to_double( time_params->default_time_unit ) * ( time_params->time_resolution / resolution ); if( time_unit < 1.0 ) { SC_REPORT_WARNING( SC_ID_DEFAULT_TIME_UNIT_CHANGED_, 0 ); time_params->default_time_unit = 1; } else { time_params->default_time_unit = static_cast( time_unit ); } time_params->time_resolution = resolution; time_params->time_resolution_specified = true; } sc_time sc_get_time_resolution() { return sc_time::from_value( sc_dt::UINT64_ONE ); } void sc_set_default_time_unit( double v, sc_time_unit tu ) { static bool warn_default_time_unit=true; if ( warn_default_time_unit ) { warn_default_time_unit=false; SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, "deprecated function: sc_set_default_time_unit"); } // first perform the necessary checks // must be positive if( v < 0.0 ) { SC_REPORT_ERROR( SC_ID_SET_DEFAULT_TIME_UNIT_, "value not positive" ); } // must be a power of ten double dummy; if( modf( log10( v ), &dummy ) != 0.0 ) { SC_REPORT_ERROR( SC_ID_SET_DEFAULT_TIME_UNIT_, "value not a power of ten" ); } sc_simcontext* simc = sc_get_curr_simcontext(); // can only be specified during elaboration if( sc_is_running() ) { SC_REPORT_ERROR( SC_ID_SET_DEFAULT_TIME_UNIT_, "simulation running" ); } sc_time_params* time_params = simc->m_time_params; // can only be specified before any sc_time is constructed if( time_params->time_resolution_fixed ) { SC_REPORT_ERROR( SC_ID_SET_DEFAULT_TIME_UNIT_, "sc_time object(s) constructed" ); } // can be specified only once if( time_params->default_time_unit_specified ) { SC_REPORT_ERROR( SC_ID_SET_DEFAULT_TIME_UNIT_, "already specified" ); } // must be larger than or equal to the time resolution volatile double time_unit = ( v * time_values[tu] ) / time_params->time_resolution; if( time_unit < 1.0 ) { SC_REPORT_ERROR( SC_ID_SET_DEFAULT_TIME_UNIT_, "value smaller than time resolution" ); } time_params->default_time_unit = static_cast( time_unit ); time_params->default_time_unit_specified = true; } sc_time sc_get_default_time_unit() { static bool warn_get_default_time_unit = true; if ( warn_get_default_time_unit ) { warn_get_default_time_unit=false; SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, "deprecated function: sc_get_default_time_unit"); } return sc_time::from_value( sc_get_curr_simcontext()->m_time_params->default_time_unit ); } // ---------------------------------------------------------------------------- SC_API const sc_time SC_ZERO_TIME; #undef SC_MAXTIME_ALLOWED_ } // namespace sc_core // $Log: sc_time.cpp,v $ // Revision 1.7 2011/08/26 20:46:11 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.6 2011/07/24 16:08:36 acg // Philipp A. Hartmann: fix C99 format specifiers for Solaris. // // Revision 1.5 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.4 2011/02/13 21:47:38 acg // Andy Goodrich: update copyright notice. // // Revision 1.3 2011/01/19 23:21:50 acg // Andy Goodrich: changes for IEEE 1666 2011 // // Revision 1.2 2008/05/22 17:06:27 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.6 2006/01/26 21:04:55 acg // Andy Goodrich: deprecation message changes and additional messages. // // Revision 1.5 2006/01/25 00:31:19 acg // Andy Goodrich: Changed over to use a standard message id of // SC_ID_IEEE_1666_DEPRECATION for all deprecation messages. // // Revision 1.4 2006/01/24 20:49:05 acg // Andy Goodrich: changes to remove the use of deprecated features within the // simulator, and to issue warning messages when deprecated features are used. // // Revision 1.3 2006/01/13 18:44:30 acg // Added $Log to record CVS changes into the source. // // Taf! systemc-2.3.3/src/sysc/kernel/sc_wait.h0000644000175000017500000001510113360325173017721 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_wait.h -- Wait() and related functions. Original Author: Stan Y. Liao, Synopsys, Inc. Martin Janssen, Synopsys, Inc. CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #ifndef SC_WAIT_H #define SC_WAIT_H #include "sysc/kernel/sc_simcontext.h" namespace sc_core { class sc_event; class sc_event_and_list; class sc_event_or_list; class sc_simcontext; extern sc_simcontext* sc_get_curr_simcontext(); // static sensitivity for SC_THREADs and SC_CTHREADs extern SC_API void wait( sc_simcontext* = sc_get_curr_simcontext() ); // dynamic sensitivity for SC_THREADs and SC_CTHREADs extern SC_API void wait( const sc_event&, sc_simcontext* = sc_get_curr_simcontext() ); extern SC_API void wait( const sc_event_or_list&, sc_simcontext* = sc_get_curr_simcontext() ); extern SC_API void wait( const sc_event_and_list&, sc_simcontext* = sc_get_curr_simcontext() ); extern SC_API void wait( const sc_time&, sc_simcontext* = sc_get_curr_simcontext() ); inline SC_API void wait( double v, sc_time_unit tu, sc_simcontext* simc = sc_get_curr_simcontext() ) { wait( sc_time( v, tu, simc ), simc ); } extern SC_API void wait( const sc_time&, const sc_event&, sc_simcontext* = sc_get_curr_simcontext() ); inline SC_API void wait( double v, sc_time_unit tu, const sc_event& e, sc_simcontext* simc = sc_get_curr_simcontext() ) { wait( sc_time( v, tu, simc ), e, simc ); } extern SC_API void wait( const sc_time&, const sc_event_or_list&, sc_simcontext* = sc_get_curr_simcontext() ); inline SC_API void wait( double v, sc_time_unit tu, const sc_event_or_list& el, sc_simcontext* simc = sc_get_curr_simcontext() ) { wait( sc_time( v, tu, simc ), el, simc ); } extern SC_API void wait( const sc_time&, const sc_event_and_list&, sc_simcontext* = sc_get_curr_simcontext() ); inline SC_API void wait( double v, sc_time_unit tu, const sc_event_and_list& el, sc_simcontext* simc = sc_get_curr_simcontext() ) { wait( sc_time( v, tu, simc ), el, simc ); } // static sensitivity for SC_METHODs extern SC_API void next_trigger( sc_simcontext* = sc_get_curr_simcontext() ); // dynamic sensitivity for SC_METHODs extern SC_API void next_trigger( const sc_event&, sc_simcontext* = sc_get_curr_simcontext() ); extern SC_API void next_trigger( const sc_event_or_list&, sc_simcontext* = sc_get_curr_simcontext() ); extern SC_API void next_trigger( const sc_event_and_list&, sc_simcontext* = sc_get_curr_simcontext() ); extern SC_API void next_trigger( const sc_time&, sc_simcontext* = sc_get_curr_simcontext() ); inline SC_API void next_trigger( double v, sc_time_unit tu, sc_simcontext* simc = sc_get_curr_simcontext() ) { next_trigger( sc_time( v, tu, simc ), simc ); } extern SC_API void next_trigger( const sc_time&, const sc_event&, sc_simcontext* = sc_get_curr_simcontext() ); inline SC_API void next_trigger( double v, sc_time_unit tu, const sc_event& e, sc_simcontext* simc = sc_get_curr_simcontext() ) { next_trigger( sc_time( v, tu, simc ), e, simc ); } extern SC_API void next_trigger( const sc_time&, const sc_event_or_list&, sc_simcontext* = sc_get_curr_simcontext() ); inline SC_API void next_trigger( double v, sc_time_unit tu, const sc_event_or_list& el, sc_simcontext* simc = sc_get_curr_simcontext() ) { next_trigger( sc_time( v, tu, simc ), el, simc ); } extern SC_API void next_trigger( const sc_time&, const sc_event_and_list&, sc_simcontext* = sc_get_curr_simcontext() ); inline void next_trigger( double v, sc_time_unit tu, const sc_event_and_list& el, sc_simcontext* simc = sc_get_curr_simcontext() ) { next_trigger( sc_time( v, tu, simc ), el, simc ); } // for SC_METHODs and SC_THREADs and SC_CTHREADs extern SC_API bool timed_out( sc_simcontext* = sc_get_curr_simcontext() ); // misc. extern SC_API void sc_set_location( const char*, int, sc_simcontext* = sc_get_curr_simcontext() ); } // namespace sc_core /* $Log: sc_wait.h,v $ Revision 1.6 2011/08/26 20:46:11 acg Andy Goodrich: moved the modification log to the end of the file to eliminate source line number skew when check-ins are done. Revision 1.5 2011/02/18 20:27:14 acg Andy Goodrich: Updated Copyrights. Revision 1.4 2011/02/13 21:47:38 acg Andy Goodrich: update copyright notice. Revision 1.3 2011/01/18 20:10:45 acg Andy Goodrich: changes for IEEE1666_2011 semantics. Revision 1.2 2008/05/22 17:06:27 acg Andy Goodrich: updated copyright notice to include 2008. Revision 1.1.1.1 2006/12/15 20:20:05 acg SystemC 2.3 Revision 1.2 2006/01/03 23:18:45 acg Changed copyright to include 2006. Revision 1.1.1.1 2005/12/19 23:16:44 acg First check in of SystemC 2.1 into its own archive. Revision 1.10 2005/07/30 03:45:05 acg Changes from 2.1, including changes for sc_process_handle. Revision 1.9 2005/04/04 00:16:08 acg Changes for directory name change to sys from systemc. Changes for sc_string going to std::string. Changes for sc_pvector going to std::vector. Changes for reference pools for bit and part selections. Changes for const sc_concatref support. Revision 1.6 2004/10/13 18:13:22 acg sc_ver.h - updated version number. sc_wait.h remove inclusion of sysc/kernel/sc_event.h because it is not necessary. Revision 1.5 2004/09/27 20:49:10 acg Andy Goodrich, Forte Design Systems, Inc. - Added a $Log comment so that CVS checkin comments appear in the checkout source. */ #endif // Taf! systemc-2.3.3/src/sysc/kernel/sc_cor.h0000644000175000017500000001021113360325173017535 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_cor.h -- Coroutine abstract base classes. Original Author: Martin Janssen, Synopsys, Inc., 2001-12-18 CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #ifndef SC_COR_H #define SC_COR_H #include // use plain assert, sc_report may not be available, yet #include #include "sysc/kernel/sc_cmnhdr.h" namespace sc_core { class sc_simcontext; // ---------------------------------------------------------------------------- // TYPEDEF : sc_cor_fn // // Function type for creating coroutines. // ---------------------------------------------------------------------------- typedef void (sc_cor_fn)( void* ); // ---------------------------------------------------------------------------- // CLASS : sc_cor // // Coroutine abstract base class. // ---------------------------------------------------------------------------- class SC_API sc_cor { protected: // constructor sc_cor() {} public: // destructor virtual ~sc_cor() {} // switch stack protection on/off virtual void stack_protect( bool /* enable */ ) {} private: // disabled sc_cor( const sc_cor& ); sc_cor& operator = ( const sc_cor& ); }; // ---------------------------------------------------------------------------- // CLASS : sc_cor_pkg // // Coroutine package abstract base class. // ---------------------------------------------------------------------------- class SC_API sc_cor_pkg { public: // constructor sc_cor_pkg( sc_simcontext* simc ) : m_simc( simc ) { assert( simc != 0 ); } // destructor virtual ~sc_cor_pkg() {} // create a new coroutine virtual sc_cor* create( std::size_t stack_size, sc_cor_fn* fn, void* arg ) = 0; // yield to the next coroutine virtual void yield( sc_cor* next_cor ) = 0; // abort the current coroutine (and resume the next coroutine) virtual void abort( sc_cor* next_cor ) = 0; // get the main coroutine virtual sc_cor* get_main() = 0; // get the simulation context sc_simcontext* simcontext() { return m_simc; } private: sc_simcontext* m_simc; private: // disabled sc_cor_pkg(); sc_cor_pkg( const sc_cor_pkg& ); sc_cor_pkg& operator = ( const sc_cor_pkg& ); }; } // namespace sc_core // $Log: sc_cor.h,v $ // Revision 1.7 2011/08/26 20:46:09 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.6 2011/08/15 16:43:24 acg // Torsten Maehne: changes to remove unused argument warnings. // // Revision 1.5 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.4 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.3 2011/01/19 23:21:49 acg // Andy Goodrich: changes for IEEE 1666 2011 // // Revision 1.2 2008/05/22 17:06:24 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.3 2006/01/13 18:44:29 acg // Added $Log to record CVS changes into the source. // #endif // Taf! systemc-2.3.3/src/sysc/kernel/sc_macros.h0000644000175000017500000001223313360325173020244 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_macros.h -- Miscellaneous definitions that are needed by the headers. Original Author: Stan Y. Liao, Synopsys, Inc. CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #ifndef SC_MACROS_H #define SC_MACROS_H #include "sysc/kernel/sc_cmnhdr.h" // SC_CPLUSPLUS namespace sc_dt { template inline const T sc_min( const T& a, const T& b ) { return ( ( a <= b ) ? a : b ); } template inline const T sc_max( const T& a, const T& b ) { return ( ( a >= b ) ? a : b ); } template inline const T sc_abs( const T& a ) { // return ( a >= 0 ? a : -a ); // the code below is functionaly the same as the code above; the // difference is that the code below works for all arithmetic // SystemC datatypes. T z( a ); z = 0; if( a >= z ) { return a; } else { T c( a ); c = -a; return c; } } } // namespace sc_dt // token stringification #define SC_STRINGIFY_HELPER_( Arg ) \ SC_STRINGIFY_HELPER_DEFERRED_( Arg ) #define SC_STRINGIFY_HELPER_DEFERRED_( Arg ) \ SC_STRINGIFY_HELPER_MORE_DEFERRED_( Arg ) #define SC_STRINGIFY_HELPER_MORE_DEFERRED_( Arg ) \ #Arg // token concatenation #define SC_CONCAT_HELPER_( a, b ) \ SC_CONCAT_HELPER_DEFERRED_( a, b ) #define SC_CONCAT_HELPER_DEFERRED_( a, b ) \ SC_CONCAT_HELPER_MORE_DEFERRED_( a,b ) #define SC_CONCAT_HELPER_MORE_DEFERRED_( a, b ) \ a ## b #define SC_CONCAT_UNDERSCORE_( a, b ) \ SC_CONCAT_HELPER_( a, SC_CONCAT_HELPER_( _, b ) ) // forced token expansion #define SC_EXPAND_HELPER_(x) x /* * These help debugging -- * -- the user can find out at which location in their source file a process calls wait. */ #define SC_WAIT() \ ::sc_core::sc_set_location( __FILE__, __LINE__ ); \ ::sc_core::wait(); \ ::sc_core::sc_set_location( NULL, 0 ) #define SC_WAITN(n) \ ::sc_core::sc_set_location( __FILE__, __LINE__ ); \ ::sc_core::wait(n); \ ::sc_core::sc_set_location( NULL, 0 ) #define SC_WAIT_UNTIL(expr) \ do { SC_WAIT(); } while( !(expr) ) // ---------------------------------------------------------------------------- // SC_NAMED - helper macro to create named objects #define SC_NAMED(...) \ SC_NAMED_IMPL_(__VA_ARGS__)(__VA_ARGS__) #if SC_CPLUSPLUS >= 201103L // use uniform initialization in C++11 or later # define SC_NAMED_IMPL_ONE_(inst) \ inst { SC_STRINGIFY_HELPER_(inst) } # define SC_NAMED_IMPL_MORE_(inst, ...) \ inst { SC_STRINGIFY_HELPER_(inst), __VA_ARGS__ } #else // use regular init # define SC_NAMED_IMPL_ONE_(inst) \ inst ( SC_STRINGIFY_HELPER_(inst) ) # define SC_NAMED_IMPL_MORE_(inst, ...) \ inst ( SC_STRINGIFY_HELPER_(inst), __VA_ARGS__ ) #endif // SC_CPLUSPLUS #define SC_NAMED_IMPL_(...) \ SC_CONCAT_HELPER_(SC_NAMED_IMPL_, SC_NAMED_IMPL_EXPAND_(__VA_ARGS__)) #define SC_NAMED_IMPL_EXPAND_(...) \ SC_EXPAND_HELPER_( SC_NAMED_IMPL_EXPAND_SEQ_( \ __VA_ARGS__, \ MORE_,MORE_,MORE_,MORE_,MORE_,MORE_,MORE_,MORE_, \ MORE_,MORE_,MORE_,MORE_,MORE_,MORE_,MORE_,MORE_, \ MORE_,MORE_,MORE_,MORE_,MORE_,MORE_,MORE_,MORE_, \ MORE_,MORE_,MORE_,MORE_,MORE_,MORE_,ONE_, FAIL_ ) ) #define SC_NAMED_IMPL_EXPAND_SEQ_( \ _1, _2, _3, _4, _5, _6, _7, _8, \ _9,_10,_11,_12,_13,_14,_15,_16, \ _17,_18,_19,_20,_21,_22,_23,_24, \ _25,_26,_27,_28,_29,_30,_31, N, ...) N // $Log: sc_macros.h,v $ // Revision 1.5 2011/08/26 20:46:09 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.4 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.3 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.2 2008/05/22 17:06:25 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.3 2006/01/13 18:44:29 acg // Added $Log to record CVS changes into the source. #endif systemc-2.3.3/src/sysc/kernel/sc_time.h0000644000175000017500000002577013360325173017730 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_time.h -- The time class. Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #ifndef SC_TIME_H #define SC_TIME_H #include "sysc/datatypes/int/sc_nbdefs.h" #include "sysc/datatypes/fx/scfx_ieee.h" #include namespace sc_core { class sc_simcontext; // friend operator declarations const sc_time operator + ( const sc_time&, const sc_time& ); const sc_time operator - ( const sc_time&, const sc_time& ); const sc_time operator * ( const sc_time&, double ); const sc_time operator * ( double, const sc_time& ); const sc_time operator / ( const sc_time&, double ); double operator / ( const sc_time&, const sc_time& ); // ---------------------------------------------------------------------------- // ENUM : sc_time_unit // // Enumeration of time units. // ---------------------------------------------------------------------------- enum sc_time_unit { SC_FS = 0, SC_PS, SC_NS, SC_US, SC_MS, SC_SEC }; class SC_API sc_time_tuple; // ---------------------------------------------------------------------------- // CLASS : sc_time // // The time class. // ---------------------------------------------------------------------------- class SC_API sc_time { public: typedef sc_dt::uint64 value_type; // constructors sc_time(); sc_time( const sc_time& ); sc_time( double, sc_time_unit ); sc_time( double, sc_time_unit, sc_simcontext* ); // convert time unit from string // "fs"/"SC_FS"->SC_FS, "ps"/"SC_PS"->SC_PS, "ns"/"SC_NS"->SC_NS, ... sc_time( double, const char* unit ); sc_time( double, const char* unit, sc_simcontext* ); static sc_time from_value( value_type ); static sc_time from_seconds( double ); static sc_time from_string( const char * str ); // deprecated, use from_value(v) sc_time( double, bool scale ); sc_time( value_type, bool scale ); // assignment operator sc_time& operator = ( const sc_time& ); // conversion functions value_type value() const; // relative to the time resolution double to_double() const; // relative to the time resolution double to_default_time_units() const; double to_seconds() const; const std::string to_string() const; // relational operators bool operator == ( const sc_time& ) const; bool operator != ( const sc_time& ) const; bool operator < ( const sc_time& ) const; bool operator <= ( const sc_time& ) const; bool operator > ( const sc_time& ) const; bool operator >= ( const sc_time& ) const; // arithmetic operators sc_time& operator += ( const sc_time& ); sc_time& operator -= ( const sc_time& ); friend const sc_time operator + ( const sc_time&, const sc_time& ); friend const sc_time operator - ( const sc_time&, const sc_time& ); sc_time& operator *= ( double ); sc_time& operator /= ( double ); sc_time& operator %= ( const sc_time& ); friend const sc_time operator * ( const sc_time&, double ); friend const sc_time operator * ( double, const sc_time& ); friend const sc_time operator / ( const sc_time&, double ); friend double operator / ( const sc_time&, const sc_time& ); friend const sc_time operator % ( const sc_time&, const sc_time& ); // print function void print( ::std::ostream& os = std::cout ) const; private: value_type m_value; }; // ---------------------------------------------------------------------------- // CLASS : sc_time_tuple // // The time tuple helper class. // ---------------------------------------------------------------------------- class SC_API sc_time_tuple { typedef sc_time::value_type value_type; friend class sc_time; private: explicit sc_time_tuple( value_type v ); void init( value_type v ); public: sc_time_tuple() : m_value(), m_unit( SC_SEC ), m_offset(1) {} sc_time_tuple( const sc_time & t ); bool has_value() const; value_type value() const; sc_time_unit unit() const { return m_unit; } // normalized unit const char * unit_symbol() const; // normalized unit symbol operator sc_time() const { return sc_time( to_double(), m_unit ); } double to_double() const; // relative to the normalized unit std::string to_string() const; private: value_type m_value; sc_time_unit m_unit; unsigned m_offset; }; // print operator inline ::std::ostream& operator << ( ::std::ostream&, const sc_time& ); // IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII extern SC_API const sc_time SC_ZERO_TIME; // constructors inline sc_time::sc_time() : m_value( 0 ) {} inline sc_time::sc_time( const sc_time& t ) : m_value( t.m_value ) {} inline sc_time_tuple::sc_time_tuple( value_type v ) : m_value(), m_unit( SC_SEC ), m_offset(1) { if( v ) init( v ); } inline sc_time_tuple::sc_time_tuple( const sc_time& t ) : m_value(), m_unit( SC_SEC ), m_offset(1) { if( t != SC_ZERO_TIME ) init( t.value() ); } inline sc_time sc_time::from_seconds( double v ) { return sc_time( v, SC_SEC ); } // assignment operator inline sc_time& sc_time::operator = ( const sc_time& t ) { m_value = t.m_value; return *this; } // conversion functions inline sc_time::value_type sc_time::value() const // relative to the time resolution { return m_value; } inline double sc_time::to_double() const // relative to the time resolution { return sc_dt::uint64_to_double( m_value ); } inline double sc_time_tuple::to_double() const // relative to the normalized time unit { return sc_dt::uint64_to_double( m_value ) * m_offset; } inline const std::string sc_time::to_string() const { return sc_time_tuple( *this ).to_string(); } // relational operators inline bool sc_time::operator == ( const sc_time& t ) const { return ( m_value == t.m_value ); } inline bool sc_time::operator != ( const sc_time& t ) const { return ( m_value != t.m_value ); } inline bool sc_time::operator < ( const sc_time& t ) const { return ( m_value < t.m_value ); } inline bool sc_time::operator <= ( const sc_time& t ) const { return ( m_value <= t.m_value ); } inline bool sc_time::operator > ( const sc_time& t ) const { return ( m_value > t.m_value ); } inline bool sc_time::operator >= ( const sc_time& t ) const { return ( m_value >= t.m_value ); } // arithmetic operators inline sc_time& sc_time::operator += ( const sc_time& t ) { m_value += t.m_value; return *this; } inline sc_time& sc_time::operator -= ( const sc_time& t ) { m_value -= t.m_value; return *this; } inline const sc_time operator + ( const sc_time& t1, const sc_time& t2 ) { return sc_time( t1 ) += t2; } inline const sc_time operator - ( const sc_time& t1, const sc_time& t2 ) { return sc_time( t1 ) -= t2; } inline sc_time& sc_time::operator *= ( double d ) { // linux bug workaround; don't change next two lines volatile double tmp = sc_dt::uint64_to_double( m_value ) * d + 0.5; m_value = static_cast( tmp ); return *this; } inline sc_time& sc_time::operator /= ( double d ) { // linux bug workaround; don't change next two lines volatile double tmp = sc_dt::uint64_to_double( m_value ) / d + 0.5; m_value = static_cast( tmp ); return *this; } inline sc_time& sc_time::operator %= ( const sc_time& t ) { m_value %= t.m_value; return *this; } inline const sc_time operator * ( const sc_time& t, double d ) { sc_time tmp( t ); return tmp *= d; } inline const sc_time operator * ( double d, const sc_time& t ) { sc_time tmp( t ); return tmp *= d; } inline const sc_time operator / ( const sc_time& t, double d ) { sc_time tmp( t ); return tmp /= d; } inline double operator / ( const sc_time& t1, const sc_time& t2 ) { return ( t1.to_double() / t2.to_double() ); } inline const sc_time operator % ( const sc_time& t1, const sc_time& t2 ) { sc_time tmp(t1); return tmp %= t2; } // print operator inline ::std::ostream& operator << ( ::std::ostream& os, const sc_time& t ) { t.print( os ); return os; } // ---------------------------------------------------------------------------- // STRUCT : sc_time_params // // Struct that holds the time resolution and default time unit. // ---------------------------------------------------------------------------- struct SC_API sc_time_params { double time_resolution; // in femto seconds bool time_resolution_specified; bool time_resolution_fixed; sc_time::value_type default_time_unit; // in time resolution bool default_time_unit_specified; sc_time_params(); ~sc_time_params(); }; // ---------------------------------------------------------------------------- // functions for accessing the time resolution and default time unit SC_API extern void sc_set_time_resolution( double, sc_time_unit ); SC_API extern sc_time sc_get_time_resolution(); SC_API extern void sc_set_default_time_unit( double, sc_time_unit ); SC_API extern sc_time sc_get_default_time_unit(); } // namespace sc_core #endif // $Log: sc_time.h,v $ // Revision 1.5 2011/08/26 20:46:11 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.4 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.3 2011/02/13 21:47:38 acg // Andy Goodrich: update copyright notice. // // Revision 1.2 2008/05/22 17:06:27 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.4 2006/05/08 18:02:06 acg // Andy Goodrich: added David Long's forward declarations for friend // functions, methods, and operators to keep the Microsoft compiler happy. // // Revision 1.3 2006/01/13 18:44:30 acg // Added $Log to record CVS changes into the source. // Taf! systemc-2.3.3/src/sysc/kernel/sc_runnable_int.h0000644000175000017500000005016713360325173021450 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /******************************************************************************* sc_runnable_int.h -- For inline definitions of some utility functions. DO NOT EXPORT THIS INCLUDE FILE. Include this file after "sc_process_int.h" so that we can get the base class right. Original Author: Bishnupriya Bhattacharya , Cadence Design, 28th July, 2003 CHANGE LOG AT THE END OF THE FILE ******************************************************************************/ #ifndef SC_RUNNABLE_INT_H #define SC_RUNNABLE_INT_H #include "sysc/kernel/sc_runnable.h" #include "sysc/kernel/sc_method_process.h" #include "sysc/kernel/sc_thread_process.h" // DEBUGGING MACROS: // // DEBUG_MSG(NAME,P,MSG) // MSG = message to print // NAME = name that must match the process for the message to print, or // null if the message should be printed unconditionally. // P = pointer to process message is for, or NULL in which case the // message will not print. #if 0 # include # define DEBUG_NAME "" # define DEBUG_MSG(NAME,P,MSG) \ { \ if ( P && ( (std::strlen(NAME)==0) || !std::strcmp(NAME,P->name())) ) \ std::cout << "**** " << sc_time_stamp() << " (" \ << sc_get_current_process_name("** NONE **") << "): " << MSG \ << " - " << P->name() << std::endl; \ } #else # define DEBUG_MSG(NAME,P,MSG) #endif namespace sc_core { // The values below are used to indicate when a queue is empty. A non-zero // non-legal pointer value is used for this so that a zero value in the // m_execute_p field of an sc_process_b instance can be used to indicate // that is has not been queued for run. (If we did not use a non-zero // queue empty indicator then a sc_process_b instance that was queued // twice in a row might end up on the queue twice if it were the first // one that was queued!) #define SC_NO_METHODS ((sc_method_handle)0xdb) #define SC_NO_THREADS ((sc_thread_handle)0xdb) //------------------------------------------------------------------------------ //"sc_runnable::dump" // // This method dumps the contents of this object instance. //------------------------------------------------------------------------------ inline void sc_runnable::dump() const { // Dump the thread queues: std::cout << "thread pop queue: " << std::endl; for ( sc_thread_handle p = m_threads_pop; p != SC_NO_THREADS; p = p->next_runnable() ) { std::cout << " " << p << std::endl; } std::cout << "thread push queue: " << std::endl; for ( sc_thread_handle p = m_threads_push_head->next_runnable(); p != SC_NO_THREADS; p = p->next_runnable() ) { std::cout << " " << p << std::endl; } } //------------------------------------------------------------------------------ //"sc_runnable::execute_method_next" // // This method pushes the the supplied method to execute as the next process. // This is done by pushing it onto the front of the m_methods_pop. // method_h -> method process to add to the queue. //------------------------------------------------------------------------------ inline void sc_runnable::execute_method_next( sc_method_handle method_h ) { DEBUG_MSG(DEBUG_NAME,method_h,"pushing this method to execute next"); method_h->set_next_runnable( m_methods_pop ); m_methods_pop = method_h; } //------------------------------------------------------------------------------ //"sc_runnable::execute_thread_next" // // This method pushes the the supplied thread to execute as the next process. // This is done by pushing it onto the front of the m_threads_pop. // thread_h -> thread process to add to the queue. //------------------------------------------------------------------------------ inline void sc_runnable::execute_thread_next( sc_thread_handle thread_h ) { DEBUG_MSG(DEBUG_NAME,thread_h,"pushing this thread to execute next"); thread_h->set_next_runnable( m_threads_pop ); m_threads_pop = thread_h; } //------------------------------------------------------------------------------ //"sc_runnable::init" // // This method initializes this object instance. Note we allocate the queue // heads if necessary. This is done here rather than in the constructor for // this class to eliminate CTOR processing errors with gcc. //------------------------------------------------------------------------------ inline void sc_runnable::init() { m_methods_pop = SC_NO_METHODS; if ( !m_methods_push_head ) { m_methods_push_head = new sc_method_process("methods_push_head", true, (SC_ENTRY_FUNC)0, 0, 0); m_methods_push_head->dont_initialize(true); m_methods_push_head->detach(); } m_methods_push_tail = m_methods_push_head; m_methods_push_head->set_next_runnable(SC_NO_METHODS); m_threads_pop = SC_NO_THREADS; if ( !m_threads_push_head ) { m_threads_push_head = new sc_thread_process("threads_push_head", true, (SC_ENTRY_FUNC)0, 0, 0); m_threads_push_head->dont_initialize(true); m_threads_push_head->detach(); } m_threads_push_head->set_next_runnable(SC_NO_THREADS); m_threads_push_tail = m_threads_push_head; } //------------------------------------------------------------------------------ //"sc_runnable::is_empty" // // This method returns true if the push queue is empty, or false if not. //------------------------------------------------------------------------------ inline bool sc_runnable::is_empty() const { return m_methods_push_head->next_runnable() == SC_NO_METHODS && m_methods_pop == SC_NO_METHODS && m_threads_push_head->next_runnable() == SC_NO_THREADS && m_threads_pop == SC_NO_THREADS; } //------------------------------------------------------------------------------ //"sc_runnable::is_initialized" // // This method returns true if the push queue is already initialized. //------------------------------------------------------------------------------ inline bool sc_runnable::is_initialized() const { return m_methods_push_head && m_threads_push_head; } //------------------------------------------------------------------------------ //"sc_runnable::push_back_method" // // This method pushes the supplied method process onto the back of the queue of // runnable method processes. // method_h -> method process to add to the queue. //------------------------------------------------------------------------------ inline void sc_runnable::push_back_method( sc_method_handle method_h ) { // sc_assert( method_h->next_runnable() == 0 ); // Can't queue twice. DEBUG_MSG(DEBUG_NAME,method_h,"pushing back method"); method_h->set_next_runnable(SC_NO_METHODS); m_methods_push_tail->set_next_runnable(method_h); m_methods_push_tail = method_h; } //------------------------------------------------------------------------------ //"sc_runnable::push_back_thread" // // This method pushes the supplied thread process onto the back of the queue of // runnable thread processes. // thread_h -> thread process to add to the queue. //------------------------------------------------------------------------------ inline void sc_runnable::push_back_thread( sc_thread_handle thread_h ) { // sc_assert( thread_h->next_runnable() == 0 ); // Can't queue twice. DEBUG_MSG(DEBUG_NAME,thread_h,"pushing back thread"); thread_h->set_next_runnable(SC_NO_THREADS); m_threads_push_tail->set_next_runnable(thread_h); m_threads_push_tail = thread_h; } //------------------------------------------------------------------------------ //"sc_runnable::push_front_method" // // This method pushes the supplied method process onto the front of the queue of // runnable method processes. If the queue is empty the process is the tail // also. // method_h -> method process to add to the queue. //------------------------------------------------------------------------------ inline void sc_runnable::push_front_method( sc_method_handle method_h ) { // sc_assert( method_h->next_runnable() == 0 ); // Can't queue twice. DEBUG_MSG(DEBUG_NAME,method_h,"pushing front method"); method_h->set_next_runnable(m_methods_push_head->next_runnable()); if ( m_methods_push_tail == m_methods_push_head ) // Empty queue. { m_methods_push_tail->set_next_runnable(method_h); m_methods_push_tail = method_h; } else // Non-empty queue. { m_methods_push_head->set_next_runnable(method_h); } } //------------------------------------------------------------------------------ //"sc_runnable::push_front_thread" // // This method pushes the supplied thread process onto the front of the queue of // runnable thread processes. If the queue is empty the process is the tail // also. // thread_h -> thread process to add to the queue. //------------------------------------------------------------------------------ inline void sc_runnable::push_front_thread( sc_thread_handle thread_h ) { // sc_assert( thread_h->next_runnable() == 0 ); // Can't queue twice. DEBUG_MSG(DEBUG_NAME,thread_h,"pushing front thread"); thread_h->set_next_runnable(m_threads_push_head->next_runnable()); if ( m_threads_push_tail == m_threads_push_head ) // Empty queue. { m_threads_push_tail->set_next_runnable(thread_h); m_threads_push_tail = thread_h; } else // Non-empty queue. { m_threads_push_head->set_next_runnable(thread_h); } } //------------------------------------------------------------------------------ //"sc_runnable::pop_method" // // This method pops the next method process to be executed, or returns a null // if no method processes are available for execution. //------------------------------------------------------------------------------ inline sc_method_handle sc_runnable::pop_method() { sc_method_handle result_p; result_p = m_methods_pop; if ( result_p != SC_NO_METHODS ) { m_methods_pop = result_p->next_runnable(); result_p->set_next_runnable(0); } else { result_p = 0; } DEBUG_MSG(DEBUG_NAME,result_p,"popping method"); return result_p; } //------------------------------------------------------------------------------ //"sc_runnable::pop_thread" // // This method pops the next thread process to be executed, or returns a null // if no thread processes are available for execution. //------------------------------------------------------------------------------ inline sc_thread_handle sc_runnable::pop_thread() { sc_thread_handle result_p; result_p = m_threads_pop; if ( result_p != SC_NO_THREADS ) { m_threads_pop = result_p->next_runnable(); result_p->set_next_runnable(0); } else { result_p = 0; } DEBUG_MSG(DEBUG_NAME,result_p,"popping thread for execution"); return result_p; } //------------------------------------------------------------------------------ //"sc_runnable::remove_method" // // This method removes the supplied method process from the push queue if it is // present. Note we clear the method's next pointer so that it may be queued // again. // remove_p -> method process to remove from the run queue. //------------------------------------------------------------------------------ inline void sc_runnable::remove_method( sc_method_handle remove_p ) { sc_method_handle now_p; // Method now checking. sc_method_handle prior_p; // Method prior to now_p. // Don't try to remove things if we have not been initialized. if ( !is_initialized() ) return; // Search the push queue: prior_p = m_methods_push_head; for ( now_p = m_methods_push_head; now_p!= SC_NO_METHODS; now_p = now_p->next_runnable() ) { if ( remove_p == now_p ) { prior_p->set_next_runnable( now_p->next_runnable() ); if (now_p == m_methods_push_tail) { m_methods_push_tail = prior_p; } now_p->set_next_runnable(0); DEBUG_MSG(DEBUG_NAME,now_p,"removing method from push queue"); return; } prior_p = now_p; } // Search the pop queue: prior_p = NULL; for ( now_p = m_methods_pop; now_p != SC_NO_METHODS; now_p = now_p->next_runnable() ) { if ( remove_p == now_p ) { if ( prior_p ) prior_p->set_next_runnable( now_p->next_runnable() ); else m_methods_pop = now_p->next_runnable(); now_p->set_next_runnable(0); DEBUG_MSG(DEBUG_NAME,now_p,"removing method from pop queue"); return; } prior_p = now_p; } } //------------------------------------------------------------------------------ //"sc_runnable::remove_thread" // // This method removes the supplied thread process from the push or pop // queue if it is present. Note we clear the thread's next pointer so that it // may be queued again. // remove_p -> thread process to remove from the run queue. //------------------------------------------------------------------------------ inline void sc_runnable::remove_thread( sc_thread_handle remove_p ) { sc_thread_handle now_p; // Thread now checking. sc_thread_handle prior_p; // Thread prior to now_p. // Don't try to remove things if we have not been initialized. if ( !is_initialized() ) return; // Search the push queue: prior_p = m_threads_push_head; for ( now_p = m_threads_push_head; now_p != SC_NO_THREADS; now_p = now_p->next_runnable() ) { if ( remove_p == now_p ) { prior_p->set_next_runnable( now_p->next_runnable() ); if (now_p == m_threads_push_tail) { m_threads_push_tail = prior_p; } now_p->set_next_runnable(0); DEBUG_MSG(DEBUG_NAME,now_p,"removing thread from push queue"); return; } prior_p = now_p; } // Search the pop queue: prior_p = NULL; for ( now_p = m_threads_pop; now_p != SC_NO_THREADS; now_p = now_p->next_runnable() ) { if ( remove_p == now_p ) { if ( prior_p ) prior_p->set_next_runnable( now_p->next_runnable() ); else m_threads_pop = now_p->next_runnable(); now_p->set_next_runnable(0); DEBUG_MSG(DEBUG_NAME,now_p,"removing thread from pop queue"); return; } prior_p = now_p; } } //------------------------------------------------------------------------------ //"sc_runnable::sc_runnable" // // This is the object instance constructor for this class. //------------------------------------------------------------------------------ inline sc_runnable::sc_runnable() : m_methods_push_head(0), m_methods_push_tail(0), m_methods_pop(SC_NO_METHODS), m_threads_push_head(0), m_threads_push_tail(0), m_threads_pop(SC_NO_THREADS) {} //------------------------------------------------------------------------------ //"sc_runnable::~sc_runnable" // // This is the object instance destructor for this class. //------------------------------------------------------------------------------ inline sc_runnable::~sc_runnable() { delete m_methods_push_head; delete m_threads_push_head; } //------------------------------------------------------------------------------ //"sc_runnable::toggle_methods" // // This method moves the methods push queue to the pop queue and zeros the push // queue. This will only be done if the pop queue is presently empty. //------------------------------------------------------------------------------ inline void sc_runnable::toggle_methods() { if ( m_methods_pop == SC_NO_METHODS ) { m_methods_pop = m_methods_push_head->next_runnable(); m_methods_push_head->set_next_runnable(SC_NO_METHODS); m_methods_push_tail = m_methods_push_head; } } //------------------------------------------------------------------------------ //"sc_runnable::toggle_threads" // // This method moves the threads push queue to the pop queue and zeros the push // queue. This will only be done if the pop queue is presently empty. //------------------------------------------------------------------------------ inline void sc_runnable::toggle_threads() { if ( m_threads_pop == SC_NO_THREADS ) { m_threads_pop = m_threads_push_head->next_runnable(); m_threads_push_head->set_next_runnable(SC_NO_THREADS); m_threads_push_tail = m_threads_push_head; } } #undef SC_NO_METHODS #undef SC_NO_THREADS #undef DEBUG_MSG } // namespace sc_core /******************************************************************************* MODIFICATION LOG - modifiers, enter your name, affiliation, date and changes you are making here. Andy Goodrich, Forte Design Systems, 2 September 2003 Changed queue heads to instances to eliminate the checks for null heads. ******************************************************************************/ // $Log: sc_runnable_int.h,v $ // Revision 1.19 2011/08/24 22:05:51 acg // Torsten Maehne: initialization changes to remove warnings. // // Revision 1.18 2011/08/07 19:08:04 acg // Andy Goodrich: moved logs to end of file so line number synching works // better between versions. // // Revision 1.17 2011/04/13 02:45:11 acg // Andy Goodrich: eliminated warning message that occurred if the DEBUG_MSG // macro was used. // // Revision 1.16 2011/04/10 22:18:23 acg // Andy Goodrich: debugging message clean up. // // Revision 1.15 2011/04/08 18:26:07 acg // Andy Goodrich: added execute_method_next() to handle method dispatch // for asynchronous notifications that occur outside the evaluation phase. // // Revision 1.14 2011/04/01 21:31:10 acg // Andy Goodrich: turn off diagnostic messages by default. // // Revision 1.13 2011/04/01 21:30:02 acg // Andy Goodrich: inserted conditional displays for queue manipulations. // // Revision 1.12 2011/03/30 00:01:34 acg // Philip A. Hartmann: change break to return in remove_method() to short // circuit the search the way remove_thread() works. // // Revision 1.11 2011/03/28 13:02:52 acg // Andy Goodrich: Changes for disable() interactions. // // Revision 1.10 2011/03/06 15:58:17 acg // Andy Goodrich: formatting changes. // // Revision 1.9 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.8 2011/02/13 21:47:38 acg // Andy Goodrich: update copyright notice. // // Revision 1.7 2011/02/02 06:37:03 acg // Andy Goodrich: removed toggle() method since it is no longer used. // // Revision 1.6 2011/02/01 21:09:13 acg // Andy Goodrich: addition of toggle_methods() and toggle_threads() calls. // // Revision 1.5 2011/01/25 20:50:37 acg // Andy Goodrich: changes for IEEE 1666 2011. // // Revision 1.4 2010/07/22 20:02:33 acg // Andy Goodrich: bug fixes. // // Revision 1.3 2009/02/28 00:26:58 acg // Andy Goodrich: changed boost name space to sc_boost to allow use with // full boost library applications. // // Revision 1.2 2008/05/22 17:06:26 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.4 2006/04/20 17:08:17 acg // Andy Goodrich: 3.0 style process changes. // // Revision 1.3 2006/01/13 18:44:30 acg // Added $Log to record CVS changes into the source. // #endif // SC_RUNNABLE_INT_H // Taf! systemc-2.3.3/src/sysc/kernel/sc_phase_callback_registry.cpp0000644000175000017500000002046013360325173024160 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_phase_callback_registry.cpp -- Implementation of phase callback registry Original Author: Philipp A. Hartmann, OFFIS, 2013-02-15 CHANGE LOG AT END OF FILE *****************************************************************************/ #include "sysc/kernel/sc_object.h" #include "sysc/kernel/sc_phase_callback_registry.h" #include "sysc/kernel/sc_kernel_ids.h" #include "sysc/utils/sc_report.h" #include #include #include namespace sc_core { #if SC_HAS_PHASE_CALLBACKS_ sc_phase_callback_registry::sc_phase_callback_registry( sc_simcontext& simc ) : m_simc( &simc ) #if 0 , m_cb_eval_vec() #endif , m_cb_update_vec() , m_cb_timestep_vec() {} sc_phase_callback_registry::~sc_phase_callback_registry() {} static const sc_phase_callback_registry::mask_type SC_PHASE_CALLBACK_MASK = SC_STATUS_ANY; namespace /* anonymous */ { struct entry_match { explicit entry_match( sc_phase_callback_registry::cb_type* ref ) : ref_(ref) {} bool operator()( const sc_phase_callback_registry::entry& e ) const { return e.target == ref_; } private: sc_phase_callback_registry::cb_type * ref_; }; // entry_match template< typename T > inline void erase_remove( std::vector* vec, T const& t ) { vec->erase( std::remove( vec->begin(), vec->end(), t ) ); } } // namespace anonymous sc_phase_callback_registry::mask_type sc_phase_callback_registry::validate_mask( cb_type& cb , mask_type m , bool warn = false ) { if( SC_UNLIKELY_(m & ~SC_PHASE_CALLBACK_MASK) ) { if( warn ) { std::stringstream ss; ss << cb.name() << ": invalid phase callback mask: " << (sc_status)m; SC_REPORT_WARNING( SC_ID_PHASE_CALLBACK_REGISTER_ , ss.str().c_str() ); } m &= SC_PHASE_CALLBACK_MASK; } mask_type check_mask; // elaboration callbacks check_mask = ( SC_ELABORATION | SC_BEFORE_END_OF_ELABORATION | SC_END_OF_ELABORATION ); if( SC_UNLIKELY_( (m & check_mask ) && m_simc->elaboration_done() ) ) { if( warn ) { std::stringstream ss; ss << cb.name() << ": elaboration done\n\t " << (sc_status)( m & check_mask ) << " callback(s) ignored"; SC_REPORT_WARNING(SC_ID_PHASE_CALLBACK_REGISTER_ , ss.str().c_str() ); } m &= ~check_mask; } check_mask = (SC_BEFORE_END_OF_ELABORATION | SC_END_OF_ELABORATION); if( SC_UNLIKELY_(m & SC_ELABORATION) ) { if( warn ) { std::stringstream ss; ss << cb.name() << ": " << SC_ELABORATION << ":\n\t substituted by " << (sc_status)(check_mask); SC_REPORT_WARNING( SC_ID_PHASE_CALLBACK_REGISTER_ , ss.str().c_str() ); } m &= ~SC_ELABORATION; m |= check_mask; } check_mask = ( SC_END_OF_INITIALIZATION #if 0 | SC_END_OF_EVALUATION #endif | SC_END_OF_UPDATE | SC_BEFORE_TIMESTEP ); if( SC_UNLIKELY_(m & SC_RUNNING) ) { if( warn ) { std::stringstream ss; ss << cb.name() << ": " << SC_RUNNING << ":\n\t substituted by " << (sc_status)(check_mask); SC_REPORT_WARNING( SC_ID_PHASE_CALLBACK_REGISTER_ , ss.str().c_str() ); } m &= ~SC_RUNNING; m |= check_mask; } return m; } sc_phase_callback_registry::mask_type sc_phase_callback_registry::register_callback( cb_type& cb, mask_type m ) { storage_type::iterator it = find_if( m_cb_vec.begin(), m_cb_vec.end(), entry_match(&cb) ); m = validate_mask(cb, m, /* warn */ true ); mask_type diff_mask = m; mask_type new_mask = m; if( it != m_cb_vec.end() ) // update existing entry { // update masks new_mask = (*it).mask | m; diff_mask = ~(*it).mask & m; (*it).mask = new_mask; } else // new entry { if( !m ) // empty, do nothing return SC_UNITIALIZED; entry new_entry = { &cb, new_mask }; m_cb_vec.push_back( new_entry ); } // add to callback shortcut sets #if 0 if( diff_mask & SC_END_OF_EVALUATION ) m_cb_eval_vec.push_back( &cb ); #endif if( diff_mask & SC_END_OF_UPDATE ) m_cb_update_vec.push_back( &cb ); if( diff_mask & SC_BEFORE_TIMESTEP ) m_cb_timestep_vec.push_back( &cb ); return new_mask; } sc_phase_callback_registry::mask_type sc_phase_callback_registry::unregister_callback( cb_type& cb, mask_type m ) { storage_type::iterator it = find_if( m_cb_vec.begin(), m_cb_vec.end(), entry_match(&cb) ); m = validate_mask(cb, m); mask_type diff_mask = m; mask_type new_mask = m; if( it == m_cb_vec.end() ) { // not registered return SC_UNITIALIZED; } // update masks new_mask = (*it).mask & ~m; diff_mask = (*it).mask & m; (*it).mask = new_mask; if( !new_mask ) m_cb_vec.erase(it); // drop from callback shortcut sets #if 0 if( diff_mask & SC_END_OF_EVALUATION ) erase_remove( &m_cb_eval_vec, &cb ); #endif if( diff_mask & SC_END_OF_UPDATE ) erase_remove( &m_cb_update_vec, &cb ); if( diff_mask & SC_BEFORE_TIMESTEP ) erase_remove( &m_cb_timestep_vec, &cb ); return new_mask; } // generic implementation (for non-critical callbacks) // - also restores hierarchy around callback object void sc_phase_callback_registry::do_callback( sc_status s ) const { typedef storage_type::const_iterator it_type; storage_type const & vec = m_cb_vec; for(it_type it = vec.begin(), end = vec.end(); it != end; ++it) { if( s & it->mask ) { sc_object::hierarchy_scope scope(it->target); it->target->do_simulation_phase_callback(); } } } #else // ! SC_HAS_PHASE_CALLBACKS_ sc_phase_callback_registry::sc_phase_callback_registry( sc_simcontext& ){} sc_phase_callback_registry::~sc_phase_callback_registry(){} static inline void warn_phase_callbacks( sc_core::sc_object const& obj ) { static bool warned = false; if (!warned) { std::stringstream ss; ss << obj.name() << ".\n" << "Please recompile SystemC with " "\"SC_ENABLE_SIMULATION_PHASE_CALLBACKS\" defined."; SC_REPORT_WARNING( SC_ID_PHASE_CALLBACKS_UNSUPPORTED_ , ss.str().c_str() ); } } sc_phase_callback_registry::mask_type sc_phase_callback_registry::register_callback( cb_type& cb, mask_type ) { warn_phase_callbacks( cb ); return SC_UNITIALIZED; } sc_phase_callback_registry::mask_type sc_phase_callback_registry::unregister_callback( cb_type& cb, mask_type ) { warn_phase_callbacks( cb ); return SC_UNITIALIZED; } #endif // ! SC_HAS_PHASE_CALLBACKS_ } // namespace sc_core /***************************************************************************** MODIFICATION LOG - modifiers, enter your name, affiliation, date and changes you are making here. Name, Affiliation, Date: Description of Modification: *****************************************************************************/ // Taf! systemc-2.3.3/src/sysc/kernel/sc_reset.cpp0000644000175000017500000003563013360325173020443 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_reset.cpp -- Support for reset. Original Author: Andy Goodrich, Forte Design Systems CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #include "sysc/kernel/sc_simcontext.h" #include "sysc/kernel/sc_reset.h" #include "sysc/kernel/sc_process_handle.h" #include "sysc/communication/sc_signal.h" #include "sysc/communication/sc_signal_ports.h" // THE SYSTEMC PROOF OF CONCEPT SIMULATOR RESET SIGNAL IMPLEMENTATION: // // (1) An instance of the sc_reset class is attached to each sc_signal // that is used as a reset signal. // // (2) Each process that is senstive to a reset signal will be registered in the // sc_reset class attached to that reset signal. // // (3) When a change in the value of a reset signal occurs it invokes the // notify_processes() method of its sc_reset object instance. The // notify_processes() method will call the reset_changed() method of each // process that is registered with it to inform the process that // state of the reset signal has changed. // // (4) A process may have multiple reset signals, so counters are kept for the // number of active asynchronous, and synchronous, reset signals that are // active. Those counters are incremented and decremented in the process' // reset_changed() method. // // (5) When a process' semantics() method is called the current reset state is // checked, and a reset sequence is initiated if the process is in reset. // This will occur every time an SC_METHOD is dispatched. SC_CTHREAD and // and SC_THREAD instances, only go through the semantics() method they // initially start up. So the reset check is duplicated in the suspend_me() // method, the tail of which will execute each time the thread is // dispatched. namespace sc_core { inline sc_reset_finder::sc_reset_finder( bool async, const sc_in* port_p, bool level, sc_process_b* target_p) : m_async(async), m_level(level), m_next_p(0), m_in_p(port_p), m_inout_p(0), m_out_p(0), m_target_p(target_p) { sc_get_curr_simcontext()->add_reset_finder(this); } inline sc_reset_finder::sc_reset_finder( bool async, const sc_inout* port_p, bool level, sc_process_b* target_p ) : m_async(async), m_level(level), m_next_p(0), m_in_p(0), m_inout_p(port_p), m_out_p(0), m_target_p(target_p) { sc_get_curr_simcontext()->add_reset_finder(this); } inline sc_reset_finder::sc_reset_finder( bool async, const sc_out* port_p, bool level, sc_process_b* target_p ) : m_async(async), m_level(level), m_next_p(0), m_in_p(0), m_inout_p(0), m_out_p(port_p), m_target_p(target_p) { sc_get_curr_simcontext()->add_reset_finder(this); } //------------------------------------------------------------------------------ //"sc_reset::notify_processes" // // Notify processes that there is a change in the reset signal value. //------------------------------------------------------------------------------ void sc_reset::notify_processes() { bool active; // true if reset is active. sc_reset_target* entry_p; // reset entry processing. std::vector::size_type process_i; // index of process resetting. std::vector::size_type process_n; // # of processes to reset. bool value; // value of our signal. value = m_iface_p->read(); process_n = m_targets.size(); for ( process_i = 0; process_i < process_n; process_i++ ) { entry_p = &m_targets[process_i]; active = ( entry_p->m_level == value ); entry_p->m_process_p->reset_changed( entry_p->m_async, active ); } } //------------------------------------------------------------------------------ //"sc_reset::reconcile_resets" // // This static method processes the sc_reset_finders to establish the actual // reset connections. // // Notes: // (1) If reset is asserted we tell the process that it is in reset. //------------------------------------------------------------------------------ void sc_reset::reconcile_resets(sc_reset_finder* reset_finder_q) { const sc_signal_in_if* iface_p; // Interface to reset signal. sc_reset_finder* next_p; // Next finder to process. sc_reset_finder* now_p; // Finder currently processing. sc_reset_target reset_target; // Target's reset entry. sc_reset* reset_p; // Reset object to use. for ( now_p = reset_finder_q; now_p; now_p = next_p ) { next_p = now_p->m_next_p; if ( now_p->m_in_p ) { iface_p = dynamic_cast*>( now_p->m_in_p->get_interface()); } else if ( now_p->m_inout_p ) { iface_p = dynamic_cast*>( now_p->m_inout_p->get_interface()); } else { iface_p = dynamic_cast*>( now_p->m_out_p->get_interface()); } sc_assert( iface_p != 0 ); reset_p = iface_p->is_reset(); now_p->m_target_p->m_resets.push_back(reset_p); reset_target.m_async = now_p->m_async; reset_target.m_level = now_p->m_level; reset_target.m_process_p = now_p->m_target_p; reset_p->m_targets.push_back(reset_target); if ( iface_p->read() == now_p->m_level ) // see note 1 above now_p->m_target_p->initially_in_reset( now_p->m_async ); delete now_p; } } //------------------------------------------------------------------------------ //"sc_reset::remove_process" // // This method removes the supplied process from the list of processes that // should be notified when there is a change in the value of the reset signal. // // Arguments: // process_p -> process to be removed. //------------------------------------------------------------------------------ void sc_reset::remove_process( sc_process_b* process_p ) { int process_i; // Index of process resetting. int process_n; // # of processes to reset. process_n = m_targets.size(); for ( process_i = 0; process_i < process_n; ) { if ( m_targets[process_i].m_process_p == process_p ) { m_targets[process_i] = m_targets[process_n-1]; process_n--; m_targets.resize(process_n); } else { process_i++; } } } //------------------------------------------------------------------------------ //"sc_reset::reset_signal_is - ports" // // These overloads of the reset_signal_is() method will register the active // process with the sc_reset object instance associated with the supplied port. // If the port does not yet have a pointer to its sc_signal instance it // will create an sc_reset_finder class object instance that will be used // to set the process' reset information when the port has been bound. // // Arguments: // async = true if the reset signal is asynchronous, false if not. // port = port for sc_signal that will provide the reset signal. // level = level at which reset is active, either true or false. //------------------------------------------------------------------------------ void sc_reset::reset_signal_is( bool async, const sc_in& port, bool level) { const sc_signal_in_if* iface_p; sc_process_b* process_p; process_p = (sc_process_b*)sc_get_current_process_handle(); sc_assert( process_p ); process_p->m_has_reset_signal = true; switch ( process_p->proc_kind() ) { case SC_THREAD_PROC_: case SC_METHOD_PROC_: case SC_CTHREAD_PROC_: iface_p = dynamic_cast*>(port.get_interface()); if ( iface_p ) reset_signal_is( async, *iface_p, level ); else new sc_reset_finder( async, &port, level, process_p ); break; default: SC_REPORT_ERROR(SC_ID_UNKNOWN_PROCESS_TYPE_, process_p->name()); break; } } void sc_reset::reset_signal_is( bool async, const sc_inout& port, bool level ) { const sc_signal_in_if* iface_p; sc_process_b* process_p; process_p = (sc_process_b*)sc_get_current_process_handle(); sc_assert( process_p ); process_p->m_has_reset_signal = true; switch ( process_p->proc_kind() ) { case SC_THREAD_PROC_: case SC_METHOD_PROC_: case SC_CTHREAD_PROC_: iface_p = dynamic_cast*>(port.get_interface()); if ( iface_p ) reset_signal_is( async, *iface_p, level ); else new sc_reset_finder( async, &port, level, process_p ); break; default: SC_REPORT_ERROR(SC_ID_UNKNOWN_PROCESS_TYPE_, process_p->name()); break; } } void sc_reset::reset_signal_is( bool async, const sc_out& port, bool level ) { const sc_signal_in_if* iface_p; sc_process_b* process_p; process_p = (sc_process_b*)sc_get_current_process_handle(); sc_assert( process_p ); process_p->m_has_reset_signal = true; switch ( process_p->proc_kind() ) { case SC_THREAD_PROC_: case SC_METHOD_PROC_: case SC_CTHREAD_PROC_: iface_p = dynamic_cast*>(port.get_interface()); if ( iface_p ) reset_signal_is( async, *iface_p, level ); else new sc_reset_finder( async, &port, level, process_p ); break; default: SC_REPORT_ERROR(SC_ID_UNKNOWN_PROCESS_TYPE_, process_p->name()); break; } } //------------------------------------------------------------------------------ //"sc_reset::reset_signal_is" // // This static method will register the active process instance as being // reset by the sc_signal whose interface has been supplied. If no // sc_reset object instance has been attached to the sc_signal yet, it // will be created and attached. The active process instance is pushed into // the list of processes that the sc_reset object instance should notify if // the value of the reset signal changes. // // Arguments: // async = true if the reset signal is asynchronous, false if not. // iface = interface for the reset signal. // level = is the level at which reset is active, either true or false. // Notes: // (1) If reset is asserted we tell the process that it is in reset // initially. //------------------------------------------------------------------------------ void sc_reset::reset_signal_is( bool async, const sc_signal_in_if& iface, bool level ) { sc_process_b* process_p; // process adding reset for. sc_reset_target reset_target; // entry to build for the process. sc_reset* reset_p; // reset object. process_p = sc_process_b::last_created_process_base(); sc_assert( process_p ); process_p->m_has_reset_signal = true; switch ( process_p->proc_kind() ) { case SC_METHOD_PROC_: case SC_CTHREAD_PROC_: case SC_THREAD_PROC_: reset_p = iface.is_reset(); process_p->m_resets.push_back(reset_p); reset_target.m_async = async; reset_target.m_level = level; reset_target.m_process_p = process_p; reset_p->m_targets.push_back(reset_target); if ( iface.read() == level ) process_p->initially_in_reset( async ); break; default: SC_REPORT_ERROR(SC_ID_UNKNOWN_PROCESS_TYPE_, process_p->name()); break; } } } // namespace sc_core // $Log: sc_reset.cpp,v $ // Revision 1.16 2011/08/26 20:46:10 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.15 2011/08/24 22:05:51 acg // Torsten Maehne: initialization changes to remove warnings. // // Revision 1.14 2011/04/08 22:37:34 acg // Andy Goodrich: documentation of the reset mechanism and additional // documentation of methods. Removal of check for SC_METHODs in // sc_reset_signal_is() that should not have been there. // // Revision 1.13 2011/03/20 15:13:01 acg // Andy Goodrich: set the reset flag for async_reset_signal_is to catch // the suspend() corner case. // // Revision 1.12 2011/03/20 13:43:23 acg // Andy Goodrich: added async_signal_is() plus suspend() as a corner case. // // Revision 1.11 2011/03/06 19:57:11 acg // Andy Goodrich: refinements for the illegal suspend - synchronous reset // interaction. // // Revision 1.10 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.9 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.8 2011/02/01 21:08:26 acg // Andy Goodrich: new multiple reset support. // // Revision 1.7 2011/01/06 18:04:38 acg // Andy Goodrich: removed commented out code. // // Revision 1.6 2010/12/07 20:09:13 acg // Andy Goodrich: removed sc_signal overloads since already have sc_signal_in_if overloads. // // Revision 1.5 2010/11/20 17:10:56 acg // Andy Goodrich: reset processing changes for new IEEE 1666 standard. // // Revision 1.4 2009/05/22 16:06:29 acg // Andy Goodrich: process control updates. // // Revision 1.3 2009/03/12 22:59:58 acg // Andy Goodrich: updates for 2.4 stuff. // // Revision 1.2 2008/05/22 17:06:26 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.7 2006/12/02 20:58:19 acg // Andy Goodrich: updates from 2.2 for IEEE 1666 support. // // Revision 1.5 2006/04/11 23:13:21 acg // Andy Goodrich: Changes for reduced reset support that only includes // sc_cthread, but has preliminary hooks for expanding to method and thread // processes also. // // Revision 1.4 2006/01/24 20:49:05 acg // Andy Goodrich: changes to remove the use of deprecated features within the // simulator, and to issue warning messages when deprecated features are used. // // Revision 1.3 2006/01/13 18:44:30 acg // Added $Log to record CVS changes into the source. // systemc-2.3.3/src/sysc/kernel/sc_module.h0000644000175000017500000005354513360325173020260 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_module.h -- Base class of all hierarchical modules and channels. Original Author: Stan Y. Liao, Synopsys, Inc. Martin Janssen, Synopsys, Inc. CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #ifndef SC_MODULE_H #define SC_MODULE_H #include "sysc/kernel/sc_kernel_ids.h" #include "sysc/kernel/sc_process.h" #include "sysc/kernel/sc_module_name.h" #include "sysc/kernel/sc_sensitive.h" #include "sysc/kernel/sc_time.h" #include "sysc/kernel/sc_wait.h" #include "sysc/kernel/sc_wait_cthread.h" #include "sysc/kernel/sc_process.h" #include "sysc/kernel/sc_process_handle.h" #include "sysc/utils/sc_list.h" namespace sc_core { class sc_name_gen; template class sc_in; template class sc_inout; template class sc_out; // ---------------------------------------------------------------------------- // STRUCT : sc_bind_proxy // // Struct for temporarily storing a pointer to an interface or port. // Used for positional binding. // ---------------------------------------------------------------------------- struct SC_API sc_bind_proxy { sc_interface* iface; sc_port_base* port; sc_bind_proxy(); sc_bind_proxy( sc_interface& ); sc_bind_proxy( sc_port_base& ); }; extern SC_API const sc_bind_proxy SC_BIND_PROXY_NIL; // ---------------------------------------------------------------------------- // CLASS : sc_module // // Base class for all structural entities. // ---------------------------------------------------------------------------- class SC_API sc_module : public sc_object, public sc_process_host { friend class sc_module_name; friend class sc_module_registry; friend class sc_object; friend class sc_port_registry; friend class sc_process_b; friend class sc_simcontext; public: sc_simcontext* sc_get_curr_simcontext() { return simcontext(); } // to generate unique names for objects in an MT-Safe way const char* gen_unique_name( const char* basename_, bool preserve_first ); virtual const char* kind() const { return "sc_module"; } protected: // called by construction_done virtual void before_end_of_elaboration(); void construction_done(); // called by elaboration_done (does nothing by default) virtual void end_of_elaboration(); void elaboration_done( bool& ); // called by start_simulation (does nothing by default) virtual void start_of_simulation(); void start_simulation(); // called by simulation_done (does nothing by default) virtual void end_of_simulation(); void simulation_done(); void sc_module_init(); // constructor sc_module(); sc_module( const sc_module_name& nm ); /* for those used to old style */ /* DEPRECATED */ sc_module( const char* nm ); /* DEPRECATED */ sc_module( const std::string& nm ); public: // destructor virtual ~sc_module(); // positional binding methods sc_module& operator << ( sc_interface& ); sc_module& operator << ( sc_port_base& ); sc_module& operator , ( sc_interface& interface_ ) { return operator << ( interface_ ); } sc_module& operator , ( sc_port_base& port_ ) { return operator << ( port_ ); } // operator() is declared at the end of the class. const ::std::vector& get_child_objects() const; protected: // this must be called by user-defined modules void end_module(); // to prevent initialization for SC_METHODs and SC_THREADs void dont_initialize(); // positional binding code - used by operator () void positional_bind( sc_interface& ); void positional_bind( sc_port_base& ); // set reset sensitivity for SC_xTHREADs void async_reset_signal_is( const sc_in& port, bool level ); void async_reset_signal_is( const sc_inout& port, bool level ); void async_reset_signal_is( const sc_out& port, bool level ); void async_reset_signal_is( const sc_signal_in_if& iface, bool level); void reset_signal_is( const sc_in& port, bool level ); void reset_signal_is( const sc_inout& port, bool level ); void reset_signal_is( const sc_out& port, bool level ); void reset_signal_is( const sc_signal_in_if& iface, bool level ); // static sensitivity for SC_THREADs and SC_CTHREADs void wait() { ::sc_core::wait( simcontext() ); } // dynamic sensitivity for SC_THREADs and SC_CTHREADs void wait( const sc_event& e ) { ::sc_core::wait( e, simcontext() ); } void wait( const sc_event_or_list& el ) { ::sc_core::wait( el, simcontext() ); } void wait( const sc_event_and_list& el ) { ::sc_core::wait( el, simcontext() ); } void wait( const sc_time& t ) { ::sc_core::wait( t, simcontext() ); } void wait( double v, sc_time_unit tu ) { ::sc_core::wait( sc_time( v, tu, simcontext() ), simcontext() ); } void wait( const sc_time& t, const sc_event& e ) { ::sc_core::wait( t, e, simcontext() ); } void wait( double v, sc_time_unit tu, const sc_event& e ) { ::sc_core::wait( sc_time( v, tu, simcontext() ), e, simcontext() ); } void wait( const sc_time& t, const sc_event_or_list& el ) { ::sc_core::wait( t, el, simcontext() ); } void wait( double v, sc_time_unit tu, const sc_event_or_list& el ) { ::sc_core::wait( sc_time( v, tu, simcontext() ), el, simcontext() ); } void wait( const sc_time& t, const sc_event_and_list& el ) { ::sc_core::wait( t, el, simcontext() ); } void wait( double v, sc_time_unit tu, const sc_event_and_list& el ) { ::sc_core::wait( sc_time( v, tu, simcontext() ), el, simcontext() ); } // static sensitivity for SC_METHODs void next_trigger() { ::sc_core::next_trigger( simcontext() ); } // dynamic sensitivty for SC_METHODs void next_trigger( const sc_event& e ) { ::sc_core::next_trigger( e, simcontext() ); } void next_trigger( const sc_event_or_list& el ) { ::sc_core::next_trigger( el, simcontext() ); } void next_trigger( const sc_event_and_list& el ) { ::sc_core::next_trigger( el, simcontext() ); } void next_trigger( const sc_time& t ) { ::sc_core::next_trigger( t, simcontext() ); } void next_trigger( double v, sc_time_unit tu ) { ::sc_core::next_trigger( sc_time( v, tu, simcontext() ), simcontext() ); } void next_trigger( const sc_time& t, const sc_event& e ) { ::sc_core::next_trigger( t, e, simcontext() ); } void next_trigger( double v, sc_time_unit tu, const sc_event& e ) { ::sc_core::next_trigger( sc_time( v, tu, simcontext() ), e, simcontext() ); } void next_trigger( const sc_time& t, const sc_event_or_list& el ) { ::sc_core::next_trigger( t, el, simcontext() ); } void next_trigger( double v, sc_time_unit tu, const sc_event_or_list& el ) { ::sc_core::next_trigger( sc_time( v, tu, simcontext() ), el, simcontext() ); } void next_trigger( const sc_time& t, const sc_event_and_list& el ) { ::sc_core::next_trigger( t, el, simcontext() ); } void next_trigger( double v, sc_time_unit tu, const sc_event_and_list& el ) { ::sc_core::next_trigger( sc_time( v, tu, simcontext() ), el, simcontext() ); } // for SC_METHODs and SC_THREADs and SC_CTHREADs bool timed_out() { return ::sc_core::timed_out(); } // for SC_CTHREADs void halt() { ::sc_core::halt( simcontext() ); } void wait( int n ) { ::sc_core::wait( n, simcontext() ); } void at_posedge( const sc_signal_in_if& s ) { ::sc_core::at_posedge( s, simcontext() ); } void at_posedge( const sc_signal_in_if& s ) { ::sc_core::at_posedge( s, simcontext() ); } void at_negedge( const sc_signal_in_if& s ) { ::sc_core::at_negedge( s, simcontext() ); } void at_negedge( const sc_signal_in_if& s ) { ::sc_core::at_negedge( s, simcontext() ); } // Catch uses of watching: void watching( bool /* expr */ ) { SC_REPORT_ERROR(SC_ID_WATCHING_NOT_ALLOWED_,""); } // These are protected so that user derived classes can refer to them. sc_sensitive sensitive; sc_sensitive_pos sensitive_pos; sc_sensitive_neg sensitive_neg; // Function to set the stack size of the current (c)thread process. void set_stack_size( std::size_t ); int append_port( sc_port_base* ); private: sc_module( const sc_module& ); const sc_module& operator = ( const sc_module& ); private: bool m_end_module_called; std::vector* m_port_vec; int m_port_index; sc_name_gen* m_name_gen; sc_module_name* m_module_name_p; public: void defunct() { } // positional binding methods (cont'd) void operator () ( const sc_bind_proxy& p001, const sc_bind_proxy& p002 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p003 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p004 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p005 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p006 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p007 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p008 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p009 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p010 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p011 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p012 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p013 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p014 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p015 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p016 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p017 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p018 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p019 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p020 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p021 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p022 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p023 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p024 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p025 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p026 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p027 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p028 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p029 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p030 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p031 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p032 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p033 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p034 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p035 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p036 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p037 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p038 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p039 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p040 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p041 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p042 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p043 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p044 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p045 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p046 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p047 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p048 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p049 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p050 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p051 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p052 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p053 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p054 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p055 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p056 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p057 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p058 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p059 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p060 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p061 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p062 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p063 = SC_BIND_PROXY_NIL, const sc_bind_proxy& p064 = SC_BIND_PROXY_NIL ); }; extern SC_API sc_module* sc_module_dynalloc(sc_module*); #define SC_NEW(x) ::sc_core::sc_module_dynalloc(new x); // ----------------------------------------------------------------------------- // SOME MACROS TO SIMPLIFY SYNTAX: // ----------------------------------------------------------------------------- #define SC_MODULE(user_module_name) \ struct user_module_name : ::sc_core::sc_module #define SC_CTOR(user_module_name) \ typedef user_module_name SC_CURRENT_USER_MODULE; \ user_module_name( ::sc_core::sc_module_name ) // the SC_HAS_PROCESS macro call must be followed by a ; #define SC_HAS_PROCESS(user_module_name) \ typedef user_module_name SC_CURRENT_USER_MODULE // The this-> construct on sensitive operators in the macros below is // required for gcc 4.x when a templated class has a templated parent that is // derived from sc_module: // // template // class B : public sc_module; // template // class A : public B #define declare_method_process(handle, name, host_tag, func) \ { \ ::sc_core::sc_process_handle handle = \ sc_core::sc_get_curr_simcontext()->create_method_process( \ name, false, SC_MAKE_FUNC_PTR( host_tag, func ), \ this, 0 ); \ this->sensitive << handle; \ this->sensitive_pos << handle; \ this->sensitive_neg << handle; \ } #define declare_thread_process(handle, name, host_tag, func) \ { \ ::sc_core::sc_process_handle handle = \ sc_core::sc_get_curr_simcontext()->create_thread_process( \ name, false, \ SC_MAKE_FUNC_PTR( host_tag, func ), this, 0 ); \ this->sensitive << handle; \ this->sensitive_pos << handle; \ this->sensitive_neg << handle; \ } #define declare_cthread_process(handle, name, host_tag, func, edge) \ { \ ::sc_core::sc_process_handle handle = \ sc_core::sc_get_curr_simcontext()->create_cthread_process( \ name, false, \ SC_MAKE_FUNC_PTR( host_tag, func ), this, 0 ); \ this->sensitive.operator() ( handle, edge );\ } #define SC_CTHREAD(func, edge) \ declare_cthread_process( func ## _handle, \ #func, \ SC_CURRENT_USER_MODULE, \ func, \ edge ) #define SC_METHOD(func) \ declare_method_process( func ## _handle, \ #func, \ SC_CURRENT_USER_MODULE, \ func ) #define SC_THREAD(func) \ declare_thread_process( func ## _handle, \ #func, \ SC_CURRENT_USER_MODULE, \ func ) // ---------------------------------------------------------------------------- // TYPEDEFS // ---------------------------------------------------------------------------- typedef sc_module sc_channel; typedef sc_module sc_behavior; } // namespace sc_core /***************************************************************************** MODIFICATION LOG - modifiers, enter your name, affiliation, date and changes you are making here. Name, Affiliation, Date: Ali Dasdan, Synopsys, Inc. Description of Modification: - Implementation of operator() and operator, positional connection method. - Implementation of error checking in operator<<'s. - Implementation of the function test_module_prm. - Implementation of set_stack_size(). Name, Affiliation, Date: Gene Bushuyev, Synopsys, Inc. Description of Modification: - Change implementation for VC6. Name, Affiliation, Date: Andy Godorich, Forte Bishnupriya Bhattacharya, Cadence Design Systems, 25 August, 2003 Description of Modification: inherit from sc_process_host as a part of implementing dynamic processes *****************************************************************************/ // $Log: sc_module.h,v $ // Revision 1.11 2011/08/26 20:46:10 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.10 2011/08/15 16:43:24 acg // Torsten Maehne: changes to remove unused argument warnings. // // Revision 1.9 2011/03/05 19:44:20 acg // Andy Goodrich: changes for object and event naming and structures. // // Revision 1.8 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.7 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.6 2011/01/18 20:10:44 acg // Andy Goodrich: changes for IEEE1666_2011 semantics. // // Revision 1.5 2010/12/07 20:09:12 acg // Andy Goodrich: remove unused signal declaration // // Revision 1.4 2009/05/22 16:06:29 acg // Andy Goodrich: process control updates. // // Revision 1.3 2008/05/22 17:06:25 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.2 2007/01/24 20:14:40 acg // Andy Goodrich: improved comments about the use of this-> in the macros // that access sensitive. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.10 2006/12/02 20:58:18 acg // Andy Goodrich: updates from 2.2 for IEEE 1666 support. // // Revision 1.7 2006/04/11 23:13:21 acg // Andy Goodrich: Changes for reduced reset support that only includes // sc_cthread, but has preliminary hooks for expanding to method and thread // processes also. // // Revision 1.6 2006/03/15 17:53:34 acg // Andy Goodrich, Forte Design // Reordered includes to pick up for use by sc_process_name.h // // Revision 1.5 2006/03/14 23:56:58 acg // Andy Goodrich: This fixes a bug when an exception is thrown in // sc_module::sc_module() for a dynamically allocated sc_module // object. We are calling sc_module::end_module() on a module that has // already been deleted. The scenario runs like this: // // a) the sc_module constructor is entered // b) the exception is thrown // c) the exception processor deletes the storage for the sc_module // d) the stack is unrolled causing the sc_module_name instance to be deleted // e) ~sc_module_name() calls end_module() with its pointer to the sc_module // f) because the sc_module has been deleted its storage is corrupted, // either by linking it to a free space chain, or by reuse of some sort // g) the m_simc field is garbage // h) the m_object_manager field is also garbage // i) an exception occurs // // This does not happen for automatic sc_module instances since the // storage for the module is not reclaimed its just part of the stack. // // I am fixing this by having the destructor for sc_module clear the // module pointer in its sc_module_name instance. That cuts things at // step (e) above, since the pointer will be null if the module has // already been deleted. To make sure the module stack is okay, I call // end-module() in ~sc_module in the case where there is an // sc_module_name pointer lying around. // // Revision 1.4 2006/01/24 20:49:05 acg // Andy Goodrich: changes to remove the use of deprecated features within the // simulator, and to issue warning messages when deprecated features are used. // // Revision 1.3 2006/01/13 18:44:30 acg // Added $Log to record CVS changes into the source. #endif systemc-2.3.3/src/sysc/kernel/sc_sensitive.cpp0000644000175000017500000005206213360325173021330 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_sensitive.cpp -- Original Author: Stan Y. Liao, Synopsys, Inc. Martin Janssen, Synopsys, Inc. CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #include "sysc/kernel/sc_event.h" #include "sysc/kernel/sc_kernel_ids.h" #include "sysc/kernel/sc_module.h" #include "sysc/kernel/sc_cthread_process.h" #include "sysc/kernel/sc_method_process.h" #include "sysc/kernel/sc_thread_process.h" #include "sysc/kernel/sc_process_handle.h" #include "sysc/kernel/sc_sensitive.h" #include "sysc/communication/sc_signal_ports.h" #include "sysc/utils/sc_utils_ids.h" namespace sc_core { // support functions static sc_method_handle as_method_handle( sc_process_b* handle_ ) { return dynamic_cast( handle_ ); } static sc_thread_handle as_thread_handle( sc_process_b* handle_ ) { return dynamic_cast( handle_ ); } static void warn_no_parens() { static bool warn_no_parentheses=true; if ( warn_no_parentheses ) { warn_no_parentheses=false; SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, "use of () to specify sensitivity is deprecated, use << instead" ); } } // ---------------------------------------------------------------------------- // CLASS : sc_sensitive // // Static sensitivity class for events. // ---------------------------------------------------------------------------- // constructor sc_sensitive::sc_sensitive( sc_module* module_ ) : m_module( module_ ), m_mode( SC_NONE_ ), m_handle( 0 ) {} // destructor sc_sensitive::~sc_sensitive() {} // changing between process handles sc_sensitive& sc_sensitive::operator << ( sc_process_handle handle_ ) { switch ( handle_.proc_kind() ) { case SC_CTHREAD_PROC_: case SC_THREAD_PROC_: m_mode = SC_THREAD_; break; case SC_METHOD_PROC_: m_mode = SC_METHOD_; break; default: sc_assert(0); } m_handle = (sc_process_b*)handle_; return *this; } sc_sensitive& sc_sensitive::operator << ( const sc_event& event_ ) { // check if( sc_is_running() ) { SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_, "simulation running" ); } // make sensitive switch( m_mode ) { case SC_METHOD_: case SC_THREAD_: { m_handle->add_static_event( event_ ); break; } case SC_NONE_: /* do nothing */ break; } return *this; } void sc_sensitive::make_static_sensitivity( sc_process_b* handle_, const sc_event& event_) { handle_->add_static_event( event_ ); } sc_sensitive& sc_sensitive::operator << ( const sc_interface& interface_ ) { // check if( sc_is_running() ) { SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_, "simulation running" ); } // make sensitive switch( m_mode ) { case SC_METHOD_: case SC_THREAD_: { m_handle->add_static_event( interface_.default_event() ); break; } case SC_NONE_: /* do nothing */ break; } return *this; } void sc_sensitive::make_static_sensitivity( sc_process_b* handle_, const sc_interface& interface_) { handle_->add_static_event( interface_.default_event() ); } sc_sensitive& sc_sensitive::operator << ( const sc_port_base& port_ ) { // check if( sc_is_running() ) { SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_, "simulation running" ); } // make sensitive switch( m_mode ) { case SC_METHOD_: { port_.make_sensitive( as_method_handle( m_handle ) ); break; } case SC_THREAD_: { port_.make_sensitive( as_thread_handle( m_handle ) ); break; } case SC_NONE_: /* do nothing */ break; } return *this; } void sc_sensitive::make_static_sensitivity( sc_process_b* handle_, const sc_port_base& port_) { sc_method_handle handle_m = as_method_handle( handle_ ); if ( handle_m ) { port_.make_sensitive( handle_m ); return; } sc_thread_handle handle_t = as_thread_handle( handle_ ); // sc_assert(handle_t); port_.make_sensitive( handle_t ); } sc_sensitive& sc_sensitive::operator << ( sc_event_finder& event_finder_ ) { // check if( sc_is_running() ) { SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_, "simulation running" ); } // make sensitive switch( m_mode ) { case SC_METHOD_: { event_finder_.port().make_sensitive( as_method_handle( m_handle ), &event_finder_ ); break; } case SC_THREAD_: { event_finder_.port().make_sensitive( as_thread_handle( m_handle ), &event_finder_ ); break; } case SC_NONE_: /* do nothing */ break; } return *this; } void sc_sensitive::make_static_sensitivity( sc_process_b* handle_, sc_event_finder& event_finder_) { if (sc_is_running()) { handle_->add_static_event( event_finder_.find_event() ); } else { sc_method_handle handle_m = as_method_handle( handle_ ); if ( handle_m ) { event_finder_.port().make_sensitive( handle_m, &event_finder_ ); return; } sc_thread_handle handle_t = as_thread_handle( handle_ ); // sc_assert(handle_t); event_finder_.port().make_sensitive( handle_t, &event_finder_); } } sc_sensitive& sc_sensitive::operator () ( const sc_event& event_ ) { warn_no_parens(); return operator << ( event_ ); } sc_sensitive& sc_sensitive::operator () ( const sc_interface& interface_ ) { warn_no_parens(); return operator << ( interface_ ); } sc_sensitive& sc_sensitive::operator () ( const sc_port_base& port_ ) { warn_no_parens(); return operator << ( port_ ); } sc_sensitive& sc_sensitive::operator () ( sc_event_finder& event_finder_ ) { warn_no_parens(); return operator << ( event_finder_ ); } sc_sensitive& sc_sensitive::operator () ( sc_cthread_handle handle_, sc_event_finder& event_finder_ ) { event_finder_.port().make_sensitive( handle_, &event_finder_ ); return *this; } sc_sensitive& sc_sensitive::operator () ( sc_cthread_handle handle_, const in_if_b_type& interface_ ) { handle_->add_static_event( interface_.posedge_event() ); return *this; } sc_sensitive& sc_sensitive::operator () ( sc_cthread_handle handle_, const in_if_l_type& interface_ ) { handle_->add_static_event( interface_.posedge_event() ); return *this; } sc_sensitive& sc_sensitive::operator () ( sc_cthread_handle handle_, const in_port_b_type& port_ ) { port_.make_sensitive( handle_, &port_.pos() ); return *this; } sc_sensitive& sc_sensitive::operator () ( sc_cthread_handle handle_, const in_port_l_type& port_ ) { port_.make_sensitive( handle_, &port_.pos() ); return *this; } sc_sensitive& sc_sensitive::operator () ( sc_cthread_handle handle_, const inout_port_b_type& port_ ) { port_.make_sensitive( handle_, &port_.pos() ); return *this; } sc_sensitive& sc_sensitive::operator () ( sc_cthread_handle handle_, const inout_port_l_type& port_ ) { port_.make_sensitive( handle_, &port_.pos() ); return *this; } void sc_sensitive::reset() { m_mode = SC_NONE_; } // ---------------------------------------------------------------------------- // CLASS : sc_sensitive_pos // // Static sensitivity class for positive edge events. // ---------------------------------------------------------------------------- static void sc_deprecated_sensitive_pos() { static bool warn_sensitive_pos=true; if ( warn_sensitive_pos ) { warn_sensitive_pos=false; SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, "sc_sensitive_pos is deprecated use sc_sensitive << with pos() instead" ); } } // constructor sc_sensitive_pos::sc_sensitive_pos( sc_module* module_ ) : m_module( module_ ), m_mode( SC_NONE_ ), m_handle( 0 ) {} // destructor sc_sensitive_pos::~sc_sensitive_pos() {} // changing between process handles sc_sensitive_pos& sc_sensitive_pos::operator << ( sc_process_handle handle_ ) { switch ( handle_.proc_kind() ) { case SC_CTHREAD_PROC_: case SC_THREAD_PROC_: m_mode = SC_THREAD_; break; case SC_METHOD_PROC_: m_mode = SC_METHOD_; break; default: sc_assert(0); } m_handle = (sc_process_b*)handle_; return *this; } sc_sensitive_pos& sc_sensitive_pos::operator << ( sc_method_handle handle_ ) { m_mode = SC_METHOD_; m_handle = handle_; return *this; } sc_sensitive_pos& sc_sensitive_pos::operator << ( sc_thread_handle handle_ ) { m_mode = SC_THREAD_; m_handle = handle_; return *this; } sc_sensitive_pos& sc_sensitive_pos::operator << ( const in_if_b_type& interface_ ) { sc_deprecated_sensitive_pos(); // check if( sc_is_running() ) { SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_POS_, "simulation running" ); } // make sensitive switch( m_mode ) { case SC_METHOD_: case SC_THREAD_: { m_handle->add_static_event( interface_.posedge_event() ); break; } case SC_NONE_: /* do nothing */ break; } return *this; } sc_sensitive_pos& sc_sensitive_pos::operator << ( const in_if_l_type& interface_ ) { sc_deprecated_sensitive_pos(); // check if( sc_is_running() ) { SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_POS_, "simulation running" ); } // make sensitive switch( m_mode ) { case SC_METHOD_: case SC_THREAD_: { m_handle->add_static_event( interface_.posedge_event() ); break; } case SC_NONE_: /* do nothing */ break; } return *this; } sc_sensitive_pos& sc_sensitive_pos::operator << ( const in_port_b_type& port_ ) { sc_deprecated_sensitive_pos(); // check if( sc_is_running() ) { SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_POS_, "simulation running" ); } // make sensitive switch( m_mode ) { case SC_METHOD_: { port_.make_sensitive( as_method_handle( m_handle ), &port_.pos() ); break; } case SC_THREAD_: { port_.make_sensitive( as_thread_handle( m_handle ), &port_.pos() ); break; } case SC_NONE_: /* do nothing */ break; } return *this; } sc_sensitive_pos& sc_sensitive_pos::operator << ( const in_port_l_type& port_ ) { sc_deprecated_sensitive_pos(); // check if( sc_is_running() ) { SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_POS_, "simulation running" ); } // make sensitive switch( m_mode ) { case SC_METHOD_: { port_.make_sensitive( as_method_handle( m_handle ), &port_.pos() ); break; } case SC_THREAD_: { port_.make_sensitive( as_thread_handle( m_handle ), &port_.pos() ); break; } case SC_NONE_: /* do nothing */ break; } return *this; } sc_sensitive_pos& sc_sensitive_pos::operator << ( const inout_port_b_type& port_ ) { sc_deprecated_sensitive_pos(); // check if( sc_is_running() ) { SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_POS_, "simulation running" ); } // make sensitive switch( m_mode ) { case SC_METHOD_: { port_.make_sensitive( as_method_handle( m_handle ), &port_.pos() ); break; } case SC_THREAD_: { port_.make_sensitive( as_thread_handle( m_handle ), &port_.pos() ); break; } case SC_NONE_: /* do nothing */ break; } return *this; } sc_sensitive_pos& sc_sensitive_pos::operator << ( const inout_port_l_type& port_ ) { sc_deprecated_sensitive_pos(); // check if( sc_is_running() ) { SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_POS_, "simulation running" ); } // make sensitive switch( m_mode ) { case SC_METHOD_: { port_.make_sensitive( as_method_handle( m_handle ), &port_.pos() ); break; } case SC_THREAD_: { port_.make_sensitive( as_thread_handle( m_handle ), &port_.pos() ); break; } case SC_NONE_: /* do nothing */ break; } return *this; } sc_sensitive_pos& sc_sensitive_pos::operator () ( const in_if_b_type& interface_ ) { warn_no_parens(); return operator << ( interface_ ); } sc_sensitive_pos& sc_sensitive_pos::operator () ( const in_if_l_type& interface_ ) { warn_no_parens(); return operator << ( interface_ ); } sc_sensitive_pos& sc_sensitive_pos::operator () ( const in_port_b_type& port_ ) { warn_no_parens(); return operator << ( port_ ); } sc_sensitive_pos& sc_sensitive_pos::operator () ( const in_port_l_type& port_ ) { warn_no_parens(); return operator << ( port_ ); } sc_sensitive_pos& sc_sensitive_pos::operator () ( const inout_port_b_type& port_ ) { warn_no_parens(); return operator << ( port_ ); } sc_sensitive_pos& sc_sensitive_pos::operator () ( const inout_port_l_type& port_ ) { warn_no_parens(); return operator << ( port_ ); } void sc_sensitive_pos::reset() { m_mode = SC_NONE_; } // ---------------------------------------------------------------------------- // CLASS : sc_sensitive_neg // // Static sensitivity class for negative edge events. // ---------------------------------------------------------------------------- static void sc_deprecated_sensitive_neg() { static bool warn_sensitive_neg=true; if ( warn_sensitive_neg ) { warn_sensitive_neg=false; SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, "sc_sensitive_neg is deprecated use sc_sensitive << with neg() instead" ); } } // constructor sc_sensitive_neg::sc_sensitive_neg( sc_module* module_ ) : m_module( module_ ), m_mode( SC_NONE_ ), m_handle( 0 ) {} // destructor sc_sensitive_neg::~sc_sensitive_neg() {} // changing between process handles sc_sensitive_neg& sc_sensitive_neg::operator << ( sc_process_handle handle_ ) { switch ( handle_.proc_kind() ) { case SC_CTHREAD_PROC_: case SC_THREAD_PROC_: m_mode = SC_THREAD_; break; case SC_METHOD_PROC_: m_mode = SC_METHOD_; break; default: sc_assert(0); } m_handle = (sc_process_b*)handle_; return *this; } sc_sensitive_neg& sc_sensitive_neg::operator << ( sc_method_handle handle_ ) { m_mode = SC_METHOD_; m_handle = handle_; return *this; } sc_sensitive_neg& sc_sensitive_neg::operator << ( sc_thread_handle handle_ ) { m_mode = SC_THREAD_; m_handle = handle_; return *this; } sc_sensitive_neg& sc_sensitive_neg::operator << ( const in_if_b_type& interface_ ) { sc_deprecated_sensitive_neg(); // check if( sc_is_running() ) { SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_NEG_, "simulation running" ); } // make sensitive switch( m_mode ) { case SC_METHOD_: case SC_THREAD_: { m_handle->add_static_event( interface_.negedge_event() ); break; } case SC_NONE_: /* do nothing */ break; } return *this; } sc_sensitive_neg& sc_sensitive_neg::operator << ( const in_if_l_type& interface_ ) { sc_deprecated_sensitive_neg(); // check if( sc_is_running() ) { SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_NEG_, "simulation running" ); } // make sensitive switch( m_mode ) { case SC_METHOD_: case SC_THREAD_: { m_handle->add_static_event( interface_.negedge_event() ); break; } case SC_NONE_: /* do nothing */ break; } return *this; } sc_sensitive_neg& sc_sensitive_neg::operator << ( const in_port_b_type& port_ ) { sc_deprecated_sensitive_neg(); // check if( sc_is_running() ) { SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_NEG_, "simulation running" ); } // make sensitive switch( m_mode ) { case SC_METHOD_: { port_.make_sensitive( as_method_handle( m_handle ), &port_.neg() ); break; } case SC_THREAD_: { port_.make_sensitive( as_thread_handle( m_handle ), &port_.neg() ); break; } case SC_NONE_: /* do nothing */ break; } return *this; } sc_sensitive_neg& sc_sensitive_neg::operator << ( const in_port_l_type& port_ ) { sc_deprecated_sensitive_neg(); // check if( sc_is_running() ) { SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_NEG_, "simulation running" ); } // make sensitive switch( m_mode ) { case SC_METHOD_: { port_.make_sensitive( as_method_handle( m_handle ), &port_.neg() ); break; } case SC_THREAD_: { port_.make_sensitive( as_thread_handle( m_handle ), &port_.neg() ); break; } case SC_NONE_: /* do nothing */ break; } return *this; } sc_sensitive_neg& sc_sensitive_neg::operator << ( const inout_port_b_type& port_ ) { sc_deprecated_sensitive_neg(); // check if( sc_is_running() ) { SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_NEG_, "simulation running" ); } // make sensitive switch( m_mode ) { case SC_METHOD_: { port_.make_sensitive( as_method_handle( m_handle ), &port_.neg() ); break; } case SC_THREAD_: { port_.make_sensitive( as_thread_handle( m_handle ), &port_.neg() ); break; } case SC_NONE_: /* do nothing */ break; } return *this; } sc_sensitive_neg& sc_sensitive_neg::operator << ( const inout_port_l_type& port_ ) { sc_deprecated_sensitive_neg(); // check if( sc_is_running() ) { SC_REPORT_ERROR( SC_ID_MAKE_SENSITIVE_NEG_, "simulation running" ); } // make sensitive switch( m_mode ) { case SC_METHOD_: { port_.make_sensitive( as_method_handle( m_handle ), &port_.neg() ); break; } case SC_THREAD_: { port_.make_sensitive( as_thread_handle( m_handle ), &port_.neg() ); break; } case SC_NONE_: /* do nothing */ break; } return *this; } sc_sensitive_neg& sc_sensitive_neg::operator () ( const in_if_b_type& interface_ ) { warn_no_parens(); return operator << ( interface_ ); } sc_sensitive_neg& sc_sensitive_neg::operator () ( const in_if_l_type& interface_ ) { warn_no_parens(); return operator << ( interface_ ); } sc_sensitive_neg& sc_sensitive_neg::operator () ( const in_port_b_type& port_ ) { warn_no_parens(); return operator << ( port_ ); } sc_sensitive_neg& sc_sensitive_neg::operator () ( const in_port_l_type& port_ ) { warn_no_parens(); return operator << ( port_ ); } sc_sensitive_neg& sc_sensitive_neg::operator () ( const inout_port_b_type& port_ ) { warn_no_parens(); return operator << ( port_ ); } sc_sensitive_neg& sc_sensitive_neg::operator () ( const inout_port_l_type& port_ ) { warn_no_parens(); return operator << ( port_ ); } void sc_sensitive_neg::reset() { m_mode = SC_NONE_; } } // namespace sc_core /***************************************************************************** MODIFICATION LOG - modifiers, enter your name, affiliation, date and changes you are making here. Name, Affiliation, Date: Bishnupriya Bhattacharya, Cadence Design Systems, 25 August, 2003 Description of Modification: add make_static_sensitivity() routines to support dynamic method process creation with static sensitivity *****************************************************************************/ // $Log: sc_sensitive.cpp,v $ // Revision 1.5 2011/08/26 20:46:10 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.4 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.3 2011/02/13 21:47:38 acg // Andy Goodrich: update copyright notice. // // Revision 1.2 2008/05/22 17:06:26 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.8 2006/04/11 23:13:21 acg // Andy Goodrich: Changes for reduced reset support that only includes // sc_cthread, but has preliminary hooks for expanding to method and thread // processes also. // // Revision 1.7 2006/01/27 17:31:24 acg // Andy Goodrich: removed debugging comments from << operator code for types // that are deprecated. // // Revision 1.6 2006/01/26 21:04:54 acg // Andy Goodrich: deprecation message changes and additional messages. // // Revision 1.5 2006/01/25 00:31:19 acg // Andy Goodrich: Changed over to use a standard message id of // SC_ID_IEEE_1666_DEPRECATION for all deprecation messages. // // Revision 1.4 2006/01/24 20:49:05 acg // Andy Goodrich: changes to remove the use of deprecated features within the // simulator, and to issue warning messages when deprecated features are used. // // Revision 1.3 2006/01/13 18:44:30 acg // Added $Log to record CVS changes into the source. // // Taf! systemc-2.3.3/src/sysc/kernel/sc_constants.h0000644000175000017500000000562613360325173021004 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_constants.h -- Default constants whose values may need to be changed depending on the application. Original Author: Ali Dasdan, Synopsys, Inc. CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #ifndef SC_CONSTANTS_H #define SC_CONSTANTS_H namespace sc_core { // Maximum number of bits for arbitrary precision arithmetic. If // defined, the arithmetic becomes faster. If not defined, the // arithmetic becomes slower and the precision becomes infinite. It // is a good idea to define this constant as a multiple of // BITS_PER_DIGIT, which is defined in numeric_bit/sc_nbdefs.h. //#define SC_MAX_NBITS 510 // 17 * BITS_PER_DIGIT // deprecated in 1666-2005 and later, but kept for backwards compatibility // - can be set by defining SC_OVERRIDE_DEFAULT_STACK_SIZE // - defaults defined in sc_thread_process.cpp extern const int SC_DEFAULT_STACK_SIZE; #ifdef DEBUG_SYSTEMC const int SC_MAX_NUM_DELTA_CYCLES = 10000; #endif } // namespace sc_core // $Log: sc_constants.h,v $ // Revision 1.7 2011/08/26 20:46:09 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.6 2011/02/18 20:33:26 acg // Philipp A. Hartmann: added default stack size for CYGWIN32. // // Revision 1.5 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.4 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.3 2010/03/15 18:29:25 acg // Andy Goodrich: Changed the default stack size to 128K from 64K. // // Revision 1.2 2008/05/22 17:06:24 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.3 2006/01/13 18:44:29 acg // Added $Log to record CVS changes into the source. // #endif systemc-2.3.3/src/sysc/kernel/sc_ver.cpp0000644000175000017500000001632113360325173020111 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_ver.cpp -- copyright information. Original Author: Stan Y. Liao, Synopsys, Inc. CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #include #include #include "sysc/kernel/sc_ver.h" #include "sysc/kernel/sc_kernel_ids.h" #include "sysc/utils/sc_report.h" #include #include using std::getenv; using std::strcmp; using std::cerr; using std::endl; namespace sc_core { static const char systemc_version[] = "SystemC " SC_VERSION " --- " __DATE__ " " __TIME__; SC_API const unsigned int sc_version_major = SC_VERSION_MAJOR; SC_API const unsigned int sc_version_minor = SC_VERSION_MINOR; SC_API const unsigned int sc_version_patch = SC_VERSION_PATCH; SC_API const bool sc_is_prerelease = SC_IS_PRERELEASE; SC_API const std::string sc_version_originator = SC_VERSION_ORIGINATOR; SC_API const std::string sc_version_release_date = SC_VERSION_RELEASE_DATE; SC_API const std::string sc_version_prerelease = SC_VERSION_PRERELEASE; SC_API const std::string sc_version_string = SC_VERSION; SC_API const std::string sc_copyright_string = SC_COPYRIGHT; SC_API const char* sc_copyright() { return SC_COPYRIGHT; } SC_API const char* sc_release() { return SC_VERSION; } SC_API const char* sc_version() { return systemc_version; } #if !defined(SC_DISABLE_COPYRIGHT_MESSAGE) # define SC_DISABLE_COPYRIGHT_MESSAGE 0 #endif // ---------------------------------------------------------------------------- SC_API void pln() { static bool lnp = SC_DISABLE_COPYRIGHT_MESSAGE; if ( lnp || getenv("SYSTEMC_DISABLE_COPYRIGHT_MESSAGE") != 0 ) lnp = true; if ( const char * lnp_env = getenv("SC_COPYRIGHT_MESSAGE") ) { lnp = !strcmp( lnp_env, "DISABLE" ); } if( ! lnp ) { static const char indent[] = " "; std::string line; std::stringstream copyright; // temporary stream to print copyright line-wise with indentation copyright << sc_copyright(); cerr << endl; cerr << indent << sc_version() << endl; while( getline( copyright, line ) ) cerr << indent << line << endl; // regressions check point if( getenv( "SYSTEMC_REGRESSION" ) != 0 ) { cerr << "SystemC Simulation" << endl; } lnp = true; } } #define SC_API_PERFORM_CHECK_( Type, Name, Symbol ) \ do { \ static bool SC_CONCAT_UNDERSCORE_( Name, config_seen ) = false; \ static Type SC_CONCAT_UNDERSCORE_( Name, config ); \ if( ! SC_CONCAT_UNDERSCORE_( Name, config_seen ) ) { \ SC_CONCAT_UNDERSCORE_( Name, config_seen ) = true; \ SC_CONCAT_UNDERSCORE_( Name, config ) = Name; \ } else if( SC_CONCAT_UNDERSCORE_( Name, config ) != Name ) { \ SC_REPORT_FATAL( SC_ID_INCONSISTENT_API_CONFIG_, Symbol ); \ /* may continue, if suppressed */ \ } \ } while( false ) // THIS CONSTRUCTOR ROOTS OUT OLD OBJECTS AT LINK TIME // // Each source file which includes sc_ver.h for this SystemC version // will have a static instance of the class sc_api_version_XXX defined // in it. That object instanciation will cause the constructor below // to be invoked. If the version of the SystemC being linked against // does not contain the constructor below a linkage error will occur. // // Some preprocessor switches need to be consistent between the application // and the library (e.g. if sizes of classes are affected or other parts of // the ABI are affected). (Some of) these are checked here at link-time as // well, by setting template parameters to sc_api_version_XXX, while only // one variant is defined here. // // Some preprocessor switches need to be consistent between different // translation units of an application. Those can't be easily checked // during link-time. Instead, perform a check during run-time by // passing the value to the constructor of the api_version_check object. // const int DEBUG_SYSTEMC_CHECK_ = 1; const int SC_DISABLE_VIRTUAL_BIND_CHECK_ = 1; template<> SC_API SC_API_VERSION_STRING < // & DEBUG_SYSTEMC_CHECK_, & SC_DISABLE_VIRTUAL_BIND_CHECK_ > ::SC_API_VERSION_STRING ( sc_writer_policy default_writer_policy ) { SC_API_PERFORM_CHECK_( sc_writer_policy , default_writer_policy , "SC_DEFAULT_WRITER_POLICY" ); } } // namespace sc_core // $Log: sc_ver.cpp,v $ // Revision 1.14 2011/08/26 21:56:55 acg // Torsten Maehne: use usings rather than absolute namespace addressing. // // Revision 1.13 2011/08/26 20:46:11 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.12 2011/07/25 10:20:34 acg // Andy Goodrich: check in aftermath of call to automake. // // Revision 1.11 2011/07/02 12:55:19 acg // Andy Goodrich: automake refresh. // // Revision 1.10 2011/07/01 18:49:07 acg // Andy Goodrich: moved pln() from sc_simcontext.cpp to sc_ver.cpp. // // Revision 1.9 2011/07/01 18:33:08 acg // Andy Goodrich: changes for IEEE 1666, removal of macros and use of them. // // Revision 1.8 2011/04/08 18:27:53 acg // Andy Goodrich: respin of the PoC. // // Revision 1.7 2011/04/05 20:50:57 acg // Andy Goodrich: // (1) changes to make sure that event(), posedge() and negedge() only // return true if the clock has not moved. // (2) fixes for method self-resumes. // (3) added SC_PRERELEASE_VERSION // (4) removed kernel events from the object hierarchy, added // sc_hierarchy_name_exists(). // // Revision 1.6 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.5 2011/02/13 21:47:38 acg // Andy Goodrich: update copyright notice. // // Revision 1.4 2011/01/18 20:10:45 acg // Andy Goodrich: changes for IEEE1666_2011 semantics. // // Revision 1.3 2010/11/20 17:10:57 acg // Andy Goodrich: reset processing changes for new IEEE 1666 standard. // // Revision 1.2 2008/05/22 17:06:27 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.3 2006/01/13 18:44:30 acg // Added $Log to record CVS changes into the source. // // Taf! systemc-2.3.3/src/sysc/kernel/sc_process.h0000644000175000017500000010007313360325173020436 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_process.h -- Process base class support. Original Author: Andy Goodrich, Forte Design Systems, 04 August 2005 CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #if !defined(sc_process_h_INCLUDED) #define sc_process_h_INCLUDED #include "sysc/kernel/sc_constants.h" #include "sysc/kernel/sc_object.h" #include "sysc/kernel/sc_kernel_ids.h" #include "sysc/communication/sc_export.h" #if defined(_MSC_VER) && !defined(SC_WIN_DLL_WARN) #pragma warning(push) #pragma warning(disable: 4251) // DLL import for std::vector #endif namespace sc_core { // Forward declarations: class sc_process_handle; class sc_thread_process; class sc_reset; SC_API const char* sc_gen_unique_name( const char*, bool preserve_first ); SC_API sc_process_handle sc_get_current_process_handle(); void sc_thread_cor_fn( void* arg ); SC_API bool timed_out( sc_simcontext* ); SC_API extern bool sc_allow_process_control_corners; // see sc_simcontext.cpp. // Process handles as forward references: typedef class sc_cthread_process* sc_cthread_handle; typedef class sc_method_process* sc_method_handle; typedef class sc_thread_process* sc_thread_handle; // Standard process types: enum sc_curr_proc_kind { SC_NO_PROC_, SC_METHOD_PROC_, SC_THREAD_PROC_, SC_CTHREAD_PROC_ }; // Descendant information for process hierarchy operations: enum sc_descendant_inclusion_info { SC_NO_DESCENDANTS=0, SC_INCLUDE_DESCENDANTS, SC_INVALID_DESCENDANTS }; //============================================================================== // CLASS sc_process_host // // This is the base class for objects which may have processes defined for // their methods (e.g., sc_module) //============================================================================== class SC_API sc_process_host { public: sc_process_host() {} virtual ~sc_process_host() { } // Needed for cast check for sc_module. void defunct() {} }; //============================================================================== // CLASS sc_process_monitor // // This class provides a way of monitoring a process' status (e.g., waiting // for a thread to complete its execution.) This class is intended to be a base // class for classes which need to monitor a process or processes (e.g., // sc_join.) Its methods should be overloaded where notifications are desired. //============================================================================== class SC_API sc_process_monitor { public: enum { spm_exit = 0 }; virtual ~sc_process_monitor() {} virtual void signal(sc_thread_handle thread_p, int type); }; inline void sc_process_monitor::signal(sc_thread_handle , int ) {} //------------------------------------------------------------------------------ // PROCESS INVOCATION METHOD OR FUNCTION: // // Define SC_USE_MEMBER_FUNC_PTR if we want to use member function pointers // to implement process dispatch. Otherwise, we'll use a hack that involves // creating a templated invocation object which will invoke the member // function. This should not be necessary, but some compilers (e.g., VC++) // do not allow the conversion from `void (callback_tag::*)()' to // `void (sc_process_host::*)()'. This is supposed to be OK as long as the // dynamic type is correct. C++ Standard 5.4 "Explicit type conversion", // clause 7: a pointer to member of derived class type may be explicitly // converted to a pointer to member of an unambiguous non-virtual base class // type. //----------------------------------------------------------------------------- #if defined(_MSC_VER) #if ( _MSC_VER > 1200 ) # define SC_USE_MEMBER_FUNC_PTR #endif #else # define SC_USE_MEMBER_FUNC_PTR #endif // COMPILER DOES SUPPORT CAST TO void (sc_process_host::*)() from (T::*)(): #if defined(SC_USE_MEMBER_FUNC_PTR) typedef void (sc_process_host::*SC_ENTRY_FUNC)(); # define SC_DECL_HELPER_STRUCT(callback_tag, func) /*EMPTY*/ # define SC_MAKE_FUNC_PTR(callback_tag, func) \ static_cast(&callback_tag::func) // COMPILER NOT DOES SUPPORT CAST TO void (sc_process_host::*)() from (T::*)(): #else // !defined(SC_USE_MEMBER_FUNC_PTR) class SC_API sc_process_call_base { public: inline sc_process_call_base() { } virtual ~sc_process_call_base() { } virtual void invoke(sc_process_host* host_p) { } }; extern sc_process_call_base sc_process_defunct; template class sc_process_call : public sc_process_call_base { public: sc_process_call( void (T::*method_p)() ) : sc_process_call_base() { m_method_p = method_p; } virtual ~sc_process_call() { } virtual void invoke(sc_process_host* host_p) { (((T*)host_p)->*m_method_p)(); } protected: void (T::*m_method_p)(); // Method implementing the process. }; typedef sc_process_call_base* SC_ENTRY_FUNC; # define SC_DECL_HELPER_STRUCT(callback_tag, func) /*EMPTY*/ # define SC_MAKE_FUNC_PTR(callback_tag, func) \ (::sc_core::SC_ENTRY_FUNC) (new \ ::sc_core::sc_process_call(&callback_tag::func)) #endif // !defined(SC_USE_MEMBER_FUNC_PTR) extern SC_API void sc_set_stack_size( sc_thread_handle, std::size_t ); class sc_event; class sc_event_list; class sc_name_gen; class sc_spawn_options; class sc_unwind_exception; //============================================================================== // CLASS sc_throw_it - ARBITRARY EXCEPTION CLASS // // This class serves as a way of throwing an execption for an aribtrary type // without knowing what that type is. A true virtual method in the base // class is used to actually throw the execption. A pointer to the base // class is used internally removing the necessity of knowing what the type // of EXCEPT is for code internal to the library. // // Note the clone() true virtual method. This is used to allow instances // of the sc_throw_it class to be easily garbage collected. Since // an exception may be propogated to more than one process knowing when // to garbage collect is non-trivial. So when a call is made to // sc_process_handle::throw_it() an instance of sc_throw_it is // allocated on the stack. For each process throwing the exception a copy is // made via clone(). That allows those objects to be deleted by the individual // processes when they are no longer needed (in this implementation of SystemC // that deletion will occur each time a new exception is thrown ( see // sc_thread_process::suspend_me() ). //============================================================================== class SC_API sc_throw_it_helper { public: virtual sc_throw_it_helper* clone() const = 0; virtual void throw_it() = 0; sc_throw_it_helper() {} virtual ~sc_throw_it_helper() {} }; template class sc_throw_it : public sc_throw_it_helper { typedef sc_throw_it this_type; public: sc_throw_it( const EXCEPT& value ) : m_value(value) { } virtual ~sc_throw_it() {} virtual inline this_type* clone() const { return new this_type(m_value); } virtual inline void throw_it() { throw m_value; } protected: EXCEPT m_value; // value to be thrown. }; //============================================================================== // CLASS sc_process_b - USER INITIATED DYNAMIC PROCESS SUPPORT: // // This class implements the base class for a threaded process_base process // whose semantics are provided by the true virtual method semantics(). // Classes derived from this one will provide a version of semantics which // implements the desired semantics. See the sc_spawn_xxx classes below. // // Notes: // (1) Object instances of this class maintain a reference count of // outstanding handles. When the handle count goes to zero the // object will be deleted. // (2) Descriptions of the methods and operators in this class appear with // their implementations. // (3) The m_sticky_reset field is used to handle synchronous resets that // are enabled via the sc_process_handle::sync_reset_on() method. These // resets are not generated by a signal, but rather are modal by // method call: sync_reset_on - sync_reset_off. // //============================================================================== class SC_API sc_process_b : public sc_object { friend class sc_simcontext; // Allow static processes to have base. friend class sc_cthread_process; // Child can access parent. friend class sc_method_process; // Child can access parent. friend class sc_process_handle; // Allow handles to modify ref. count. friend class sc_process_table; // Allow process_table to modify ref. count. friend class sc_thread_process; // Child can access parent. friend class sc_event; friend class sc_object; friend class sc_port_base; friend class sc_runnable; friend class sc_sensitive; friend class sc_sensitive_pos; friend class sc_sensitive_neg; friend class sc_module; friend class sc_report_handler; friend class sc_reset; friend class sc_reset_finder; friend class sc_unwind_exception; friend SC_API const char* sc_gen_unique_name( const char*, bool preserve_first ); friend SC_API sc_process_handle sc_get_current_process_handle(); friend void sc_thread_cor_fn( void* arg ); friend SC_API bool timed_out( sc_simcontext* ); public: enum process_throw_type { THROW_NONE = 0, THROW_KILL, THROW_USER, THROW_ASYNC_RESET, THROW_SYNC_RESET }; enum process_state { ps_bit_disabled = 1, // process is disabled. ps_bit_ready_to_run = 2, // process is ready to run. ps_bit_suspended = 4, // process is suspended. ps_bit_zombie = 8, // process is a zombie. ps_normal = 0 // must be zero. }; enum reset_type { // types for sc_process_b::reset_process() reset_asynchronous = 0, // asynchronous reset. reset_synchronous_off, // turn off synchronous reset sticky bit. reset_synchronous_on // turn on synchronous reset sticky bit. }; enum trigger_t { STATIC, EVENT, OR_LIST, AND_LIST, TIMEOUT, EVENT_TIMEOUT, OR_LIST_TIMEOUT, AND_LIST_TIMEOUT }; protected: enum spawn_t { SPAWN_ELAB = 0x0, // spawned during elaboration (static process) SPAWN_START = 0x1, // spawned during simulation start (dynamic process) SPAWN_SIM = 0x2 // spawned during simulation (dynamic process) }; public: sc_process_b( const char* name_p, bool is_thread, bool free_host, SC_ENTRY_FUNC method_p, sc_process_host* host_p, const sc_spawn_options* opt_p ); protected: // may not be deleted manually (called from destroy_process()) virtual ~sc_process_b(); public: inline int current_state() { return m_state; } bool dont_initialize() const { return m_dont_init; } virtual void dont_initialize( bool dont ); std::string dump_state() const; const ::std::vector& get_child_objects() const; inline sc_curr_proc_kind proc_kind() const; sc_event& reset_event(); sc_event& terminated_event(); public: static inline sc_process_handle last_created_process_handle(); protected: virtual void add_child_object( sc_object* ); void add_static_event( const sc_event& ); bool dynamic() const { return m_dynamic_proc != SPAWN_ELAB; } const char* gen_unique_name( const char* basename_, bool preserve_first ); inline sc_report* get_last_report() { return m_last_report_p; } inline bool is_disabled() const; inline bool is_runnable() const; static inline sc_process_b* last_created_process_base(); virtual bool remove_child_object( sc_object* ); void remove_dynamic_events( bool skip_timeout = false ); void remove_static_events(); inline void set_last_report( sc_report* last_p ) { delete m_last_report_p; m_last_report_p = last_p; } inline bool timed_out() const; void report_error( const char* msgid, const char* msg = "" ) const; void report_immediate_self_notification() const; protected: // process control methods: virtual void disable_process( sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ) = 0; void disconnect_process(); virtual void enable_process( sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ) = 0; inline void initially_in_reset( bool async ); inline bool is_unwinding() const; inline bool start_unwinding(); inline bool clear_unwinding(); virtual void kill_process( sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ) = 0; void reset_changed( bool async, bool asserted ); void reset_process( reset_type rt, sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); virtual void resume_process( sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ) = 0; virtual void suspend_process( sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ) = 0; virtual void throw_user( const sc_throw_it_helper& helper, sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ) = 0; virtual void throw_reset( bool async ) = 0; virtual bool terminated() const; void trigger_reset_event(); private: void delete_process(); inline void reference_decrement(); inline void reference_increment(); protected: inline void semantics(); // debugging stuff: public: const char* file; int lineno; int proc_id; protected: int m_active_areset_n; // number of aresets active. int m_active_reset_n; // number of resets active. bool m_dont_init; // true: no initialize call. spawn_t m_dynamic_proc; // SPAWN_ELAB, SPAWN_START, SPAWN_SIM const sc_event* m_event_p; // Dynamic event waiting on. int m_event_count; // number of events. const sc_event_list* m_event_list_p; // event list waiting on. sc_process_b* m_exist_p; // process existence link. bool m_free_host; // free sc_semantic_host_p. bool m_has_reset_signal; // has reset_signal_is. bool m_has_stack; // true is stack present. bool m_is_thread; // true if this is thread. sc_report* m_last_report_p; // last report this process. sc_name_gen* m_name_gen_p; // subprocess name generator sc_curr_proc_kind m_process_kind; // type of process. int m_references_n; // outstanding handles. std::vector m_resets; // resets for process. sc_event* m_reset_event_p; // reset event. sc_event* m_resume_event_p; // resume event. sc_process_b* m_runnable_p; // sc_runnable link sc_process_host* m_semantics_host_p; // host for semantics. SC_ENTRY_FUNC m_semantics_method_p; // method for semantics. int m_state; // process state. std::vector m_static_events; // static events waiting on. bool m_sticky_reset; // see note 3 above. sc_event* m_term_event_p; // terminated event. sc_throw_it_helper* m_throw_helper_p; // what to throw. process_throw_type m_throw_status; // exception throwing status bool m_timed_out; // true if we timed out. sc_event* m_timeout_event_p; // timeout event. trigger_t m_trigger_type; // type of trigger using. bool m_unwinding; // true if unwinding stack. protected: static sc_process_b* m_last_created_process_p; // Last process created. }; typedef sc_process_b sc_process_b; // For compatibility. //------------------------------------------------------------------------------ //"sc_process_b::XXXX_child_YYYYY" // // These methods provide child object support. //------------------------------------------------------------------------------ inline void sc_process_b::add_child_object( sc_object* object_p ) { sc_object::add_child_object( object_p ); reference_increment(); } inline bool sc_process_b::remove_child_object( sc_object* object_p ) { if ( sc_object::remove_child_object( object_p ) ) { reference_decrement(); return true; } else { return false; } } inline const ::std::vector& sc_process_b::get_child_objects() const { return m_child_objects; } //------------------------------------------------------------------------------ //"sc_process_b::initially_in_reset" // // This inline method is a callback to indicate that a reset is active at // start up. This is because the signal will have been initialized before // a reset linkage for it is set up, so we won't get a reset_changed() // callback. // async = true if this an asynchronous reset. //------------------------------------------------------------------------------ inline void sc_process_b::initially_in_reset( bool async ) { if ( async ) m_active_areset_n++; else m_active_reset_n++; } //------------------------------------------------------------------------------ //"sc_process_b::is_disabled" // // This method returns true if this process is disabled. //------------------------------------------------------------------------------ inline bool sc_process_b::is_disabled() const { return (m_state & ps_bit_disabled) ? true : false; } //------------------------------------------------------------------------------ //"sc_process_b::is_runnable" // // This method returns true if this process is runnable. That is indicated // by a non-zero m_runnable_p field. //------------------------------------------------------------------------------ inline bool sc_process_b::is_runnable() const { return m_runnable_p != 0; } //------------------------------------------------------------------------------ //"sc_process_b::is_unwinding" // // This method returns true if this process is unwinding from a kill or reset. //------------------------------------------------------------------------------ inline bool sc_process_b::is_unwinding() const { return m_unwinding; } //------------------------------------------------------------------------------ //"sc_process_b::start_unwinding" // // This method flags that this object instance should start unwinding if the // current throw status requires an unwind. // // Result is true if the flag is set, false if the flag is already set. //------------------------------------------------------------------------------ inline bool sc_process_b::start_unwinding() { if ( !m_unwinding ) { switch( m_throw_status ) { case THROW_KILL: case THROW_ASYNC_RESET: case THROW_SYNC_RESET: m_unwinding = true; return true; case THROW_USER: default: break; } } return false; } //------------------------------------------------------------------------------ //"sc_process_b::clear_unwinding" // // This method clears this object instance's throw status and always returns // true. //------------------------------------------------------------------------------ inline bool sc_process_b::clear_unwinding() { m_unwinding = false; return true; } //------------------------------------------------------------------------------ //"sc_process_b::last_created_process_base" // // This virtual method returns the sc_process_b pointer for the last // created process. It is only used internally by the simulator. //------------------------------------------------------------------------------ inline sc_process_b* sc_process_b::last_created_process_base() { return m_last_created_process_p; } //------------------------------------------------------------------------------ //"sc_process_b::proc_kind" // // This method returns the kind of this process. //------------------------------------------------------------------------------ inline sc_curr_proc_kind sc_process_b::proc_kind() const { return m_process_kind; } //------------------------------------------------------------------------------ //"sc_process_b::reference_decrement" // // This inline method decrements the number of outstanding references to this // object instance. If the number of references goes to zero, this object // can be deleted in "sc_process_b::delete_process()". //------------------------------------------------------------------------------ inline void sc_process_b::reference_decrement() { m_references_n--; if ( m_references_n == 0 ) delete_process(); } //------------------------------------------------------------------------------ //"sc_process_b::reference_increment" // // This inline method increments the number of outstanding references to this // object instance. //------------------------------------------------------------------------------ inline void sc_process_b::reference_increment() { sc_assert(m_references_n != 0); m_references_n++; } //------------------------------------------------------------------------------ //"sc_process_b::semantics" // // This inline method invokes the semantics for this object instance. // We check to see if we are initially in reset and then invoke the // process semantics. // // Notes: // (1) For a description of the process reset mechanism see the top of // the file sc_reset.cpp. //------------------------------------------------------------------------------ struct SC_API scoped_flag { scoped_flag( bool& b ) : ref(b){ ref = true; } ~scoped_flag() { ref = false; } bool& ref; private: scoped_flag& operator=(const scoped_flag&) /* = delete */; }; inline void sc_process_b::semantics() { // within this function, the process has a stack associated scoped_flag scoped_stack_flag( m_has_stack ); sc_assert( m_process_kind != SC_NO_PROC_ ); // Determine the reset status of this object instance and potentially // trigger its notify event: // See if we need to trigger the notify event: if ( m_reset_event_p && ( (m_throw_status == THROW_SYNC_RESET) || (m_throw_status == THROW_ASYNC_RESET) ) ) { trigger_reset_event(); } // Set the new reset status of this object based on the reset counts: m_throw_status = m_active_areset_n ? THROW_ASYNC_RESET : ( m_active_reset_n ? THROW_SYNC_RESET : THROW_NONE); // Dispatch the actual semantics for the process: # ifndef SC_USE_MEMBER_FUNC_PTR m_semantics_method_p->invoke( m_semantics_host_p ); # else (m_semantics_host_p->*m_semantics_method_p)(); # endif } //------------------------------------------------------------------------------ //"sc_process_b::terminated" // // This inline method returns true if this object has terminated. //------------------------------------------------------------------------------ inline bool sc_process_b::terminated() const { return (m_state & ps_bit_zombie) != 0; } //------------------------------------------------------------------------------ //"sc_process_b::timed_out" // // This inline method returns true if this object instance timed out. //------------------------------------------------------------------------------ inline bool sc_process_b::timed_out() const { return m_timed_out; } } // namespace sc_core #if defined(_MSC_VER) && !defined(SC_WIN_DLL_WARN) #pragma warning(pop) #endif /***************************************************************************** MODIFICATION LOG - modifiers, enter your name, affiliation, date and changes you are making here. Name, Affiliation, Date: Andy Goodrich, Forte Design Systems, 12 Aug 05 Description of Modification: This is the rewrite of process support. It contains some code from the original sc_process.h by Stan Liao, and the now-defunct sc_process_b.h by Stan Liao and Martin Janssen, all of Synopsys, Inc., It also contains code from the original sc_process_b.h by Andy Goodrich of Forte Design Systems and Bishnupriya Bhattacharya of Cadence Design Systems. Name, Affiliation, Date: Description of Modification: *****************************************************************************/ // $Log: sc_process.h,v $ // Revision 1.36 2011/08/26 22:44:30 acg // Torsten Maehne: eliminate unused argument warning. // // Revision 1.35 2011/08/26 20:46:10 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.34 2011/08/24 22:05:51 acg // Torsten Maehne: initialization changes to remove warnings. // // Revision 1.33 2011/08/15 16:43:24 acg // Torsten Maehne: changes to remove unused argument warnings. // // Revision 1.32 2011/07/24 11:20:03 acg // Philipp A. Hartmann: process control error message improvements: // (1) Downgrade error to warning for re-kills of processes. // (2) Add process name to process messages. // (3) drop some superfluous colons in messages. // // Revision 1.31 2011/04/13 02:44:26 acg // Andy Goodrich: added m_unwinding flag in place of THROW_NOW because the // throw status will be set back to THROW_*_RESET if reset is active and // the check for an unwind being complete was expecting THROW_NONE as the // clearing of THROW_NOW. // // Revision 1.30 2011/04/11 22:07:27 acg // Andy Goodrich: check for reset event notification before resetting the // throw_status value. // // Revision 1.29 2011/04/10 22:17:36 acg // Andy Goodrich: added trigger_reset_event() to allow sc_process.h to // contain the run_process() inline method. sc_process.h cannot have // sc_simcontext information because of recursive includes. // // Revision 1.28 2011/04/08 22:34:06 acg // Andy Goodrich: moved the semantics() method to this file and made it // an inline method. Added reset processing to the semantics() method. // // Revision 1.27 2011/04/08 18:24:48 acg // Andy Goodrich: moved reset_changed() to .cpp since it needs visibility // to sc_simcontext. // // Revision 1.26 2011/04/01 21:24:57 acg // Andy Goodrich: removed unused code. // // Revision 1.25 2011/03/28 13:02:51 acg // Andy Goodrich: Changes for disable() interactions. // // Revision 1.24 2011/03/20 13:43:23 acg // Andy Goodrich: added async_signal_is() plus suspend() as a corner case. // // Revision 1.23 2011/03/12 21:07:51 acg // Andy Goodrich: changes to kernel generated event support. // // Revision 1.22 2011/03/08 20:49:31 acg // Andy Goodrich: implement coarse checking for synchronous reset - suspend // interaction. // // Revision 1.21 2011/03/07 17:38:43 acg // Andy Goodrich: tightening up of checks for undefined interaction between // synchronous reset and suspend. // // Revision 1.20 2011/03/06 19:57:11 acg // Andy Goodrich: refinements for the illegal suspend - synchronous reset // interaction. // // Revision 1.19 2011/03/05 19:44:20 acg // Andy Goodrich: changes for object and event naming and structures. // // Revision 1.18 2011/02/19 08:30:53 acg // Andy Goodrich: Moved process queueing into trigger_static from // sc_event::notify. // // Revision 1.17 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.16 2011/02/18 20:10:44 acg // Philipp A. Hartmann: force return expression to be a bool to keep MSVC // happy. // // Revision 1.15 2011/02/17 19:52:45 acg // Andy Goodrich: // (1) Simplified process control usage. // (2) Changed dump_status() to dump_state() with new signature. // // Revision 1.14 2011/02/16 22:37:30 acg // Andy Goodrich: clean up to remove need for ps_disable_pending. // // Revision 1.13 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.12 2011/02/13 21:41:34 acg // Andy Goodrich: get the log messages for the previous check in correct. // // Revision 1.11 2011/02/13 21:32:24 acg // Andy Goodrich: moved sc_process_b::reset_process() implementation // from header to cpp file . Added dump_status() to print out the status of a // process. // // Revision 1.10 2011/02/11 13:25:24 acg // Andy Goodrich: Philipp A. Hartmann's changes: // (1) Removal of SC_CTHREAD method overloads. // (2) New exception processing code. // // Revision 1.9 2011/02/04 15:27:36 acg // Andy Goodrich: changes for suspend-resume semantics. // // Revision 1.8 2011/02/01 21:06:12 acg // Andy Goodrich: new layout for the process_state enum. // // Revision 1.7 2011/01/25 20:50:37 acg // Andy Goodrich: changes for IEEE 1666 2011. // // Revision 1.6 2011/01/19 23:21:50 acg // Andy Goodrich: changes for IEEE 1666 2011 // // Revision 1.5 2011/01/18 20:10:45 acg // Andy Goodrich: changes for IEEE1666_2011 semantics. // // Revision 1.4 2010/07/22 20:02:33 acg // Andy Goodrich: bug fixes. // // Revision 1.3 2009/05/22 16:06:29 acg // Andy Goodrich: process control updates. // // Revision 1.2 2008/05/22 17:06:26 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.11 2006/05/08 17:58:10 acg // Andy Goodrich: added David Long's forward declarations for friend // functions, methods, and operators to keep the Microsoft compiler happy. // // Revision 1.10 2006/04/28 23:29:01 acg // Andy Goodrich: added an sc_core:: prefix to SC_FUNC_PTR in the // SC_MAKE_FUNC_PTR macro to allow its transpareuse outside of the sc_core // namespace. // // Revision 1.9 2006/04/28 21:52:57 acg // Andy Goodrich: changed SC_MAKE_FUNC_PTR to use a static cast to address // and AIX issue wrt sc_module's inherited classes. // // Revision 1.8 2006/04/20 17:08:17 acg // Andy Goodrich: 3.0 style process changes. // // Revision 1.7 2006/04/11 23:13:21 acg // Andy Goodrich: Changes for reduced reset support that only includes // sc_cthread, but has preliminary hooks for expanding to method and thread // processes also. // // Revision 1.6 2006/03/13 20:26:50 acg // Andy Goodrich: Addition of forward class declarations, e.g., // sc_reset, to keep gcc 4.x happy. // // Revision 1.5 2006/01/31 20:09:10 acg // Andy Goodrich: added explaination of static vs dynamic waits to // sc_process_b::trigger_static. // // Revision 1.4 2006/01/24 20:49:05 acg // Andy Goodrich: changes to remove the use of deprecated features within the // simulator, and to issue warning messages when deprecated features are used. // // Revision 1.3 2006/01/13 18:44:30 acg // Added $Log to record CVS changes into the source. #endif // !defined(sc_process_h_INCLUDED) systemc-2.3.3/src/sysc/kernel/sc_name_gen.cpp0000644000175000017500000000666213360325173021075 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_name_gen.cpp -- Unique name generator. Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #include "sysc/kernel/sc_kernel_ids.h" #include "sysc/kernel/sc_name_gen.h" #include namespace sc_core { // ---------------------------------------------------------------------------- // CLASS : sc_name_gen // // Unique name generator class. // ---------------------------------------------------------------------------- sc_name_gen::sc_name_gen() : m_unique_name_map(), m_unique_name() {} sc_name_gen::~sc_name_gen() { sc_strhash::iterator it( m_unique_name_map ); for( ; ! it.empty(); it ++ ) { delete it.contents(); } m_unique_name_map.erase(); } // to generate unique names for objects in an MT-Safe way const char* sc_name_gen::gen_unique_name( const char* basename_, bool preserve_first ) { if( basename_ == 0 || *basename_ == 0 ) { SC_REPORT_ERROR( SC_ID_GEN_UNIQUE_NAME_, 0 ); basename_ = "unnamed"; // usually not reached } int* c = m_unique_name_map[basename_]; if( c == 0 ) { c = new int( 0 ); m_unique_name_map.insert( const_cast( basename_ ), c ); if (preserve_first) { m_unique_name = basename_; } else { std::stringstream sstr; sstr << basename_ << "_" << *c; sstr.str().swap( m_unique_name ); } } else { std::stringstream sstr; sstr << basename_ << "_" << ++ (*c); sstr.str().swap( m_unique_name ); } return m_unique_name.c_str(); } } // namespace sc_core // $Log: sc_name_gen.cpp,v $ // Revision 1.6 2011/08/26 20:46:10 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.5 2011/08/24 22:05:51 acg // Torsten Maehne: initialization changes to remove warnings. // // Revision 1.4 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.3 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.2 2008/05/22 17:06:26 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.3 2006/01/13 18:44:30 acg // Added $Log to record CVS changes into the source. // // Taf! systemc-2.3.3/src/sysc/kernel/sc_wait.cpp0000644000175000017500000003461513360325173020267 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_wait.cpp -- Wait() and related functions. Original Author: Stan Y. Liao, Synopsys, Inc. Martin Janssen, Synopsys, Inc. CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #include "sysc/kernel/sc_except.h" #include "sysc/kernel/sc_kernel_ids.h" #include "sysc/kernel/sc_cthread_process.h" #include "sysc/kernel/sc_thread_process.h" #include "sysc/kernel/sc_simcontext_int.h" #include "sysc/kernel/sc_wait.h" #include "sysc/utils/sc_utils_ids.h" namespace sc_core { // static sensitivity for SC_THREADs and SC_CTHREADs void warn_cthread_wait() { static bool warn_wait = true; if ( warn_wait ) { warn_wait = false; SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, "all waits except wait() and wait(N)\n" \ " are deprecated for SC_CTHREAD, " \ "use an SC_THREAD instead"); } } SC_API void wait( sc_simcontext* simc ) { sc_curr_proc_handle cpi = simc->get_curr_proc_info(); switch( cpi->kind ) { case SC_THREAD_PROC_: case SC_CTHREAD_PROC_: { reinterpret_cast( cpi->process_handle )->wait_cycles(); break; } default: SC_REPORT_ERROR( SC_ID_WAIT_NOT_ALLOWED_, "\n " "in SC_METHODs use next_trigger() instead" ); break; } } // dynamic sensitivity for SC_THREADs and SC_CTHREADs SC_API void wait( const sc_event& e, sc_simcontext* simc ) { sc_curr_proc_handle cpi = simc->get_curr_proc_info(); switch( cpi->kind ) { case SC_THREAD_PROC_: { reinterpret_cast( cpi->process_handle )->wait( e ); break; } case SC_CTHREAD_PROC_: { warn_cthread_wait(); sc_cthread_handle cthread_h = reinterpret_cast( cpi->process_handle ); cthread_h->wait( e ); cthread_h->wait_cycles(); break; } default: SC_REPORT_ERROR( SC_ID_WAIT_NOT_ALLOWED_, "\n " "in SC_METHODs use next_trigger() instead" ); break; } } SC_API void wait( const sc_event_or_list& el, sc_simcontext* simc ) { if( el.empty() ) { SC_REPORT_ERROR( SC_ID_EVENT_LIST_FAILED_, "wait() on empty event list not allowed" ); // may continue, if suppressed } sc_curr_proc_handle cpi = simc->get_curr_proc_info(); switch( cpi->kind ) { case SC_THREAD_PROC_: { reinterpret_cast( cpi->process_handle )->wait( el ); break; } case SC_CTHREAD_PROC_: { warn_cthread_wait(); SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, "wait(event_list) is deprecated for SC_CTHREAD, use SC_THREAD"); sc_cthread_handle cthread_h = reinterpret_cast( cpi->process_handle ); cthread_h->wait( el ); cthread_h->wait_cycles(); break; } default: SC_REPORT_ERROR( SC_ID_WAIT_NOT_ALLOWED_, "\n " "in SC_METHODs use next_trigger() instead" ); break; } } SC_API void wait( const sc_event_and_list& el, sc_simcontext* simc ) { if( el.empty() ) { SC_REPORT_ERROR( SC_ID_EVENT_LIST_FAILED_, "wait() on empty event list not allowed" ); // may continue, if suppressed } sc_curr_proc_handle cpi = simc->get_curr_proc_info(); switch( cpi->kind ) { case SC_THREAD_PROC_: { reinterpret_cast( cpi->process_handle )->wait( el ); break; } case SC_CTHREAD_PROC_: { warn_cthread_wait(); sc_cthread_handle cthread_h = reinterpret_cast( cpi->process_handle ); cthread_h->wait( el ); cthread_h->wait_cycles(); break; } default: SC_REPORT_ERROR( SC_ID_WAIT_NOT_ALLOWED_, "\n " "in SC_METHODs use next_trigger() instead" ); break; } } SC_API void wait( const sc_time& t, sc_simcontext* simc ) { sc_curr_proc_handle cpi = simc->get_curr_proc_info(); switch( cpi->kind ) { case SC_THREAD_PROC_: { reinterpret_cast( cpi->process_handle )->wait( t ); break; } case SC_CTHREAD_PROC_: { warn_cthread_wait(); sc_cthread_handle cthread_h = reinterpret_cast( cpi->process_handle ); cthread_h->wait( t ); cthread_h->wait_cycles(); break; } default: SC_REPORT_ERROR( SC_ID_WAIT_NOT_ALLOWED_, "\n " "in SC_METHODs use next_trigger() instead" ); break; } } SC_API void wait( const sc_time& t, const sc_event& e, sc_simcontext* simc ) { sc_curr_proc_handle cpi = simc->get_curr_proc_info(); switch( cpi->kind ) { case SC_THREAD_PROC_: { reinterpret_cast( cpi->process_handle )->wait( t, e ); break; } case SC_CTHREAD_PROC_: { warn_cthread_wait(); sc_cthread_handle cthread_h = reinterpret_cast( cpi->process_handle ); cthread_h->wait( t, e ); cthread_h->wait_cycles(); break; } default: SC_REPORT_ERROR( SC_ID_WAIT_NOT_ALLOWED_, "\n " "in SC_METHODs use next_trigger() instead" ); break; } } SC_API void wait( const sc_time& t, const sc_event_or_list& el, sc_simcontext* simc ) { if( el.empty() ) { SC_REPORT_ERROR( SC_ID_EVENT_LIST_FAILED_, "wait() on empty event list not allowed" ); // may continue, if suppressed } sc_curr_proc_handle cpi = simc->get_curr_proc_info(); switch( cpi->kind ) { case SC_THREAD_PROC_: { reinterpret_cast( cpi->process_handle )->wait( t, el ); break; } case SC_CTHREAD_PROC_: { warn_cthread_wait(); sc_cthread_handle cthread_h = reinterpret_cast( cpi->process_handle ); cthread_h->wait( t, el ); cthread_h->wait_cycles(); break; } default: SC_REPORT_ERROR( SC_ID_WAIT_NOT_ALLOWED_, "\n " "in SC_METHODs use next_trigger() instead" ); break; } } SC_API void wait( const sc_time& t, const sc_event_and_list& el, sc_simcontext* simc ) { if( el.empty() ) { SC_REPORT_ERROR( SC_ID_EVENT_LIST_FAILED_, "wait() on empty event list not allowed" ); // may continue, if suppressed } sc_curr_proc_handle cpi = simc->get_curr_proc_info(); switch( cpi->kind ) { case SC_THREAD_PROC_: { reinterpret_cast( cpi->process_handle )->wait( t, el ); break; } case SC_CTHREAD_PROC_: { warn_cthread_wait(); sc_cthread_handle cthread_h = reinterpret_cast( cpi->process_handle ); cthread_h->wait( t, el ); cthread_h->wait_cycles(); break; } default: SC_REPORT_ERROR( SC_ID_WAIT_NOT_ALLOWED_, "\n " "in SC_METHODs use next_trigger() instead" ); break; } } // static sensitivity for SC_METHODs SC_API void next_trigger( sc_simcontext* simc ) { sc_curr_proc_handle cpi = simc->get_curr_proc_info(); if( cpi->kind == SC_METHOD_PROC_ ) { reinterpret_cast( cpi->process_handle )->clear_trigger(); } else { SC_REPORT_ERROR( SC_ID_NEXT_TRIGGER_NOT_ALLOWED_, "\n " "in SC_THREADs and SC_CTHREADs use wait() instead" ); } } // dynamic sensitivity for SC_METHODs SC_API void next_trigger( const sc_event& e, sc_simcontext* simc ) { sc_curr_proc_handle cpi = simc->get_curr_proc_info(); if( cpi->kind == SC_METHOD_PROC_ ) { reinterpret_cast( cpi->process_handle )->next_trigger( e ); } else { SC_REPORT_ERROR( SC_ID_NEXT_TRIGGER_NOT_ALLOWED_, "\n " "in SC_THREADs and SC_CTHREADs use wait() instead" ); } } SC_API void next_trigger( const sc_event_or_list& el, sc_simcontext* simc ) { if( el.empty() ) { SC_REPORT_ERROR( SC_ID_EVENT_LIST_FAILED_, "next_trigger() on empty event list not allowed" ); // may continue, if suppressed } sc_curr_proc_handle cpi = simc->get_curr_proc_info(); if( cpi->kind == SC_METHOD_PROC_ ) { reinterpret_cast( cpi->process_handle )->next_trigger( el ); } else { SC_REPORT_ERROR( SC_ID_NEXT_TRIGGER_NOT_ALLOWED_, "\n " "in SC_THREADs and SC_CTHREADs use wait() instead" ); } } SC_API void next_trigger( const sc_event_and_list& el, sc_simcontext* simc ) { if( el.empty() ) { SC_REPORT_ERROR( SC_ID_EVENT_LIST_FAILED_, "next_trigger() on empty event list not allowed" ); // may continue, if suppressed } sc_curr_proc_handle cpi = simc->get_curr_proc_info(); if( cpi->kind == SC_METHOD_PROC_ ) { reinterpret_cast( cpi->process_handle )->next_trigger( el ); } else { SC_REPORT_ERROR( SC_ID_NEXT_TRIGGER_NOT_ALLOWED_, "\n " "in SC_THREADs and SC_CTHREADs use wait() instead" ); } } SC_API void next_trigger( const sc_time& t, sc_simcontext* simc ) { sc_curr_proc_handle cpi = simc->get_curr_proc_info(); if( cpi->kind == SC_METHOD_PROC_ ) { reinterpret_cast( cpi->process_handle )->next_trigger( t ); } else { SC_REPORT_ERROR( SC_ID_NEXT_TRIGGER_NOT_ALLOWED_, "\n " "in SC_THREADs and SC_CTHREADs use wait() instead" ); } } SC_API void next_trigger( const sc_time& t, const sc_event& e, sc_simcontext* simc ) { sc_curr_proc_handle cpi = simc->get_curr_proc_info(); if( cpi->kind == SC_METHOD_PROC_ ) { reinterpret_cast( cpi->process_handle )->next_trigger( t, e ); } else { SC_REPORT_ERROR( SC_ID_NEXT_TRIGGER_NOT_ALLOWED_, "\n " "in SC_THREADs and SC_CTHREADs use wait() instead" ); } } SC_API void next_trigger( const sc_time& t, const sc_event_or_list& el, sc_simcontext* simc) { if( el.empty() ) { SC_REPORT_ERROR( SC_ID_EVENT_LIST_FAILED_, "next_trigger() on empty event list not allowed" ); // may continue, if suppressed } sc_curr_proc_handle cpi = simc->get_curr_proc_info(); if( cpi->kind == SC_METHOD_PROC_ ) { reinterpret_cast( cpi->process_handle )->next_trigger( t, el ); } else { SC_REPORT_ERROR( SC_ID_NEXT_TRIGGER_NOT_ALLOWED_, "\n " "in SC_THREADs and SC_CTHREADs use wait() instead" ); } } SC_API void next_trigger(const sc_time& t, const sc_event_and_list& el, sc_simcontext* simc) { if( el.empty() ) { SC_REPORT_ERROR( SC_ID_EVENT_LIST_FAILED_, "next_trigger() on empty event list not allowed" ); // may continue, if suppressed } sc_curr_proc_handle cpi = simc->get_curr_proc_info(); if( cpi->kind == SC_METHOD_PROC_ ) { reinterpret_cast( cpi->process_handle )->next_trigger( t, el ); } else { SC_REPORT_ERROR( SC_ID_NEXT_TRIGGER_NOT_ALLOWED_, "\n " "in SC_THREADs and SC_CTHREADs use wait() instead" ); } } // for SC_METHODs and SC_THREADs and SC_CTHREADs SC_API bool timed_out( sc_simcontext* simc ) { static bool warn_timed_out=true; if ( warn_timed_out ) { warn_timed_out = false; SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, "timed_out() function is deprecated" ); } sc_curr_proc_handle cpi = simc->get_curr_proc_info(); return cpi->process_handle->timed_out(); } // misc. SC_API void sc_set_location( const char* file, int lineno, sc_simcontext* simc ) { sc_curr_proc_handle cpi = simc->get_curr_proc_info(); sc_process_b* handle = cpi->process_handle; handle->file = file; handle->lineno = lineno; } } // namespace sc_core /* $Log: sc_wait.cpp,v $ Revision 1.6 2011/08/26 20:46:11 acg Andy Goodrich: moved the modification log to the end of the file to eliminate source line number skew when check-ins are done. Revision 1.5 2011/02/18 20:27:14 acg Andy Goodrich: Updated Copyrights. Revision 1.4 2011/02/13 21:47:38 acg Andy Goodrich: update copyright notice. Revision 1.3 2011/01/18 20:10:45 acg Andy Goodrich: changes for IEEE1666_2011 semantics. Revision 1.2 2008/05/22 17:06:27 acg Andy Goodrich: updated copyright notice to include 2008. Revision 1.1.1.1 2006/12/15 20:20:05 acg SystemC 2.3 Revision 1.7 2006/02/02 20:20:39 acg Andy Goodrich: warnings for SC_THREAD waits. Revision 1.6 2006/02/01 01:36:54 acg Andy Goodrich: addition of deprecation comments for SC_CTHREAD waits other than wait() and wait(N). Revision 1.5 2006/01/31 22:17:40 acg Andy Goodrich: added deprecation warnings for SC_CTHREAD waits other than wait() and wait(N). Revision 1.4 2006/01/25 00:31:20 acg Andy Goodrich: Changed over to use a standard message id of SC_ID_IEEE_1666_DEPRECATION for all deprecation messages. Revision 1.3 2006/01/24 20:49:05 acg Andy Goodrich: changes to remove the use of deprecated features within the simulator, and to issue warning messages when deprecated features are used. Revision 1.2 2006/01/03 23:18:45 acg Changed copyright to include 2006. Revision 1.1.1.1 2005/12/19 23:16:44 acg First check in of SystemC 2.1 into its own archive. Revision 1.10 2005/09/02 19:03:30 acg Changes for dynamic processes. Removal of lambda support. Revision 1.9 2005/07/30 03:45:05 acg Changes from 2.1, including changes for sc_process_handle. Revision 1.8 2005/04/04 00:16:07 acg Changes for directory name change to sys from systemc. Changes for sc_string going to std::string. Changes for sc_pvector going to std::vector. Changes for reference pools for bit and part selections. Changes for const sc_concatref support. Revision 1.5 2004/09/27 20:49:10 acg Andy Goodrich, Forte Design Systems, Inc. - Added a $Log comment so that CVS checkin comments appear in the checkout source. */ // Taf! systemc-2.3.3/src/sysc/kernel/sc_runnable.h0000644000175000017500000001124113360325173020564 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_runnable.h -- Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #ifndef SC_RUNNABLE_H #define SC_RUNNABLE_H #include "sysc/kernel/sc_process.h" namespace sc_core { //============================================================================= // CLASS : sc_runnable // // Class that manages the ready-to-run queues. //============================================================================= class SC_API sc_runnable { public: sc_runnable(); ~sc_runnable(); inline void init(); inline void toggle_methods(); inline void toggle_threads(); inline void remove_method( sc_method_handle ); inline void remove_thread( sc_thread_handle ); inline void execute_method_next( sc_method_handle ); inline void execute_thread_next( sc_thread_handle ); inline void push_back_method( sc_method_handle ); inline void push_back_thread( sc_thread_handle ); inline void push_front_method( sc_method_handle ); inline void push_front_thread( sc_thread_handle ); inline bool is_initialized() const; inline bool is_empty() const; inline sc_method_handle pop_method(); inline sc_thread_handle pop_thread(); public: // diagnostics: void dump() const; private: sc_method_handle m_methods_push_head; sc_method_handle m_methods_push_tail; sc_method_handle m_methods_pop; sc_thread_handle m_threads_push_head; sc_thread_handle m_threads_push_tail; sc_thread_handle m_threads_pop; private: // disabled sc_runnable( const sc_runnable& ); sc_runnable& operator = ( const sc_runnable& ); }; } // namespace sc_core #endif /***************************************************************************** MODIFICATION LOG - modifiers, enter your name, affiliation, date and changes you are making here. Name, Affiliation, Date: Andy Goodrich, 30 June 2003, Forte Design Systems Description of Modification: Total rewrite using linked list rather than fixed vector. Name, Affiliation, Date: Bishnupriya Bhattacharya, Cadence Design Systems, 25 August, 2003 Description of Modification: Add tail pointers for m_methods_push and m_threads_push to maintain the same scheduler ordering as 2.0.1 *****************************************************************************/ // $Log: sc_runnable.h,v $ // Revision 1.9 2011/08/26 20:46:10 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.8 2011/04/08 18:26:07 acg // Andy Goodrich: added execute_method_next() to handle method dispatch // for asynchronous notifications that occur outside the evaluation phase. // // Revision 1.7 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.6 2011/02/13 21:47:38 acg // Andy Goodrich: update copyright notice. // // Revision 1.5 2011/02/02 06:37:03 acg // Andy Goodrich: removed toggle() method since it is no longer used. // // Revision 1.4 2011/02/01 21:09:13 acg // Andy Goodrich: addition of toggle_methods() and toggle_threads() calls. // // Revision 1.3 2011/01/25 20:50:37 acg // Andy Goodrich: changes for IEEE 1666 2011. // // Revision 1.2 2008/05/22 17:06:26 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.3 2006/01/13 18:44:30 acg // Added $Log to record CVS changes into the source. // Taf! systemc-2.3.3/src/sysc/kernel/sc_thread_process.cpp0000644000175000017500000011062313360325173022322 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_thread_process.cpp -- Thread process implementation Original Author: Andy Goodrich, Forte Design Systems, 4 August 2005 CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #include "sysc/kernel/sc_cmnhdr.h" #include "sysc/kernel/sc_constants.h" #include "sysc/kernel/sc_thread_process.h" #include "sysc/kernel/sc_process_handle.h" #include "sysc/kernel/sc_simcontext_int.h" #include "sysc/kernel/sc_module.h" #include "sysc/utils/sc_machine.h" // DEBUGGING MACROS: // // DEBUG_MSG(NAME,P,MSG) // MSG = message to print // NAME = name that must match the process for the message to print, or // null if the message should be printed unconditionally. // P = pointer to process message is for, or NULL in which case the // message will not print. #if 0 # include # define DEBUG_NAME "" # define DEBUG_MSG(NAME,P,MSG) \ { \ if ( P && ( (std::strlen(NAME)==0) || !std::strcmp(NAME,P->name())) ) \ std::cout << "**** " << sc_time_stamp() << " (" \ << sc_get_current_process_name("** NONE **") << "): " << MSG \ << " - " << P->name() << std::endl; \ } #else # define DEBUG_MSG(NAME,P,MSG) #endif //------------------------------------------------------------------------------ // user-defined default stack-size //------------------------------------------------------------------------------ #if defined(SC_OVERRIDE_DEFAULT_STACK_SIZE) # define SC_DEFAULT_STACK_SIZE_ SC_OVERRIDE_DEFAULT_STACK_SIZE //------------------------------------------------------------------------------ // architecture-specific default stack sizes //------------------------------------------------------------------------------ #elif !defined(SC_USE_PTHREADS) && (defined(__CYGWIN32__) || defined(__CYGWIN32)) # define SC_DEFAULT_STACK_SIZE_ 0x50000 #elif defined(SC_LONG_64) || defined(__x86_64__) || defined(__LP64__) || \ defined(_M_X64) || defined(_M_AMD64) # define SC_DEFAULT_STACK_SIZE_ 0x40000 #else # define SC_DEFAULT_STACK_SIZE_ 0x20000 #endif // SC_DEFAULT_STACK_SIZE_ //------------------------------------------------------------------------------ // force 16-byte alignment on coroutine entry functions, needed for // QuickThreads (32-bit, see also fixes in qt/md/{i386,iX86_64}.[hs]), // and MinGW32 / Cygwin32 compilers on Windows platforms #if defined(__GNUC__) && !defined(__ICC) && !defined(__x86_64__) && \ (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ > 1 ) # define SC_ALIGNED_STACK_ \ __attribute__((force_align_arg_pointer)) #else # define SC_ALIGNED_STACK_ /* empty */ #endif namespace sc_core { const int SC_DEFAULT_STACK_SIZE = SC_DEFAULT_STACK_SIZE_; #undef SC_DEFAULT_STACK_SIZE_ #undef SC_OVERRIDE_DEFAULT_STACK_SIZE //------------------------------------------------------------------------------ //"sc_thread_cor_fn" // // This function invokes the coroutine for the supplied object instance. //------------------------------------------------------------------------------ SC_ALIGNED_STACK_ void sc_thread_cor_fn( void* arg ) { sc_simcontext* simc_p = sc_get_curr_simcontext(); sc_thread_handle thread_h = reinterpret_cast( arg ); // PROCESS THE THREAD AND PROCESS ANY EXCEPTIONS THAT ARE THROWN: while( true ) { try { thread_h->semantics(); } catch( sc_user ) { continue; } catch( sc_halt ) { ::std::cout << "Terminating process " << thread_h->name() << ::std::endl; } catch( const sc_unwind_exception& ex ) { ex.clear(); if ( ex.is_reset() ) continue; } catch( ... ) { sc_report* err_p = sc_handle_exception(); thread_h->simcontext()->set_error( err_p ); } break; } sc_process_b* active_p = sc_get_current_process_b(); // REMOVE ALL TRACES OF OUR THREAD FROM THE SIMULATORS DATA STRUCTURES: thread_h->disconnect_process(); // IF WE AREN'T ACTIVE MAKE SURE WE WON'T EXECUTE: if ( thread_h->next_runnable() != 0 ) { simc_p->remove_runnable_thread(thread_h); } // IF WE ARE THE ACTIVE PROCESS ABORT OUR EXECUTION: if ( active_p == (sc_process_b*)thread_h ) { sc_core::sc_cor* x = simc_p->next_cor(); simc_p->cor_pkg()->abort( x ); } } //------------------------------------------------------------------------------ //"sc_thread_process::disable_process" // // This virtual method suspends this process and its children if requested to. // descendants = indicator of whether this process' children should also // be suspended //------------------------------------------------------------------------------ void sc_thread_process::disable_process( sc_descendant_inclusion_info descendants ) { // IF NEEDED PROPOGATE THE DISABLE REQUEST THROUGH OUR DESCENDANTS: if ( descendants == SC_INCLUDE_DESCENDANTS ) { const std::vector& children = get_child_objects(); int child_n = children.size(); for ( int child_i = 0; child_i < child_n; child_i++ ) { sc_process_b* child_p = dynamic_cast(children[child_i]); if ( child_p ) child_p->disable_process(descendants); } } // DON'T ALLOW CORNER CASE BY DEFAULT: if ( !sc_allow_process_control_corners ) { switch( m_trigger_type ) { case AND_LIST_TIMEOUT: case EVENT_TIMEOUT: case OR_LIST_TIMEOUT: case TIMEOUT: report_error(SC_ID_PROCESS_CONTROL_CORNER_CASE_, "attempt to disable a thread with timeout wait"); // may continue, if suppressed break; default: break; } } // DISABLE OUR OBJECT INSTANCE: m_state = m_state | ps_bit_disabled; // IF THIS CALL IS BEFORE THE SIMULATION DON'T RUN THE THREAD: if ( !sc_is_running() ) { m_state = m_state | ps_bit_ready_to_run; simcontext()->remove_runnable_thread(this); } } //------------------------------------------------------------------------------ //"sc_thread_process::enable_process" // // This method resumes the execution of this process, and if requested, its // descendants. If the process was suspended and has a resumption pending it // will be dispatched in the next delta cycle. Otherwise the state will be // adjusted to indicate it is no longer suspended, but no immediate execution // will occur. //------------------------------------------------------------------------------ void sc_thread_process::enable_process( sc_descendant_inclusion_info descendants ) { // IF NEEDED PROPOGATE THE ENABLE REQUEST THROUGH OUR DESCENDANTS: if ( descendants == SC_INCLUDE_DESCENDANTS ) { const std::vector& children = get_child_objects(); int child_n = children.size(); for ( int child_i = 0; child_i < child_n; child_i++ ) { sc_process_b* child_p = dynamic_cast(children[child_i]); if ( child_p ) child_p->enable_process(descendants); } } // ENABLE THIS OBJECT INSTANCE: // // If it was disabled and ready to run then put it on the run queue. m_state = m_state & ~ps_bit_disabled; if ( m_state == ps_bit_ready_to_run && sc_allow_process_control_corners ) { m_state = ps_normal; if ( next_runnable() == 0 ) simcontext()->push_runnable_thread(this); } } //------------------------------------------------------------------------------ //"sc_thread_process::kill_process" // // This method removes this object instance from use. It calls the // sc_process_b::kill_process() method to perform low level clean up. Then // it aborts this process if it is the active process. //------------------------------------------------------------------------------ void sc_thread_process::kill_process(sc_descendant_inclusion_info descendants ) { // IF THE SIMULATION HAS NOT BEEN INITIALIZED YET THAT IS AN ERROR: if ( !sc_is_running() ) { report_error( SC_ID_KILL_PROCESS_WHILE_UNITIALIZED_ ); return; } // IF NEEDED PROPOGATE THE KILL REQUEST THROUGH OUR DESCENDANTS: if ( descendants == SC_INCLUDE_DESCENDANTS ) { const std::vector children = get_child_objects(); int child_n = children.size(); for ( int child_i = 0; child_i < child_n; child_i++ ) { sc_process_b* child_p = dynamic_cast(children[child_i]); if ( child_p ) child_p->kill_process(descendants); } } // IF THE PROCESS IS CURRENTLY UNWINDING OR IS ALREADY A ZOMBIE // IGNORE THE KILL: if ( m_unwinding ) { SC_REPORT_WARNING( SC_ID_PROCESS_ALREADY_UNWINDING_, name() ); return; } if ( m_state & ps_bit_zombie ) return; // SET UP TO KILL THE PROCESS IF SIMULATION HAS STARTED: // // If the thread does not have a stack don't try the throw! if ( sc_is_running() && m_has_stack ) { m_throw_status = THROW_KILL; m_wait_cycle_n = 0; simcontext()->preempt_with(this); } // IF THE SIMULATION HAS NOT STARTED REMOVE TRACES OF OUR PROCESS FROM // EVENT QUEUES, ETC.: else { disconnect_process(); } } //------------------------------------------------------------------------------ //"sc_thread_process::prepare_for_simulation" // // This method prepares this object instance for simulation. It calls the // coroutine package to create the actual thread. //------------------------------------------------------------------------------ void sc_thread_process::prepare_for_simulation() { m_cor_p = simcontext()->cor_pkg()->create( m_stack_size, sc_thread_cor_fn, this ); m_cor_p->stack_protect( true ); } //------------------------------------------------------------------------------ //"sc_thread_process::resume_process" // // This method resumes the execution of this process, and if requested, its // descendants. If the process was suspended and has a resumption pending it // will be dispatched in the next delta cycle. Otherwise the state will be // adjusted to indicate it is no longer suspended, but no immediate execution // will occur. //------------------------------------------------------------------------------ void sc_thread_process::resume_process( sc_descendant_inclusion_info descendants ) { // IF NEEDED PROPOGATE THE RESUME REQUEST THROUGH OUR DESCENDANTS: if ( descendants == SC_INCLUDE_DESCENDANTS ) { const std::vector& children = get_child_objects(); int child_n = children.size(); for ( int child_i = 0; child_i < child_n; child_i++ ) { sc_process_b* child_p = dynamic_cast(children[child_i]); if ( child_p ) child_p->resume_process(descendants); } } // BY DEFAULT THE CORNER CASE IS AN ERROR: if ( !sc_allow_process_control_corners && (m_state & ps_bit_disabled) && (m_state & ps_bit_suspended) ) { m_state = m_state & ~ps_bit_suspended; report_error(SC_ID_PROCESS_CONTROL_CORNER_CASE_, "call to resume() on a disabled suspended thread"); // may continue, if suppressed } // CLEAR THE SUSPENDED BIT: m_state = m_state & ~ps_bit_suspended; // RESUME OBJECT INSTANCE IF IT IS READY TO RUN: if ( m_state & ps_bit_ready_to_run ) { m_state = m_state & ~ps_bit_ready_to_run; if ( next_runnable() == 0 ) simcontext()->push_runnable_thread(this); remove_dynamic_events(); // order important. } } //------------------------------------------------------------------------------ //"sc_thread_process::sc_thread_process" // // This is the object instance constructor for this class. //------------------------------------------------------------------------------ sc_thread_process::sc_thread_process( const char* name_p, bool free_host, SC_ENTRY_FUNC method_p, sc_process_host* host_p, const sc_spawn_options* opt_p ): sc_process_b( name_p ? name_p : sc_gen_unique_name("thread_p"), true, free_host, method_p, host_p, opt_p), m_cor_p(0), m_monitor_q(), m_stack_size(SC_DEFAULT_STACK_SIZE), m_wait_cycle_n(0) { // CHECK IF THIS IS AN sc_module-BASED PROCESS AND SIMULATION HAS STARTED: if ( dynamic_cast(host_p) != 0 && sc_is_running() ) { report_error( SC_ID_MODULE_THREAD_AFTER_START_ ); sc_abort(); // can't recover from here } // INITIALIZE VALUES: // // If there are spawn options use them. m_process_kind = SC_THREAD_PROC_; if (opt_p) { m_dont_init = opt_p->m_dont_initialize; if ( opt_p->m_stack_size ) m_stack_size = opt_p->m_stack_size; // traverse event sensitivity list for (unsigned int i = 0; i < opt_p->m_sensitive_events.size(); i++) { sc_sensitive::make_static_sensitivity( this, *opt_p->m_sensitive_events[i]); } // traverse port base sensitivity list for ( unsigned int i = 0; i < opt_p->m_sensitive_port_bases.size(); i++) { sc_sensitive::make_static_sensitivity( this, *opt_p->m_sensitive_port_bases[i]); } // traverse interface sensitivity list for ( unsigned int i = 0; i < opt_p->m_sensitive_interfaces.size(); i++) { sc_sensitive::make_static_sensitivity( this, *opt_p->m_sensitive_interfaces[i]); } // traverse event finder sensitivity list for ( unsigned int i = 0; i < opt_p->m_sensitive_event_finders.size(); i++) { sc_sensitive::make_static_sensitivity( this, *opt_p->m_sensitive_event_finders[i]); } // process any reset signal specification: opt_p->specify_resets(); } else { m_dont_init = false; } } //------------------------------------------------------------------------------ //"sc_thread_process::~sc_thread_process" // // This is the object instance constructor for this class. //------------------------------------------------------------------------------ sc_thread_process::~sc_thread_process() { // DESTROY THE COROUTINE FOR THIS THREAD: if( m_cor_p != 0 ) { m_cor_p->stack_protect( false ); delete m_cor_p; m_cor_p = 0; } // Remove from simcontext, if not spawned during simulation if( m_dynamic_proc != SPAWN_SIM ) { simcontext()->remove_process(this); } } //------------------------------------------------------------------------------ //"sc_thread_process::signal_monitors" // // This methods signals the list of monitors for this object instance. //------------------------------------------------------------------------------ void sc_thread_process::signal_monitors(int type) { int mon_n; // # of monitors present. mon_n = m_monitor_q.size(); for ( int mon_i = 0; mon_i < mon_n; mon_i++ ) m_monitor_q[mon_i]->signal(this, type); } //------------------------------------------------------------------------------ //"sc_thread_process::suspend_process" // // This virtual method suspends this process and its children if requested to. // descendants = indicator of whether this process' children should also // be suspended //------------------------------------------------------------------------------ void sc_thread_process::suspend_process( sc_descendant_inclusion_info descendants ) { // IF NEEDED PROPOGATE THE SUSPEND REQUEST THROUGH OUR DESCENDANTS: if ( descendants == SC_INCLUDE_DESCENDANTS ) { const std::vector& children = get_child_objects(); int child_n = children.size(); for ( int child_i = 0; child_i < child_n; child_i++ ) { sc_process_b* child_p = dynamic_cast(children[child_i]); if ( child_p ) child_p->suspend_process(descendants); } } // CORNER CASE CHECKS, THE FOLLOWING ARE ERRORS: // (a) if this thread has a reset_signal_is specification // (b) if this thread is in synchronous reset if ( !sc_allow_process_control_corners && m_has_reset_signal ) { report_error(SC_ID_PROCESS_CONTROL_CORNER_CASE_, "attempt to suspend a thread that has a reset signal"); // may continue, if suppressed } else if ( !sc_allow_process_control_corners && m_sticky_reset ) { report_error(SC_ID_PROCESS_CONTROL_CORNER_CASE_, "attempt to suspend a thread in synchronous reset"); // may continue, if suppressed } // SUSPEND OUR OBJECT INSTANCE: // // (1) If we are on the runnable queue then set suspended and ready_to_run, // and remove ourselves from the run queue. // (2) If this is a self-suspension then a resume should cause immediate // scheduling of the process, and we need to call suspend_me() here. m_state = m_state | ps_bit_suspended; if ( next_runnable() != 0 ) { m_state = m_state | ps_bit_ready_to_run; simcontext()->remove_runnable_thread( this ); } if ( sc_get_current_process_b() == dynamic_cast(this) ) { m_state = m_state | ps_bit_ready_to_run; suspend_me(); } } //------------------------------------------------------------------------------ //"sc_thread_process::throw_reset" // // This virtual method is invoked when an reset is to be thrown. The // method will cancel any dynamic waits. If the reset is asynchronous it will // queue this object instance to be executed. //------------------------------------------------------------------------------ void sc_thread_process::throw_reset( bool async ) { // IF THE PROCESS IS CURRENTLY UNWINDING OR IS ALREADY A ZOMBIE // IGNORE THE RESET: if ( m_unwinding ) { SC_REPORT_WARNING( SC_ID_PROCESS_ALREADY_UNWINDING_, name() ); return; } if ( m_state & ps_bit_zombie ) return; // Set the throw type and clear any pending dynamic events: m_throw_status = async ? THROW_ASYNC_RESET : THROW_SYNC_RESET; m_wait_cycle_n = 0; // If this is an asynchronous reset: // // (a) Cancel any dynamic events // (b) Set the thread up for execution: // (i) If we are in the execution phase do it now. // (ii) If we are not queue it to execute next when we hit // the execution phase. if ( async ) { m_state = m_state & ~ps_bit_ready_to_run; remove_dynamic_events(); if ( simcontext()->evaluation_phase() ) { simcontext()->preempt_with( this ); } else { if ( is_runnable() ) simcontext()->remove_runnable_thread(this); simcontext()->execute_thread_next(this); } } } //------------------------------------------------------------------------------ //"sc_thread_process::throw_user" // // This virtual method is invoked when a user exception is to be thrown. // If requested it will also throw the exception to the children of this // object instance. The order of dispatch for the processes that are // thrown the exception is from youngest child to oldest child and then // this process instance. This means that this instance will be pushed onto // the front of the simulator's runnable queue and then the children will // be processed recursively. // helper_p = helper object to use to throw the exception. // descendants = indicator of whether this process' children should also // be suspended //------------------------------------------------------------------------------ void sc_thread_process::throw_user( const sc_throw_it_helper& helper, sc_descendant_inclusion_info descendants ) { // IF THE SIMULATION IS NOT ACTAULLY RUNNING THIS IS AN ERROR: if ( sc_get_status() != SC_RUNNING ) { report_error( SC_ID_THROW_IT_WHILE_NOT_RUNNING_ ); return; } // IF NEEDED PROPOGATE THE THROW REQUEST THROUGH OUR DESCENDANTS: if ( descendants == SC_INCLUDE_DESCENDANTS ) { const std::vector children = get_child_objects(); int child_n = children.size(); for ( int child_i = 0; child_i < child_n; child_i++ ) { sc_process_b* child_p = dynamic_cast(children[child_i]); if ( child_p ) { DEBUG_MSG(DEBUG_NAME,child_p,"about to throw user on"); child_p->throw_user(helper, descendants); } } } // IF THE PROCESS IS CURRENTLY UNWINDING IGNORE THE THROW: if ( m_unwinding ) { SC_REPORT_WARNING( SC_ID_PROCESS_ALREADY_UNWINDING_, name() ); return; } // SET UP THE THROW REQUEST FOR THIS OBJECT INSTANCE AND QUEUE IT FOR // EXECUTION: if( m_has_stack ) { remove_dynamic_events(); DEBUG_MSG(DEBUG_NAME,this,"throwing user exception to"); m_throw_status = THROW_USER; if ( m_throw_helper_p != 0 ) delete m_throw_helper_p; m_throw_helper_p = helper.clone(); simcontext()->preempt_with( this ); } else { SC_REPORT_WARNING( SC_ID_THROW_IT_IGNORED_, name() ); } } //------------------------------------------------------------------------------ //"sc_thread_process::trigger_dynamic" // // This method sets up a dynamic trigger on an event. // // Notes: // (1) This method is identical to sc_method_process::trigger_dynamic(), // but they cannot be combined as sc_process_b::trigger_dynamic() // because the signatures things like sc_event::remove_dynamic() // have different overloads for sc_thread_process* and sc_method_process*. // So if you change code here you'll also need to change it in // sc_method_process.cpp. // // Result is true if this process should be removed from the event's list, // false if not. //------------------------------------------------------------------------------ bool sc_thread_process::trigger_dynamic( sc_event* e ) { // No time outs yet, and keep gcc happy. m_timed_out = false; // Escape cases: // (a) If this thread issued the notify() don't schedule it for // execution, but leave the sensitivity in place. // (b) If this thread is already runnable can't trigger an event. // not possible for thread processes! #if 0 // ! defined( SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS ) if ( sc_get_current_process_b() == (sc_process_b*)this ) { report_immediate_self_notification(); return false; } #endif // SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS if( is_runnable() ) return true; // If a process is disabled then we ignore any events, leaving them enabled: // // But if this is a time out event we need to remove both it and the // event that was being waited for. if ( m_state & ps_bit_disabled ) { if ( e == m_timeout_event_p ) { remove_dynamic_events( true ); return true; } else { return false; } } // Process based on the event type and current process state: // // Every case needs to set 'rc' and continue on to the end of // this method to allow suspend processing to work correctly. switch( m_trigger_type ) { case EVENT: m_event_p = 0; m_trigger_type = STATIC; break; case AND_LIST: -- m_event_count; if ( m_event_count == 0 ) { m_event_list_p->auto_delete(); m_event_list_p = 0; m_trigger_type = STATIC; } else { return true; } break; case OR_LIST: m_event_list_p->remove_dynamic( this, e ); m_event_list_p->auto_delete(); m_event_list_p = 0; m_trigger_type = STATIC; break; case TIMEOUT: m_trigger_type = STATIC; break; case EVENT_TIMEOUT: if ( e == m_timeout_event_p ) { m_timed_out = true; m_event_p->remove_dynamic( this ); m_event_p = 0; m_trigger_type = STATIC; } else { m_timeout_event_p->cancel(); m_timeout_event_p->reset(); m_event_p = 0; m_trigger_type = STATIC; } break; case OR_LIST_TIMEOUT: if ( e == m_timeout_event_p ) { m_timed_out = true; m_event_list_p->remove_dynamic( this, e ); m_event_list_p->auto_delete(); m_event_list_p = 0; m_trigger_type = STATIC; } else { m_timeout_event_p->cancel(); m_timeout_event_p->reset(); m_event_list_p->remove_dynamic( this, e ); m_event_list_p->auto_delete(); m_event_list_p = 0; m_trigger_type = STATIC; } break; case AND_LIST_TIMEOUT: if ( e == m_timeout_event_p ) { m_timed_out = true; m_event_list_p->remove_dynamic( this, e ); m_event_list_p->auto_delete(); m_event_list_p = 0; m_trigger_type = STATIC; } else { -- m_event_count; if ( m_event_count == 0 ) { m_timeout_event_p->cancel(); m_timeout_event_p->reset(); // no need to remove_dynamic m_event_list_p->auto_delete(); m_event_list_p = 0; m_trigger_type = STATIC; } else { return true; } } break; case STATIC: { // we should never get here, but throw_it() can make it happen. SC_REPORT_WARNING(SC_ID_NOT_EXPECTING_DYNAMIC_EVENT_NOTIFY_, name()); return true; } } // If we get here then the thread is has satisfied its wait criteria, if // its suspended mark its state as ready to run. If its not suspended then // push it onto the runnable queue. if ( (m_state & ps_bit_suspended) ) { m_state = m_state | ps_bit_ready_to_run; } else { simcontext()->push_runnable_thread(this); } return true; } //------------------------------------------------------------------------------ //"sc_set_stack_size" // //------------------------------------------------------------------------------ SC_API void sc_set_stack_size( sc_thread_handle thread_h, std::size_t size ) { thread_h->set_stack_size( size ); } #undef DEBUG_MSG #undef DEBUG_NAME } // namespace sc_core /***************************************************************************** MODIFICATION LOG - modifiers, enter your name, affiliation, date and changes you are making here. Name, Affiliation, Date: Description of Modification: *****************************************************************************/ // $Log: sc_thread_process.cpp,v $ // Revision 1.57 2011/08/24 22:05:51 acg // Torsten Maehne: initialization changes to remove warnings. // // Revision 1.56 2011/08/07 19:08:04 acg // Andy Goodrich: moved logs to end of file so line number synching works // better between versions. // // Revision 1.55 2011/08/04 17:16:22 acg // Philipp A. Hartmann: fix handling of child objects in kill routine, need // to use a copy rather than a reference. // // Revision 1.53 2011/07/29 22:45:38 acg // Philipp A. Hartmann: changes to handle case where a process control // invocation on a child process causes the list of child processes to change. // // Revision 1.52 2011/07/24 11:27:04 acg // Andy Goodrich: moved the check for unwinding processes until after the // descendants have been processed in throw_user and kill. // // Revision 1.51 2011/07/24 11:20:03 acg // Philipp A. Hartmann: process control error message improvements: // (1) Downgrade error to warning for re-kills of processes. // (2) Add process name to process messages. // (3) drop some superfluous colons in messages. // // Revision 1.50 2011/05/09 04:07:49 acg // Philipp A. Hartmann: // (1) Restore hierarchy in all phase callbacks. // (2) Ensure calls to before_end_of_elaboration. // // Revision 1.49 2011/05/05 17:45:27 acg // Philip A. Hartmann: changes in WIN64 support. // Andy Goodrich: additional DEBUG_MSG instances to trace process handling. // // Revision 1.48 2011/04/19 15:04:27 acg // Philipp A. Hartmann: clean up SC_ID messages. // // Revision 1.47 2011/04/19 02:39:09 acg // Philipp A. Hartmann: added checks for additional throws during stack unwinds. // // Revision 1.46 2011/04/14 22:33:43 acg // Andy Goodrich: added missing checks for a process being a zombie. // // Revision 1.45 2011/04/13 02:45:11 acg // Andy Goodrich: eliminated warning message that occurred if the DEBUG_MSG // macro was used. // // Revision 1.44 2011/04/11 22:04:33 acg // Andy Goodrich: use the DEBUG_NAME macro for DEBUG_MSG messages. // // Revision 1.43 2011/04/10 22:12:32 acg // Andy Goodrich: adding debugging macros. // // Revision 1.42 2011/04/08 22:40:26 acg // Andy Goodrich: moved the reset event notification code out of throw_reset() // and into suspend_me. // // Revision 1.41 2011/04/08 18:24:07 acg // Andy Goodrich: fix asynchronous reset dispatch and when the reset_event() // is fired. // // Revision 1.40 2011/04/05 20:50:57 acg // Andy Goodrich: // (1) changes to make sure that event(), posedge() and negedge() only // return true if the clock has not moved. // (2) fixes for method self-resumes. // (3) added SC_PRERELEASE_VERSION // (4) removed kernel events from the object hierarchy, added // sc_hierarchy_name_exists(). // // Revision 1.39 2011/04/01 22:30:39 acg // Andy Goodrich: change hard assertion to warning for trigger_dynamic() // getting called when there is only STATIC sensitivity. This can result // because of sc_process_handle::throw_it(). // // Revision 1.38 2011/03/23 16:17:52 acg // Andy Goodrich: don't emit an error message for a resume on a disabled // process that is not suspended. // // Revision 1.37 2011/03/20 13:43:23 acg // Andy Goodrich: added async_signal_is() plus suspend() as a corner case. // // Revision 1.36 2011/03/08 20:49:31 acg // Andy Goodrich: implement coarse checking for synchronous reset - suspend // interaction. // // Revision 1.35 2011/03/08 20:32:28 acg // Andy Goodrich: implemented "coarse" checking for undefined process // control interactions. // // Revision 1.34 2011/03/07 18:25:19 acg // Andy Goodrich: tightening of check for resume on a disabled process to // only produce an error if it is ready to run. // // Revision 1.33 2011/03/07 17:38:44 acg // Andy Goodrich: tightening up of checks for undefined interaction between // synchronous reset and suspend. // // Revision 1.32 2011/03/06 23:30:13 acg // Andy Goodrich: refining suspend - sync reset corner case checking so that // the following are error situations: // (1) Calling suspend on a process with a reset_signal_is() specification // or sync_reset_on() is active. // (2) Calling sync_reset_on() on a suspended process. // // Revision 1.31 2011/03/06 19:57:11 acg // Andy Goodrich: refinements for the illegal suspend - synchronous reset // interaction. // // Revision 1.30 2011/03/06 16:47:09 acg // Andy Goodrich: changes for testing sync_reset - suspend corner cases. // // Revision 1.29 2011/03/06 15:59:23 acg // Andy Goodrich: added process control corner case checks. // // Revision 1.28 2011/03/05 19:44:20 acg // Andy Goodrich: changes for object and event naming and structures. // // Revision 1.27 2011/02/19 08:30:53 acg // Andy Goodrich: Moved process queueing into trigger_static from // sc_event::notify. // // Revision 1.26 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.25 2011/02/17 19:54:33 acg // Andy Goodrich: // (1) Changed signature of trigger_dynamic() back to bool, and moved // run queue processing into trigger_dynamic. // (2) Simplified process control usage. // // Revision 1.24 2011/02/16 22:37:31 acg // Andy Goodrich: clean up to remove need for ps_disable_pending. // // Revision 1.23 2011/02/14 17:51:40 acg // Andy Goodrich: proper pushing an poppping of the module hierarchy for // start_of_simulation() and end_of_simulation. // // Revision 1.22 2011/02/13 23:09:58 acg // Andy Goodrich: only remove dynamic events for asynchronous resets. // // Revision 1.21 2011/02/13 21:47:38 acg // Andy Goodrich: update copyright notice. // // Revision 1.20 2011/02/13 21:37:13 acg // Andy Goodrich: removed temporary diagnostic. Also there is // remove_dynamic_events() call in reset code. // // Revision 1.19 2011/02/13 21:35:09 acg // Andy Goodrich: added error messages for throws before the simulator is // initialized. // // Revision 1.18 2011/02/11 13:25:24 acg // Andy Goodrich: Philipp A. Hartmann's changes: // (1) Removal of SC_CTHREAD method overloads. // (2) New exception processing code. // // Revision 1.17 2011/02/08 08:18:16 acg // Andy Goodrich: removed obsolete code. // // Revision 1.16 2011/02/07 19:17:20 acg // Andy Goodrich: changes for IEEE 1666 compatibility. // // Revision 1.15 2011/02/04 15:27:36 acg // Andy Goodrich: changes for suspend-resume semantics. // // Revision 1.14 2011/02/01 23:01:53 acg // Andy Goodrich: removed dead code. // // Revision 1.13 2011/02/01 21:16:36 acg // Andy Goodrich: // (1) New version of trigger_dynamic() to implement new return codes and // proper processing of events with new dynamic process rules. // (2) Recoding of kill_process(), throw_user() and reset support to // consolidate preemptive thread execution in sc_simcontext::preempt_with(). // // Revision 1.12 2011/01/25 20:50:37 acg // Andy Goodrich: changes for IEEE 1666 2011. // // Revision 1.11 2011/01/20 16:52:20 acg // Andy Goodrich: changes for IEEE 1666 2011. // // Revision 1.10 2011/01/19 23:21:50 acg // Andy Goodrich: changes for IEEE 1666 2011 // // Revision 1.9 2011/01/18 20:10:45 acg // Andy Goodrich: changes for IEEE1666_2011 semantics. // // Revision 1.8 2011/01/06 18:02:16 acg // Andy Goodrich: added check for disabled thread to trigger_dynamic(). // // Revision 1.7 2010/11/20 17:10:57 acg // Andy Goodrich: reset processing changes for new IEEE 1666 standard. // // Revision 1.6 2010/07/22 20:02:33 acg // Andy Goodrich: bug fixes. // // Revision 1.5 2009/07/28 01:10:53 acg // Andy Goodrich: updates for 2.3 release candidate. // // Revision 1.4 2009/05/22 16:06:29 acg // Andy Goodrich: process control updates. // // Revision 1.3 2008/05/22 17:06:06 acg // Andy Goodrich: formatting and comments. // // Revision 1.2 2007/09/20 20:32:35 acg // Andy Goodrich: changes to the semantics of throw_it() to match the // specification. A call to throw_it() will immediately suspend the calling // thread until all the throwees have executed. At that point the calling // thread will be restarted before the execution of any other threads. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.8 2006/04/20 17:08:17 acg // Andy Goodrich: 3.0 style process changes. // // Revision 1.7 2006/04/11 23:13:21 acg // Andy Goodrich: Changes for reduced reset support that only includes // sc_cthread, but has preliminary hooks for expanding to method and thread // processes also. // // Revision 1.6 2006/03/21 00:00:34 acg // Andy Goodrich: changed name of sc_get_current_process_base() to be // sc_get_current_process_b() since its returning an sc_process_b instance. // // Revision 1.5 2006/01/26 21:04:55 acg // Andy Goodrich: deprecation message changes and additional messages. // // Revision 1.4 2006/01/24 20:49:05 acg // Andy Goodrich: changes to remove the use of deprecated features within the // simulator, and to issue warning messages when deprecated features are used. // // Revision 1.3 2006/01/13 18:44:30 acg // Added $Log to record CVS changes into the source. // systemc-2.3.3/src/sysc/kernel/sc_attribute.cpp0000644000175000017500000001123413360325173021316 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_attribute.cpp -- Attribute classes. Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 CHANGE LOG APPEARS AT THE END OF THE FILE *****************************************************************************/ #include "sysc/kernel/sc_attribute.h" namespace sc_core { // ---------------------------------------------------------------------------- // CLASS : sc_attr_base // // Attribute base class. // ---------------------------------------------------------------------------- // constructors sc_attr_base::sc_attr_base( const std::string& name_ ) : m_name( name_ ) {} sc_attr_base::sc_attr_base( const sc_attr_base& a ) : m_name( a.m_name ) {} // destructor (does nothing) sc_attr_base::~sc_attr_base() {} // get the name const std::string& sc_attr_base::name() const { return m_name; } // ---------------------------------------------------------------------------- // CLASS : sc_attr_cltn // // Attribute collection class. Stores pointers to attributes. // Note: iterate over the collection by using iterators. // ---------------------------------------------------------------------------- // constructors sc_attr_cltn::sc_attr_cltn() : m_cltn() {} sc_attr_cltn::sc_attr_cltn( const sc_attr_cltn& a ) : m_cltn( a.m_cltn ) {} // destructor sc_attr_cltn::~sc_attr_cltn() { remove_all(); } // add attribute to the collection. // returns 'true' if the name of the attribute is unique, // returns 'false' otherwise (attribute is not added). bool sc_attr_cltn::push_back( sc_attr_base* attribute_ ) { if( attribute_ == 0 ) { return false; } for( int i = m_cltn.size() - 1; i >= 0; -- i ) { if( attribute_->name() == m_cltn[i]->name() ) { return false; } } m_cltn.push_back( attribute_ ); return true; } // get attribute by name. // returns pointer to attribute, or 0 if name does not exist. sc_attr_base* sc_attr_cltn::operator [] ( const std::string& name_ ) { for( int i = m_cltn.size() - 1; i >= 0; -- i ) { if( name_ == m_cltn[i]->name() ) { return m_cltn[i]; } } return 0; } const sc_attr_base* sc_attr_cltn::operator [] ( const std::string& name_ ) const { for( int i = m_cltn.size() - 1; i >= 0; -- i ) { if( name_ == m_cltn[i]->name() ) { return m_cltn[i]; } } return 0; } // remove attribute by name. // returns pointer to attribute, or 0 if name does not exist. sc_attr_base* sc_attr_cltn::remove( const std::string& name_ ) { for( int i = m_cltn.size() - 1; i >= 0; -- i ) { if( name_ == m_cltn[i]->name() ) { sc_attr_base* attribute = m_cltn[i]; std::swap( m_cltn[i], m_cltn.back() ); m_cltn.pop_back(); return attribute; } } return 0; } // remove all attributes void sc_attr_cltn::remove_all() { m_cltn.clear(); } } // namespace sc_core // $Log: sc_attribute.cpp,v $ // Revision 1.7 2011/08/26 20:46:08 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.6 2011/08/24 22:05:50 acg // Torsten Maehne: initialization changes to remove warnings. // // Revision 1.5 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.4 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.3 2010/07/22 20:02:33 acg // Andy Goodrich: bug fixes. // // Revision 1.2 2008/05/22 17:06:24 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.4 2006/01/16 22:27:08 acg // Test of $Log comment. // // Revision 1.3 2006/01/13 18:44:29 acg // Added $Log to record CVS changes into the source. // Taf! systemc-2.3.3/src/sysc/kernel/sc_simcontext_int.h0000644000175000017500000002730213360325173022032 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_simcontext_int.h -- For inline definitions of some utility functions. DO NOT EXPORT THIS INCLUDE FILE. Include this file after "sc_process_int.h" so that we can get the base class right. Original Author: Stan Y. Liao, Synopsys, Inc. CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #ifndef SC_SIMCONTEXT_INT_H #define SC_SIMCONTEXT_INT_H #include "sysc/kernel/sc_simcontext.h" #include "sysc/kernel/sc_runnable.h" #include "sysc/kernel/sc_runnable_int.h" // DEBUGGING MACROS: // // DEBUG_MSG(NAME,P,MSG) // MSG = message to print // NAME = name that must match the process for the message to print, or // null if the message should be printed unconditionally. // P = pointer to process message is for, or NULL in which case the // message will not print. #if 0 # include # define DEBUG_NAME "" # define DEBUG_MSG(NAME,P,MSG) \ { \ if ( P && ( (std::strlen(NAME)==0) || !std::strcmp(NAME,P->name())) ) \ std::cout << "**** " << sc_time_stamp() << " (" \ << sc_get_current_process_name("** NONE **") << "): " << MSG \ << " - " << P->name() << std::endl; \ } #else # define DEBUG_MSG(NAME,P,MSG) #endif namespace sc_core { inline const char* sc_get_current_process_name( const char * if_empty = NULL ) { sc_process_b* active_p; // active process to get name of. const char* result; // name of active process. active_p = sc_get_curr_simcontext()->get_curr_proc_info()->process_handle; if ( active_p ) result = active_p->name(); else result = if_empty; return result; } // We use m_current_writer rather than m_curr_proc_info.process_handle to // return the active process for sc_signal::check_write since that lets // us turn it off a library compile time, and only incur the overhead at // the time of process switches rather than having to interrogate an // additional switch every time a signal is written. inline void sc_simcontext::set_curr_proc( sc_process_b* process_h ) { m_curr_proc_info.process_handle = process_h; m_curr_proc_info.kind = process_h->proc_kind(); m_current_writer = (m_write_check != SC_SIGNAL_WRITE_CHECK_DISABLE_) ? process_h : 0; } inline void sc_simcontext::reset_curr_proc() { m_curr_proc_info.process_handle = 0; m_curr_proc_info.kind = SC_NO_PROC_; m_current_writer = 0; sc_process_b::m_last_created_process_p = 0; } inline void sc_simcontext::execute_method_next( sc_method_handle method_h ) { m_runnable->execute_method_next( method_h ); } inline void sc_simcontext::execute_thread_next( sc_thread_handle thread_h ) { m_runnable->execute_thread_next( thread_h ); } // +---------------------------------------------------------------------------- // |"sc_simcontext::preempt_with" // | // | This method executes the supplied thread immediately, suspending the // | caller. After executing the supplied thread the caller's execution will // | be restored. It is used to allow a thread to immediately throw an // | exception, e.g., when the thread's kill_process() method was called. // | There are three cases to consider: // | (1) The caller is a method, e.g., murder by method. // | (2) The caller is another thread instance, e.g., murder by thread. // | (3) The caller is this thread instance, e.g., suicide. // | // | Arguments: // | thread_h -> thread to be executed. // +---------------------------------------------------------------------------- inline void sc_simcontext::preempt_with( sc_thread_handle thread_h ) { sc_thread_handle active_p; // active thread or null. sc_curr_proc_info caller_info; // process info for caller. // Determine the active process and take the thread to be run off the // run queue, if its there, since we will be explicitly causing its // execution. active_p = dynamic_cast(sc_get_current_process_b()); if ( thread_h->next_runnable() != NULL ) remove_runnable_thread( thread_h ); // THE CALLER IS A METHOD: // // (a) Set the current process information to our thread. // (b) If the method was called by an invoker thread push that thread // onto the front of the run queue, this will cause the method // to be resumed after this thread waits. // (c) Invoke our thread directly by-passing the run queue. // (d) Restore the process info to the caller. // (e) Check to see if the calling method should throw an exception // because of activity that occurred during the preemption. if ( active_p == NULL ) { std::vector* invokers_p; // active invokers stack. sc_thread_handle invoke_thread_p; // latest invocation thread. sc_method_handle method_p; // active method. method_p = dynamic_cast(sc_get_current_process_b()); invokers_p = &get_active_invokers(); caller_info = m_curr_proc_info; if ( invokers_p->size() != 0 ) { invoke_thread_p = invokers_p->back(); DEBUG_MSG( DEBUG_NAME, invoke_thread_p, "queueing invocation thread to execute next" ); execute_thread_next(invoke_thread_p); } DEBUG_MSG( DEBUG_NAME, thread_h, "preempting method with thread" ); set_curr_proc( (sc_process_b*)thread_h ); m_cor_pkg->yield( thread_h->m_cor_p ); m_curr_proc_info = caller_info; DEBUG_MSG(DEBUG_NAME, thread_h, "back from preempting method w/thread"); method_p->check_for_throws(); } // CALLER IS A THREAD, BUT NOT THE THREAD TO BE RUN: // // (a) Push the calling thread onto the front of the runnable queue // so it be the first thread to be run after this thread. // (b) Push the thread to be run onto the front of the runnable queue so // it will execute when we suspend the calling thread. // (c) Suspend the active thread. else if ( active_p != thread_h ) { DEBUG_MSG( DEBUG_NAME, thread_h, "preempting active thread with thread" ); execute_thread_next( active_p ); execute_thread_next( thread_h ); active_p->suspend_me(); } // CALLER IS THE THREAD TO BE RUN: // // (a) Push the thread to be run onto the front of the runnable queue so // it will execute when we suspend the calling thread. // (b) Suspend the active thread. else { DEBUG_MSG(DEBUG_NAME,thread_h,"self preemption of active thread"); execute_thread_next( thread_h ); active_p->suspend_me(); } } inline void sc_simcontext::push_runnable_method( sc_method_handle method_h ) { m_runnable->push_back_method( method_h ); } inline void sc_simcontext::push_runnable_method_front( sc_method_handle method_h ) { m_runnable->push_front_method( method_h ); } inline void sc_simcontext::push_runnable_thread( sc_thread_handle thread_h ) { m_runnable->push_back_thread( thread_h ); } inline void sc_simcontext::push_runnable_thread_front( sc_thread_handle thread_h ) { m_runnable->push_front_thread( thread_h ); } inline sc_method_handle sc_simcontext::pop_runnable_method() { sc_method_handle method_h = m_runnable->pop_method(); if( method_h == 0 ) { reset_curr_proc(); return 0; } set_curr_proc( (sc_process_b*)method_h ); return method_h; } inline sc_thread_handle sc_simcontext::pop_runnable_thread() { sc_thread_handle thread_h = m_runnable->pop_thread(); if( thread_h == 0 ) { reset_curr_proc(); return 0; } set_curr_proc( (sc_process_b*)thread_h ); return thread_h; } inline void sc_simcontext::remove_runnable_method( sc_method_handle method_h ) { m_runnable->remove_method( method_h ); } inline void sc_simcontext::remove_runnable_thread( sc_thread_handle thread_h ) { m_runnable->remove_thread( thread_h ); } inline std::vector& sc_simcontext::get_active_invokers() { return m_active_invokers; } inline bool sc_simcontext::write_check_conflicts_only() const { return ( m_write_check == SC_SIGNAL_WRITE_CHECK_CONFLICT_ ); } // ---------------------------------------------------------------------------- extern SC_API void sc_defunct_process_function( sc_module* ); } // namespace sc_core #undef DEBUG_MSG #undef DEBUG_NAME // $Log: sc_simcontext_int.h,v $ // Revision 1.14 2011/08/29 18:04:32 acg // Philipp A. Hartmann: miscellaneous clean ups. // // Revision 1.13 2011/08/26 20:46:11 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.12 2011/07/29 22:45:06 acg // Andy Goodrich: added invocation of sc_method_process::check_for_throws() // to the preempt_with() code to handle case where the preempting process // causes a throw on the invoking method process. // // Revision 1.11 2011/04/13 02:45:11 acg // Andy Goodrich: eliminated warning message that occurred if the DEBUG_MSG // macro was used. // // Revision 1.10 2011/04/11 22:05:48 acg // Andy Goodrich: use the DEBUG_NAME macro in DEBUG_MSG invocations. // // Revision 1.9 2011/04/10 22:12:32 acg // Andy Goodrich: adding debugging macros. // // Revision 1.8 2011/04/08 18:26:07 acg // Andy Goodrich: added execute_method_next() to handle method dispatch // for asynchronous notifications that occur outside the evaluation phase. // // Revision 1.7 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.6 2011/02/13 21:47:38 acg // Andy Goodrich: update copyright notice. // // Revision 1.5 2011/02/08 08:17:50 acg // Andy Goodrich: fixed bug in preempt_with() where I was resetting the // process context rather than saving and restoring it. // // Revision 1.4 2011/02/01 21:12:56 acg // Andy Goodrich: addition of preempt_with() method to allow immediate // execution of threads for throws. // // Revision 1.3 2011/01/25 20:50:37 acg // Andy Goodrich: changes for IEEE 1666 2011. // // Revision 1.2 2008/05/22 17:06:26 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.6 2006/05/26 20:33:16 acg // Andy Goodrich: changes required by additional platform compilers (i.e., // Microsoft VC++, Sun Forte, HP aCC). // // Revision 1.5 2006/01/19 00:29:52 acg // Andy Goodrich: Yet another implementation for signal write checking. This // one uses an environment variable SC_SIGNAL_WRITE_CHECK, that when set to // DISABLE will disable write checking on signals. // // Revision 1.4 2006/01/18 21:42:37 acg // Andy Goodrich: Changes for check writer support. // // Revision 1.3 2006/01/13 18:44:30 acg // Added $Log to record CVS changes into the source. #endif systemc-2.3.3/src/sysc/kernel/sc_simcontext.cpp0000644000175000017500000021323013360325173021510 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_simcontext.cpp -- Provides a simulation context for use with multiple simulations. Original Author: Stan Y. Liao, Synopsys, Inc. Martin Janssen, Synopsys, Inc. CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #include "sysc/kernel/sc_simcontext.h" #include "sysc/kernel/sc_simcontext_int.h" #include "sysc/kernel/sc_cor_fiber.h" #include "sysc/kernel/sc_cor_pthread.h" #include "sysc/kernel/sc_cor_qt.h" #include "sysc/kernel/sc_event.h" #include "sysc/kernel/sc_kernel_ids.h" #include "sysc/kernel/sc_module.h" #include "sysc/kernel/sc_module_registry.h" #include "sysc/kernel/sc_name_gen.h" #include "sysc/kernel/sc_object_manager.h" #include "sysc/kernel/sc_cthread_process.h" #include "sysc/kernel/sc_method_process.h" #include "sysc/kernel/sc_thread_process.h" #include "sysc/kernel/sc_process_handle.h" #include "sysc/kernel/sc_reset.h" #include "sysc/kernel/sc_ver.h" #include "sysc/kernel/sc_dynamic_processes.h" #include "sysc/kernel/sc_phase_callback_registry.h" #include "sysc/communication/sc_port.h" #include "sysc/communication/sc_export.h" #include "sysc/communication/sc_prim_channel.h" #include "sysc/tracing/sc_trace.h" #include "sysc/utils/sc_mempool.h" #include "sysc/utils/sc_list.h" #include "sysc/utils/sc_string_view.h" #include "sysc/utils/sc_utils_ids.h" #include #include #include // DEBUGGING MACROS: // // DEBUG_MSG(NAME,P,MSG) // MSG = message to print // NAME = name that must match the process for the message to print, or // null if the message should be printed unconditionally. // P = pointer to process message is for, or NULL in which case the // message will not print. #if 0 # include # define DEBUG_NAME "" # define DEBUG_MSG(NAME,P,MSG) \ { \ if ( P && ( (std::strlen(NAME)==0) || !std::strcmp(NAME,P->name())) ) \ std::cout << "**** " << sc_time_stamp() << " (" \ << sc_get_current_process_name("** NONE **") << "): " << MSG \ << " - " << P->name() << std::endl; \ } #else # define DEBUG_MSG(NAME,P,MSG) #endif #if SC_HAS_PHASE_CALLBACKS_ # define SC_DO_PHASE_CALLBACK_( Kind ) \ m_phase_cb_registry->Kind() #else # define SC_DO_PHASE_CALLBACK_( Kind ) \ ((void)0) /* do nothing */ #endif #if defined( SC_ENABLE_SIMULATION_PHASE_CALLBACKS_TRACING ) // use callback based tracing # define SC_SIMCONTEXT_TRACING_ 0 #else // enable tracing via explicit trace_cycle calls from simulator loop # define SC_SIMCONTEXT_TRACING_ 1 #endif namespace sc_core { sc_stop_mode stop_mode = SC_STOP_FINISH_DELTA; // ---------------------------------------------------------------------------- // CLASS : sc_process_table // // Container class that keeps track of all method processes, // (c)thread processes. // ---------------------------------------------------------------------------- class sc_process_table { public: template struct queue { queue() : m_head() {} ~queue(); ProcessHandle head() const { return m_head; } void push_front(ProcessHandle h); ProcessHandle remove(ProcessHandle h); private: ProcessHandle m_head; }; void push_front( sc_method_handle handle ) { m_methods.push_front(handle); } void push_front( sc_thread_handle handle ) { m_threads.push_front(handle); } sc_method_handle method_q_head() const { return m_methods.head(); } sc_thread_handle thread_q_head() const { return m_threads.head(); } sc_method_handle remove( sc_method_handle handle ) { return m_methods.remove(handle); } sc_thread_handle remove( sc_thread_handle handle ) { return m_threads.remove(handle); } private: queue m_methods; // Queue of existing method processes. queue m_threads; // Queue of existing thread processes. }; template sc_process_table::queue::~queue() { while( m_head ) { ProcessHandle now_p = m_head; m_head = m_head->next_exist(); now_p->reference_decrement(); } } template void sc_process_table::queue::push_front( ProcessHandle handle ) { handle->set_next_exist(m_head); m_head = handle; } template ProcessHandle sc_process_table::queue::remove( ProcessHandle handle ) { ProcessHandle now_p = m_head; // Entry now examining. ProcessHandle prior_p = NULL; // Entry prior to one now examining. while( now_p ) { if ( now_p == handle ) { if ( prior_p ) prior_p->set_next_exist( now_p->next_exist() ); else m_head = now_p->next_exist(); return handle; } prior_p = now_p; now_p = now_p->next_exist(); } return NULL; } // IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII sc_method_handle sc_simcontext::remove_process( sc_method_handle handle ) { return m_process_table->remove(handle); } sc_thread_handle sc_simcontext::remove_process( sc_thread_handle handle ) { return m_process_table->remove(handle); } SC_API int sc_notify_time_compare( const void* p1, const void* p2 ) { const sc_event_timed* et1 = static_cast( p1 ); const sc_event_timed* et2 = static_cast( p2 ); const sc_time& t1 = et1->notify_time(); const sc_time& t2 = et2->notify_time(); if( t1 < t2 ) { return 1; } else if( t1 > t2 ) { return -1; } else { return 0; } } // +============================================================================ // | CLASS sc_invoke_method - class to invoke sc_method's to support // | sc_simcontext::preempt_with(). // +============================================================================ SC_MODULE(sc_invoke_method) { SC_CTOR(sc_invoke_method) { // remove from object hierarchy detach(); } virtual ~sc_invoke_method() {} // Method to call to execute a method's semantics. void invoke_method( sc_method_handle method_h ) { sc_process_handle invoker_h; // handle for invocation thread to use. std::vector::size_type invokers_n; // number of invocation threads available. m_method = method_h; // There is not an invocation thread to use, so allocate one. invokers_n = m_invokers.size(); if ( invokers_n == 0 ) { sc_spawn_options options; options.dont_initialize(); options.set_stack_size(0x100000); options.set_sensitivity(&m_dummy); invoker_h = sc_spawn(sc_bind(&sc_invoke_method::invoker,this), sc_gen_unique_name("invoker"), &options); ((sc_process_b*)invoker_h)->detach(); } // There is an invocation thread to use, use the last one on the list. else { invoker_h = m_invokers[invokers_n-1]; m_invokers.pop_back(); } // Fire off the invocation thread to invoke the method's semantics, // When it blocks put it onto the list of invocation threads that // are available. sc_get_curr_simcontext()->preempt_with( (sc_thread_handle)invoker_h ); DEBUG_MSG( DEBUG_NAME, m_method, "back from preemption" ); m_invokers.push_back(invoker_h); } // Thread to call method from: void invoker() { sc_simcontext* csc_p = sc_get_curr_simcontext(); sc_process_b* me = sc_get_current_process_b(); DEBUG_MSG( DEBUG_NAME, me, "invoker initialization" ); for (;; ) { DEBUG_MSG( DEBUG_NAME, m_method, "invoker executing method" ); csc_p->set_curr_proc( (sc_process_b*)m_method ); csc_p->get_active_invokers().push_back((sc_thread_handle)me); m_method->run_process(); csc_p->set_curr_proc( me ); csc_p->get_active_invokers().pop_back(); DEBUG_MSG( DEBUG_NAME, m_method, "back from executing method" ); wait(); } } sc_event m_dummy; // dummy event to wait on. sc_method_handle m_method; // method to be invoked. std::vector m_invokers; // list of invoking threads. }; // ---------------------------------------------------------------------------- // CLASS : sc_simcontext // // The simulation context. // ---------------------------------------------------------------------------- void sc_simcontext::init() { // ALLOCATE VARIOUS MANAGERS AND REGISTRIES: m_object_manager = new sc_object_manager; m_module_registry = new sc_module_registry( *this ); m_port_registry = new sc_port_registry( *this ); m_export_registry = new sc_export_registry( *this ); m_prim_channel_registry = new sc_prim_channel_registry( *this ); m_phase_cb_registry = new sc_phase_callback_registry( *this ); m_name_gen = new sc_name_gen; m_process_table = new sc_process_table; m_current_writer = 0; // CHECK FOR ENVIRONMENT VARIABLES THAT MODIFY SIMULATOR EXECUTION: const char* write_check = std::getenv("SC_SIGNAL_WRITE_CHECK"); sc_string_view write_check_s = (write_check != NULL) ? write_check : ""; if ( write_check_s == "DISABLE" ) m_write_check = SC_SIGNAL_WRITE_CHECK_DISABLE_; else if ( write_check_s == "CONFLICT" ) m_write_check = SC_SIGNAL_WRITE_CHECK_CONFLICT_; else m_write_check = SC_SIGNAL_WRITE_CHECK_DEFAULT_; // FINISH INITIALIZATIONS: reset_curr_proc(); m_next_proc_id = -1; m_timed_events = new sc_ppq( 128, sc_notify_time_compare ); m_something_to_trace = false; m_runnable = new sc_runnable; m_collectable = new sc_process_list; m_time_params = new sc_time_params; m_curr_time = SC_ZERO_TIME; m_max_time = SC_ZERO_TIME; m_change_stamp = 0; m_delta_count = 0; m_initial_delta_count_at_current_time = 0; m_forced_stop = false; m_paused = false; m_ready_to_simulate = false; m_elaboration_done = false; m_execution_phase = phase_initialize; m_error = NULL; m_cor_pkg = 0; m_method_invoker_p = NULL; m_cor = 0; m_reset_finder_q = 0; m_in_simulator_control = false; m_start_of_simulation_called = false; m_end_of_simulation_called = false; m_simulation_status = SC_ELABORATION; } void sc_simcontext::clean() { // remove remaining zombie processes do_collect_processes(); delete m_method_invoker_p; delete m_error; delete m_cor_pkg; delete m_time_params; delete m_collectable; delete m_runnable; delete m_timed_events; delete m_process_table; delete m_name_gen; delete m_phase_cb_registry; delete m_prim_channel_registry; delete m_export_registry; delete m_port_registry; delete m_module_registry; delete m_object_manager; m_delta_events.clear(); m_child_objects.clear(); m_trace_files.clear(); while( m_reset_finder_q ) { sc_reset_finder* rf = m_reset_finder_q; m_reset_finder_q = rf->m_next_p; delete rf; } } sc_simcontext::sc_simcontext() : m_object_manager(0), m_module_registry(0), m_port_registry(0), m_export_registry(0), m_prim_channel_registry(0), m_phase_cb_registry(0), m_name_gen(0), m_process_table(0), m_curr_proc_info(), m_current_writer(0), m_write_check(SC_SIGNAL_WRITE_CHECK_DEFAULT_), m_next_proc_id(-1), m_child_events(), m_child_objects(), m_delta_events(), m_timed_events(0), m_trace_files(), m_something_to_trace(false), m_runnable(0), m_collectable(0), m_time_params(), m_curr_time(SC_ZERO_TIME), m_max_time(SC_ZERO_TIME), m_change_stamp(0), m_delta_count(0), m_initial_delta_count_at_current_time(0), m_forced_stop(false), m_paused(false), m_ready_to_simulate(false), m_elaboration_done(false), m_execution_phase(phase_initialize), m_error(0), m_in_simulator_control(false), m_end_of_simulation_called(false), m_simulation_status(SC_ELABORATION), m_start_of_simulation_called(false), m_cor_pkg(0), m_cor(0), m_reset_finder_q(0) { init(); } sc_simcontext::~sc_simcontext() { clean(); } // +---------------------------------------------------------------------------- // |"sc_simcontext::active_object" // | // | This method returns the currently active object with respect to // | additions to the hierarchy. It will be the top of the object hierarchy // | stack if it is non-empty, or it will be the active process, or NULL // | if there is no active process. // +---------------------------------------------------------------------------- sc_object* sc_simcontext::active_object() { sc_object* result_p; // pointer to return. result_p = m_object_manager->hierarchy_curr(); if ( !result_p ) result_p = (sc_object*)get_curr_proc_info()->process_handle; return result_p; } // +---------------------------------------------------------------------------- // |"sc_simcontext::crunch" // | // | This method implements the simulator's execution of processes. It performs // | one or more "delta" cycles. Each delta cycle consists of an evaluation, // | an update phase, and a notification phase. During the evaluation phase any // | processes that are ready to run are executed. After all the processes have // | been executed the update phase is entered. During the update phase the // | values of any signals that have changed are updated. After the updates // | have been performed the notification phase is entered. During that phase // | any notifications that need to occur because of of signal values changes // | are performed. This will result in the queueing of processes for execution // | that are sensitive to those notifications. At that point a delta cycle // | is complete, and the process is started again unless 'once' is true. // | // | Arguments: // | once = true if only one delta cycle is to be performed. // +---------------------------------------------------------------------------- inline void sc_simcontext::crunch( bool once ) { #ifdef DEBUG_SYSTEMC int num_deltas = 0; // number of delta cycles #endif while ( true ) { // EVALUATE PHASE m_execution_phase = phase_evaluate; bool empty_eval_phase = true; while( true ) { // execute method processes m_runnable->toggle_methods(); sc_method_handle method_h = pop_runnable_method(); while( method_h != 0 ) { empty_eval_phase = false; if ( !method_h->run_process() ) { goto out; } method_h = pop_runnable_method(); } // execute (c)thread processes m_runnable->toggle_threads(); sc_thread_handle thread_h = pop_runnable_thread(); while( thread_h != 0 ) { if ( thread_h->m_cor_p != NULL ) break; thread_h = pop_runnable_thread(); } if( thread_h != 0 ) { empty_eval_phase = false; m_cor_pkg->yield( thread_h->m_cor_p ); } if( m_error ) { goto out; } // check for call(s) to sc_stop if( m_forced_stop ) { if ( stop_mode == SC_STOP_IMMEDIATE ) goto out; } // no more runnable processes if( m_runnable->is_empty() ) { break; } } // remove finally dead zombies: do_collect_processes(); // UPDATE PHASE // // The change stamp must be updated first so that event_occurred() // will work. m_execution_phase = phase_update; if ( !empty_eval_phase ) { // SC_DO_PHASE_CALLBACK_(evaluation_done); m_change_stamp++; } m_prim_channel_registry->perform_update(); SC_DO_PHASE_CALLBACK_(update_done); m_execution_phase = phase_notify; #if SC_SIMCONTEXT_TRACING_ if( m_something_to_trace ) { trace_cycle( /* delta cycle? */ true ); } #endif // check for call(s) to sc_stop if( m_forced_stop ) { break; } #ifdef DEBUG_SYSTEMC // check for possible infinite loops if( ++ num_deltas > SC_MAX_NUM_DELTA_CYCLES ) { ::std::cerr << "SystemC warning: " << "the number of delta cycles exceeds the limit of " << SC_MAX_NUM_DELTA_CYCLES << ", defined in sc_constants.h.\n" << "This is a possible sign of an infinite loop.\n" << "Increase the limit if this warning is invalid.\n"; break; } #endif // NOTIFICATION PHASE: // // Process delta notifications which will queue processes for // subsequent execution. int size = m_delta_events.size(); if ( size != 0 ) { sc_event** l_events = &m_delta_events[0]; int i = size - 1; do { l_events[i]->trigger(); } while( -- i >= 0 ); m_delta_events.clear(); } if ( !empty_eval_phase ) m_delta_count ++; if( m_runnable->is_empty() ) { // no more runnable processes break; } // if sc_pause() was called we are done. if ( m_paused ) break; // IF ONLY DOING ONE CYCLE, WE ARE DONE. OTHERWISE EXECUTE NEW CALLBACKS if ( once ) break; } // When this point is reached the processing of delta cycles is complete, // if the completion was because of an error throw the exception specified // by '*m_error'. out: this->reset_curr_proc(); do_collect_processes(); if( m_error ) throw *m_error; // re-throw propagated error } inline void sc_simcontext::cycle( const sc_time& t) { sc_time next_event_time; m_in_simulator_control = true; crunch(); do_timestep( m_curr_time + t ); if ( next_time(next_event_time) && next_event_time <= m_curr_time) { SC_REPORT_WARNING(SC_ID_CYCLE_MISSES_EVENTS_, ""); } m_in_simulator_control = false; SC_DO_PHASE_CALLBACK_(simulation_paused); } void sc_simcontext::elaborate() { if( m_elaboration_done || sim_status() != SC_SIM_OK ) { return; } // Instantiate the method invocation module // (not added to public object hierarchy) m_method_invoker_p = new sc_invoke_method("$$$$kernel_module$$$$_invoke_method" ); m_simulation_status = SC_BEFORE_END_OF_ELABORATION; for( int cd = 0; cd != 4; /* empty */ ) { cd = m_port_registry->construction_done(); cd += m_export_registry->construction_done(); cd += m_prim_channel_registry->construction_done(); cd += m_module_registry->construction_done(); // check for call(s) to sc_stop if( m_forced_stop ) { do_sc_stop_action(); return; } } SC_DO_PHASE_CALLBACK_(construction_done); // SIGNAL THAT ELABORATION IS DONE // // We set the switch before the calls in case someone creates a process // in an end_of_elaboration callback. We need the information to flag // the process as being dynamic. m_elaboration_done = true; m_simulation_status = SC_END_OF_ELABORATION; m_port_registry->elaboration_done(); m_export_registry->elaboration_done(); m_prim_channel_registry->elaboration_done(); m_module_registry->elaboration_done(); SC_DO_PHASE_CALLBACK_(elaboration_done); sc_reset::reconcile_resets(m_reset_finder_q); // check for call(s) to sc_stop if( m_forced_stop ) { do_sc_stop_action(); return; } } void sc_simcontext::prepare_to_simulate() { sc_method_handle method_p; // Pointer to method process accessing. sc_thread_handle thread_p; // Pointer to thread process accessing. if( m_ready_to_simulate || sim_status() != SC_SIM_OK ) { return; } // instantiate the coroutine package m_cor_pkg = new sc_cor_pkg_t( this ); m_cor = m_cor_pkg->get_main(); // NOTIFY ALL OBJECTS THAT SIMULATION IS ABOUT TO START: m_simulation_status = SC_START_OF_SIMULATION; m_port_registry->start_simulation(); m_export_registry->start_simulation(); m_prim_channel_registry->start_simulation(); m_module_registry->start_simulation(); SC_DO_PHASE_CALLBACK_(start_simulation); m_start_of_simulation_called = true; // CHECK FOR CALL(S) TO sc_stop if( m_forced_stop ) { do_sc_stop_action(); return; } // PREPARE ALL (C)THREAD PROCESSES FOR SIMULATION: for ( thread_p = m_process_table->thread_q_head(); thread_p; thread_p = thread_p->next_exist() ) { thread_p->prepare_for_simulation(); } m_simulation_status = SC_RUNNING; m_ready_to_simulate = true; m_runnable->init(); // update phase m_execution_phase = phase_update; m_prim_channel_registry->perform_update(); m_execution_phase = phase_notify; int size; // make all method processes runnable for ( method_p = m_process_table->method_q_head(); method_p; method_p = method_p->next_exist() ) { if ( ((method_p->m_state & sc_process_b::ps_bit_disabled) != 0) || method_p->dont_initialize() ) { if ( method_p->m_static_events.size() == 0 ) { SC_REPORT_WARNING( SC_ID_DISABLE_WILL_ORPHAN_PROCESS_, method_p->name() ); } } else if ( (method_p->m_state & sc_process_b::ps_bit_suspended) == 0) { if ( !method_p->is_runnable() ) // already scheduled? push_runnable_method_front( method_p ); } else { method_p->m_state |= sc_process_b::ps_bit_ready_to_run; } } // make thread processes runnable // (cthread processes always have the dont_initialize flag set) for ( thread_p = m_process_table->thread_q_head(); thread_p; thread_p = thread_p->next_exist() ) { if ( ((thread_p->m_state & sc_process_b::ps_bit_disabled) != 0) || thread_p->dont_initialize() ) { if ( thread_p->m_static_events.size() == 0 ) { SC_REPORT_WARNING( SC_ID_DISABLE_WILL_ORPHAN_PROCESS_, thread_p->name() ); } } else if ( (thread_p->m_state & sc_process_b::ps_bit_suspended) == 0) { if ( !thread_p->is_runnable() ) // already scheduled? push_runnable_thread_front( thread_p ); } else { thread_p->m_state |= sc_process_b::ps_bit_ready_to_run; } } // process delta notifications if( ( size = m_delta_events.size() ) != 0 ) { sc_event** l_delta_events = &m_delta_events[0]; int i = size - 1; do { l_delta_events[i]->trigger(); } while( -- i >= 0 ); m_delta_events.clear(); } SC_DO_PHASE_CALLBACK_(initialization_done); } void sc_simcontext::initial_crunch( bool no_crunch ) { if( no_crunch || m_runnable->is_empty() ) { return; } // run the delta cycle loop crunch(); if( m_error ) { return; } // check for call(s) to sc_stop if( m_forced_stop ) { do_sc_stop_action(); } } void sc_simcontext::initialize( bool no_crunch ) { m_in_simulator_control = true; elaborate(); prepare_to_simulate(); initial_crunch(no_crunch); m_in_simulator_control = false; } // +---------------------------------------------------------------------------- // |"sc_simcontext::simulate" // | // | This method runs the simulation for the specified amount of time. // | // | Notes: // | (1) This code always run with an SC_EXIT_ON_STARVATION starvation policy, // | so the simulation time on return will be the minimum of the // | simulation on entry plus the duration, and the maximum time of any // | event present in the simulation. If the simulation policy is // | SC_RUN_TO_TIME starvation it is implemented by the caller of this // | method, e.g., sc_start(), by artificially setting the simulation // | time forward after this method completes. // | // | Arguments: // | duration = amount of time to simulate. // +---------------------------------------------------------------------------- void sc_simcontext::simulate( const sc_time& duration ) { initialize( true ); if (sim_status() != SC_SIM_OK) { return; } sc_time non_overflow_time = max_time() - m_curr_time; if ( duration > non_overflow_time ) { SC_REPORT_ERROR(SC_ID_SIMULATION_TIME_OVERFLOW_, ""); return; } m_in_simulator_control = true; m_paused = false; sc_time until_t = m_curr_time + duration; sc_time t; // current simulaton time. // IF DURATION WAS ZERO WE ONLY CRUNCH ONCE: // // We duplicate the code so that we don't add the overhead of the // check to each loop in the do below. if ( duration == SC_ZERO_TIME ) { m_in_simulator_control = true; crunch( true ); if( m_error ) { m_in_simulator_control = false; return; } if( m_forced_stop ) { do_sc_stop_action(); return; } // return via implicit pause goto exit_pause; } // NON-ZERO DURATION: EXECUTE UP TO THAT TIME, OR UNTIL EVENT STARVATION: do { crunch(); if( m_error ) { m_in_simulator_control = false; return; } // check for call(s) to sc_stop() or sc_pause(). if( m_forced_stop ) { do_sc_stop_action(); return; } if( m_paused ) goto exit_pause; // return explicit pause t = m_curr_time; do { // See note 1 above: if ( !next_time(t) || (t > until_t) ) { if ( (t > until_t) || m_prim_channel_registry->async_suspend() ) { // requested simulation time completed or no external updates goto exit_time; } // received external updates, continue simulation break; } if ( t > m_curr_time ) do_timestep(t); // PROCESS TIMED NOTIFICATIONS AT THE CURRENT TIME do { sc_event_timed* et = m_timed_events->extract_top(); sc_event* e = et->event(); delete et; if( e != 0 ) { e->trigger(); } } while( m_timed_events->size() && m_timed_events->top()->notify_time() == t ); } while( m_runnable->is_empty() ); } while ( t < until_t ); // hold off on the delta for the until_t time. exit_time: // final simulation time update, if needed if ( t > m_curr_time && t <= until_t ) do_timestep(t); exit_pause: // call pause callback upon implicit or explicit pause m_execution_phase = phase_evaluate; m_in_simulator_control = false; SC_DO_PHASE_CALLBACK_(simulation_paused); } void sc_simcontext::do_timestep(const sc_time& t) { sc_assert( m_curr_time < t ); SC_DO_PHASE_CALLBACK_(before_timestep); #if SC_SIMCONTEXT_TRACING_ if( m_something_to_trace ) { trace_cycle( false ); } #endif m_curr_time = t; m_change_stamp++; m_initial_delta_count_at_current_time = m_delta_count; } void sc_simcontext::do_sc_stop_action() { SC_REPORT_INFO("/OSCI/SystemC","Simulation stopped by user."); if (m_start_of_simulation_called) { end(); m_in_simulator_control = false; } m_simulation_status = SC_STOPPED; SC_DO_PHASE_CALLBACK_(simulation_stopped); } void sc_simcontext::mark_to_collect_process( sc_process_b* zombie ) { m_collectable->push_back( zombie ); } void sc_simcontext::do_collect_processes() { while( ! m_collectable->empty() ) { sc_process_b* del_p = m_collectable->front(); m_collectable->pop_front(); del_p->reference_decrement(); } } //------------------------------------------------------------------------------ //"sc_simcontext::stop" // // This method stops the simulator after some amount of further processing. // How much processing is done depends upon the value of the global variable // stop_mode: // SC_STOP_IMMEDIATE - aborts the execution phase of the current delta // cycle and performs whatever updates are pending. // SC_STOP_FINISH_DELTA - finishes the current delta cycle - both execution // and updates. // If sc_stop is called outside of the purview of the simulator kernel // (e.g., directly from sc_main), the end of simulation notifications // are performed. From within the purview of the simulator kernel, these // will be performed at a later time. //------------------------------------------------------------------------------ void sc_simcontext::stop() { static bool stop_warning_issued = false; if (m_forced_stop) { if ( !stop_warning_issued ) { stop_warning_issued = true; // This must be before the WARNING!!! SC_REPORT_WARNING(SC_ID_SIMULATION_STOP_CALLED_TWICE_, ""); } return; } if ( stop_mode == SC_STOP_IMMEDIATE ) m_runnable->init(); m_forced_stop = true; if ( !m_in_simulator_control ) { do_sc_stop_action(); } } void sc_simcontext::reset() { clean(); init(); } void sc_simcontext::end() { m_simulation_status = SC_END_OF_SIMULATION; m_ready_to_simulate = false; m_port_registry->simulation_done(); m_export_registry->simulation_done(); m_prim_channel_registry->simulation_done(); m_module_registry->simulation_done(); SC_DO_PHASE_CALLBACK_(simulation_done); m_end_of_simulation_called = true; } void sc_simcontext::hierarchy_push( sc_module* mod ) { m_object_manager->hierarchy_push( mod ); } sc_module* sc_simcontext::hierarchy_pop() { return static_cast( m_object_manager->hierarchy_pop() ); } sc_module* sc_simcontext::hierarchy_curr() const { return static_cast( m_object_manager->hierarchy_curr() ); } sc_object* sc_simcontext::first_object() { return m_object_manager->first_object(); } sc_object* sc_simcontext::next_object() { return m_object_manager->next_object(); } sc_object* sc_simcontext::find_object( const char* name ) { static bool warn_find_object=true; if ( warn_find_object ) { warn_find_object = false; SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, "sc_simcontext::find_object() is deprecated,\n" \ " use sc_find_object()" ); } return m_object_manager->find_object( name ); } std::string sc_simcontext::construct_hierarchical_name(const sc_object* parent, const std::string& name) { std::string hierarchical_name = parent ? ( std::string(parent->name()) + SC_HIERARCHY_CHAR ) : ""; hierarchical_name += name; return hierarchical_name; } bool sc_simcontext::register_hierarchical_name(const sc_object* parent, const std::string& name) { return m_object_manager->insert_external_name( construct_hierarchical_name(parent, name)); } bool sc_simcontext::unregister_hierarchical_name(const sc_object* parent, const std::string& name) { return m_object_manager->remove_external_name( construct_hierarchical_name(parent, name)); } bool sc_simcontext::hierarchical_name_exists(const sc_object* parent, const std::string& name) { return m_object_manager->name_exists( construct_hierarchical_name(parent, name)); } const char* sc_simcontext::get_hierarchical_name(const sc_object* parent, const std::string& name) { return m_object_manager->get_name( construct_hierarchical_name(parent, name)); } // to generate unique names for objects in an MT-Safe way const char* sc_simcontext::gen_unique_name( const char* basename_, bool preserve_first ) { return m_name_gen->gen_unique_name( basename_, preserve_first ); } sc_process_handle sc_simcontext::create_cthread_process( const char* name_p, bool free_host, SC_ENTRY_FUNC method_p, sc_process_host* host_p, const sc_spawn_options* opt_p ) { sc_thread_handle handle = new sc_cthread_process(name_p, free_host, method_p, host_p, opt_p); if ( m_ready_to_simulate ) { handle->prepare_for_simulation(); } else { m_process_table->push_front( handle ); } return sc_process_handle(handle); } sc_process_handle sc_simcontext::create_method_process( const char* name_p, bool free_host, SC_ENTRY_FUNC method_p, sc_process_host* host_p, const sc_spawn_options* opt_p ) { sc_method_handle handle = new sc_method_process(name_p, free_host, method_p, host_p, opt_p); if ( m_ready_to_simulate ) { // dynamic process if ( !handle->dont_initialize() ) { #ifdef SC_HAS_PHASE_CALLBACKS_ if( SC_UNLIKELY_( m_simulation_status & (SC_END_OF_UPDATE|SC_BEFORE_TIMESTEP) ) ) { std::stringstream msg; msg << m_simulation_status << ":\n\t immediate method spawning of " "`" << handle->name() << "' ignored"; SC_REPORT_WARNING( SC_ID_PHASE_CALLBACK_FORBIDDEN_ , msg.str().c_str() ); } else #endif // SC_HAS_PHASE_CALLBACKS_ { push_runnable_method( handle ); } } else if ( handle->m_static_events.size() == 0 ) { SC_REPORT_WARNING( SC_ID_DISABLE_WILL_ORPHAN_PROCESS_, handle->name() ); } } else { m_process_table->push_front( handle ); } return sc_process_handle(handle); } sc_process_handle sc_simcontext::create_thread_process( const char* name_p, bool free_host, SC_ENTRY_FUNC method_p, sc_process_host* host_p, const sc_spawn_options* opt_p ) { sc_thread_handle handle = new sc_thread_process(name_p, free_host, method_p, host_p, opt_p); if ( m_ready_to_simulate ) { // dynamic process handle->prepare_for_simulation(); if ( !handle->dont_initialize() ) { #ifdef SC_HAS_PHASE_CALLBACKS_ if( SC_UNLIKELY_( m_simulation_status & (SC_END_OF_UPDATE|SC_BEFORE_TIMESTEP) ) ) { std::stringstream msg; msg << m_simulation_status << ":\n\t immediate thread spawning of " "`" << handle->name() << "' ignored"; SC_REPORT_WARNING( SC_ID_PHASE_CALLBACK_FORBIDDEN_ , msg.str().c_str() ); } else #endif // SC_HAS_PHASE_CALLBACKS_ { push_runnable_thread( handle ); } } else if ( handle->m_static_events.size() == 0 ) { SC_REPORT_WARNING( SC_ID_DISABLE_WILL_ORPHAN_PROCESS_, handle->name() ); } } else { m_process_table->push_front( handle ); } return sc_process_handle(handle); } void sc_simcontext::add_trace_file( sc_trace_file* tf ) { m_trace_files.push_back( tf ); m_something_to_trace = true; } void sc_simcontext::remove_trace_file( sc_trace_file* tf ) { m_trace_files.erase( std::remove( m_trace_files.begin(), m_trace_files.end(), tf ) ); m_something_to_trace = ( m_trace_files.size() > 0 ); } sc_cor* sc_simcontext::next_cor() { if( m_error ) { return m_cor; } sc_thread_handle thread_h = pop_runnable_thread(); while( thread_h != 0 ) { if ( thread_h->m_cor_p != NULL ) break; thread_h = pop_runnable_thread(); } if( thread_h != 0 ) { return thread_h->m_cor_p; } else { return m_cor; } } void sc_simcontext::add_reset_finder( sc_reset_finder* reset_finder ) { reset_finder->m_next_p = m_reset_finder_q; m_reset_finder_q = reset_finder; } const ::std::vector& sc_simcontext::get_child_objects() const { static bool warn_get_child_objects=true; if ( warn_get_child_objects ) { warn_get_child_objects = false; SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, "sc_simcontext::get_child_objects() is deprecated,\n" \ " use sc_get_top_level_objects()" ); } return m_child_objects; } void sc_simcontext::add_child_event( sc_event* event_ ) { // no check if object_ is already in the set m_child_events.push_back( event_ ); } void sc_simcontext::add_child_object( sc_object* object_ ) { // no check if object_ is already in the set m_child_objects.push_back( object_ ); } void sc_simcontext::remove_child_event( sc_event* event_ ) { int size = m_child_events.size(); for( int i = 0; i < size; ++ i ) { if( event_ == m_child_events[i] ) { m_child_events[i] = m_child_events[size - 1]; m_child_events.pop_back(); return; } } // no check if event_ is really in the set } void sc_simcontext::remove_child_object( sc_object* object_ ) { int size = m_child_objects.size(); for( int i = 0; i < size; ++ i ) { if( object_ == m_child_objects[i] ) { m_child_objects[i] = m_child_objects[size - 1]; m_child_objects.pop_back(); return; } } // no check if object_ is really in the set } sc_dt::uint64 sc_simcontext::delta_count() const { static bool warn_delta_count=true; if ( warn_delta_count ) { warn_delta_count = false; SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, "sc_simcontext::delta_count() is deprecated, use sc_delta_count()" ); } return m_delta_count; } bool sc_simcontext::is_running() const { static bool warn_is_running=true; if ( warn_is_running ) { warn_is_running = false; SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, "sc_simcontext::is_running() is deprecated, use sc_is_running()" ); } return m_ready_to_simulate; } // +---------------------------------------------------------------------------- // |"sc_simcontext::next_time" // | // | This method returns the time of the next event. If there are no events // | it returns false. // | // | Arguments: // | result = where to place time of the next event, if no event is // | found this value will not be changed. // | Result is true if an event is found, false if not. // +---------------------------------------------------------------------------- bool sc_simcontext::next_time( sc_time& result ) const { while( m_timed_events->size() ) { sc_event_timed* et = m_timed_events->top(); if( et->event() != 0 ) { result = et->notify_time(); return true; } delete m_timed_events->extract_top(); } return false; } void sc_simcontext::remove_delta_event( sc_event* e ) { int i = e->m_delta_event_index; int j = m_delta_events.size() - 1; sc_assert( i >= 0 && i <= j ); if( i != j ) { sc_event** l_delta_events = &m_delta_events[0]; l_delta_events[i] = l_delta_events[j]; l_delta_events[i]->m_delta_event_index = i; } m_delta_events.pop_back(); e->m_delta_event_index = -1; } // +---------------------------------------------------------------------------- // |"sc_simcontext::preempt_with" // | // | This method executes the supplied method immediately, suspending the // | caller. After executing the supplied method the caller's execution will // | be restored. It is used to allow a method to immediately throw an // | exception, e.g., when the method's kill_process() method was called. // | There are three cases to consider: // | (1) The caller is a method, e.g., murder by method. // | (2) The caller is a thread instance, e.g., murder by thread. // | (3) The caller is this method instance, e.g., suicide. // | // | Arguments: // | method_h -> method to be executed. // +---------------------------------------------------------------------------- void sc_simcontext::preempt_with( sc_method_handle method_h ) { sc_curr_proc_info caller_info; // process info for caller. sc_method_handle active_method_h; // active method or null. sc_thread_handle active_thread_h; // active thread or null. // Determine the active process and take the thread to be run off the // run queue, if its there, since we will be explicitly causing its // execution. active_method_h = dynamic_cast(sc_get_current_process_b()); active_thread_h = dynamic_cast(sc_get_current_process_b()); if ( method_h->next_runnable() != NULL ) remove_runnable_method( method_h ); // CALLER IS THE METHOD TO BE RUN: // // Should never get here, ignore it unless we are debugging. if ( method_h == active_method_h ) { DEBUG_MSG(DEBUG_NAME,method_h,"self preemption of active method"); } // THE CALLER IS A METHOD: // // (a) Set the current process information to our method. // (b) Invoke our method directly by-passing the run queue. // (c) Restore the process info to the caller. // (d) Check to see if the calling method should throw an exception // because of activity that occurred during the preemption. else if ( active_method_h != NULL ) { caller_info = m_curr_proc_info; DEBUG_MSG( DEBUG_NAME, method_h, "preempting active method with method" ); sc_get_curr_simcontext()->set_curr_proc( (sc_process_b*)method_h ); method_h->run_process(); sc_get_curr_simcontext()->set_curr_proc((sc_process_b*)active_method_h); active_method_h->check_for_throws(); } // CALLER IS A THREAD: // // (a) Use an invocation thread to execute the method. else if ( active_thread_h != NULL ) { DEBUG_MSG( DEBUG_NAME, method_h, "preempting active thread with method" ); m_method_invoker_p->invoke_method(method_h); } // CALLER IS THE SIMULATOR: // // That is not allowed. else { caller_info = m_curr_proc_info; DEBUG_MSG( DEBUG_NAME, method_h, "preempting no active process with method" ); sc_get_curr_simcontext()->set_curr_proc( (sc_process_b*)method_h ); method_h->run_process(); m_curr_proc_info = caller_info; } } //------------------------------------------------------------------------------ //"sc_simcontext::requeue_current_process" // // This method requeues the current process at the beginning of the run queue // if it is a thread. This is called by sc_process_handle::throw_it() to assure // that a thread that is issuing a throw will execute immediately after the // processes it notifies via the throw. //------------------------------------------------------------------------------ void sc_simcontext::requeue_current_process() { sc_thread_handle thread_p; thread_p = dynamic_cast(get_curr_proc_info()->process_handle); if ( thread_p ) { execute_thread_next( thread_p ); } } //------------------------------------------------------------------------------ //"sc_simcontext::suspend_current_process" // // This method suspends the current process if it is a thread. This is called // by sc_process_handle::throw_it() to allow the processes that have received // a throw to execute. //------------------------------------------------------------------------------ void sc_simcontext::suspend_current_process() { sc_thread_handle thread_p; thread_p = dynamic_cast(get_curr_proc_info()->process_handle); if ( thread_p ) { thread_p->suspend_me(); } } void sc_simcontext::trace_cycle( bool delta_cycle ) { int size; if( ( size = m_trace_files.size() ) != 0 ) { sc_trace_file** l_trace_files = &m_trace_files[0]; int i = size - 1; do { l_trace_files[i]->cycle( delta_cycle ); } while( -- i >= 0 ); } } // ---------------------------------------------------------------------------- #if 1 #ifdef PURIFY static sc_simcontext sc_default_global_context; sc_simcontext* sc_curr_simcontext = &sc_default_global_context; #else SC_API sc_simcontext* sc_curr_simcontext = 0; SC_API sc_simcontext* sc_default_global_context = 0; #endif #else // Not MT-safe! static sc_simcontext* sc_curr_simcontext = 0; SC_API sc_simcontext* sc_get_curr_simcontext() { if( sc_curr_simcontext == 0 ) { #ifdef PURIFY static sc_simcontext sc_default_global_context; sc_curr_simcontext = &sc_default_global_context; #else static sc_simcontext* sc_default_global_context = new sc_simcontext; sc_curr_simcontext = sc_default_global_context; #endif } return sc_curr_simcontext; } #endif // 0 // Generates unique names within each module. SC_API const char* sc_gen_unique_name( const char* basename_, bool preserve_first ) { sc_simcontext* simc = sc_get_curr_simcontext(); sc_module* curr_module = simc->hierarchy_curr(); if( curr_module != 0 ) { return curr_module->gen_unique_name( basename_, preserve_first ); } else { sc_process_b* curr_proc_p = sc_get_current_process_b(); if ( curr_proc_p ) { return curr_proc_p->gen_unique_name( basename_, preserve_first ); } else { return simc->gen_unique_name( basename_, preserve_first ); } } } // Get a handle for the current process // // Note that this method should not be called if the current process is // in the act of being deleted, it will mess up the reference count management // of sc_process_b instance the handle represents. Instead, use the a // pointer to the raw sc_process_b instance, which may be acquired via // sc_get_current_process_b(). SC_API sc_process_handle sc_get_current_process_handle() { return ( sc_is_running() ) ? sc_process_handle(sc_get_current_process_b()) : sc_get_last_created_process_handle(); } // THE FOLLOWING FUNCTION IS DEPRECATED IN 2.1 SC_API sc_process_b* sc_get_curr_process_handle() { static bool warn=true; if ( warn ) { warn = false; SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, "sc_get_curr_process_handle deprecated use sc_get_current_process_handle" ); } return sc_get_curr_simcontext()->get_curr_proc_info()->process_handle; } // Return indication if there are more processes to execute in this delta phase bool sc_simcontext::pending_activity_at_current_time() const { return ( m_delta_events.size() != 0) || ( m_runnable->is_initialized() && !m_runnable->is_empty() ) || m_prim_channel_registry->pending_updates(); } // Return time of next activity. SC_API sc_time sc_time_to_pending_activity( const sc_simcontext* simc_p ) { // If there is an activity pending at the current time // return a delta of zero. sc_time result=SC_ZERO_TIME; // time of pending activity. if ( simc_p->pending_activity_at_current_time() ) { return result; } // Any activity will take place in the future pick up the next event's time. else { result = simc_p->max_time(); simc_p->next_time(result); result -= sc_time_stamp(); } return result; } // Set the random seed for controlled randomization -- not yet implemented SC_API void sc_set_random_seed( unsigned int ) { SC_REPORT_WARNING( SC_ID_NOT_IMPLEMENTED_, "void sc_set_random_seed( unsigned int )" ); } // +---------------------------------------------------------------------------- // |"sc_start" // | // | This function starts, or restarts, the execution of the simulator. // | // | Arguments: // | duration = the amount of time the simulator should execute. // | p = event starvation policy. // +---------------------------------------------------------------------------- SC_API void sc_start( const sc_time& duration, sc_starvation_policy p ) { sc_simcontext* context_p; // current simulation context. sc_time entry_time; // simulation time upon entry. sc_time exit_time; // simulation time to set upon exit. sc_dt::uint64 starting_delta; // delta count upon entry. int sim_status; // current simulation status. int status; // current status. // Set up based on the arguments passed to us: context_p = sc_get_curr_simcontext(); starting_delta = sc_delta_count(); entry_time = context_p->m_curr_time; if ( p == SC_RUN_TO_TIME ) exit_time = context_p->m_curr_time + duration; // called with duration = SC_ZERO_TIME for the first time static bool init_delta_or_pending_updates = ( starting_delta == 0 && exit_time == SC_ZERO_TIME ); // If the simulation status is bad issue the appropriate message: sim_status = context_p->sim_status(); if( sim_status != SC_SIM_OK ) { if ( sim_status == SC_SIM_USER_STOP ) SC_REPORT_ERROR(SC_ID_SIMULATION_START_AFTER_STOP_, ""); if ( sim_status == SC_SIM_ERROR ) SC_REPORT_ERROR(SC_ID_SIMULATION_START_AFTER_ERROR_, ""); return; } status = context_p->get_status(); if( !(status == SC_PAUSED || status == SC_ELABORATION) ) { SC_REPORT_ERROR(SC_ID_SIMULATION_START_UNEXPECTED_, ""); return; } if ( context_p->m_prim_channel_registry->pending_updates() || ! context_p->m_delta_events.empty() ) init_delta_or_pending_updates = true; // If the simulation status is good perform the simulation: context_p->simulate( duration ); // Re-check the status: sim_status = context_p->sim_status(); // Update the current time to the exit time if that is the starvation // policy: if ( p == SC_RUN_TO_TIME && !context_p->m_paused && sim_status == SC_SIM_OK && context_p->m_curr_time < exit_time ) { context_p->do_timestep( exit_time ); } // If there was no activity and the simulation clock did not move warn // the user, except if we're in a first sc_start(SC_ZERO_TIME) for // initialisation (only) or there have been pending updates: if ( !init_delta_or_pending_updates && starting_delta == sc_delta_count() && context_p->m_curr_time == entry_time && sim_status == SC_SIM_OK ) { SC_REPORT_WARNING(SC_ID_NO_SC_START_ACTIVITY_, ""); } // reset init/update flag for subsequent calls init_delta_or_pending_updates = false; } SC_API void sc_start() { sc_start( sc_max_time() - sc_time_stamp(), SC_EXIT_ON_STARVATION ); } SC_API void sc_stop() { sc_get_curr_simcontext()->stop(); } // The following function is deprecated in favor of sc_start(SC_ZERO_TIME): SC_API void sc_initialize() { static bool warning_initialize = true; if ( warning_initialize ) { warning_initialize = false; SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, "sc_initialize() is deprecated: use sc_start(SC_ZERO_TIME)" ); } sc_get_curr_simcontext()->initialize(); } // The following function has been deprecated in favor of sc_start(duration): SC_API void sc_cycle( const sc_time& duration ) { static bool warning_cycle = true; if ( warning_cycle ) { warning_cycle = false; SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, "sc_cycle is deprecated: use sc_start(sc_time)" ); } sc_get_curr_simcontext()->cycle( duration ); } SC_API sc_event* sc_find_event( const char* name ) { return sc_get_curr_simcontext()->get_object_manager()->find_event( name ); } SC_API sc_object* sc_find_object( const char* name ) { return sc_get_curr_simcontext()->get_object_manager()->find_object( name ); } SC_API const sc_time& sc_max_time() { return sc_get_curr_simcontext()->max_time(); } SC_API const sc_time& sc_time_stamp() { return sc_get_curr_simcontext()->time_stamp(); } SC_API double sc_simulation_time() { static bool warn_simulation_time=true; if ( warn_simulation_time ) { warn_simulation_time=false; SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, "sc_simulation_time() is deprecated use sc_time_stamp()" ); } return sc_get_curr_simcontext()->time_stamp().to_default_time_units(); } SC_API void sc_defunct_process_function( sc_module* ) { // This function is pointed to by defunct sc_thread_process'es and // sc_cthread_process'es. In a correctly constructed world, this // function should never be called; hence the assert. assert( false ); sc_assert( false ); } //------------------------------------------------------------------------------ //"sc_set_stop_mode" // // This function sets the mode of operation when sc_stop() is called. // mode = SC_STOP_IMMEDIATE or SC_STOP_FINISH_DELTA. //------------------------------------------------------------------------------ SC_API void sc_set_stop_mode(sc_stop_mode mode) { if ( sc_is_running() ) { SC_REPORT_ERROR(SC_ID_STOP_MODE_AFTER_START_,""); return; } switch( mode ) { case SC_STOP_IMMEDIATE: case SC_STOP_FINISH_DELTA: stop_mode = mode; break; default: break; } } SC_API sc_stop_mode sc_get_stop_mode() { return stop_mode; } SC_API bool sc_is_unwinding() { return sc_get_current_process_handle().is_unwinding(); } // The IEEE 1666 Standard for 2011 designates that the treatment of // certain process control interactions as being "implementation dependent". // These interactions are: // (1) What happens when a resume() call is performed on a disabled, // suspended process. // (2) What happens when sync_reset_on() or sync_reset_off() is called // on a suspended process. // (3) What happens when the value specified in a reset_signal_is() // call changes value while a process is suspended. // // By default this Proof of Concept implementation reports an error // for these interactions. However, the implementation also provides // a non-error treatment. The non-error treatment for the interactions is: // (1) A resume() call performed on a disabled, suspended process will // mark the process as no longer suspended, and if it is capable // of execution (not waiting on any events) it will be placed on // the queue of runnable processes. See the state diagram below. // (2) A call to sync_reset_on() or sync_reset_off() will set or clear // the synchronous reset flag. Whether the process is in reset or // not will be determined when the process actually executes by // looking at the flag's value at that time. // (3) If a suspended process has a reset_signal_is() specification // the value of the reset variable at the time of its next execution // will determine whether it is in reset or not. // // TO GET THE NON-ERROR BEHAVIOR SET THE VARIABLE BELOW TO TRUE. // // This can be done in this source before you build the library, or you // can use an assignment as the first statement in your sc_main() function: // sc_core::sc_allow_process_control_corners = true; bool sc_allow_process_control_corners = false; // The state transition diagram for the interaction of disable and suspend // when sc_allow_process_control_corners is true is shown below: // // ...................................................................... // . ENABLED . DISABLED . // . . . // . +----------+ disable +----------+ . // . +------------>| |-------.-------->| | . // . | | runnable | . | runnable | . // . | +-------| |<------.---------| |------+ . // . | | +----------+ enable +----------+ | . // . | | | ^ . | ^ | . // . | | suspend | | resume . suspend | | resume | . // . | | V | . V | | . // . | | +----------+ disable +----------+ | . // . | | | suspend |-------.-------->| suspend | | . // . t | r | | | . | | | r . // . r | u | | ready |<------.---------| ready | | u . // . i | n | +----------+ enable +----------+ | n . // . g | / | ^ . | / . // . g | w | trigger| . | w . // . e | a | | . | a . // . r | i | +----------+ disable +----------+ | i . // . | t | | suspend |-------.-------->| suspend | | t . // . | | | | . | | | . // . | | | waiting |<------.---------| waiting | | . // . | | +----------+ enable +----------+ | . // . | | | ^ . | ^ | . // . | | suspend | | resume . suspend | | resume | . // . | | V | . V | | . // . | | +----------+ disable +----------+ | . // . | +------>| |-------.-------->| | | . // . | | waiting | . | waiting | | . // . +-------------| |<------.---------| |<-----+ . // . +----------+ enable +----------+ . // . . . // ...................................................................... // ---------------------------------------------------------------------------- static std::ostream& print_status_expression( std::ostream& os, sc_status s ); // utility helper to print a simulation status SC_API std::ostream& operator << ( std::ostream& os, sc_status s ) { // print primitive values switch(s) { # define PRINT_STATUS( Status ) \ case Status: { os << #Status; } break PRINT_STATUS( SC_UNITIALIZED ); PRINT_STATUS( SC_ELABORATION ); PRINT_STATUS( SC_BEFORE_END_OF_ELABORATION ); PRINT_STATUS( SC_END_OF_ELABORATION ); PRINT_STATUS( SC_START_OF_SIMULATION ); PRINT_STATUS( SC_RUNNING ); PRINT_STATUS( SC_PAUSED ); PRINT_STATUS( SC_STOPPED ); PRINT_STATUS( SC_END_OF_SIMULATION ); PRINT_STATUS( SC_END_OF_INITIALIZATION ); // PRINT_STATUS( SC_END_OF_EVALUATION ); PRINT_STATUS( SC_END_OF_UPDATE ); PRINT_STATUS( SC_BEFORE_TIMESTEP ); PRINT_STATUS( SC_STATUS_ANY ); # undef PRINT_STATUS default: if( s & SC_STATUS_ANY ) // combination of status bits print_status_expression( os, s ); else // invalid number, print hex value os << "0x" << std::hex << +s; } return os; } // pretty-print a combination of sc_status bits (i.e. a callback mask) static std::ostream& print_status_expression( std::ostream& os, sc_status s ) { std::vector bits; unsigned is_set = SC_ELABORATION; // collect bits while( is_set <= SC_STATUS_LAST ) { if( s & is_set ) bits.push_back( (sc_status)is_set ); is_set <<= 1; } if( s & ~SC_STATUS_ANY ) // remaining bits bits.push_back( (sc_status)( s & ~SC_STATUS_ANY ) ); // print expression std::vector::size_type i=0, n=bits.size(); if ( n>1 ) os << "("; for( ; i1 ) os << ")"; return os; } } // namespace sc_core /***************************************************************************** MODIFICATION LOG - modifiers, enter your name, affiliation, date and changes you are making here. Name, Affiliation, Date: Ali Dasdan, Synopsys, Inc. Description of Modification: - Added sc_stop() detection into initial_crunch and crunch. This makes it possible to exit out of a combinational loop using sc_stop(). Name, Affiliation, Date: Andy Goodrich, Forte Design Systems 20 May 2003 Description of Modification: - sc_stop mode - phase callbacks Name, Affiliation, Date: Bishnupriya Bhattacharya, Cadence Design Systems, 25 August 2003 Description of Modification: - support for dynamic process - support for sc export registry - new member methods elaborate(), prepare_to_simulate(), and initial_crunch() that are invoked by initialize() in that order - implement sc_get_last_created_process_handle() for use before simulation starts - remove "set_curr_proc(handle)" from register_method_process and register_thread_process - led to bugs Name, Affiliation, Date: Andy Goodrich, Forte Design Systems 04 Sep 2003 Description of Modification: - changed process existence structures to linked lists to eliminate exponential execution problem with using sc_pvector. *****************************************************************************/ // $Log: sc_simcontext.cpp,v $ // Revision 1.37 2011/08/29 18:04:32 acg // Philipp A. Hartmann: miscellaneous clean ups. // // Revision 1.36 2011/08/26 20:46:10 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.35 2011/08/24 22:05:51 acg // Torsten Maehne: initialization changes to remove warnings. // // Revision 1.34 2011/08/04 17:15:28 acg // Andy Goodrich: added documentation to crunch() routine. // // Revision 1.32 2011/07/24 11:16:36 acg // Philipp A. Hartmann: fix reference counting on deferred deletions of // processes. // // Revision 1.31 2011/07/01 18:49:07 acg // Andy Goodrich: moved pln() from sc_simcontext.cpp to sc_ver.cpp. // // Revision 1.30 2011/05/09 04:07:49 acg // Philipp A. Hartmann: // (1) Restore hierarchy in all phase callbacks. // (2) Ensure calls to before_end_of_elaboration. // // Revision 1.29 2011/04/08 22:39:09 acg // Andy Goodrich: moved method invocation code to sc_method.h so that the // details are hidden from sc_simcontext. // // Revision 1.28 2011/04/05 20:50:57 acg // Andy Goodrich: // (1) changes to make sure that event(), posedge() and negedge() only // return true if the clock has not moved. // (2) fixes for method self-resumes. // (3) added SC_PRERELEASE_VERSION // (4) removed kernel events from the object hierarchy, added // sc_hierarchy_name_exists(). // // Revision 1.27 2011/04/05 06:14:15 acg // Andy Goodrich: fix typo. // // Revision 1.26 2011/04/05 06:03:32 acg // Philipp A. Hartmann: added code to set ready to run bit for a suspended // process that does not have dont_initialize specified at simulation // start up. // // Revision 1.25 2011/04/01 21:31:55 acg // Andy Goodrich: make sure processes suspended before the start of execution // don't get scheduled for initial execution. // // Revision 1.24 2011/03/28 13:02:52 acg // Andy Goodrich: Changes for disable() interactions. // // Revision 1.23 2011/03/12 21:07:51 acg // Andy Goodrich: changes to kernel generated event support. // // Revision 1.22 2011/03/07 17:38:43 acg // Andy Goodrich: tightening up of checks for undefined interaction between // synchronous reset and suspend. // // Revision 1.21 2011/03/06 19:57:11 acg // Andy Goodrich: refinements for the illegal suspend - synchronous reset // interaction. // // Revision 1.20 2011/03/06 15:58:50 acg // Andy Goodrich: added escape to turn off process control corner case // checks. // // Revision 1.19 2011/03/05 04:45:16 acg // Andy Goodrich: moved active process calculation to the sc_simcontext class. // // Revision 1.18 2011/03/05 01:39:21 acg // Andy Goodrich: changes for named events. // // Revision 1.17 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.16 2011/02/17 19:53:28 acg // Andy Goodrich: eliminated use of ready_to_run() as part of process control // simplification. // // Revision 1.15 2011/02/13 21:47:38 acg // Andy Goodrich: update copyright notice. // // Revision 1.14 2011/02/11 13:25:24 acg // Andy Goodrich: Philipp A. Hartmann's changes: // (1) Removal of SC_CTHREAD method overloads. // (2) New exception processing code. // // Revision 1.13 2011/02/08 08:42:50 acg // Andy Goodrich: fix ordering of check for stopped versus paused. // // Revision 1.12 2011/02/07 19:17:20 acg // Andy Goodrich: changes for IEEE 1666 compatibility. // // Revision 1.11 2011/02/02 07:18:11 acg // Andy Goodrich: removed toggle() calls for the new crunch() toggle usage. // // Revision 1.10 2011/02/01 23:01:53 acg // Andy Goodrich: removed dead code. // // Revision 1.9 2011/02/01 21:11:59 acg // Andy Goodrich: // (1) Use of new toggle_methods() and toggle_threads() run queue methods // to make sure the thread run queue does not execute when allow preempt_me() // is called from an SC_METHOD. // (2) Use of execute_thread_next() to allow thread execution in the current // delta cycle() rather than push_runnable_thread_front which executed // in the following cycle. // // Revision 1.8 2011/01/25 20:50:37 acg // Andy Goodrich: changes for IEEE 1666 2011. // // Revision 1.7 2011/01/19 23:21:50 acg // Andy Goodrich: changes for IEEE 1666 2011 // // Revision 1.6 2011/01/18 20:10:45 acg // Andy Goodrich: changes for IEEE1666_2011 semantics. // // Revision 1.5 2010/11/20 17:10:57 acg // Andy Goodrich: reset processing changes for new IEEE 1666 standard. // // Revision 1.4 2010/07/22 20:02:33 acg // Andy Goodrich: bug fixes. // // Revision 1.3 2008/05/22 17:06:26 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.2 2007/09/20 20:32:35 acg // Andy Goodrich: changes to the semantics of throw_it() to match the // specification. A call to throw_it() will immediately suspend the calling // thread until all the throwees have executed. At that point the calling // thread will be restarted before the execution of any other threads. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.21 2006/08/29 23:37:13 acg // Andy Goodrich: Added check for negative time. // // Revision 1.20 2006/05/26 20:33:16 acg // Andy Goodrich: changes required by additional platform compilers (i.e., // Microsoft VC++, Sun Forte, HP aCC). // // Revision 1.19 2006/05/08 17:59:52 acg // Andy Goodrich: added a check before m_curr_time is set to make sure it // is not set to a time before its current value. This will treat // sc_event.notify( ) calls with negative times as calls with a zero time. // // Revision 1.18 2006/04/20 17:08:17 acg // Andy Goodrich: 3.0 style process changes. // // Revision 1.17 2006/04/11 23:13:21 acg // Andy Goodrich: Changes for reduced reset support that only includes // sc_cthread, but has preliminary hooks for expanding to method and thread // processes also. // // Revision 1.16 2006/03/21 00:00:34 acg // Andy Goodrich: changed name of sc_get_current_process_base() to be // sc_get_current_process_b() since its returning an sc_process_b instance. // // Revision 1.15 2006/03/13 20:26:50 acg // Andy Goodrich: Addition of forward class declarations, e.g., // sc_reset, to keep gcc 4.x happy. // // Revision 1.14 2006/02/02 23:42:41 acg // Andy Goodrich: implemented a much better fix to the sc_event_finder // proliferation problem. This new version allocates only a single event // finder for each port for each type of event, e.g., pos(), neg(), and // value_change(). The event finder persists as long as the port does, // which is what the LRM dictates. Because only a single instance is // allocated for each event type per port there is not a potential // explosion of storage as was true in the 2.0.1/2.1 versions. // // Revision 1.13 2006/02/02 21:29:10 acg // Andy Goodrich: removed the call to sc_event_finder::free_instances() that // was in end_of_elaboration(), leaving only the call in clean(). This is // because the LRM states that sc_event_finder instances are persistent as // long as the sc_module hierarchy is valid. // // Revision 1.12 2006/02/02 21:09:50 acg // Andy Goodrich: added call to sc_event_finder::free_instances in the clean() // method. // // Revision 1.11 2006/02/02 20:43:14 acg // Andy Goodrich: Added an existence linked list to sc_event_finder so that // the dynamically allocated instances can be freed after port binding // completes. This replaces the individual deletions in ~sc_bind_ef, as these // caused an exception if an sc_event_finder instance was used more than // once, due to a double freeing of the instance. // // Revision 1.10 2006/01/31 21:43:26 acg // Andy Goodrich: added comments in constructor to highlight environmental // overrides section. // // Revision 1.9 2006/01/26 21:04:54 acg // Andy Goodrich: deprecation message changes and additional messages. // // Revision 1.8 2006/01/25 00:31:19 acg // Andy Goodrich: Changed over to use a standard message id of // SC_ID_IEEE_1666_DEPRECATION for all deprecation messages. // // Revision 1.7 2006/01/24 20:49:05 acg // Andy Goodrich: changes to remove the use of deprecated features within the // simulator, and to issue warning messages when deprecated features are used. // // Revision 1.6 2006/01/19 00:29:52 acg // Andy Goodrich: Yet another implementation for signal write checking. This // one uses an environment variable SC_SIGNAL_WRITE_CHECK, that when set to // DISABLE will disable write checking on signals. // // Revision 1.5 2006/01/13 18:44:30 acg // Added $Log to record CVS changes into the source. // // Revision 1.4 2006/01/03 23:18:44 acg // Changed copyright to include 2006. // // Revision 1.3 2005/12/20 22:11:10 acg // Fixed $Log lines. // // Revision 1.2 2005/12/20 22:02:30 acg // Changed where delta cycles are incremented to match IEEE 1666. Added the // event_occurred() method to hide how delta cycle comparisions are done within // sc_simcontext. Changed the boolean update_phase to an enum that shows all // the phases. // Taf! systemc-2.3.3/src/sysc/kernel/sc_status.h0000644000175000017500000000617013360325173020306 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_status.h -- Definition of the simulation phases Original Author: Philipp A. Hartmann, OFFIS, 2013-02-15 CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #ifndef SC_STATUS_H_INCLUDED_ #define SC_STATUS_H_INCLUDED_ #include #include "sysc/kernel/sc_cmnhdr.h" namespace sc_core { // simulation status codes const int SC_SIM_OK = 0; const int SC_SIM_ERROR = 1; const int SC_SIM_USER_STOP = 2; enum sc_status { // sc_get_status values: SC_UNITIALIZED=0x00, // initialize() not called yet SC_ELABORATION = 0x01, // during module hierarchy construction SC_BEFORE_END_OF_ELABORATION = 0x02, // during before_end_of_elaboration() SC_END_OF_ELABORATION = 0x04, // during end_of_elaboration() SC_START_OF_SIMULATION = 0x08, // during start_of_simulation() SC_RUNNING = 0x10, // initialization, evaluation or update SC_PAUSED = 0x20, // when scheduler stopped by sc_pause() SC_STOPPED = 0x40, // when scheduler stopped by sc_stop() SC_END_OF_SIMULATION = 0x80, // during end_of_simulation() // detailed simulation phases (for dynamic callbacks) SC_END_OF_INITIALIZATION = 0x100, // after initialization // SC_END_OF_EVALUATION = 0x200, // between eval and update SC_END_OF_UPDATE = 0x400, // after update/notify phase SC_BEFORE_TIMESTEP = 0x800, // before next time step SC_STATUS_LAST = SC_BEFORE_TIMESTEP, SC_STATUS_ANY = 0xdff }; // pretty-printing of sc_status values SC_API std::ostream& operator << ( std::ostream&, sc_status ); } // namespace sc_core /***************************************************************************** MODIFICATION LOG - modifiers, enter your name, affiliation, date and changes you are making here. Name, Affiliation, Date: Description of Modification: *****************************************************************************/ #endif /* SC_STATUS_H_INCLUDED_ */ // Taf! systemc-2.3.3/src/sysc/kernel/sc_spawn_options.cpp0000644000175000017500000001137713360325173022226 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_spawn_options.cpp -- Process spawning options implementation. Original Authors: Andy Goodrich, Forte Design Systems, 17 June 2003 Stuart Swan, Cadence, Bishnupriya Bhattacharya, Cadence Design Systems, 25 August, 2003 CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #include "sysc/kernel/sc_spawn_options.h" #include "sysc/kernel/sc_reset.h" namespace sc_core { // +====================================================================== // | CLASS sc_spawn_reset_base - Class to do a generic access to an // | sc_spawn_rest object instance // +====================================================================== class sc_spawn_reset_base { public: sc_spawn_reset_base( bool async, bool level ) : m_async( async ), m_level(level) {} virtual ~sc_spawn_reset_base() {} virtual void specify_reset() = 0; protected: bool m_async; // = true if async reset. bool m_level; // level indicating reset. }; // +====================================================================== // | CLASS sc_spawn_reset // | - Reset specification for sc_spawn_options. // +====================================================================== template class sc_spawn_reset : public sc_spawn_reset_base { public: sc_spawn_reset( bool async, const SOURCE& source, bool level ) : sc_spawn_reset_base(async, level), m_source(source) {} virtual ~sc_spawn_reset() {} virtual void specify_reset() { sc_reset::reset_signal_is( m_async, m_source, m_level ); } protected: const SOURCE& m_source; // source of reset signal. }; // +====================================================================== // | CLASS sc_spawn_options (implementation) // | // +====================================================================== sc_spawn_options::~sc_spawn_options() { std::vector::size_type resets_n = m_resets.size(); for ( std::vector::size_type reset_i = 0; reset_i < resets_n; reset_i++ ) delete m_resets[reset_i]; } #define SC_DEFINE_RESET_SIGNALS( Port ) \ /* asynchronous reset */ \ void \ sc_spawn_options:: \ async_reset_signal_is ( const Port & port, bool level ) \ { \ m_resets.push_back( \ new sc_spawn_reset< Port >(true, port, level) ); \ } \ /* sync reset */ \ void \ sc_spawn_options:: \ reset_signal_is ( const Port & port, bool level ) \ { \ m_resets.push_back( \ new sc_spawn_reset< Port >(false, port, level) ); \ } SC_DEFINE_RESET_SIGNALS( sc_in ) SC_DEFINE_RESET_SIGNALS( sc_inout ) SC_DEFINE_RESET_SIGNALS( sc_out ) SC_DEFINE_RESET_SIGNALS( sc_signal_in_if ) #undef SC_DEFINE_RESET_SIGNALS void sc_spawn_options::specify_resets() const { std::vector::size_type resets_n; // number of reset specifications to process. resets_n = m_resets.size(); for ( std::vector::size_type reset_i = 0; reset_i < resets_n; reset_i++ ) m_resets[reset_i]->specify_reset(); } } // namespace sc_core // Taf! systemc-2.3.3/src/sysc/kernel/sc_main.cpp0000644000175000017500000000403613360325173020241 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_main.cpp - Wrapper around user's toplevel routine `sc_main'. Original Author: Stan Y. Liao, Synopsys, Inc. CHANGE LOG APPEARS AT THE END OF THE FILE *****************************************************************************/ #include "sysc/kernel/sc_cmnhdr.h" #include "sysc/kernel/sc_externs.h" int main( int argc, char* argv[] ) { return sc_core::sc_elab_and_sim( argc, argv ); } // $Log: sc_main.cpp,v $ // Revision 1.5 2011/08/26 20:46:09 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.4 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.3 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.2 2008/05/22 17:06:25 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.3 2006/01/13 18:44:29 acg // Added $Log to record CVS changes into the source. // systemc-2.3.3/src/sysc/kernel/sc_module_name.h0000644000175000017500000001103513360325173021244 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_module_name.h -- An object used to help manage object names and hierarchy. Original Author: Stan Y. Liao, Synopsys, Inc. CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ // $Log: sc_module_name.h,v $ // Revision 1.5 2011/08/26 20:46:10 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // #ifndef SC_MODULE_NAME_H #define SC_MODULE_NAME_H namespace sc_core { class sc_module; class sc_simcontext; // ---------------------------------------------------------------------------- // CLASS : sc_module_name // // Module name class. // ---------------------------------------------------------------------------- class SC_API sc_module_name { friend class sc_module; friend class sc_object_manager; public: sc_module_name( const char* ); sc_module_name( const sc_module_name& ); ~sc_module_name(); operator const char*() const; protected: inline void clear_module( sc_module* module_p ); inline void set_module( sc_module* module_p ); private: const char* m_name; sc_module* m_module_p; sc_module_name* m_next; sc_simcontext* m_simc; bool m_pushed; private: // disabled sc_module_name(); sc_module_name& operator = ( const sc_module_name& ); }; inline void sc_module_name::clear_module( sc_module* module_p ) { sc_assert( m_module_p == module_p ); m_module_p = module_p = 0; // avoid unused parameter warning (module_p) } inline void sc_module_name::set_module( sc_module* module_p ) { m_module_p = module_p; } } // namespace sc_core // Revision 1.4 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.3 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.2 2008/05/22 17:06:26 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.4 2006/03/14 23:56:58 acg // Andy Goodrich: This fixes a bug when an exception is thrown in // sc_module::sc_module() for a dynamically allocated sc_module // object. We are calling sc_module::end_module() on a module that has // already been deleted. The scenario runs like this: // // a) the sc_module constructor is entered // b) the exception is thrown // c) the exception processor deletes the storage for the sc_module // d) the stack is unrolled causing the sc_module_name instance to be deleted // e) ~sc_module_name() calls end_module() with its pointer to the sc_module // f) because the sc_module has been deleted its storage is corrupted, // either by linking it to a free space chain, or by reuse of some sort // g) the m_simc field is garbage // h) the m_object_manager field is also garbage // i) an exception occurs // // This does not happen for automatic sc_module instances since the // storage for the module is not reclaimed its just part of the stack. // // I am fixing this by having the destructor for sc_module clear the // module pointer in its sc_module_name instance. That cuts things at // step (e) above, since the pointer will be null if the module has // already been deleted. To make sure the module stack is okay, I call // end-module() in ~sc_module in the case where there is an // sc_module_name pointer lying around. // // Revision 1.3 2006/01/13 18:44:30 acg // Added $Log to record CVS changes into the source. #endif systemc-2.3.3/src/sysc/kernel/sc_spawn_options.h0000644000175000017500000001424613360325173021671 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_spawn_options.h -- Process spawning options specification. Original Authors: Andy Goodrich, Forte Design Systems, 17 June 2003 Stuart Swan, Cadence, Bishnupriya Bhattacharya, Cadence Design Systems, 25 August, 2003 CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #if !defined(sc_spawn_options_h_INCLUDED) #define sc_spawn_options_h_INCLUDED #include #include "sysc/communication/sc_export.h" #include "sysc/communication/sc_signal_ports.h" #if defined(_MSC_VER) && !defined(SC_WIN_DLL_WARN) #pragma warning(push) #pragma warning(disable: 4251) // DLL import for std::vector #endif namespace sc_core { class sc_event; class sc_port_base; class sc_interface; class sc_event_finder; class sc_process_b; class sc_spawn_reset_base; //============================================================================= // CLASS sc_spawn_options // //============================================================================= class SC_API sc_spawn_options { friend class sc_cthread_process; friend class sc_method_process; friend class sc_process_b; friend class sc_thread_process; public: sc_spawn_options() : m_dont_initialize(false), m_resets(), m_sensitive_events(), m_sensitive_event_finders(), m_sensitive_interfaces(), m_sensitive_port_bases(), m_spawn_method(false), m_stack_size(0) { } ~sc_spawn_options(); void async_reset_signal_is( const sc_in&, bool level ); void async_reset_signal_is( const sc_inout&, bool level ); void async_reset_signal_is( const sc_out&, bool level ); void async_reset_signal_is( const sc_signal_in_if&, bool level ); void reset_signal_is( const sc_in&, bool level ); void reset_signal_is( const sc_inout&, bool level ); void reset_signal_is( const sc_out&, bool level ); void reset_signal_is( const sc_signal_in_if&, bool level ); void dont_initialize() { m_dont_initialize = true; } bool is_method() const { return m_spawn_method; } void set_stack_size(int stack_size) { m_stack_size = stack_size; } void set_sensitivity(const sc_event* event) { m_sensitive_events.push_back(event); } void set_sensitivity(sc_port_base* port_base) { m_sensitive_port_bases.push_back(port_base); } void set_sensitivity(sc_interface* interface_p) { m_sensitive_interfaces.push_back(interface_p); } void set_sensitivity(sc_export_base* export_base) { m_sensitive_interfaces.push_back(export_base->get_interface()); } void set_sensitivity(sc_event_finder* event_finder) { m_sensitive_event_finders.push_back(event_finder); } void spawn_method() { m_spawn_method = true; } protected: void specify_resets() const; private: sc_spawn_options( const sc_spawn_options& ); const sc_spawn_options& operator = ( const sc_spawn_options& ); protected: bool m_dont_initialize; std::vector m_resets; std::vector m_sensitive_events; std::vector m_sensitive_event_finders; std::vector m_sensitive_interfaces; std::vector m_sensitive_port_bases; bool m_spawn_method; // Method not thread. int m_stack_size; // Thread stack size. }; } // namespace sc_core #if defined(_MSC_VER) && !defined(SC_WIN_DLL_WARN) #pragma warning(pop) #endif // $Log: sc_spawn_options.h,v $ // Revision 1.11 2011/08/26 20:46:11 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.10 2011/08/24 22:05:51 acg // Torsten Maehne: initialization changes to remove warnings. // // Revision 1.9 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.8 2011/02/13 21:47:38 acg // Andy Goodrich: update copyright notice. // // Revision 1.7 2011/02/07 19:17:20 acg // Andy Goodrich: changes for IEEE 1666 compatibility. // // Revision 1.6 2010/12/07 20:09:15 acg // Andy Goodrich: replaced sc_signal signatures with sc_signal_in_if signatures for reset methods. // // Revision 1.5 2010/11/20 17:10:57 acg // Andy Goodrich: reset processing changes for new IEEE 1666 standard. // // Revision 1.4 2009/05/22 16:06:29 acg // Andy Goodrich: process control updates. // // Revision 1.3 2009/02/28 00:26:58 acg // Andy Goodrich: changed boost name space to sc_boost to allow use with // full boost library applications. // // Revision 1.2 2008/05/22 17:06:26 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.4 2006/04/20 17:08:17 acg // Andy Goodrich: 3.0 style process changes. // // Revision 1.3 2006/01/13 18:44:30 acg // Added $Log to record CVS changes into the source. #endif // !defined(sc_spawn_options_h_INCLUDED) systemc-2.3.3/src/sysc/kernel/sc_wait_cthread.cpp0000644000175000017500000001171613360325173021756 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_wait_cthread.cpp -- Wait() and related functions for SC_CTHREADs. Original Author: Stan Y. Liao, Synopsys, Inc. Martin Janssen, Synopsys, Inc. CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #include "sysc/kernel/sc_kernel_ids.h" #include "sysc/kernel/sc_cthread_process.h" #include "sysc/kernel/sc_simcontext_int.h" #include "sysc/kernel/sc_wait_cthread.h" #include "sysc/communication/sc_port.h" #include "sysc/kernel/sc_wait.h" #include namespace sc_core { // for SC_CTHREADs void halt( sc_simcontext* simc ) { sc_curr_proc_handle cpi = simc->get_curr_proc_info(); switch( cpi->kind ) { case SC_CTHREAD_PROC_: { reinterpret_cast( cpi->process_handle )->wait_halt(); break; } default: SC_REPORT_ERROR( SC_ID_HALT_NOT_ALLOWED_, 0 ); break; } } void wait( int n, sc_simcontext* simc ) { sc_curr_proc_handle cpi = simc->get_curr_proc_info(); if( n <= 0 ) { std::stringstream msg; msg << "n = " << n; SC_REPORT_ERROR( SC_ID_WAIT_N_INVALID_, msg.str().c_str() ); } switch( cpi->kind ) { case SC_THREAD_PROC_: case SC_CTHREAD_PROC_: reinterpret_cast( cpi->process_handle )->wait_cycles( n ); break; default: SC_REPORT_ERROR( SC_ID_WAIT_NOT_ALLOWED_, "\n " "in SC_METHODs use next_trigger() instead" ); break; } } void at_posedge( const sc_signal_in_if& s, sc_simcontext* simc ) { if( s.read() == true ) do { wait(simc); } while ( s.read() == true ); do { wait(simc); } while ( s.read() == false ); } void at_posedge( const sc_signal_in_if& s, sc_simcontext* simc ) { if( s.read() == '1' ) do { wait(simc); } while ( s.read() == '1' ); do { wait(simc); } while ( s.read() == '0' ); } void at_negedge( const sc_signal_in_if& s, sc_simcontext* simc ) { if( s.read() == false ) do { wait(simc); } while ( s.read() == false ); do { wait(simc); } while ( s.read() == true ); } void at_negedge( const sc_signal_in_if& s, sc_simcontext* simc ) { if( s.read() == '0' ) do { wait(simc); } while ( s.read() == '0' ); do { wait(simc); } while ( s.read() == '1' ); } } // namespace sc_core /* $Log: sc_wait_cthread.cpp,v $ Revision 1.6 2011/08/26 20:46:11 acg Andy Goodrich: moved the modification log to the end of the file to eliminate source line number skew when check-ins are done. Revision 1.5 2011/02/18 20:27:14 acg Andy Goodrich: Updated Copyrights. Revision 1.4 2011/02/13 21:47:38 acg Andy Goodrich: update copyright notice. Revision 1.3 2009/10/14 19:07:42 acg Andy Goodrich: added an error message for wait(n) being called from an SC_METHOD. Revision 1.2 2008/05/22 17:06:27 acg Andy Goodrich: updated copyright notice to include 2008. Revision 1.1.1.1 2006/12/15 20:20:05 acg SystemC 2.3 Revision 1.3 2006/03/13 20:26:51 acg Andy Goodrich: Addition of forward class declarations, e.g., sc_reset, to keep gcc 4.x happy. Revision 1.2 2006/01/03 23:18:45 acg Changed copyright to include 2006. Revision 1.1.1.1 2005/12/19 23:16:44 acg First check in of SystemC 2.1 into its own archive. Revision 1.10 2005/09/15 23:02:18 acg Added std:: prefix to appropriate methods and types to get around issues with the Edison Front End. Revision 1.9 2005/09/02 19:03:30 acg Changes for dynamic processes. Removal of lambda support. Revision 1.8 2005/04/04 00:16:08 acg Changes for directory name change to sys from systemc. Changes for sc_string going to std::string. Changes for sc_pvector going to std::vector. Changes for reference pools for bit and part selections. Changes for const sc_concatref support. Revision 1.5 2004/09/27 20:49:10 acg Andy Goodrich, Forte Design Systems, Inc. - Added a $Log comment so that CVS checkin comments appear in the checkout source. */ // Taf! systemc-2.3.3/src/sysc/kernel/sc_method_process.cpp0000644000175000017500000010162013360325173022330 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_method_process.cpp -- Method process implementation Original Author: Andy Goodrich, Forte Design Systems, 4 August 2005 CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #include "sysc/kernel/sc_method_process.h" #include "sysc/kernel/sc_simcontext_int.h" #include "sysc/kernel/sc_module.h" #include "sysc/kernel/sc_spawn_options.h" // DEBUGGING MACROS: // // DEBUG_MSG(NAME,P,MSG) // MSG = message to print // NAME = name that must match the process for the message to print, or // null if the message should be printed unconditionally. // P = pointer to process message is for, or NULL in which case the // message will not print. #if 0 # include # define DEBUG_NAME "" # define DEBUG_MSG(NAME,P,MSG) \ { \ if ( P && ( (std::strlen(NAME)==0) || !std::strcmp(NAME,P->name())) ) \ std::cout << "**** " << sc_time_stamp() << " (" \ << sc_get_current_process_name("** NONE **") << "): " << MSG \ << " - " << P->name() << std::endl; \ } #else # define DEBUG_MSG(NAME,P,MSG) #endif namespace sc_core { // +---------------------------------------------------------------------------- // |"sc_method_process::check_for_throws" // | // | This method checks to see if this method process should throw an exception // | or not. It is called from sc_simcontext::preempt_with() to see if the // | thread that was executed during the preemption did a kill or other // | manipulation on this object instance that requires it to throw an // | exception. // +---------------------------------------------------------------------------- void sc_method_process::check_for_throws() { if ( !m_unwinding ) { switch( m_throw_status ) { case THROW_ASYNC_RESET: simcontext()->preempt_with(this); break; case THROW_KILL: throw sc_unwind_exception( this, false ); default: break; } } } //------------------------------------------------------------------------------ //"sc_method_process::clear_trigger" // // This method clears any pending trigger for this object instance. //------------------------------------------------------------------------------ void sc_method_process::clear_trigger() { switch( m_trigger_type ) { case STATIC: return; case EVENT: m_event_p->remove_dynamic( this ); m_event_p = 0; break; case OR_LIST: m_event_list_p->remove_dynamic( this, 0 ); m_event_list_p->auto_delete(); m_event_list_p = 0; break; case AND_LIST: m_event_list_p->remove_dynamic( this, 0 ); m_event_list_p->auto_delete(); m_event_list_p = 0; m_event_count = 0; break; case TIMEOUT: m_timeout_event_p->cancel(); m_timeout_event_p->reset(); break; case EVENT_TIMEOUT: m_timeout_event_p->cancel(); m_timeout_event_p->reset(); m_event_p->remove_dynamic( this ); m_event_p = 0; break; case OR_LIST_TIMEOUT: m_timeout_event_p->cancel(); m_timeout_event_p->reset(); m_event_list_p->remove_dynamic( this, 0 ); m_event_list_p->auto_delete(); m_event_list_p = 0; break; case AND_LIST_TIMEOUT: m_timeout_event_p->cancel(); m_timeout_event_p->reset(); m_event_list_p->remove_dynamic( this, 0 ); m_event_list_p->auto_delete(); m_event_list_p = 0; m_event_count = 0; break; } m_trigger_type = STATIC; } //------------------------------------------------------------------------------ //"sc_method_process::disable_process" // // This virtual method disables this process and its children if requested to. // descendants = indicator of whether this process' children should also // be suspended //------------------------------------------------------------------------------ void sc_method_process::disable_process( sc_descendant_inclusion_info descendants ) { // IF NEEDED PROPOGATE THE SUSPEND REQUEST THROUGH OUR DESCENDANTS: if ( descendants == SC_INCLUDE_DESCENDANTS ) { const std::vector& children = get_child_objects(); int child_n = children.size(); for ( int child_i = 0; child_i < child_n; child_i++ ) { sc_process_b* child_p = dynamic_cast(children[child_i]); if ( child_p ) child_p->disable_process(descendants); } } // DON'T ALLOW CORNER CASE BY DEFAULT: if ( !sc_allow_process_control_corners ) { switch( m_trigger_type ) { case AND_LIST_TIMEOUT: case EVENT_TIMEOUT: case OR_LIST_TIMEOUT: case TIMEOUT: report_error( SC_ID_PROCESS_CONTROL_CORNER_CASE_, "attempt to disable a method with timeout wait" ); // may continue, if suppressed break; default: break; } } // DISABLE OUR OBJECT INSTANCE: m_state = m_state | ps_bit_disabled; // IF THIS CALL IS BEFORE THE SIMULATION DON'T RUN THE METHOD: if ( !sc_is_running() ) { sc_get_curr_simcontext()->remove_runnable_method(this); } } //------------------------------------------------------------------------------ //"sc_method_process::enable_process" // // This method enables the execution of this process, and if requested, its // descendants. If the process was suspended and has a resumption pending it // will be dispatched in the next delta cycle. Otherwise the state will be // adjusted to indicate it is no longer suspended, but no immediate execution // will occur. //------------------------------------------------------------------------------ void sc_method_process::enable_process( sc_descendant_inclusion_info descendants ) { // IF NEEDED PROPOGATE THE RESUME REQUEST THROUGH OUR DESCENDANTS: if ( descendants == SC_INCLUDE_DESCENDANTS ) { const std::vector& children = get_child_objects(); int child_n = children.size(); for ( int child_i = 0; child_i < child_n; child_i++ ) { sc_process_b* child_p = dynamic_cast(children[child_i]); if ( child_p ) child_p->enable_process(descendants); } } // ENABLE THIS OBJECT INSTANCE: // // If it was disabled and ready to run then put it on the run queue. m_state = m_state & ~ps_bit_disabled; if ( m_state == ps_bit_ready_to_run ) { m_state = ps_normal; if ( next_runnable() == 0 ) simcontext()->push_runnable_method(this); } } //------------------------------------------------------------------------------ //"sc_method_process::kill_process" // // This method removes throws a kill for this object instance. It calls the // sc_process_b::kill_process() method to perform low level clean up. //------------------------------------------------------------------------------ void sc_method_process::kill_process(sc_descendant_inclusion_info descendants) { // IF THE SIMULATION HAS NOT BEEN INITIALIZED YET THAT IS AN ERROR: if ( !sc_is_running() ) { report_error( SC_ID_KILL_PROCESS_WHILE_UNITIALIZED_ ); return; } // IF NEEDED, PROPOGATE THE KILL REQUEST THROUGH OUR DESCENDANTS: if ( descendants == SC_INCLUDE_DESCENDANTS ) { const std::vector children = get_child_objects(); int child_n = children.size(); for ( int child_i = 0; child_i < child_n; child_i++ ) { sc_process_b* child_p = dynamic_cast(children[child_i]); if ( child_p ) child_p->kill_process(descendants); } } // IF THE PROCESS IS CURRENTLY UNWINDING OR IS ALREADY A ZOMBIE // IGNORE THE KILL: if ( m_unwinding ) { SC_REPORT_WARNING( SC_ID_PROCESS_ALREADY_UNWINDING_, name() ); return; } if ( m_state & ps_bit_zombie ) return; // REMOVE OUR PROCESS FROM EVENTS, ETC., AND IF ITS THE ACTIVE PROCESS // THROW ITS KILL. // // Note we set the throw status to kill regardless if we throw or not. // That lets check_for_throws stumble across it if we were in the call // chain when the kill call occurred. if ( next_runnable() != 0 ) simcontext()->remove_runnable_method( this ); disconnect_process(); m_throw_status = THROW_KILL; if ( sc_get_current_process_b() == this ) { throw sc_unwind_exception( this, false ); } } //------------------------------------------------------------------------------ //"sc_method_process::sc_method_process" // // This is the object instance constructor for this class. //------------------------------------------------------------------------------ sc_method_process::sc_method_process( const char* name_p, bool free_host, SC_ENTRY_FUNC method_p, sc_process_host* host_p, const sc_spawn_options* opt_p ): sc_process_b( name_p ? name_p : sc_gen_unique_name("method_p"), false, free_host, method_p, host_p, opt_p), m_cor(0), m_stack_size(0), m_monitor_q() { // CHECK IF THIS IS AN sc_module-BASED PROCESS AND SIMUALTION HAS STARTED: if ( dynamic_cast(host_p) != 0 && sc_is_running() ) { report_error( SC_ID_MODULE_METHOD_AFTER_START_, "" ); sc_abort(); // can't recover from here } // INITIALIZE VALUES: // // If there are spawn options use them. m_process_kind = SC_METHOD_PROC_; if (opt_p) { m_dont_init = opt_p->m_dont_initialize; // traverse event sensitivity list for (unsigned int i = 0; i < opt_p->m_sensitive_events.size(); i++) { sc_sensitive::make_static_sensitivity( this, *opt_p->m_sensitive_events[i]); } // traverse port base sensitivity list for ( unsigned int i = 0; i < opt_p->m_sensitive_port_bases.size(); i++) { sc_sensitive::make_static_sensitivity( this, *opt_p->m_sensitive_port_bases[i]); } // traverse interface sensitivity list for ( unsigned int i = 0; i < opt_p->m_sensitive_interfaces.size(); i++) { sc_sensitive::make_static_sensitivity( this, *opt_p->m_sensitive_interfaces[i]); } // traverse event finder sensitivity list for ( unsigned int i = 0; i < opt_p->m_sensitive_event_finders.size(); i++) { sc_sensitive::make_static_sensitivity( this, *opt_p->m_sensitive_event_finders[i]); } // process any reset signal specification: opt_p->specify_resets(); } else { m_dont_init = false; } } //------------------------------------------------------------------------------ //"sc_method_process::sc_method_process" // // This is the object instance destructor for this class. //------------------------------------------------------------------------------ sc_method_process::~sc_method_process() { // Remove from simcontext, if not spawned during simulation if( m_dynamic_proc != SPAWN_SIM ) { simcontext()->remove_process(this); } } //------------------------------------------------------------------------------ //"sc_method_process::suspend_process" // // This virtual method suspends this process and its children if requested to. // descendants = indicator of whether this process' children should also // be suspended //------------------------------------------------------------------------------ void sc_method_process::suspend_process( sc_descendant_inclusion_info descendants ) { // IF NEEDED PROPOGATE THE SUSPEND REQUEST THROUGH OUR DESCENDANTS: if ( descendants == SC_INCLUDE_DESCENDANTS ) { const std::vector& children = get_child_objects(); int child_n = children.size(); for ( int child_i = 0; child_i < child_n; child_i++ ) { sc_process_b* child_p = dynamic_cast(children[child_i]); if ( child_p ) child_p->suspend_process(descendants); } } // CORNER CASE CHECKS, THE FOLLOWING ARE ERRORS: // (a) if this method has a reset_signal_is specification // (b) if this method is in synchronous reset if ( !sc_allow_process_control_corners && m_has_reset_signal ) { report_error(SC_ID_PROCESS_CONTROL_CORNER_CASE_, "attempt to suspend a method that has a reset signal"); // may continue, if suppressed } else if ( !sc_allow_process_control_corners && m_sticky_reset ) { report_error(SC_ID_PROCESS_CONTROL_CORNER_CASE_, "attempt to suspend a method in synchronous reset"); // may continue, if suppressed } // SUSPEND OUR OBJECT INSTANCE: // // (1) If we are on the runnable queue then set suspended and ready_to_run, // and remove ourselves from the run queue. // (2) If this is a self-suspension then a resume should cause immediate // scheduling of the process. m_state = m_state | ps_bit_suspended; if ( next_runnable() != 0 ) { m_state = m_state | ps_bit_ready_to_run; simcontext()->remove_runnable_method( this ); } if ( sc_get_current_process_b() == dynamic_cast(this) ) { m_state = m_state | ps_bit_ready_to_run; } } //------------------------------------------------------------------------------ //"sc_method_process::resume_process" // // This method resumes the execution of this process, and if requested, its // descendants. If the process was suspended and has a resumption pending it // will be dispatched in the next delta cycle. Otherwise the state will be // adjusted to indicate it is no longer suspended, but no immediate execution // will occur. //------------------------------------------------------------------------------ void sc_method_process::resume_process( sc_descendant_inclusion_info descendants ) { // IF NEEDED PROPOGATE THE RESUME REQUEST THROUGH OUR DESCENDANTS: if ( descendants == SC_INCLUDE_DESCENDANTS ) { const std::vector& children = get_child_objects(); int child_n = children.size(); for ( int child_i = 0; child_i < child_n; child_i++ ) { sc_process_b* child_p = dynamic_cast(children[child_i]); if ( child_p ) child_p->resume_process(descendants); } } // BY DEFAULT THE CORNER CASE IS AN ERROR: if ( !sc_allow_process_control_corners && (m_state & ps_bit_disabled) && (m_state & ps_bit_suspended) ) { m_state = m_state & ~ps_bit_suspended; report_error( SC_ID_PROCESS_CONTROL_CORNER_CASE_, "call to resume() on a disabled suspended method" ); // may continue, if suppressed } // CLEAR THE SUSPENDED BIT: m_state = m_state & ~ps_bit_suspended; // RESUME OBJECT INSTANCE: // // If this is not a self-resume and the method is ready to run then // put it on the runnable queue. if ( m_state & ps_bit_ready_to_run ) { m_state = m_state & ~ps_bit_ready_to_run; if ( next_runnable() == 0 && ( sc_get_current_process_b() != dynamic_cast(this) ) ) { simcontext()->push_runnable_method(this); remove_dynamic_events(); } } } //------------------------------------------------------------------------------ //"sc_method_process::throw_reset" // // This virtual method is invoked to "throw" a reset. // // If the reset is synchronous this is a no-op, except for triggering the // reset event if it is present. // // If the reset is asynchronous we: // (a) cancel any dynamic waits // (b) if it is the active process actually throw a reset exception. // (c) if it was not the active process and does not have a static // sensitivity emit an error if corner cases are to be considered // errors. // // Notes: // (1) If the process had a reset event it will have been triggered in // sc_process_b::semantics() // // Arguments: // async = true if this is an asynchronous reset. //------------------------------------------------------------------------------ void sc_method_process::throw_reset( bool async ) { // IF THE PROCESS IS CURRENTLY UNWINDING OR IS ALREADY A ZOMBIE // IGNORE THE RESET: if ( m_unwinding ) { SC_REPORT_WARNING( SC_ID_PROCESS_ALREADY_UNWINDING_, name() ); return; } if ( m_state & ps_bit_zombie ) return; // Set the throw status and if its an asynchronous reset throw an // exception: m_throw_status = async ? THROW_ASYNC_RESET : THROW_SYNC_RESET; if ( async ) { remove_dynamic_events(); if ( sc_get_current_process_b() == this ) { DEBUG_MSG(DEBUG_NAME,this,"throw_reset: throwing exception"); m_throw_status = THROW_ASYNC_RESET; throw sc_unwind_exception( this, true ); } else { DEBUG_MSG(DEBUG_NAME,this, "throw_reset: queueing this method for execution"); simcontext()->preempt_with(this); } } } //------------------------------------------------------------------------------ //"sc_method_process::throw_user" // // This virtual method is invoked when a user exception is to be thrown. // If requested it will also throw the exception to the children of this // object instance. Since this is a method no throw will occur for this // object instance. The children will be awakened from youngest child to // eldest. // helper_p -> object to use to throw the exception. // descendants = indicator of whether this process' children should also // be suspended //------------------------------------------------------------------------------ void sc_method_process::throw_user( const sc_throw_it_helper& helper, sc_descendant_inclusion_info descendants ) { // IF THE SIMULATION IS NOT ACTUALLY RUNNING THIS IS AN ERROR: if ( sc_get_status() != SC_RUNNING ) { report_error( SC_ID_THROW_IT_WHILE_NOT_RUNNING_ ); return; } // IF NEEDED PROPOGATE THE THROW REQUEST THROUGH OUR DESCENDANTS: if ( descendants == SC_INCLUDE_DESCENDANTS ) { const std::vector children = get_child_objects(); int child_n = children.size(); for ( int child_i = 0; child_i < child_n; child_i++ ) { sc_process_b* child_p = dynamic_cast(children[child_i]); if ( child_p ) { DEBUG_MSG(DEBUG_NAME,child_p,"about to throw user on"); child_p->throw_user(helper, descendants); } } } #if 0 // shouldn't we throw, if we're currently running? if ( sc_get_current_process_b() == (sc_process_b*)this ) { remove_dynamic_events(); m_throw_status = THROW_USER; if ( m_throw_helper_p != 0 ) delete m_throw_helper_p; m_throw_helper_p = helper.clone(); m_throw_helper_p->throw_it(); } // throw_it HAS NO EFFECT ON A METHOD, ISSUE A WARNING: else #endif { SC_REPORT_WARNING( SC_ID_THROW_IT_IGNORED_, name() ); } } //------------------------------------------------------------------------------ //"sc_method_process::trigger_dynamic" // // This method sets up a dynamic trigger on an event. // // Notes: // (1) This method is identical to sc_thread_process::trigger_dynamic(), // but they cannot be combined as sc_process_b::trigger_dynamic() // because the signatures things like sc_event::remove_dynamic() // have different overloads for sc_method_process* and sc_thread_process*. // So if you change code here you'll also need to change it in // sc_thread_process.cpp. // // Result is true if this process should be removed from the event's list, // false if not. // // If the triggering process is the same process, the trigger is // ignored as well, unless SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS // is defined. //------------------------------------------------------------------------------ bool sc_method_process::trigger_dynamic( sc_event* e ) { // No time outs yet, and keep gcc happy. m_timed_out = false; // Escape cases: // (a) If this method issued the notify() don't schedule it for // execution, but leave the sensitivity in place. // (b) If this method is already runnable can't trigger an event. #if ! defined( SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS ) if( SC_UNLIKELY_( sc_get_current_process_b() == this ) ) { report_immediate_self_notification(); return false; } #endif // SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS if( is_runnable() ) return true; // If a process is disabled then we ignore any events, leaving them enabled: // // But if this is a time out event we need to remove both it and the // event that was being waited for. if ( m_state & ps_bit_disabled ) { if ( e == m_timeout_event_p ) { remove_dynamic_events( true ); return true; } else { return false; } } // Process based on the event type and current process state: // // Every case needs to set 'rc' and continue on to the end of // this method to allow suspend processing to work correctly. switch( m_trigger_type ) { case EVENT: m_event_p = 0; m_trigger_type = STATIC; break; case AND_LIST: -- m_event_count; if ( m_event_count == 0 ) { m_event_list_p->auto_delete(); m_event_list_p = 0; m_trigger_type = STATIC; } else { return true; } break; case OR_LIST: m_event_list_p->remove_dynamic( this, e ); m_event_list_p->auto_delete(); m_event_list_p = 0; m_trigger_type = STATIC; break; case TIMEOUT: m_trigger_type = STATIC; break; case EVENT_TIMEOUT: if ( e == m_timeout_event_p ) { m_timed_out = true; m_event_p->remove_dynamic( this ); m_event_p = 0; m_trigger_type = STATIC; } else { m_timeout_event_p->cancel(); m_timeout_event_p->reset(); m_event_p = 0; m_trigger_type = STATIC; } break; case OR_LIST_TIMEOUT: if ( e == m_timeout_event_p ) { m_timed_out = true; m_event_list_p->remove_dynamic( this, e ); m_event_list_p->auto_delete(); m_event_list_p = 0; m_trigger_type = STATIC; } else { m_timeout_event_p->cancel(); m_timeout_event_p->reset(); m_event_list_p->remove_dynamic( this, e ); m_event_list_p->auto_delete(); m_event_list_p = 0; m_trigger_type = STATIC; } break; case AND_LIST_TIMEOUT: if ( e == m_timeout_event_p ) { m_timed_out = true; m_event_list_p->remove_dynamic( this, e ); m_event_list_p->auto_delete(); m_event_list_p = 0; m_trigger_type = STATIC; } else { -- m_event_count; if ( m_event_count == 0 ) { m_timeout_event_p->cancel(); m_timeout_event_p->reset(); // no need to remove_dynamic m_event_list_p->auto_delete(); m_event_list_p = 0; m_trigger_type = STATIC; } else { return true; } } break; case STATIC: { // we should never get here, but throw_it() can make it happen. SC_REPORT_WARNING(SC_ID_NOT_EXPECTING_DYNAMIC_EVENT_NOTIFY_, name()); return true; } } // If we get here then the method has satisfied its next_trigger, if its // suspended mark its state as ready to run. If its not suspended then push // it onto the runnable queue. if ( (m_state & ps_bit_suspended) ) { m_state = m_state | ps_bit_ready_to_run; } else { simcontext()->push_runnable_method(this); } return true; } } // namespace sc_core /***************************************************************************** MODIFICATION LOG - modifiers, enter your name, affiliation, date and changes you are making here. Name, Affiliation, Date: Description of Modification: *****************************************************************************/ // $Log: sc_method_process.cpp,v $ // Revision 1.49 2011/08/29 18:24:47 acg // Andy Goodrich: remove temporary comment flagging new preempt_with() call. // // Revision 1.48 2011/08/29 18:04:32 acg // Philipp A. Hartmann: miscellaneous clean ups. // // Revision 1.47 2011/08/24 22:05:50 acg // Torsten Maehne: initialization changes to remove warnings. // // Revision 1.46 2011/08/07 19:08:04 acg // Andy Goodrich: moved logs to end of file so line number synching works // better between versions. // // Revision 1.45 2011/07/29 22:42:45 acg // Andy Goodrich: added check_for_throws() to fix case where a method is // deleted by a process it resets or kills so that it can throw itself. // Philipp A. Hartmann: changes to handle case where a process control // invocation on a child process causes the list of child processes to change. // // Revision 1.44 2011/07/24 11:27:04 acg // Andy Goodrich: moved the check for unwinding processes until after the // descendants have been processed in throw_user and kill. // // Revision 1.43 2011/07/24 11:20:03 acg // Philipp A. Hartmann: process control error message improvements: // (1) Downgrade error to warning for re-kills of processes. // (2) Add process name to process messages. // (3) drop some superfluous colons in messages. // // Revision 1.42 2011/05/05 17:45:27 acg // Philip A. Hartmann: changes in WIN64 support. // Andy Goodrich: additional DEBUG_MSG instances to trace process handling. // // Revision 1.41 2011/04/19 19:15:41 acg // Andy Goodrich: fix so warning message is always issued for a throw_it() // on a method process. // // Revision 1.40 2011/04/19 15:04:27 acg // Philipp A. Hartmann: clean up SC_ID messages. // // Revision 1.39 2011/04/19 02:39:09 acg // Philipp A. Hartmann: added checks for additional throws during stack unwinds. // // Revision 1.38 2011/04/13 02:41:34 acg // Andy Goodrich: eliminate warning messages generated when the DEBUG_MSG // macro is used. // // Revision 1.37 2011/04/11 22:10:46 acg // Andy Goodrich: // (1) Add DEBUG_MSG macro and use it to generate a journal of method // throws if it is enabled. // (2) Trim down to the expected behavior of scheduling a method that // is asynchronously reset in anticipation of IEEE 1666 being revised. // // Revision 1.36 2011/04/10 22:15:29 acg // Andy Goodrich: change to call methods on asynchronous reset. // // Revision 1.35 2011/04/08 22:31:40 acg // Andy Goodrich: removed unused code. // // Revision 1.34 2011/04/08 18:24:07 acg // Andy Goodrich: fix asynchronous reset dispatch and when the reset_event() // is fired. // // Revision 1.33 2011/04/05 20:50:56 acg // Andy Goodrich: // (1) changes to make sure that event(), posedge() and negedge() only // return true if the clock has not moved. // (2) fixes for method self-resumes. // (3) added SC_PRERELEASE_VERSION // (4) removed kernel events from the object hierarchy, added // sc_hierarchy_name_exists(). // // Revision 1.32 2011/04/01 22:30:39 acg // Andy Goodrich: change hard assertion to warning for trigger_dynamic() // getting called when there is only STATIC sensitivity. This can result // because of sc_process_handle::throw_it(). // // Revision 1.31 2011/03/28 13:02:51 acg // Andy Goodrich: Changes for disable() interactions. // // Revision 1.30 2011/03/23 16:17:52 acg // Andy Goodrich: don't emit an error message for a resume on a disabled // process that is not suspended. // // Revision 1.29 2011/03/20 13:43:23 acg // Andy Goodrich: added async_signal_is() plus suspend() as a corner case. // // Revision 1.28 2011/03/08 20:49:30 acg // Andy Goodrich: implement coarse checking for synchronous reset - suspend // interaction. // // Revision 1.27 2011/03/08 20:32:28 acg // Andy Goodrich: implemented "coarse" checking for undefined process // control interactions. // // Revision 1.26 2011/03/07 18:25:19 acg // Andy Goodrich: tightening of check for resume on a disabled process to // only produce an error if it is ready to run. // // Revision 1.25 2011/03/07 17:38:43 acg // Andy Goodrich: tightening up of checks for undefined interaction between // synchronous reset and suspend. // // Revision 1.24 2011/03/06 23:30:13 acg // Andy Goodrich: refining suspend - sync reset corner case checking so that // the following are error situations: // (1) Calling suspend on a process with a reset_signal_is() specification // or sync_reset_on() is active. // (2) Calling sync_reset_on() on a suspended process. // // Revision 1.23 2011/03/06 19:57:11 acg // Andy Goodrich: refinements for the illegal suspend - synchronous reset // interaction. // // Revision 1.22 2011/03/06 16:47:09 acg // Andy Goodrich: changes for testing sync_reset - suspend corner cases. // // Revision 1.21 2011/03/06 15:57:08 acg // Andy Goodrich: added process control corner case checks. // // Revision 1.20 2011/03/05 19:44:20 acg // Andy Goodrich: changes for object and event naming and structures. // // Revision 1.19 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.18 2011/02/17 19:50:43 acg // Andy Goodrich: // (1) Changed signature of trigger_dynamic back to a bool. // (2) Added run queue processing into trigger dynamic. // (3) Simplified process control support. // // Revision 1.17 2011/02/16 22:37:30 acg // Andy Goodrich: clean up to remove need for ps_disable_pending. // // Revision 1.16 2011/02/13 23:09:58 acg // Andy Goodrich: only remove dynamic events for asynchronous resets. // // Revision 1.15 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.14 2011/02/13 21:31:02 acg // Andy Goodrich: added error messages for throws when simulator has not // been initialized. Added missing remove_dynamic_events() call to the // reset code. // // Revision 1.13 2011/02/11 13:25:24 acg // Andy Goodrich: Philipp A. Hartmann's changes: // (1) Removal of SC_CTHREAD method overloads. // (2) New exception processing code. // // Revision 1.12 2011/02/07 19:17:20 acg // Andy Goodrich: changes for IEEE 1666 compatibility. // // Revision 1.11 2011/02/04 15:27:36 acg // Andy Goodrich: changes for suspend-resume semantics. // // Revision 1.10 2011/02/01 23:01:53 acg // Andy Goodrich: removed dead code. // // Revision 1.9 2011/02/01 21:05:05 acg // Andy Goodrich: Changes in trigger_dynamic methods to handle new // process control rules about event sensitivity. // // Revision 1.8 2011/01/25 20:50:37 acg // Andy Goodrich: changes for IEEE 1666 2011. // // Revision 1.7 2011/01/18 20:10:44 acg // Andy Goodrich: changes for IEEE1666_2011 semantics. // // Revision 1.6 2011/01/06 18:02:43 acg // Andy Goodrich: added check for ps_disabled to method_dynamic(). // // Revision 1.5 2010/11/20 17:10:56 acg // Andy Goodrich: reset processing changes for new IEEE 1666 standard. // // Revision 1.4 2010/07/22 20:02:33 acg // Andy Goodrich: bug fixes. // // Revision 1.3 2009/05/22 16:06:29 acg // Andy Goodrich: process control updates. // // Revision 1.2 2008/05/22 17:06:25 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.7 2006/04/20 17:08:16 acg // Andy Goodrich: 3.0 style process changes. // // Revision 1.6 2006/04/11 23:13:20 acg // Andy Goodrich: Changes for reduced reset support that only includes // sc_cthread, but has preliminary hooks for expanding to method and thread // processes also. // // Revision 1.5 2006/01/26 21:04:54 acg // Andy Goodrich: deprecation message changes and additional messages. // // Revision 1.4 2006/01/24 20:49:05 acg // Andy Goodrich: changes to remove the use of deprecated features within the // simulator, and to issue warning messages when deprecated features are used. // // Revision 1.3 2006/01/13 18:44:29 acg // Added $Log to record CVS changes into the source. // systemc-2.3.3/src/sysc/kernel/sc_join.cpp0000644000175000017500000001171313360325173020254 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_join.cpp -- Join Process Synchronization Implementation Original Author: Andy Goodrich, Forte Design Systems, 5 May 2003 CHANGE LOG APPEARS AT THE END OF THE FILE *****************************************************************************/ #include #include #include "sysc/kernel/sc_process_handle.h" #include "sysc/kernel/sc_simcontext.h" #include "sysc/kernel/sc_simcontext_int.h" #include "sysc/kernel/sc_kernel_ids.h" #include "sysc/kernel/sc_thread_process.h" #include "sysc/kernel/sc_join.h" namespace sc_core { //------------------------------------------------------------------------------ //"sc_join::sc_join" // // This is the object instance constructor for this class. //------------------------------------------------------------------------------ sc_join::sc_join() : m_join_event( sc_event::kernel_event, "join_event" ) , m_threads_n(0) {} //------------------------------------------------------------------------------ //"sc_join::add_process - sc_process_b*" // // This method adds a process to this join object instance. This consists of // incrementing the count of processes in the join process and adding this // object instance to the supplied thread's monitoring queue. // process_p -> thread to be monitored. //------------------------------------------------------------------------------ void sc_join::add_process( sc_process_b* process_p ) { sc_thread_handle handle = dynamic_cast(process_p); sc_assert( handle != 0 ); m_threads_n++; handle->add_monitor( this ); } //------------------------------------------------------------------------------ //"sc_join::add_process - sc_process_handle" // // This method adds a process to this join object instance. This consists of // incrementing the count of processes in the join process and adding this // object instance to the supplied thread's monitoring queue. // process_h = handle for process to be monitored. //------------------------------------------------------------------------------ void sc_join::add_process( sc_process_handle process_h ) { sc_thread_handle thread_p; // Thread within process_h. thread_p = process_h.operator sc_thread_handle(); if ( thread_p ) { m_threads_n++; thread_p->add_monitor( this ); } else { SC_REPORT_ERROR( SC_ID_JOIN_ON_METHOD_HANDLE_, 0 ); } } //------------------------------------------------------------------------------ //"sc_join::signal" // // This virtual method is called when a process being monitored by this object // instance sends a signal. If the signal type is spm_exit and the count of // threads that we are waiting to terminate on goes to zero we fire our join // event. // thread_p -> thread that is signalling. // type = type of signal being sent. //------------------------------------------------------------------------------ void sc_join::signal(sc_thread_handle thread_p, int type) { switch ( type ) { case sc_process_monitor::spm_exit: thread_p->remove_monitor(this); if ( --m_threads_n == 0 ) m_join_event.notify(); break; } } } // namespace sc_core // $Log: sc_join.cpp,v $ // Revision 1.7 2011/08/26 21:45:00 acg // Andy Goodrich: fix internal event naming. // // Revision 1.6 2011/08/26 20:46:09 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.5 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.4 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.3 2009/07/28 01:10:53 acg // Andy Goodrich: updates for 2.3 release candidate. // // Revision 1.2 2008/05/22 17:06:25 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.3 2006/01/13 18:44:29 acg // Added $Log to record CVS changes into the source. // systemc-2.3.3/src/sysc/kernel/sc_ver.h0000644000175000017500000001503513360325173017557 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_ver.h -- Version and copyright information. Original Author: Stan Y. Liao, Synopsys, Inc. NO AUTOMATIC CHANGE LOG IS GENERATED, EXPLICIT CHANGE LOG AT END OF FILE *****************************************************************************/ #ifndef SC_VER_H #define SC_VER_H #include "sysc/kernel/sc_cmnhdr.h" #include "sysc/kernel/sc_macros.h" // SC_CONCAT_UNDERSCORE_ // SC_STRINGIFY_HELPER_ #include "sysc/communication/sc_writer_policy.h" // SC_DEFAULT_WRITER_POLICY #include namespace sc_core { extern SC_API const char* sc_copyright(); extern SC_API const char* sc_release(); extern SC_API const char* sc_version(); extern SC_API const unsigned int sc_version_major; extern SC_API const unsigned int sc_version_minor; extern SC_API const unsigned int sc_version_patch; extern SC_API const std::string sc_version_originator; extern SC_API const std::string sc_version_release_date; extern SC_API const std::string sc_version_prerelease; extern SC_API const bool sc_is_prerelease; extern SC_API const std::string sc_version_string; extern SC_API const std::string sc_copyright_string; #define SYSTEMC_2_3_3 #define SYSTEMC_VERSION 20181013 #define SC_VERSION_ORIGINATOR "Accellera" #define SC_VERSION_MAJOR 2 #define SC_VERSION_MINOR 3 #define SC_VERSION_PATCH 3 #define SC_IS_PRERELEASE 0 /// compliancy with IEEE 1666-2011 (see 8.6.5) #define IEEE_1666_SYSTEMC 201101L #define SC_COPYRIGHT \ "Copyright (c) 1996-2018 by all Contributors,\n" \ "ALL RIGHTS RESERVED\n" #define SC_VERSION_RELEASE_DATE \ SC_STRINGIFY_HELPER_( SYSTEMC_VERSION ) #if ( SC_IS_PRERELEASE == 1 ) # define SC_VERSION_PRERELEASE "pub_rev" # define SC_VERSION \ SC_STRINGIFY_HELPER_( SC_VERSION_MAJOR.SC_VERSION_MINOR.SC_VERSION_PATCH ) \ "_" SC_VERSION_PRERELEASE "_" SC_VERSION_RELEASE_DATE \ "-" SC_VERSION_ORIGINATOR #else # define SC_VERSION_PRERELEASE "" // nothing # define SC_VERSION \ SC_STRINGIFY_HELPER_( SC_VERSION_MAJOR.SC_VERSION_MINOR.SC_VERSION_PATCH ) \ "-" SC_VERSION_ORIGINATOR #endif // THIS CLASS AND STATIC INSTANCE BELOW DETECTS BAD REV OBJECTS AT LINK TIME // // Each source file which includes this file for the current SystemC version // will have a static instance of the class sc_api_version_XXX defined // in it. That object instance will cause the constructor below // to be invoked. If the version of the SystemC being linked against // does not contain the constructor below a linkage error will occur. // // The static API check includes the SystemC version numbers as well as // the underlying C++ standard version (SC_CPLUSPLUS). #define SC_API_VERSION_STRING \ SC_CONCAT_UNDERSCORE_( sc_api_version, \ SC_CONCAT_UNDERSCORE_( SC_VERSION_MAJOR, \ SC_CONCAT_UNDERSCORE_( SC_VERSION_MINOR, \ SC_CONCAT_UNDERSCORE_( SC_VERSION_PATCH, \ SC_CONCAT_HELPER_( cxx, SC_CPLUSPLUS ) \ ) ) ) ) // explicitly avoid macro expansion #define SC_API_DEFINED_( Symbol ) \ Symbol ## _DEFINED_ #define SC_API_UNDEFINED_( Symbol ) \ Symbol ## _UNDEFINED_ // Some preprocessor switches need to be consistent between the application // and the library (e.g. if sizes of classes are affected or other parts of // the ABI are affected). (Some of) these are checked here at link-time as // well, by setting template parameters to sc_api_version_XXX, while only // one variant is defined in sc_ver.cpp. #if 0 // don't enforce check of DEBUG_SYSTEMC for now // DEBUG_SYSTEMC #if defined( DEBUG_SYSTEMC ) # define DEBUG_SYSTEMC_CHECK_ \ SC_CONFIG_DEFINED_(DEBUG_SYSTEMC) #else # define DEBUG_SYSTEMC_CHECK_ \ SC_CONFIG_UNDEFINED_(DEBUG_SYSTEMC) #endif extern const int DEBUG_SYSTEMC_CHECK_; #endif // SC_DISABLE_VIRTUAL_BIND #if defined( SC_DISABLE_VIRTUAL_BIND ) # define SC_DISABLE_VIRTUAL_BIND_CHECK_ \ SC_API_DEFINED_(SC_DISABLE_VIRTUAL_BIND) #else # define SC_DISABLE_VIRTUAL_BIND_CHECK_ \ SC_API_UNDEFINED_(SC_DISABLE_VIRTUAL_BIND) #endif extern const int SC_DISABLE_VIRTUAL_BIND_CHECK_; // Some preprocessor switches need to be consistent between different // translation units of an application. Those can't be easily checked // during link-time. Instead, perform a check during run-time by // passing the value to the constructor of the api_version_check object. // Note: Template and constructor parameters are not passed as default // values to avoid ODR violations in the check itself. template // use pointers for more verbose error messages < // const int * DebugSystemC, const int * DisableVirtualBind > struct SC_API_VERSION_STRING { SC_API_VERSION_STRING ( // SC_DEFAULT_WRITER_POLICY sc_writer_policy default_writer_policy ); }; #if !defined(SC_BUILD) // import explicitly instantiated template SC_TPLEXTERN_ template struct SC_API SC_API_VERSION_STRING < &SC_DISABLE_VIRTUAL_BIND_CHECK_ >; #if !defined(SC_DISABLE_API_VERSION_CHECK) static SC_API_VERSION_STRING < // & DEBUG_SYSTEMC_CHECK_, & SC_DISABLE_VIRTUAL_BIND_CHECK_ > api_version_check ( SC_DEFAULT_WRITER_POLICY ); #endif // SC_DISABLE_API_VERSION_CHECK #endif // SC_BUILD //#undef SC_API_DEFINED_ //#undef SC_API_UNDEFINED_ } // namespace sc_core /***************************************************************************** MODIFICATION LOG - modifiers, enter your name, affiliation, date and changes you are making here. Name, Affiliation, Date: Description of Modification: *****************************************************************************/ #endif systemc-2.3.3/src/sysc/kernel/sc_object.h0000644000175000017500000001744213360325173020235 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_object.h -- Abstract base class of all SystemC `simulation' objects. Original Author: Stan Y. Liao, Synopsys, Inc. CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #ifndef SC_OBJECT_H #define SC_OBJECT_H #include "sysc/kernel/sc_attribute.h" #include #if defined(_MSC_VER) && !defined(SC_WIN_DLL_WARN) #pragma warning(push) #pragma warning(disable: 4251) // DLL import for std::string,vector #endif namespace sc_core { class SC_API sc_event; class SC_API sc_module; class sc_phase_callback_registry; class sc_runnable; class SC_API sc_simcontext; class SC_API sc_trace_file; class SC_API sc_trace_file_base; // ---------------------------------------------------------------------------- // CLASS : sc_object // // Abstract base class of all SystemC `simulation' objects. // ---------------------------------------------------------------------------- class SC_API sc_object { friend class sc_event; friend class sc_module; friend struct sc_invoke_method; friend class sc_module_dynalloc_list; friend class sc_object_manager; friend class sc_phase_callback_registry; friend class sc_process_b; friend class sc_runnable; friend class sc_simcontext; friend class sc_trace_file_base; public: typedef unsigned phase_cb_mask; const char* name() const { return m_name.c_str(); } const char* basename() const; virtual void print(::std::ostream& os=::std::cout ) const; // dump() is more detailed than print() virtual void dump(::std::ostream& os=::std::cout ) const; virtual void trace( sc_trace_file* tf ) const; virtual const char* kind() const { return "sc_object"; } sc_simcontext* simcontext() const { return m_simc; } // add attribute bool add_attribute( sc_attr_base& ); // get attribute by name sc_attr_base* get_attribute( const std::string& name_ ); const sc_attr_base* get_attribute( const std::string& name_ ) const; // remove attribute by name sc_attr_base* remove_attribute( const std::string& name_ ); // remove all attributes void remove_all_attributes(); // get the number of attributes int num_attributes() const; // get the attribute collection sc_attr_cltn& attr_cltn(); const sc_attr_cltn& attr_cltn() const; virtual const std::vector& get_child_events() const { return m_child_events; } virtual const std::vector& get_child_objects() const { return m_child_objects; } sc_object* get_parent() const; sc_object* get_parent_object() const { return m_parent; } protected: sc_object(); sc_object(const char* nm); sc_object( const sc_object& ); sc_object& operator=( const sc_object& ); virtual ~sc_object(); virtual void add_child_event( sc_event* event_p ); virtual void add_child_object( sc_object* object_p ); virtual bool remove_child_event( sc_event* event_p ); virtual bool remove_child_object( sc_object* object_p ); phase_cb_mask register_simulation_phase_callback( phase_cb_mask ); phase_cb_mask unregister_simulation_phase_callback( phase_cb_mask ); class hierarchy_scope; private: void do_simulation_phase_callback(); virtual void simulation_phase_callback(); void detach(); virtual void orphan_child_events(); virtual void orphan_child_objects(); void sc_object_init(const char* nm); private: /* Each simulation object is associated with a simulation context */ mutable sc_attr_cltn* m_attr_cltn_p; // attributes for this object. std::vector m_child_events; // list of child events. std::vector m_child_objects; // list of child objects. std::string m_name; // name of this object. sc_object* m_parent; // parent for this object. sc_simcontext* m_simc; // simcontext ptr / empty indicator }; inline sc_object& sc_object::operator=( sc_object const & ) { // deliberately do nothing return *this; } // ---------------------------------------------------------------------------- extern const char SC_HIERARCHY_CHAR; extern bool sc_enable_name_checking; inline sc_object* sc_get_parent( const sc_object* obj_p ) { return obj_p->get_parent_object(); } } // namespace sc_core #if defined(_MSC_VER) && !defined(SC_WIN_DLL_WARN) #pragma warning(pop) #endif /***************************************************************************** MODIFICATION LOG - modifiers, enter your name, affiliation, date and changes you are making here. Name, Affiliation, Date: Andy Goodrich, Forte Design Systems 5 September 2003 Description of Modification: - Made creation of attributes structure conditional on its being used. This eliminates 100 bytes of storage for each normal sc_object. *****************************************************************************/ // $Log: sc_object.h,v $ // Revision 1.13 2011/08/29 18:04:32 acg // Philipp A. Hartmann: miscellaneous clean ups. // // Revision 1.12 2011/08/26 20:46:10 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.11 2011/03/06 15:55:11 acg // Andy Goodrich: Changes for named events. // // Revision 1.10 2011/03/05 19:44:20 acg // Andy Goodrich: changes for object and event naming and structures. // // Revision 1.9 2011/03/05 01:39:21 acg // Andy Goodrich: changes for named events. // // Revision 1.8 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.7 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.6 2011/01/25 20:50:37 acg // Andy Goodrich: changes for IEEE 1666 2011. // // Revision 1.5 2011/01/18 20:10:44 acg // Andy Goodrich: changes for IEEE1666_2011 semantics. // // Revision 1.4 2010/07/22 20:02:33 acg // Andy Goodrich: bug fixes. // // Revision 1.3 2009/02/28 00:26:58 acg // Andy Goodrich: changed boost name space to sc_boost to allow use with // full boost library applications. // // Revision 1.2 2008/05/22 17:06:26 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.5 2006/04/20 17:08:17 acg // Andy Goodrich: 3.0 style process changes. // // Revision 1.4 2006/04/11 23:13:21 acg // Andy Goodrich: Changes for reduced reset support that only includes // sc_cthread, but has preliminary hooks for expanding to method and thread // processes also. // // Revision 1.3 2006/01/13 18:44:30 acg // Added $Log to record CVS changes into the source. #endif // SC_OBJECT_H systemc-2.3.3/src/sysc/kernel/sc_cmnhdr.h0000644000175000017500000001710413360325173020235 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_cmnhdr.h - Common header file containing handy pragmas, macros and definitions common to all SystemC source files. Original Author: Amit Rao, Synopsys, Inc. CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #ifndef SC_CMNHDR_H #define SC_CMNHDR_H #if defined(_WIN32) || defined(_MSC_VER) || defined(__BORLANDC__) || \ defined(__MINGW32__) // all windows 32-bit compilers should define WIN32 #if !defined(WIN32) && !defined(WIN64) && !defined(_WIN64) #define WIN32 #endif // Windows Version Build Option #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0400 #endif // remember to later include windows.h, if needed #define SC_HAS_WINDOWS_H_ #endif // WIN32 // ---------------------------------------------------------------------------- #ifdef _MSC_VER // Disable VC++ warnings that are harmless // extern template instantiations #pragma warning(disable: 4231) // this : used in base member initializer list #pragma warning(disable: 4355) // new and delete warning when exception handling is turned on #pragma warning(disable: 4291) // in many places implicit conversion to bool // from other integral types is performed #pragma warning(disable: 4800) // unary minus operator applied to unsigned #pragma warning(disable: 4146) // multiple copy constructors #pragma warning(disable: 4521) // identifier was truncated to '255' characters in the browser information #pragma warning(disable: 4786) #endif // ---------------------------------------------------------------------------- // helper macros to aid branch prediction on GCC (compatible) compilers #ifndef __GNUC__ # define SC_LIKELY_( x ) !!(x) # define SC_UNLIKELY_( x ) !!(x) #else # define SC_LIKELY_( x ) __builtin_expect( !!(x), 1 ) # define SC_UNLIKELY_( x ) __builtin_expect( !!(x), 0 ) #endif // ---------------------------------------------------------------------------- // C++ standard // // Selected C++ standard baseline, supported values are // 199711L (C++03, ISO/IEC 14882:1998, 14882:2003) // 201103L (C++11, ISO/IEC 14882:2011) // 201402L (C++14, ISO/IEC 14882:2014) // 201703L (C++17, ISO/IEC 14882:2017) // // This macro can be used inside the library sources to make certain assumptions // on the available features in the underlying C++ implementation. // #ifndef SC_CPLUSPLUS # ifdef _MSC_VER // don't rely on __cplusplus for MSVC // Instead, we select the C++ standard with reasonable support. // If some features still need to be excluded on specific MSVC // versions, we'll do so at the point of definition. # if defined(_MSVC_LANG) // MSVC'2015 Update 3 or later, use compiler setting # define SC_CPLUSPLUS _MSVC_LANG # elif _MSC_VER < 1800 // MSVC'2010 and earlier, assume C++03 # define SC_CPLUSPLUS 199711L # elif _MSC_VER < 1900 // MSVC'2013, assume C++11 # define SC_CPLUSPLUS 201103L # else // MSVC'2015 before Update 3, assume C++14 # define SC_CPLUSPLUS 201402L # endif # else // not _MSC_VER // use compiler setting # define SC_CPLUSPLUS __cplusplus # endif // not _MSC_VER #endif // SC_CPLUSPLUS // SystemC adds some features under C++11 already (see RELEASENOTES) #define SC_CPLUSPLUS_BASE_ 201103L // The IEEE_1666_CPLUSPLUS macro is meant to be queried in the models, // checking for availability of SystemC features relying on specific // C++ standard versions. // // IEEE_1666_CPLUSPLUS = min(SC_CPLUSPLUS, SC_CPLUSPLUS_BASE_) #if SC_CPLUSPLUS >= SC_CPLUSPLUS_BASE_ # define IEEE_1666_CPLUSPLUS SC_CPLUSPLUS_BASE_ #else # define IEEE_1666_CPLUSPLUS SC_CPLUSPLUS #endif // IEEE_1666_CPLUSPLUS // ---------------------------------------------------------------------------- // (no) exception specifiers #ifndef SC_NOEXCEPT_ #if SC_CPLUSPLUS >= 201103L && !(defined(_MSC_VER) && _MSC_VER < 1900) # define SC_NOEXCEPT_ noexcept # define SC_NOEXCEPT_EXPR_(expr) noexcept(expr) #else # define SC_NOEXCEPT_ throw() # define SC_NOEXCEPT_EXPR_(expr) /* nothing */ #endif #endif // SC_NOEXCEPT_ // ---------------------------------------------------------------------------- #include #include #include #include // ---------------------------------------------------------------------------- // declare certain template instantiations as "extern" during library build // and adding an explicit instantiation into the (shared) SystemC library #if defined(__GNUC__) && SC_CPLUSPLUS < 201103L # define SC_TPLEXTERN_ __extension__ extern #else # define SC_TPLEXTERN_ extern #endif // build SystemC DLL on Windows #if defined(SC_WIN_DLL) && (defined(_WIN32) || defined(_WIN64)) # if defined(SC_BUILD) // building SystemC library # define SC_API __declspec(dllexport) # else // building SystemC application # define SC_API __declspec(dllimport) # endif // SC_BUILD #else // !SC_WIN_DLL # define SC_API /* nothing */ #endif // SC_WIN_DLL #if defined(SC_BUILD) && defined(_MSC_VER) // always instantiate during Windows library build # define SC_API_TEMPLATE_DECL_ template class SC_API #else // keep extern when building an application (or on non-Windows) # define SC_API_TEMPLATE_DECL_ SC_TPLEXTERN_ template class SC_API #endif #endif // SC_CMNHDR_H // ---------------------------------------------------------------------------- // only include Windows.h, if explicitly requested // (deliberately outside of include guards to enable later effect) #if defined(SC_HAS_WINDOWS_H_) && defined(SC_INCLUDE_WINDOWS_H) # undef SC_HAS_WINDOWS_H_ # include #endif // $Log: sc_cmnhdr.h,v $ // Revision 1.8 2011/08/26 20:46:09 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.7 2011/05/09 04:07:48 acg // Philipp A. Hartmann: // (1) Restore hierarchy in all phase callbacks. // (2) Ensure calls to before_end_of_elaboration. // // Revision 1.6 2011/05/05 17:45:27 acg // Philip A. Hartmann: changes in WIN64 support. // Andy Goodrich: additional DEBUG_MSG instances to trace process handling. // // Revision 1.5 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.4 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.3 2009/05/22 16:06:29 acg // Andy Goodrich: process control updates. // // Revision 1.2 2008/05/22 17:06:24 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.3 2006/01/13 18:44:29 acg // Added $Log to record CVS changes into the source. // Taf! systemc-2.3.3/src/sysc/kernel/sc_event.h0000644000175000017500000005163413360325173020111 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_event.h -- Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #ifndef SC_EVENT_H #define SC_EVENT_H #include "sysc/kernel/sc_cmnhdr.h" #include "sysc/kernel/sc_kernel_ids.h" #include "sysc/kernel/sc_simcontext.h" #include "sysc/communication/sc_writer_policy.h" #if defined(_MSC_VER) && !defined(SC_WIN_DLL_WARN) #pragma warning(push) #pragma warning(disable: 4251) // DLL import for std::string #endif namespace sc_core { // forward declarations class sc_event; class sc_event_timed; class sc_event_list; class sc_event_or_list; class sc_event_and_list; class sc_object; class sc_signal_channel; // friend function declarations SC_API int sc_notify_time_compare( const void*, const void* ); // ---------------------------------------------------------------------------- // CLASS : sc_event_expr // // The event expression class. // ---------------------------------------------------------------------------- template< typename T > class sc_event_expr { friend class sc_event; friend class sc_event_and_list; friend class sc_event_or_list; typedef T type; inline sc_event_expr() : m_expr( new T(true) ) {} public: inline sc_event_expr( sc_event_expr const & e) // move semantics : m_expr(e.m_expr) { e.m_expr = 0; } T const & release() const { sc_assert( m_expr ); T* expr = m_expr; m_expr=0; return *expr; } void push_back( sc_event const & e) const { sc_assert( m_expr ); m_expr->push_back(e); } void push_back( type const & el) const { sc_assert( m_expr ); m_expr->push_back(el); } operator T const &() const { return release(); } ~sc_event_expr() { delete m_expr; } private: mutable type * m_expr; // disabled void operator=( sc_event_expr const & ); }; // ---------------------------------------------------------------------------- // CLASS : sc_event_list // // Base class for lists of events. // ---------------------------------------------------------------------------- class SC_API sc_event_list { friend class sc_process_b; friend class sc_method_process; friend class sc_thread_process; friend void sc_thread_cor_fn( void* arg ); public: sc_event_list( const sc_event_list& ); sc_event_list& operator = ( const sc_event_list& ); int size() const; bool empty() const { return size() == 0; } protected: void push_back( const sc_event& ); void push_back( const sc_event_list& ); explicit sc_event_list( bool and_list_, bool auto_delete_ = false ); sc_event_list( const sc_event&, bool and_list_, bool auto_delete_ = false ); ~sc_event_list(); void swap( sc_event_list& ); void move_from( const sc_event_list& ); bool and_list() const; void add_dynamic( sc_method_handle ) const; void add_dynamic( sc_thread_handle ) const; void remove_dynamic( sc_method_handle, const sc_event* ) const; void remove_dynamic( sc_thread_handle, const sc_event* ) const; bool busy() const; bool temporary() const; void auto_delete() const; void report_premature_destruction() const; void report_invalid_modification() const; private: std::vector m_events; bool m_and_list; bool m_auto_delete; mutable unsigned m_busy; }; // ---------------------------------------------------------------------------- // CLASS : sc_event_and_list // // AND list of events. // ---------------------------------------------------------------------------- class SC_API sc_event_and_list : public sc_event_list { friend class sc_event; friend class sc_event_expr; friend class sc_process_b; friend class sc_method_process; friend class sc_thread_process; protected: explicit sc_event_and_list( bool auto_delete_ ); public: sc_event_and_list(); sc_event_and_list( const sc_event& ); void swap( sc_event_and_list& ); sc_event_and_list& operator &= ( const sc_event& ); sc_event_and_list& operator &= ( const sc_event_and_list & ); sc_event_expr operator & ( const sc_event& ); sc_event_expr operator & ( const sc_event_and_list& ); }; typedef sc_event_expr sc_event_and_expr; // ---------------------------------------------------------------------------- // CLASS : sc_event_or_list // // OR list of events. // ---------------------------------------------------------------------------- class SC_API sc_event_or_list : public sc_event_list { friend class sc_event; friend class sc_event_expr; friend class sc_process_b; friend class sc_method_process; friend class sc_thread_process; protected: explicit sc_event_or_list( bool auto_delete_ ); public: sc_event_or_list(); sc_event_or_list( const sc_event& ); void swap( sc_event_or_list& ); sc_event_or_list& operator |= ( const sc_event& ); sc_event_or_list& operator |= ( const sc_event_or_list & ); sc_event_expr operator | ( const sc_event& ) const; sc_event_expr operator | ( const sc_event_or_list& ) const; }; typedef sc_event_expr sc_event_or_expr; // ---------------------------------------------------------------------------- // CLASS : sc_event // // The event class. // ---------------------------------------------------------------------------- class SC_API sc_event { friend class sc_event_list; friend class sc_event_timed; friend class sc_simcontext; friend class sc_object; friend class sc_process_b; friend class sc_process_handle; friend class sc_method_process; friend class sc_thread_process; friend void sc_thread_cor_fn( void* arg ); friend class sc_clock; friend class sc_event_queue; friend class sc_signal_channel; template friend class sc_fifo; friend class sc_semaphore; friend class sc_mutex; friend class sc_join; friend class sc_trace_file; public: sc_event(); explicit sc_event( const char* name ); ~sc_event(); void cancel(); const char* name() const { return m_name.c_str(); } const char* basename() const; sc_object* get_parent_object() const { return m_parent_p; } bool in_hierarchy() const { return m_name.length() != 0; } void notify(); void notify( const sc_time& ); void notify( double, sc_time_unit ); void notify_delayed(); void notify_delayed( const sc_time& ); void notify_delayed( double, sc_time_unit ); sc_event_or_expr operator | ( const sc_event& ) const; sc_event_or_expr operator | ( const sc_event_or_list& ) const; sc_event_and_expr operator & ( const sc_event& ) const; sc_event_and_expr operator & ( const sc_event_and_list& ) const; // has this event been triggered in the current delta cycle? bool triggered() const; // never notified event static const sc_event none; private: void add_static( sc_method_handle ) const; void add_static( sc_thread_handle ) const; void add_dynamic( sc_method_handle ) const; void add_dynamic( sc_thread_handle ) const; void notify_internal( const sc_time& ); void notify_next_delta(); bool remove_static( sc_method_handle ) const; bool remove_static( sc_thread_handle ) const; bool remove_dynamic( sc_method_handle ) const; bool remove_dynamic( sc_thread_handle ) const; void register_event( const char* name, bool is_kernel_event = false ); void reset(); void trigger(); private: enum notify_t { NONE, DELTA, TIMED }; std::string m_name; // name of object. sc_object* m_parent_p; // parent sc_object for this event. sc_simcontext* m_simc; sc_dt::uint64 m_trigger_stamp; // delta of last trigger notify_t m_notify_type; int m_delta_event_index; sc_event_timed* m_timed; mutable std::vector m_methods_static; mutable std::vector m_methods_dynamic; mutable std::vector m_threads_static; mutable std::vector m_threads_dynamic; private: static struct kernel_tag {} kernel_event; explicit sc_event( kernel_tag, const char* name = NULL ); // disabled sc_event( const sc_event& ); sc_event& operator = ( const sc_event& ); }; // ---------------------------------------------------------------------------- // CLASS : sc_event_timed // // Class for storing the time to notify a timed event. // ---------------------------------------------------------------------------- class SC_API sc_event_timed { friend class sc_event; friend class sc_simcontext; friend SC_API int sc_notify_time_compare( const void*, const void* ); private: sc_event_timed( sc_event* e, const sc_time& t ) : m_event( e ), m_notify_time( t ) {} ~sc_event_timed() { if( m_event != 0 ) { m_event->m_timed = 0; } } sc_event* event() const { return m_event; } const sc_time& notify_time() const { return m_notify_time; } static void* operator new( std::size_t ) { return allocate(); } static void operator delete( void* p, std::size_t ) { deallocate( p ); } private: // dedicated memory management static void* allocate(); static void deallocate( void* ); private: sc_event* m_event; sc_time m_notify_time; private: // disabled sc_event_timed(); sc_event_timed( const sc_event_timed& ); sc_event_timed& operator = ( const sc_event_timed& ); }; // IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII inline void sc_event::notify( double v, sc_time_unit tu ) { notify( sc_time( v, tu, m_simc ) ); } inline void sc_event::notify_internal( const sc_time& t ) { if( t == SC_ZERO_TIME ) { // add this event to the delta events set 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; } } inline void sc_event::notify_next_delta() { if( m_notify_type != NONE ) { SC_REPORT_ERROR( SC_ID_NOTIFY_DELAYED_, 0 ); } // add this event to the delta events set m_delta_event_index = m_simc->add_delta_event( this ); m_notify_type = DELTA; } inline void sc_event::notify_delayed( double v, sc_time_unit tu ) { notify_delayed( sc_time( v, tu, m_simc ) ); } inline void sc_event::add_static( sc_method_handle method_h ) const { m_methods_static.push_back( method_h ); } inline void sc_event::add_static( sc_thread_handle thread_h ) const { m_threads_static.push_back( thread_h ); } inline void sc_event::add_dynamic( sc_method_handle method_h ) const { m_methods_dynamic.push_back( method_h ); } inline void sc_event::add_dynamic( sc_thread_handle thread_h ) const { m_threads_dynamic.push_back( thread_h ); } // ---------------------------------------------------------------------------- // Deprecated functional notation for notifying events. // ---------------------------------------------------------------------------- extern void notify( sc_event& e ); extern void notify( const sc_time& t, sc_event& e ); extern void notify( double v, sc_time_unit tu, sc_event& e ); // IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII inline sc_event_list::sc_event_list( bool and_list_, bool auto_delete_ ) : m_events() , m_and_list( and_list_ ) , m_auto_delete( auto_delete_ ) , m_busy( 0 ) { } inline sc_event_list::sc_event_list( const sc_event& e, bool and_list_, bool auto_delete_ ) : m_events() , m_and_list( and_list_ ) , m_auto_delete( auto_delete_ ) , m_busy(0) { m_events.push_back( &e ); } inline sc_event_list::sc_event_list( sc_event_list const & that ) : m_events() , m_and_list( that.m_and_list ) , m_auto_delete( false ) , m_busy( 0 ) { move_from( that ); that.auto_delete(); // free automatic lists } inline sc_event_list& sc_event_list::operator=( sc_event_list const & that ) { if( m_busy ) report_invalid_modification(); if( SC_LIKELY_(this != &that) ) { move_from( that ); that.auto_delete(); // free automatic lists } return *this; } inline sc_event_list::~sc_event_list() { if( m_busy ) report_premature_destruction(); } inline void sc_event_list::swap( sc_event_list& that ) { if( busy() || that.busy() ) report_invalid_modification(); m_events.swap( that.m_events ); } inline void sc_event_list::move_from( sc_event_list const& that ) { if( that.temporary() ) { swap( const_cast(that) ); // move from source } else { m_events = that.m_events; // copy from source } } inline int sc_event_list::size() const { return static_cast(m_events.size()); } inline bool sc_event_list::and_list() const { return m_and_list; } inline bool sc_event_list::busy() const { return m_busy != 0; } inline bool sc_event_list::temporary() const { return m_auto_delete && ! m_busy; } inline void sc_event_list::auto_delete() const { if( m_busy ) { --m_busy; } if( ! m_busy && m_auto_delete ) { delete this; } } // IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII inline sc_event_or_list::sc_event_or_list() : sc_event_list( false ) {} inline sc_event_or_list::sc_event_or_list( const sc_event& e ) : sc_event_list( false ) { push_back( e ); } inline sc_event_or_list::sc_event_or_list( bool auto_delete_ ) : sc_event_list( false, auto_delete_ ) {} inline sc_event_or_list& sc_event_or_list::operator |= ( const sc_event& e ) { if( busy() ) report_invalid_modification(); push_back( e ); return *this; } inline sc_event_or_list& sc_event_or_list::operator |= ( const sc_event_or_list& el ) { if( busy() ) report_invalid_modification(); push_back( el ); return *this; } inline sc_event_or_expr sc_event_or_list::operator | ( const sc_event& e2 ) const { sc_event_or_expr expr; expr.push_back( *this ); expr.push_back( e2 ); return expr; } inline sc_event_or_expr sc_event_or_list::operator | ( const sc_event_or_list& e2 ) const { sc_event_or_expr expr; expr.push_back( *this ); expr.push_back( e2 ); return expr; } // sc_event inline sc_event_or_expr sc_event::operator | ( const sc_event& e2 ) const { sc_event_or_expr expr; expr.push_back( *this ); expr.push_back( e2 ); return expr; } inline sc_event_or_expr sc_event::operator | ( const sc_event_or_list& e2 ) const { sc_event_or_expr expr; expr.push_back( *this ); expr.push_back( e2 ); return expr; } // sc_event_expr inline sc_event_or_expr operator | ( sc_event_or_expr expr, sc_event const & e ) { expr.push_back( e ); return expr; } inline sc_event_or_expr operator | ( sc_event_or_expr expr, sc_event_or_list const & el ) { expr.push_back( el ); return expr; } inline void sc_event_or_list::swap( sc_event_or_list & that ) { sc_event_list::swap( that ); } // IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII inline sc_event_and_list::sc_event_and_list() : sc_event_list( true ) {} inline sc_event_and_list::sc_event_and_list( const sc_event& e ) : sc_event_list( true ) { push_back( e ); } inline sc_event_and_list::sc_event_and_list( bool auto_delete_ ) : sc_event_list( true, auto_delete_ ) {} inline void sc_event_and_list::swap( sc_event_and_list & that ) { sc_event_list::swap( that ); } inline sc_event_and_list& sc_event_and_list::operator &= ( const sc_event& e ) { if( busy() ) report_invalid_modification(); push_back( e ); return *this; } inline sc_event_and_list& sc_event_and_list::operator &= ( const sc_event_and_list& el ) { if( busy() ) report_invalid_modification(); push_back( el ); return *this; } inline sc_event_and_expr sc_event_and_list::operator & ( const sc_event& e ) { sc_event_and_expr expr; expr.push_back( *this ); expr.push_back( e ); return expr; } inline sc_event_and_expr sc_event_and_list::operator & ( const sc_event_and_list& el ) { sc_event_and_expr expr; expr.push_back( *this ); expr.push_back( el ); return expr; } // sc_event inline sc_event_and_expr sc_event::operator & ( const sc_event& e2 ) const { sc_event_and_expr expr; expr.push_back( *this ); expr.push_back( e2 ); return expr; } inline sc_event_and_expr sc_event::operator & ( const sc_event_and_list& e2 ) const { sc_event_and_expr expr; expr.push_back( *this ); expr.push_back( e2 ); return expr; } // sc_event_expr inline sc_event_and_expr operator & ( sc_event_and_expr expr, sc_event const & e ) { expr.push_back( e ); return expr; } inline sc_event_and_expr operator & ( sc_event_and_expr expr, sc_event_and_list const & el ) { expr.push_back( el ); return expr; } } // namespace sc_core #if defined(_MSC_VER) && !defined(SC_WIN_DLL_WARN) #pragma warning(pop) #endif // $Log: sc_event.h,v $ // Revision 1.14 2011/08/29 18:04:32 acg // Philipp A. Hartmann: miscellaneous clean ups. // // Revision 1.13 2011/08/26 20:46:09 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.12 2011/08/24 22:05:50 acg // Torsten Maehne: initialization changes to remove warnings. // // Revision 1.11 2011/03/12 21:07:51 acg // Andy Goodrich: changes to kernel generated event support. // // Revision 1.10 2011/03/06 15:55:11 acg // Andy Goodrich: Changes for named events. // // Revision 1.9 2011/03/05 01:39:21 acg // Andy Goodrich: changes for named events. // // Revision 1.8 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.7 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.6 2011/02/01 21:03:23 acg // Andy Goodrich: new return codes for trigger_dynamic calls. // // Revision 1.5 2011/01/18 20:10:44 acg // Andy Goodrich: changes for IEEE1666_2011 semantics. // // Revision 1.4 2010/12/07 20:09:11 acg // Andy Goodrich: writer policy fix. // // Revision 1.3 2009/05/22 16:06:29 acg // Andy Goodrich: process control updates. // // Revision 1.2 2008/05/22 17:06:25 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.8 2006/05/26 20:33:16 acg // Andy Goodrich: changes required by additional platform compilers (i.e., // Microsoft VC++, Sun Forte, HP aCC). // // Revision 1.7 2006/05/08 17:57:51 acg // Andy Goodrich: added David Long's forward declarations for friend // functions, methods, and operators to keep the Microsoft compiler happy. // // Revision 1.6 2006/04/11 23:13:20 acg // Andy Goodrich: Changes for reduced reset support that only includes // sc_cthread, but has preliminary hooks for expanding to method and thread // processes also. // // Revision 1.5 2006/01/24 20:56:00 acg // Andy Goodrich: fixed up CVS comment. // // Revision 1.4 2006/01/24 20:48:14 acg // Andy Goodrich: added deprecation warnings for notify_delayed(). Added two // new implementation-dependent methods, notify_next_delta() & notify_internal() // to replace calls to notify_delayed() from within the simulator. These two // new methods are simpler than notify_delayed() and should speed up simulations // // Revision 1.3 2006/01/13 18:44:29 acg // Added $Log to record CVS changes into the source. // #endif // Taf! systemc-2.3.3/src/sysc/kernel/sc_cthread_process.cpp0000644000175000017500000001102513360325173022461 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_cthread_process.cpp -- Clocked thread implementation. Original Author: Andy Goodrich, Forte Design Systems, 4 August 2005 CHANGE LOG APPEARS AT THE END OF THE FILE *****************************************************************************/ #include "sysc/kernel/sc_cthread_process.h" #include "sysc/kernel/sc_simcontext_int.h" namespace sc_core { //------------------------------------------------------------------------------ //"sc_cthread_process::dont_initialize" // // This virtual method sets the initialization switch for this object instance. //------------------------------------------------------------------------------ void sc_cthread_process::dont_initialize( bool /* dont */ ) { SC_REPORT_WARNING( SC_ID_DONT_INITIALIZE_, 0 ); } //------------------------------------------------------------------------------ //"sc_cthread_process::sc_cthread_process" // // This is the object instance constructor for this class. //------------------------------------------------------------------------------ sc_cthread_process::sc_cthread_process( const char* name_p, bool free_host, SC_ENTRY_FUNC method_p, sc_process_host* host_p, const sc_spawn_options* opt_p ): sc_thread_process(name_p, free_host, method_p, host_p, opt_p) { m_dont_init = true; m_process_kind = SC_CTHREAD_PROC_; } //------------------------------------------------------------------------------ //"sc_cthread_process::~sc_cthread_process" // // This is the object instance constructor for this class. //------------------------------------------------------------------------------ sc_cthread_process::~sc_cthread_process() { } } // namespace sc_core // $Log: sc_cthread_process.cpp,v $ // Revision 1.11 2011/08/26 20:46:09 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.10 2011/08/15 16:43:24 acg // Torsten Maehne: changes to remove unused argument warnings. // // Revision 1.9 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.8 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.7 2011/02/11 13:25:24 acg // Andy Goodrich: Philipp A. Hartmann's changes: // (1) Removal of SC_CTHREAD method overloads. // (2) New exception processing code. // // Revision 1.6 2011/02/01 21:00:35 acg // Andy Goodrich: removed throw_reset as it is now handled by parent // sc_thread_process::throw_reset(). // // Revision 1.5 2011/01/18 20:10:44 acg // Andy Goodrich: changes for IEEE1666_2011 semantics. // // Revision 1.4 2009/07/28 01:10:53 acg // Andy Goodrich: updates for 2.3 release candidate. // // Revision 1.3 2009/05/22 16:06:29 acg // Andy Goodrich: process control updates. // // Revision 1.2 2008/05/22 17:06:25 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.6 2006/04/20 17:08:16 acg // Andy Goodrich: 3.0 style process changes. // // Revision 1.5 2006/04/11 23:13:20 acg // Andy Goodrich: Changes for reduced reset support that only includes // sc_cthread, but has preliminary hooks for expanding to method and thread // processes also. // // Revision 1.4 2006/01/24 20:49:04 acg // Andy Goodrich: changes to remove the use of deprecated features within the // simulator, and to issue warning messages when deprecated features are used. // // Revision 1.3 2006/01/13 18:44:29 acg // Added $Log to record CVS changes into the source. // systemc-2.3.3/src/sysc/kernel/sc_except.h0000644000175000017500000001260513360325173020253 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_except.h - Exception classes to be handled by SystemC. Original Author: Stan Y. Liao, Synopsys, Inc. CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #ifndef SC_EXCEPT_H #define SC_EXCEPT_H #include #include "sysc/kernel/sc_cmnhdr.h" #if defined(_MSC_VER) && !defined(SC_WIN_DLL_WARN) # pragma warning(push) # pragma warning(disable:4275) // ignore missing std::exception DLL export #endif namespace sc_core { class sc_simcontext; class sc_process_b; class sc_method_process; class sc_thread_process; void sc_thread_cor_fn( void* arg ); /* * These classes are intentionally empty. Their raison d'etre is for * the implementation of various SystemC throws. */ class SC_API sc_user { /*EMPTY*/ public: sc_user() {} sc_user( const sc_user& ) {} }; class SC_API sc_halt { public: sc_halt() {} sc_halt( const sc_halt& ) {} }; class SC_API sc_kill { public: sc_kill() {} sc_kill( const sc_kill& ) {} }; class SC_API sc_unwind_exception : public std::exception { friend class sc_simcontext; friend class sc_process_b; friend class sc_method_process; friend class sc_thread_process; friend void sc_thread_cor_fn( void* arg ); public: virtual bool is_reset() const { return m_is_reset; } virtual const char* what() const SC_NOEXCEPT_; public: // enable catch by value sc_unwind_exception( const sc_unwind_exception& ); virtual ~sc_unwind_exception() SC_NOEXCEPT_; protected: explicit sc_unwind_exception( sc_process_b* target_p, bool is_reset = false ); bool active() const; void clear() const; private: // disabled sc_unwind_exception& operator=( const sc_unwind_exception& ); mutable sc_process_b* m_proc_p; // used to check, if caught by the kernel const bool m_is_reset; // true if this is an unwind of a reset }; inline sc_unwind_exception::sc_unwind_exception( const sc_unwind_exception& that ) : std::exception( that ) , m_proc_p( that.m_proc_p ) , m_is_reset( that.m_is_reset ) { that.m_proc_p = 0; // move to new instance } //------------------------------------------------------------------------------ // global exception handling //------------------------------------------------------------------------------ class sc_report; SC_API sc_report* sc_handle_exception(); } // namespace sc_core #if defined(_MSC_VER) && !defined(SC_WIN_DLL_WARN) # pragma warning(pop) #endif /***************************************************************************** MODIFICATION LOG - modifiers, enter your name, affiliation, date and changes you are making here. Name, Affiliation, Date: Gene Bushuyev. Synopsys, Inc. Description of Modification: - Had to add empty public default and copy constructors to satisfy VC6.0. Name, Affiliation, Date: Description of Modification: *****************************************************************************/ // $Log: sc_except.h,v $ // Revision 1.11 2011/08/26 21:40:26 acg // Philipp A. Hartmann: fix up sc_unwind_exception copy-ctor. // // Revision 1.10 2011/08/26 20:46:09 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.9 2011/08/24 22:05:50 acg // Torsten Maehne: initialization changes to remove warnings. // // Revision 1.8 2011/05/09 04:07:48 acg // Philipp A. Hartmann: // (1) Restore hierarchy in all phase callbacks. // (2) Ensure calls to before_end_of_elaboration. // // Revision 1.7 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.6 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.5 2011/02/11 13:25:24 acg // Andy Goodrich: Philipp A. Hartmann's changes: // (1) Removal of SC_CTHREAD method overloads. // (2) New exception processing code. // // Revision 1.4 2011/01/18 20:10:44 acg // Andy Goodrich: changes for IEEE1666_2011 semantics. // // Revision 1.3 2009/05/22 16:06:29 acg // Andy Goodrich: process control updates. // // Revision 1.2 2008/05/22 17:06:25 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.3 2006/01/13 18:44:29 acg // Added $Log to record CVS changes into the source. #endif systemc-2.3.3/src/sysc/kernel/sc_cor_qt.cpp0000644000175000017500000001617413360325173020612 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_cor_qt.cpp -- Coroutine implementation with QuickThreads. Original Author: Martin Janssen, Synopsys, Inc., 2001-12-18 CHANGE LOG APPEARS AT THE END OF THE FILE *****************************************************************************/ #if !defined(_WIN32) && !defined(WIN32) && !defined(SC_USE_PTHREADS) #include #include #include #include "sysc/kernel/sc_cor_qt.h" #include "sysc/kernel/sc_simcontext.h" namespace sc_core { // ---------------------------------------------------------------------------- // File static variables. // ---------------------------------------------------------------------------- // main coroutine static sc_cor_qt main_cor; // current coroutine static sc_cor_qt* curr_cor = 0; // ---------------------------------------------------------------------------- // CLASS : sc_cor_qt // // Coroutine class implemented with QuickThreads. // ---------------------------------------------------------------------------- // switch stack protection on/off void sc_cor_qt::stack_protect( bool enable ) { // Code needs to be tested on HP-UX and disabled if it doesn't work there // Code still needs to be ported to WIN32 static std::size_t pagesize; if( pagesize == 0 ) { # if defined(__ppc__) pagesize = getpagesize(); # else pagesize = sysconf( _SC_PAGESIZE ); # endif } sc_assert( pagesize != 0 ); sc_assert( m_stack_size > ( 2 * pagesize ) ); #ifdef QUICKTHREADS_GROW_DOWN // Stacks grow from high address down to low address caddr_t redzone = caddr_t( ( ( std::size_t( m_stack ) + pagesize - 1 ) / pagesize ) * pagesize ); #else // Stacks grow from low address up to high address caddr_t redzone = caddr_t( ( ( std::size_t( m_stack ) + m_stack_size - pagesize ) / pagesize ) * pagesize ); #endif int ret; // Enable the red zone at the end of the stack so that references within // it will cause an interrupt. if( enable ) { ret = mprotect( redzone, pagesize - 1, PROT_NONE ); } // Revert the red zone to normal memory usage. Try to make it read - write - // execute. If that does not work then settle for read - write else { ret = mprotect( redzone, pagesize - 1, PROT_READ|PROT_WRITE|PROT_EXEC); if ( ret != 0 ) ret = mprotect( redzone, pagesize - 1, PROT_READ | PROT_WRITE ); } sc_assert( ret == 0 ); } // ---------------------------------------------------------------------------- // CLASS : sc_cor_pkg_qt // // Coroutine package class implemented with QuickThreads. // ---------------------------------------------------------------------------- int sc_cor_pkg_qt::instance_count = 0; // support function inline void* stack_align( void* sp, int alignment, std::size_t* stack_size ) { int round_up_mask = alignment - 1; *stack_size = (*stack_size + round_up_mask) & ~round_up_mask; return ( (void*)(((qt_word_t) sp + round_up_mask) & ~round_up_mask) ); } // constructor sc_cor_pkg_qt::sc_cor_pkg_qt( sc_simcontext* simc ) : sc_cor_pkg( simc ) { if( ++ instance_count == 1 ) { // initialize the current coroutine sc_assert( curr_cor == 0 ); curr_cor = &main_cor; } } // destructor sc_cor_pkg_qt::~sc_cor_pkg_qt() { if( -- instance_count == 0 ) { // cleanup the current coroutine curr_cor = 0; } } // create a new coroutine extern "C" void sc_cor_qt_wrapper( void* arg, void* cor, qt_userf_t* fn ) { curr_cor = reinterpret_cast( cor ); // invoke the user function (*(sc_cor_fn*) fn)( arg ); // not reached } sc_cor* sc_cor_pkg_qt::create( std::size_t stack_size, sc_cor_fn* fn, void* arg ) { sc_cor_qt* cor = new sc_cor_qt(); cor->m_pkg = this; cor->m_stack_size = stack_size; cor->m_stack = new char[cor->m_stack_size]; void* sto = stack_align( cor->m_stack, QUICKTHREADS_STKALIGN, &cor->m_stack_size ); cor->m_sp = QUICKTHREADS_SP(sto, cor->m_stack_size - QUICKTHREADS_STKALIGN); cor->m_sp = QUICKTHREADS_ARGS( cor->m_sp, arg, cor, (qt_userf_t*) fn, sc_cor_qt_wrapper ); return cor; } // yield to the next coroutine extern "C" void* sc_cor_qt_yieldhelp( qt_t* sp, void* old_cor, void* ) { reinterpret_cast( old_cor )->m_sp = sp; return 0; } void sc_cor_pkg_qt::yield( sc_cor* next_cor ) { sc_cor_qt* new_cor = static_cast( next_cor ); sc_cor_qt* old_cor = curr_cor; curr_cor = new_cor; QUICKTHREADS_BLOCK( sc_cor_qt_yieldhelp, old_cor, 0, new_cor->m_sp ); } // abort the current coroutine (and resume the next coroutine) extern "C" void* sc_cor_qt_aborthelp( qt_t*, void*, void* ) { return 0; } void sc_cor_pkg_qt::abort( sc_cor* next_cor ) { sc_cor_qt* new_cor = static_cast( next_cor ); sc_cor_qt* old_cor = curr_cor; curr_cor = new_cor; QUICKTHREADS_ABORT( sc_cor_qt_aborthelp, old_cor, 0, new_cor->m_sp ); } // get the main coroutine sc_cor* sc_cor_pkg_qt::get_main() { return &main_cor; } } // namespace sc_core #endif // $Log: sc_cor_qt.cpp,v $ // Revision 1.9 2011/08/29 18:04:32 acg // Philipp A. Hartmann: miscellaneous clean ups. // // Revision 1.8 2011/08/26 20:46:09 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.7 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.6 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.5 2010/08/03 16:52:14 acg // Andy Goodrich: line formatting. // // Revision 1.4 2008/11/11 14:03:07 acg // Andy Goodrich: added execute access to the release of red zone storage // per Ulli's suggestion. // // Revision 1.3 2008/05/22 17:06:25 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.2 2008/03/24 18:32:36 acg // Andy Goodrich: added include of sys/types.h to pick up the declaration // of caddr_t. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.3 2006/01/13 18:44:29 acg // Added $Log to record CVS changes into the source. // Taf! systemc-2.3.3/src/sysc/kernel/sc_join.h0000644000175000017500000001063013360325173017716 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_join.h -- Join Process Synchronization Definition Original Author: Andy Goodrich, Forte Design Systems, 5 May 2003 CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ // $Log: sc_join.h,v $ // Revision 1.8 2011/08/26 21:45:00 acg // Andy Goodrich: fix internal event naming. // // Revision 1.7 2011/08/26 20:46:09 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // #ifndef SC_JOIN_H #define SC_JOIN_H #include "sysc/kernel/sc_process.h" #include "sysc/kernel/sc_wait.h" namespace sc_core { //============================================================================== // CLASS sc_join // // This class provides a way of waiting for a set of threads to complete their // execution. The threads whose completion is to be monitored are registered, // and upon their completion an event notification will occur. //============================================================================== class SC_API sc_join : public sc_process_monitor { friend class sc_process_b; friend class sc_process_handle; public: sc_join(); void add_process( sc_process_handle process_h ); inline int process_count(); virtual void signal(sc_thread_handle thread_p, int type); inline void wait(); inline void wait_clocked(); protected: void add_process( sc_process_b* process_p ); protected: sc_event m_join_event; // Event to notify when all threads have reported. int m_threads_n; // # of threads still need to wait for. private: sc_join( const sc_join& ); sc_join& operator = ( const sc_join& ); }; int sc_join::process_count() { return m_threads_n; } // suspend a thread that does not have a sensitivity list: inline void sc_join::wait() { ::sc_core::wait(m_join_event); } // suspend a thread that has a sensitivity list: inline void sc_join::wait_clocked() { do { ::sc_core::wait(); } while (m_threads_n != 0); } #define SC_CJOIN \ }; \ sc_core::sc_join join; \ for ( unsigned int i = 0; \ i < sizeof(forkees)/sizeof(sc_core::sc_process_handle); \ i++ ) \ join.add_process(forkees[i]); \ join.wait_clocked(); \ } #define SC_FORK \ { \ sc_core::sc_process_handle forkees[] = { #define SC_JOIN \ }; \ sc_core::sc_join join; \ for ( unsigned int i = 0; \ i < sizeof(forkees)/sizeof(sc_core::sc_process_handle); \ i++ ) \ join.add_process(forkees[i]); \ join.wait(); \ } } // namespace sc_core // Revision 1.6 2011/08/24 22:05:50 acg // Torsten Maehne: initialization changes to remove warnings. // // Revision 1.5 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.4 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.3 2009/07/28 01:10:53 acg // Andy Goodrich: updates for 2.3 release candidate. // // Revision 1.2 2008/05/22 17:06:25 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.5 2006/04/28 21:38:27 acg // Andy Goodrich: fixed loop constraint that was using sizeof(sc_thread_handle) // rather than sizeof(sc_process_handle). // // Revision 1.4 2006/01/13 18:44:29 acg // Added $Log to record CVS changes into the source. #endif // SC_JOIN_H systemc-2.3.3/src/sysc/kernel/sc_module.cpp0000644000175000017500000006070013360325173020602 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_module.cpp -- Base class of all sequential and combinational processes. Original Author: Stan Y. Liao, Synopsys, Inc. CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #include #include #include #include #include #include "sysc/kernel/sc_event.h" #include "sysc/kernel/sc_kernel_ids.h" #include "sysc/kernel/sc_module.h" #include "sysc/kernel/sc_module_registry.h" #include "sysc/kernel/sc_name_gen.h" #include "sysc/kernel/sc_object_manager.h" #include "sysc/kernel/sc_process.h" #include "sysc/kernel/sc_process_handle.h" #include "sysc/kernel/sc_simcontext.h" #include "sysc/kernel/sc_simcontext_int.h" #include "sysc/kernel/sc_object_int.h" #include "sysc/kernel/sc_reset.h" #include "sysc/communication/sc_communication_ids.h" #include "sysc/communication/sc_interface.h" #include "sysc/communication/sc_port.h" #include "sysc/communication/sc_signal.h" #include "sysc/communication/sc_signal_ports.h" #include "sysc/utils/sc_utils_ids.h" namespace sc_core { // ---------------------------------------------------------------------------- // CLASS : sc_module_dynalloc_list // // Garbage collection for modules dynamically allocated with SC_NEW. // ---------------------------------------------------------------------------- class sc_module_dynalloc_list { public: sc_module_dynalloc_list() : m_list() {} ~sc_module_dynalloc_list(); void add( sc_module* p ) { m_list.push_back( p ); } private: sc_plist m_list; }; //------------------------------------------------------------------------------ //"~sc_module_dynalloc_list" // // Note we clear the m_parent field for the module being deleted. This because // we process the list front to back so the parent has already been deleted, // and we don't want ~sc_object() to try to access the parent which may // contain garbage. //------------------------------------------------------------------------------ sc_module_dynalloc_list::~sc_module_dynalloc_list() { sc_plist::iterator it( m_list ); while( ! it.empty() ) { (*it)->m_parent = 0; delete *it; it ++; } } // ---------------------------------------------------------------------------- SC_API sc_module* sc_module_dynalloc( sc_module* module_ ) { static sc_module_dynalloc_list dynalloc_list; dynalloc_list.add( module_ ); return module_; } // ---------------------------------------------------------------------------- // STRUCT : sc_bind_proxy // // Struct for temporarily storing a pointer to an interface or port. // Used for positional binding. // ---------------------------------------------------------------------------- sc_bind_proxy::sc_bind_proxy() : iface( 0 ), port( 0 ) {} sc_bind_proxy::sc_bind_proxy( sc_interface& iface_ ) : iface( &iface_ ), port( 0 ) {} sc_bind_proxy::sc_bind_proxy( sc_port_base& port_ ) : iface( 0 ), port( &port_ ) {} SC_API const sc_bind_proxy SC_BIND_PROXY_NIL; // ---------------------------------------------------------------------------- // CLASS : sc_module // // Base class for all structural entities. // ---------------------------------------------------------------------------- void sc_module::sc_module_init() { simcontext()->get_module_registry()->insert( *this ); simcontext()->hierarchy_push( this ); m_end_module_called = false; m_module_name_p = 0; m_port_vec = new std::vector; m_port_index = 0; } /* * This form of the constructor assumes that the user has * used an sc_module_name parameter for his/her constructor. * That parameter object has been pushed onto the stack, * and can be looked up by calling the * top_of_module_name_stack() function of the object manager. * This technique has two advantages: * * 1) The user no longer has to write sc_module(name) in the * constructor initializer. * 2) The user no longer has to call end_module() at the end * of the constructor -- a common negligence. * * But it is important to note that sc_module_name may be used * in the user's constructor's parameter. If it is used anywhere * else, unexpected things will happen. The error-checking * mechanism builtin here cannot hope to catch all misuses. * */ sc_module::sc_module() : sc_object(::sc_core::sc_get_curr_simcontext() ->get_object_manager() ->top_of_module_name_stack() ->operator const char*()), sensitive(this), sensitive_pos(this), sensitive_neg(this), m_end_module_called(false), m_port_vec(), m_port_index(0), m_name_gen(0), m_module_name_p(0) { /* When this form is used, we better have a fresh sc_module_name on the top of the stack */ sc_module_name* mod_name = simcontext()->get_object_manager()->top_of_module_name_stack(); if (0 == mod_name || 0 != mod_name->m_module_p) { SC_REPORT_ERROR( SC_ID_SC_MODULE_NAME_REQUIRED_, 0 ); sc_abort(); // can't recover from here } sc_module_init(); mod_name->set_module( this ); m_module_name_p = mod_name; // must come after sc_module_init call. } sc_module::sc_module( const sc_module_name& ) : sc_object(::sc_core::sc_get_curr_simcontext() ->get_object_manager() ->top_of_module_name_stack() ->operator const char*()), sensitive(this), sensitive_pos(this), sensitive_neg(this), m_end_module_called(false), m_port_vec(), m_port_index(0), m_name_gen(0), m_module_name_p(0) { /* For those used to the old style of passing a name to sc_module, this constructor will reduce the chance of making a mistake */ /* When this form is used, we better have a fresh sc_module_name on the top of the stack */ sc_module_name* mod_name = simcontext()->get_object_manager()->top_of_module_name_stack(); if (0 == mod_name || 0 != mod_name->m_module_p) { SC_REPORT_ERROR( SC_ID_SC_MODULE_NAME_REQUIRED_, 0 ); sc_abort(); // can't recover from here } sc_module_init(); mod_name->set_module( this ); m_module_name_p = mod_name; // must come after sc_module_init call. } /* -------------------------------------------------------------------- * * Deprecated constructors: * sc_module( const char* ) * sc_module( const std::string& ) */ sc_module::sc_module( const char* nm ) : sc_object(nm), sensitive(this), sensitive_pos(this), sensitive_neg(this), m_end_module_called(false), m_port_vec(), m_port_index(0), m_name_gen(0), m_module_name_p(0) { SC_REPORT_WARNING( SC_ID_BAD_SC_MODULE_CONSTRUCTOR_, nm ); sc_module_init(); } sc_module::sc_module( const std::string& s ) : sc_object( s.c_str() ), sensitive(this), sensitive_pos(this), sensitive_neg(this), m_end_module_called(false), m_port_vec(), m_port_index(0), m_name_gen(0), m_module_name_p(0) { SC_REPORT_WARNING( SC_ID_BAD_SC_MODULE_CONSTRUCTOR_, s.c_str() ); sc_module_init(); } /* -------------------------------------------------------------------- */ sc_module::~sc_module() { delete m_port_vec; delete m_name_gen; orphan_child_objects(); if ( m_module_name_p ) { m_module_name_p->clear_module( this ); // must be before end_module() end_module(); } simcontext()->get_module_registry()->remove( *this ); } const ::std::vector& sc_module::get_child_objects() const { return m_child_objects; } // set SC_THREAD asynchronous reset sensitivity void sc_module::async_reset_signal_is( const sc_in& port, bool level ) { sc_reset::reset_signal_is(true, port, level); } void sc_module::async_reset_signal_is( const sc_inout& port, bool level ) { sc_reset::reset_signal_is(true, port, level); } void sc_module::async_reset_signal_is( const sc_out& port, bool level ) { sc_reset::reset_signal_is(true, port, level); } void sc_module::async_reset_signal_is(const sc_signal_in_if& iface, bool level) { sc_reset::reset_signal_is(true, iface, level); } void sc_module::end_module() { if( ! m_end_module_called ) { /* TBD: Can check here to alert the user that end_module was not called for a previous module. */ (void)sc_get_curr_simcontext()->hierarchy_pop(); sc_get_curr_simcontext()->reset_curr_proc(); sensitive.reset(); sensitive_pos.reset(); sensitive_neg.reset(); m_end_module_called = true; m_module_name_p = 0; // make sure we are not called in ~sc_module(). } } // to prevent initialization for SC_METHODs and SC_THREADs void sc_module::dont_initialize() { sc_process_handle last_proc = sc_get_last_created_process_handle(); last_proc.dont_initialize( true ); } // set SC_THREAD synchronous reset sensitivity void sc_module::reset_signal_is( const sc_in& port, bool level ) { sc_reset::reset_signal_is(false, port, level); } void sc_module::reset_signal_is( const sc_inout& port, bool level ) { sc_reset::reset_signal_is(false, port, level); } void sc_module::reset_signal_is( const sc_out& port, bool level ) { sc_reset::reset_signal_is(false, port, level); } void sc_module::reset_signal_is( const sc_signal_in_if& iface, bool level ) { sc_reset::reset_signal_is(false, iface, level); } // to generate unique names for objects in an MT-Safe way const char* sc_module::gen_unique_name( const char* basename_, bool preserve_first ) { if( !m_name_gen ) m_name_gen = new sc_name_gen; return m_name_gen->gen_unique_name( basename_, preserve_first ); } // called by construction_done void sc_module::before_end_of_elaboration() {} // We push the sc_module instance onto the stack of open objects so // that any objects that are created in before_end_of_elaboration have // the proper parent. After the call we pop the hierarchy. void sc_module::construction_done() { hierarchy_scope scope(this); before_end_of_elaboration(); } // called by elaboration_done (does nothing by default) void sc_module::end_of_elaboration() {} // We push the sc_module instance onto the stack of open objects so // that any objects that are created in end_of_elaboration have // the proper parent. After the call we pop the hierarchy. void sc_module::elaboration_done( bool& error_ ) { if( ! m_end_module_called ) { std::stringstream msg; msg << "module '" << name() << "'"; SC_REPORT_WARNING( SC_ID_END_MODULE_NOT_CALLED_, msg.str().c_str() ); if( error_ ) { SC_REPORT_WARNING( SC_ID_HIER_NAME_INCORRECT_, 0 ); } error_ = true; } hierarchy_scope scope(this); end_of_elaboration(); } // called by start_simulation (does nothing by default) void sc_module::start_of_simulation() {} void sc_module::start_simulation() { hierarchy_scope scope(this); start_of_simulation(); } // called by simulation_done (does nothing by default) void sc_module::end_of_simulation() {} void sc_module::simulation_done() { hierarchy_scope scope(this); end_of_simulation(); } void sc_module::set_stack_size( std::size_t size ) { sc_process_handle proc_h( sc_is_running() ? sc_get_current_process_handle() : sc_get_last_created_process_handle() ); sc_thread_handle thread_h; // Current process as thread. thread_h = (sc_thread_handle)proc_h; if ( thread_h ) { thread_h->set_stack_size( size ); } else { SC_REPORT_WARNING( SC_ID_SET_STACK_SIZE_, 0 ); } } int sc_module::append_port( sc_port_base* port_ ) { int index = m_port_vec->size(); m_port_vec->push_back( port_ ); return index; } // positional binding methods static void sc_warn_arrow_arrow_bind() { static bool warn_arrow_arrow_bind=true; if ( warn_arrow_arrow_bind ) { warn_arrow_arrow_bind = false; SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, "positional binding using << or , is deprecated, use () instead."); } } sc_module& sc_module::operator << ( sc_interface& interface_ ) { sc_warn_arrow_arrow_bind(); positional_bind(interface_); return *this; } sc_module& sc_module::operator << ( sc_port_base& port_ ) { sc_warn_arrow_arrow_bind(); positional_bind(port_); return *this; } void sc_module::positional_bind( sc_interface& interface_ ) { if( m_port_index == (int)m_port_vec->size() ) { std::stringstream msg; if( m_port_index == 0 ) { msg << "module `" << name() << "' has no ports"; } else { msg << "all ports of module `" << name() << "' are bound"; } SC_REPORT_ERROR( SC_ID_BIND_IF_TO_PORT_, msg.str().c_str() ); return; } int status = (*m_port_vec)[m_port_index]->pbind( interface_ ); if( status != 0 ) { std::stringstream msg; switch( status ) { case 1: msg << "port " << m_port_index << " of module `" << name() << "' is already bound"; break; case 2: msg << "type mismatch on port " << m_port_index << " of module `" << name() << "'"; break; default: msg << "unknown error"; break; } SC_REPORT_ERROR( SC_ID_BIND_IF_TO_PORT_, msg.str().c_str() ); } ++ m_port_index; } void sc_module::positional_bind( sc_port_base& port_ ) { if( m_port_index == (int)m_port_vec->size() ) { std::stringstream msg; if( m_port_index == 0 ) { msg << "module `" << name() << "' has no ports"; } else { msg << "all ports of module `" << name() << "' are bound"; } SC_REPORT_ERROR( SC_ID_BIND_IF_TO_PORT_, msg.str().c_str() ); return; } int status = (*m_port_vec)[m_port_index]->pbind( port_ ); if( status != 0 ) { std::stringstream msg; switch( status ) { case 1: msg << "port " << m_port_index << " of module `" << name() << "' is already bound"; break; case 2: msg << "type mismatch on port " << m_port_index << " of module `" << name() << "'"; break; default: msg << "unknown error"; break; } SC_REPORT_ERROR( SC_ID_BIND_IF_TO_PORT_, msg.str().c_str() ); } ++ m_port_index; } #define TRY_BIND( p ) \ if( (p).iface != 0 ) { \ positional_bind( *(p).iface ); \ } else if( (p).port != 0 ) { \ positional_bind( *(p).port ); \ } else { \ return; \ } void sc_module::operator () ( const sc_bind_proxy& p001, const sc_bind_proxy& p002, const sc_bind_proxy& p003, const sc_bind_proxy& p004, const sc_bind_proxy& p005, const sc_bind_proxy& p006, const sc_bind_proxy& p007, const sc_bind_proxy& p008, const sc_bind_proxy& p009, const sc_bind_proxy& p010, const sc_bind_proxy& p011, const sc_bind_proxy& p012, const sc_bind_proxy& p013, const sc_bind_proxy& p014, const sc_bind_proxy& p015, const sc_bind_proxy& p016, const sc_bind_proxy& p017, const sc_bind_proxy& p018, const sc_bind_proxy& p019, const sc_bind_proxy& p020, const sc_bind_proxy& p021, const sc_bind_proxy& p022, const sc_bind_proxy& p023, const sc_bind_proxy& p024, const sc_bind_proxy& p025, const sc_bind_proxy& p026, const sc_bind_proxy& p027, const sc_bind_proxy& p028, const sc_bind_proxy& p029, const sc_bind_proxy& p030, const sc_bind_proxy& p031, const sc_bind_proxy& p032, const sc_bind_proxy& p033, const sc_bind_proxy& p034, const sc_bind_proxy& p035, const sc_bind_proxy& p036, const sc_bind_proxy& p037, const sc_bind_proxy& p038, const sc_bind_proxy& p039, const sc_bind_proxy& p040, const sc_bind_proxy& p041, const sc_bind_proxy& p042, const sc_bind_proxy& p043, const sc_bind_proxy& p044, const sc_bind_proxy& p045, const sc_bind_proxy& p046, const sc_bind_proxy& p047, const sc_bind_proxy& p048, const sc_bind_proxy& p049, const sc_bind_proxy& p050, const sc_bind_proxy& p051, const sc_bind_proxy& p052, const sc_bind_proxy& p053, const sc_bind_proxy& p054, const sc_bind_proxy& p055, const sc_bind_proxy& p056, const sc_bind_proxy& p057, const sc_bind_proxy& p058, const sc_bind_proxy& p059, const sc_bind_proxy& p060, const sc_bind_proxy& p061, const sc_bind_proxy& p062, const sc_bind_proxy& p063, const sc_bind_proxy& p064 ) { static bool warn_only_once=true; if ( m_port_index > 0 && warn_only_once ) { warn_only_once = false; SC_REPORT_INFO(SC_ID_IEEE_1666_DEPRECATION_, "multiple () binding deprecated, use explicit port binding instead." ); } TRY_BIND( p001 ); TRY_BIND( p002 ); TRY_BIND( p003 ); TRY_BIND( p004 ); TRY_BIND( p005 ); TRY_BIND( p006 ); TRY_BIND( p007 ); TRY_BIND( p008 ); TRY_BIND( p009 ); TRY_BIND( p010 ); TRY_BIND( p011 ); TRY_BIND( p012 ); TRY_BIND( p013 ); TRY_BIND( p014 ); TRY_BIND( p015 ); TRY_BIND( p016 ); TRY_BIND( p017 ); TRY_BIND( p018 ); TRY_BIND( p019 ); TRY_BIND( p020 ); TRY_BIND( p021 ); TRY_BIND( p022 ); TRY_BIND( p023 ); TRY_BIND( p024 ); TRY_BIND( p025 ); TRY_BIND( p026 ); TRY_BIND( p027 ); TRY_BIND( p028 ); TRY_BIND( p029 ); TRY_BIND( p030 ); TRY_BIND( p031 ); TRY_BIND( p032 ); TRY_BIND( p033 ); TRY_BIND( p034 ); TRY_BIND( p035 ); TRY_BIND( p036 ); TRY_BIND( p037 ); TRY_BIND( p038 ); TRY_BIND( p039 ); TRY_BIND( p040 ); TRY_BIND( p041 ); TRY_BIND( p042 ); TRY_BIND( p043 ); TRY_BIND( p044 ); TRY_BIND( p045 ); TRY_BIND( p046 ); TRY_BIND( p047 ); TRY_BIND( p048 ); TRY_BIND( p049 ); TRY_BIND( p050 ); TRY_BIND( p051 ); TRY_BIND( p052 ); TRY_BIND( p053 ); TRY_BIND( p054 ); TRY_BIND( p055 ); TRY_BIND( p056 ); TRY_BIND( p057 ); TRY_BIND( p058 ); TRY_BIND( p059 ); TRY_BIND( p060 ); TRY_BIND( p061 ); TRY_BIND( p062 ); TRY_BIND( p063 ); TRY_BIND( p064 ); } } // namespace sc_core /***************************************************************************** MODIFICATION LOG - modifiers, enter your name, affiliation, date and changes you are making here. Name, Affiliation, Date: Ali Dasdan, Synopsys, Inc. Description of Modification: - Implementation of operator() and operator, positional connection method. - Implementation of error checking in operator<<'s. - Implementation of the function test_module_prm. - Implementation of set_stack_size(). Name, Affiliation, Date: Andy Goodrich, Forte Design Systems 20 May 2003 Description of Modification: Inherit from sc_process_host Name, Affiliation, Date: Bishnupriya Bhattacharya, Cadence Design Systems, 25 August, 2003 Description of Modification: dont_initialize() uses sc_get_last_created_process_handle() instead of sc_get_current_process_b() Name, Affiliation, Date: Andy Goodrich, Forte Design Systems 25 Mar 2003 Description of Modification: Fixed bug in SC_NEW, see comments on ~sc_module_dynalloc_list below. *****************************************************************************/ // $Log: sc_module.cpp,v $ // Revision 1.14 2011/08/29 18:04:32 acg // Philipp A. Hartmann: miscellaneous clean ups. // // Revision 1.13 2011/08/26 20:46:10 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.12 2011/08/24 22:05:51 acg // Torsten Maehne: initialization changes to remove warnings. // // Revision 1.11 2011/03/05 19:44:20 acg // Andy Goodrich: changes for object and event naming and structures. // // Revision 1.10 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.9 2011/02/16 22:37:30 acg // Andy Goodrich: clean up to remove need for ps_disable_pending. // // Revision 1.8 2011/02/14 17:51:40 acg // Andy Goodrich: proper pushing an poppping of the module hierarchy for // start_of_simulation() and end_of_simulation. // // Revision 1.7 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.6 2011/01/25 20:50:37 acg // Andy Goodrich: changes for IEEE 1666 2011. // // Revision 1.5 2009/05/22 16:06:29 acg // Andy Goodrich: process control updates. // // Revision 1.4 2008/11/17 15:57:15 acg // Andy Goodrich: added deprecation message for sc_module(const char*) // // Revision 1.3 2008/05/22 17:06:25 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.2 2007/05/17 20:16:33 acg // Andy Goodrich: changes for beta release to LWG. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.9 2006/12/02 20:58:18 acg // Andy Goodrich: updates from 2.2 for IEEE 1666 support. // // Revision 1.8 2006/03/21 00:00:34 acg // Andy Goodrich: changed name of sc_get_current_process_base() to be // sc_get_current_process_b() since its returning an sc_process_b instance. // // Revision 1.7 2006/03/14 23:56:58 acg // Andy Goodrich: This fixes a bug when an exception is thrown in // sc_module::sc_module() for a dynamically allocated sc_module // object. We are calling sc_module::end_module() on a module that has // already been deleted. The scenario runs like this: // // a) the sc_module constructor is entered // b) the exception is thrown // c) the exception processor deletes the storage for the sc_module // d) the stack is unrolled causing the sc_module_name instance to be deleted // e) ~sc_module_name() calls end_module() with its pointer to the sc_module // f) because the sc_module has been deleted its storage is corrupted, // either by linking it to a free space chain, or by reuse of some sort // g) the m_simc field is garbage // h) the m_object_manager field is also garbage // i) an exception occurs // // This does not happen for automatic sc_module instances since the // storage for the module is not reclaimed its just part of the stack. // // I am fixing this by having the destructor for sc_module clear the // module pointer in its sc_module_name instance. That cuts things at // step (e) above, since the pointer will be null if the module has // already been deleted. To make sure the module stack is okay, I call // end-module() in ~sc_module in the case where there is an // sc_module_name pointer lying around. // // Revision 1.6 2006/01/26 21:04:54 acg // Andy Goodrich: deprecation message changes and additional messages. // // Revision 1.5 2006/01/25 00:31:19 acg // Andy Goodrich: Changed over to use a standard message id of // SC_ID_IEEE_1666_DEPRECATION for all deprecation messages. // // Revision 1.4 2006/01/24 20:49:05 acg // Andy Goodrich: changes to remove the use of deprecated features within the // simulator, and to issue warning messages when deprecated features are used. // // Revision 1.3 2006/01/13 18:44:29 acg // Added $Log to record CVS changes into the source. // // Taf! systemc-2.3.3/src/sysc/kernel/sc_object_manager.cpp0000644000175000017500000004642213360325173022262 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_object_manager.cpp -- Manager of objects (naming, &c.) Original Author: Stan Y. Liao, Synopsys, Inc. CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #include #include #include #include #include #include #include // pick up std::sort. #include "sysc/kernel/sc_object.h" #include "sysc/utils/sc_hash.h" #include "sysc/utils/sc_list.h" #include "sysc/utils/sc_mempool.h" #include "sysc/kernel/sc_simcontext.h" #include "sysc/kernel/sc_object_manager.h" #include "sysc/kernel/sc_kernel_ids.h" #include "sysc/kernel/sc_process.h" #include "sysc/kernel/sc_module_name.h" #include namespace sc_core { // ---------------------------------------------------------------------------- // CLASS : sc_object_manager // // Manager of objects. // ---------------------------------------------------------------------------- sc_object_manager::sc_object_manager() : m_event_it(), m_event_walk_ok(0), m_instance_table(), m_module_name_stack(0), m_object_it(), m_object_stack(), m_object_walk_ok() { } // +---------------------------------------------------------------------------- // |"sc_object_manager::~sc_object_manager" // | // | This is the object instance destructor for this class. It goes through // | each sc_object instance in the instance table and sets its m_simc field // | to NULL. // +---------------------------------------------------------------------------- sc_object_manager::~sc_object_manager() { instance_table_t::iterator it; // instance table iterator. for ( it = m_instance_table.begin(); it != m_instance_table.end(); it++) { if(it->second.m_name_origin == SC_NAME_OBJECT) { sc_object* obj_p = static_cast(it->second.m_element_p); obj_p->m_simc = 0; } } } // +---------------------------------------------------------------------------- // |"sc_object_manager::create_name" // | // | This method creates a hierarchical name based on the name of the active // | object and the supplied leaf name. If the resultant name is not unique it // | will be made unique and a warning message issued. // | // | Arguments: // | leaf_name = name to use for the leaf of the hierarchy. // | Result is an std::string containing the name. // +---------------------------------------------------------------------------- std::string sc_object_manager::create_name(const char* leaf_name) { bool clash; // true if path name exists in obj table std::string leafname_string; // string containing the leaf name. std::string parentname_string; // parent path name sc_object* parent_p; // parent for this instance or NULL. std::string result_orig_string; // save for warning message. std::string result_string; // name to return. // CONSTRUCT PATHNAME TO THE NAME TO BE RETURNED: // // If there is not a leaf name generate one. parent_p = sc_get_curr_simcontext()->active_object(); parentname_string = parent_p ? parent_p->name() : ""; leafname_string = leaf_name; if (parent_p) { result_string = parentname_string; result_string += SC_HIERARCHY_CHAR; result_string += leafname_string; } else { result_string = leafname_string; } // SAVE the original path name result_orig_string = result_string; // MAKE SURE THE ENTITY NAME IS UNIQUE: // // If not use unique name generator to make it unique. clash = false; for (;;) { if ( !name_exists(result_string) ) { break; } clash = true; leafname_string = sc_gen_unique_name(leafname_string.c_str(), false); if (parent_p) { result_string = parentname_string; result_string += SC_HIERARCHY_CHAR; result_string += leafname_string; } else { result_string = leafname_string; } } if (clash) { std::string message = result_orig_string; message += ". Latter declaration will be renamed to "; message += result_string; SC_REPORT_WARNING( SC_ID_INSTANCE_EXISTS_, message.c_str()); } return result_string; } // +---------------------------------------------------------------------------- // |"sc_object_manager::name_exists" // | // | This method returns true if the supplied name exists in the hierarchy // | or false if the element does not exist. // | // | Arguments: // | name = name of the element // | Result is a boolean // +---------------------------------------------------------------------------- bool sc_object_manager::name_exists(const std::string& name) { instance_table_t::const_iterator it = m_instance_table.find(name); return (it != m_instance_table.end()) && (it->second.m_name_origin != SC_NAME_NONE); } // +---------------------------------------------------------------------------- // |"sc_object_manager::get_name" // | // | This method returns the pointer to the supplied name if it exists in the // | hierarchy or NULL if it doesn't exist. // | // | Arguments: // | name = name of the element // | Result is a pointer to the name or NULL if it doesn't exist. // +---------------------------------------------------------------------------- const char* sc_object_manager::get_name(const std::string& name) { instance_table_t::iterator it = m_instance_table.find(name); if (it != m_instance_table.end() && it->second.m_name_origin != SC_NAME_NONE) { return it->first.c_str(); } else { return NULL; } } // +---------------------------------------------------------------------------- // |"sc_object_manager::find_event" // | // | This method returns the sc_event with the supplied name, or a NULL if // | the event does not exist. // | // | Arguments: // | name = name of the event // | Result is a pointer to the event or NULL if it does not exist. // +---------------------------------------------------------------------------- sc_event* sc_object_manager::find_event(const char* name) { instance_table_t::iterator it; it = m_instance_table.find(name); if(it != m_instance_table.end() && it->second.m_name_origin == SC_NAME_EVENT) { return static_cast(it->second.m_element_p); } else { return NULL; } } // +---------------------------------------------------------------------------- // |"sc_object_manager::find_object" // | // | This method returns the sc_object with the supplied name, or a NULL if // | the object does not exist. // | // | Arguments: // | name = name of the object // | Result is a pointer to the object or NULL if it does not exist. // +---------------------------------------------------------------------------- sc_object* sc_object_manager::find_object(const char* name) { instance_table_t::iterator it; it = m_instance_table.find(name); if(it != m_instance_table.end() && it->second.m_name_origin == SC_NAME_OBJECT) { return static_cast(it->second.m_element_p); } else { return NULL; } } // +---------------------------------------------------------------------------- // |"sc_object_manager::first_object" // | // | This method initializes the object iterator to point to the first object // | in the instance table, and returns its address. If there are no objects // | in the table a NULL value is returned. // +---------------------------------------------------------------------------- sc_object* sc_object_manager::first_object() { sc_object* result_p; // result to return. m_object_walk_ok = true; result_p = NULL; for ( m_object_it = m_instance_table.begin(); m_object_it != m_instance_table.end(); m_object_it++ ) { if(m_object_it->second.m_name_origin == SC_NAME_OBJECT) { return static_cast(m_object_it->second.m_element_p); } } return result_p; } // +---------------------------------------------------------------------------- // |"sc_object_manager::hierarchy_curr" // | // | This method returns the current object in the object hierarchy or NULL // | if it does not exist. // +---------------------------------------------------------------------------- sc_object* sc_object_manager::hierarchy_curr() { std::size_t hierarchy_n; // current size of the hierarchy. hierarchy_n = m_object_stack.size(); return hierarchy_n ? m_object_stack[hierarchy_n-1] : 0; } // +---------------------------------------------------------------------------- // |"sc_object_manager::hierarchy_pop" // | // | This method pops the current object off the object hierarchy and returns // | it. // +---------------------------------------------------------------------------- sc_object* sc_object_manager::hierarchy_pop() { std::size_t hierarchy_n; // current size of the hierarchy. sc_object* result_p; // object to return. hierarchy_n = m_object_stack.size(); if ( hierarchy_n == 0 ) return NULL; hierarchy_n--; result_p = m_object_stack[hierarchy_n]; m_object_stack.pop_back(); return result_p; } // +---------------------------------------------------------------------------- // |"sc_object_manager::hierarchy_push" // | // | This method pushes down the sc_object hierarchy to make the supplied // | object the current object in the hierarchy. // | // | Arguments: // | object_p -> object to become the new current object in the hierarchy. // +---------------------------------------------------------------------------- void sc_object_manager::hierarchy_push(sc_object* object_p) { m_object_stack.push_back(object_p); } // +---------------------------------------------------------------------------- // |"sc_object_manager::hierarchy_size" // | // | This method returns the current size of the object hierarchy stack. // +---------------------------------------------------------------------------- int sc_object_manager::hierarchy_size() { return m_object_stack.size(); } // +---------------------------------------------------------------------------- // |"sc_object_manager::insert_external_name" // | // | This method inserts the supplied name into the instance table using // | the supplied name. // | // | Arguments: // | name = external to be inserted. // +---------------------------------------------------------------------------- bool sc_object_manager::insert_external_name(const std::string& name) { if(!name_exists(name)) { m_instance_table[name].m_element_p = NULL; m_instance_table[name].m_name_origin = SC_NAME_EXTERNAL; return true; } else { table_entry element = m_instance_table[name]; std::stringstream msg; msg << name << " (" << ((element.m_name_origin == SC_NAME_OBJECT) ? (static_cast(element.m_element_p))->kind() : (element.m_name_origin == SC_NAME_EVENT) ? "event" : "external name") << ")"; SC_REPORT_WARNING( SC_ID_NAME_EXISTS_, msg.str().c_str()); return false; } } // +---------------------------------------------------------------------------- // |"sc_object_manager::insert_event" // | // | This method inserts the supplied sc_event instance into the instance // | table using the supplied name. // | // | Arguments: // | name = name of the event to be inserted. // | event_p -> event to be inserted. // +---------------------------------------------------------------------------- void sc_object_manager::insert_event(const std::string& name, sc_event* event_p) { m_instance_table[name].m_element_p = static_cast(event_p); m_instance_table[name].m_name_origin = SC_NAME_EVENT; } // +---------------------------------------------------------------------------- // |"sc_object_manager::insert_object" // | // | This method inserts the supplied sc_object instance into the instance // | table using the supplied name. // | // | Arguments: // | name = name of the event to be inserted. // | object_p -> object to be inserted. // +---------------------------------------------------------------------------- void sc_object_manager::insert_object(const std::string& name, sc_object* object_p) { m_instance_table[name].m_element_p = static_cast(object_p); m_instance_table[name].m_name_origin = SC_NAME_OBJECT; } // +---------------------------------------------------------------------------- // |"sc_object_manager::next_object" // | // | This method returns the next object pointed to by the instance iterator. // +---------------------------------------------------------------------------- sc_object* sc_object_manager::next_object() { sc_object* result_p; // result to return. sc_assert( m_object_walk_ok ); if ( m_object_it == m_instance_table.end() ) return NULL; m_object_it++; for ( result_p = NULL; m_object_it != m_instance_table.end(); m_object_it++ ) { if(m_object_it->second.m_name_origin == SC_NAME_OBJECT) { return static_cast(m_object_it->second.m_element_p); } } return result_p; } // +---------------------------------------------------------------------------- // |"sc_object_manager::pop_module_name" // | // | This method pops an entry off the module name stack and returns it. // +---------------------------------------------------------------------------- sc_module_name* sc_object_manager::pop_module_name() { sc_module_name* mod_name = m_module_name_stack; m_module_name_stack = m_module_name_stack->m_next; mod_name->m_next = 0; return mod_name; } // +---------------------------------------------------------------------------- // |"sc_object_manager::push_module_name" // | // | This method pushes the supplied entry onto the module name stack. // | // | Arguments: // | mod_name_p -> entry to push onto the module name stack. // +---------------------------------------------------------------------------- void sc_object_manager::push_module_name(sc_module_name* mod_name_p) { mod_name_p->m_next = m_module_name_stack; m_module_name_stack = mod_name_p; } // +---------------------------------------------------------------------------- // |"sc_object_manager::top_of_module_name_stack" // | // | This method returns the module name that is on the top of the module // | name stack. // +---------------------------------------------------------------------------- sc_module_name* sc_object_manager::top_of_module_name_stack() { if( m_module_name_stack == 0 ) { SC_REPORT_ERROR( SC_ID_MODULE_NAME_STACK_EMPTY_, 0 ); } return m_module_name_stack; } // +---------------------------------------------------------------------------- // |"sc_object_manager::remove_event" // | // | This method removes the sc_event instance with the supplied name from // | the table of instances. // | // | Arguments: // | name = name of the event to be removed. // +---------------------------------------------------------------------------- void sc_object_manager::remove_event(const std::string& name) { instance_table_t::iterator it; // instance table iterator. it = m_instance_table.find(name); if(it != m_instance_table.end() && it->second.m_name_origin == SC_NAME_EVENT) { it->second.m_element_p = NULL; it->second.m_name_origin = SC_NAME_NONE; } } // +---------------------------------------------------------------------------- // |"sc_object_manager::remove_object" // | // | This method removes the sc_object instance with the supplied name from // | the table of instances. // | // | Arguments: // | name = name of the object to be removed. // +---------------------------------------------------------------------------- void sc_object_manager::remove_object(const std::string& name) { instance_table_t::iterator it; // instance table iterator. it = m_instance_table.find(name); if(it != m_instance_table.end() && it->second.m_name_origin == SC_NAME_OBJECT) { it->second.m_element_p = NULL; it->second.m_name_origin = SC_NAME_NONE; } } // +---------------------------------------------------------------------------- // |"sc_object_manager::remove_external_name" // | // | This method removes the name instance with the supplied name from // | the table of instances. // | // | Arguments: // | name = external name to be removed. // +---------------------------------------------------------------------------- bool sc_object_manager::remove_external_name(const std::string& name) { instance_table_t::iterator it; // instance table iterator. it = m_instance_table.find(name); if(it != m_instance_table.end() && it->second.m_name_origin == SC_NAME_EXTERNAL) { it->second.m_element_p = NULL; it->second.m_name_origin = SC_NAME_NONE; return true; } else { return false; } } } // namespace sc_core // $Log: sc_object_manager.cpp,v $ // Revision 1.13 2011/08/26 20:46:10 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.12 2011/08/24 22:05:51 acg // Torsten Maehne: initialization changes to remove warnings. // // Revision 1.11 2011/06/25 17:08:39 acg // Andy Goodrich: Jerome Cornet's changes to use libtool to build the // library. // // Revision 1.10 2011/04/01 21:27:54 acg // Andy Goodrich: documentation of event and object insertion methods. // // Revision 1.9 2011/03/06 15:55:11 acg // Andy Goodrich: Changes for named events. // // Revision 1.8 2011/03/05 19:44:20 acg // Andy Goodrich: changes for object and event naming and structures. // // Revision 1.7 2011/03/05 04:45:16 acg // Andy Goodrich: moved active process calculation to the sc_simcontext class. // // Revision 1.6 2011/03/05 01:39:21 acg // Andy Goodrich: changes for named events. // // Revision 1.5 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.4 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.3 2010/07/22 20:02:33 acg // Andy Goodrich: bug fixes. // // Revision 1.2 2008/05/22 17:06:26 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.3 2006/01/13 18:44:30 acg // Added $Log to record CVS changes into the source. // systemc-2.3.3/src/sysc/kernel/sc_except.cpp0000644000175000017500000001011113360325173020574 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_except.cpp -- kill/reset exception handling Original Author: Philipp A. Hartmann, OFFIS CHANGE LOG APPEARS AT THE END OF THE FILE *****************************************************************************/ #include "sysc/kernel/sc_cmnhdr.h" // #include "sysc/kernel/sc_except.h" #include "sysc/kernel/sc_process.h" // #include "sysc/utils/sc_report.h" namespace sc_core { sc_unwind_exception::sc_unwind_exception( sc_process_b* proc_p, bool is_reset ) : m_proc_p(proc_p), m_is_reset( is_reset ) { sc_assert( m_proc_p ); m_proc_p->start_unwinding(); } bool sc_unwind_exception::active() const { return m_proc_p && m_proc_p->is_unwinding(); } void sc_unwind_exception::clear() const { sc_assert( m_proc_p ); m_proc_p->clear_unwinding(); } const char* sc_unwind_exception::what() const SC_NOEXCEPT_ { return ( m_is_reset ) ? "RESET" : "KILL"; } sc_unwind_exception::~sc_unwind_exception() SC_NOEXCEPT_ { if( active() ) { // can't throw an exception, since we're already throwing // -> abort instead SC_REPORT_FATAL( SC_ID_RETHROW_UNWINDING_, m_proc_p->name() ); sc_abort(); // can't recover from here } } // handle and translate uncaught exceptions here // // These exceptions can either escape from sc_main() directly, // indirectly from an SC_METHOD(), or are thrown from within // an SC_(C)THREAD() // // returns a pointer to a dynamically allocated sc_report object, // containing the caught message SC_API sc_report* sc_handle_exception() { try { // re-throw exception here try { throw; } catch( sc_report & ) // to be on the safe side { throw; // continue } catch( sc_unwind_exception const & ) { SC_REPORT_ERROR( SC_ID_INTERNAL_ERROR_, "unhandled kill/reset, should never happen" ); } catch( std::exception const & x ) { SC_REPORT_ERROR( SC_ID_SIMULATION_UNCAUGHT_EXCEPTION_, x.what() ); } catch( char const * x ) { SC_REPORT_ERROR( SC_ID_SIMULATION_UNCAUGHT_EXCEPTION_, x ); } catch( ... ) { SC_REPORT_ERROR( SC_ID_SIMULATION_UNCAUGHT_EXCEPTION_, "UNKNOWN EXCEPTION" ); } } // everything is an sc_report now catch( sc_report & rpt ) { sc_report* rpt_p = new sc_report; rpt_p->swap( rpt ); return rpt_p; } return 0; } } // namespace sc_core // $Log: sc_except.cpp,v $ // Revision 1.4 2011/08/26 20:46:09 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.3 2011/05/09 04:07:48 acg // Philipp A. Hartmann: // (1) Restore hierarchy in all phase callbacks. // (2) Ensure calls to before_end_of_elaboration. // // Revision 1.2 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.1 2011/02/10 22:47:38 acg // Andy Goodrich: first check in of Philipp A. Hartmann's new exception // processing code. // // Taf! systemc-2.3.3/src/sysc/kernel/sc_sensitive.h0000644000175000017500000002362513360325173021000 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_sensitive.h -- Sensitivity classes. Requires "sc_process.h" for declarations of sc_method_handle, &.c. Original Author: Stan Y. Liao, Synopsys, Inc. Martin Janssen, Synopsys, Inc. CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #ifndef SC_SENSITIVE_H #define SC_SENSITIVE_H #include "sysc/kernel/sc_process.h" namespace sc_dt { class sc_logic; } namespace sc_core { class sc_process_handle; class sc_event; class sc_event_finder; class sc_interface; class sc_module; class sc_port_base; template class sc_in; template class sc_inout; template class sc_signal_in_if; // ---------------------------------------------------------------------------- // CLASS : sc_sensitive // // Static sensitivity class for events. // ---------------------------------------------------------------------------- class SC_API sc_sensitive { friend class sc_module; public: // typedefs typedef sc_signal_in_if in_if_b_type; typedef sc_signal_in_if in_if_l_type; typedef sc_in in_port_b_type; typedef sc_in in_port_l_type; typedef sc_inout inout_port_b_type; typedef sc_inout inout_port_l_type; private: // constructor explicit sc_sensitive( sc_module* ); // destructor ~sc_sensitive(); public: // changing between process handles sc_sensitive& operator << ( sc_process_handle ); #if 0 sc_sensitive& operator << ( sc_method_handle ); sc_sensitive& operator << ( sc_thread_handle ); #endif // 0 sc_sensitive& operator () ( const sc_event& ); sc_sensitive& operator () ( const sc_interface& ); sc_sensitive& operator () ( const sc_port_base& ); sc_sensitive& operator () ( sc_event_finder& ); sc_sensitive& operator << ( const sc_event& ); sc_sensitive& operator << ( const sc_interface& ); sc_sensitive& operator << ( const sc_port_base& ); sc_sensitive& operator << ( sc_event_finder& ); sc_sensitive& operator () ( sc_cthread_handle, sc_event_finder& ); sc_sensitive& operator () ( sc_cthread_handle, const in_if_b_type& ); sc_sensitive& operator () ( sc_cthread_handle, const in_if_l_type& ); sc_sensitive& operator () ( sc_cthread_handle, const in_port_b_type& ); sc_sensitive& operator () ( sc_cthread_handle, const in_port_l_type& ); sc_sensitive& operator () ( sc_cthread_handle, const inout_port_b_type& ); sc_sensitive& operator () ( sc_cthread_handle, const inout_port_l_type& ); static void make_static_sensitivity( sc_process_b*, const sc_event& ); static void make_static_sensitivity( sc_process_b*, const sc_interface& ); static void make_static_sensitivity( sc_process_b*, const sc_port_base&); static void make_static_sensitivity( sc_process_b*, sc_event_finder& ); void reset(); private: sc_module* m_module; enum { SC_NONE_, SC_METHOD_, SC_THREAD_ } m_mode; sc_process_b* m_handle; private: // disabled sc_sensitive(); sc_sensitive( const sc_sensitive& ); sc_sensitive& operator = ( const sc_sensitive& ); }; // ---------------------------------------------------------------------------- // CLASS : sc_sensitive_pos // // Static sensitivity class for positive edge events. // ---------------------------------------------------------------------------- class SC_API sc_sensitive_pos { friend class sc_module; public: // typedefs typedef sc_signal_in_if in_if_b_type; typedef sc_signal_in_if in_if_l_type; typedef sc_in in_port_b_type; typedef sc_in in_port_l_type; typedef sc_inout inout_port_b_type; typedef sc_inout inout_port_l_type; private: // constructor explicit sc_sensitive_pos( sc_module* ); // destructor ~sc_sensitive_pos(); public: // changing between process handles sc_sensitive_pos& operator << ( sc_process_handle ); sc_sensitive_pos& operator << ( sc_method_handle ); sc_sensitive_pos& operator << ( sc_thread_handle ); sc_sensitive_pos& operator () ( const in_if_b_type& ); sc_sensitive_pos& operator () ( const in_if_l_type& ); sc_sensitive_pos& operator () ( const in_port_b_type& ); sc_sensitive_pos& operator () ( const in_port_l_type& ); sc_sensitive_pos& operator () ( const inout_port_b_type& ); sc_sensitive_pos& operator () ( const inout_port_l_type& ); sc_sensitive_pos& operator << ( const in_if_b_type& ); sc_sensitive_pos& operator << ( const in_if_l_type& ); sc_sensitive_pos& operator << ( const in_port_b_type& ); sc_sensitive_pos& operator << ( const in_port_l_type& ); sc_sensitive_pos& operator << ( const inout_port_b_type& ); sc_sensitive_pos& operator << ( const inout_port_l_type& ); void reset(); private: sc_module* m_module; enum { SC_NONE_, SC_METHOD_, SC_THREAD_ } m_mode; sc_process_b* m_handle; private: // disabled sc_sensitive_pos(); sc_sensitive_pos( const sc_sensitive_pos& ); sc_sensitive_pos& operator = ( const sc_sensitive_pos& ); }; // ---------------------------------------------------------------------------- // CLASS : sc_sensitive_neg // // Static sensitivity class for negative edge events. // ---------------------------------------------------------------------------- class SC_API sc_sensitive_neg { friend class sc_module; public: // typedefs typedef sc_signal_in_if in_if_b_type; typedef sc_signal_in_if in_if_l_type; typedef sc_in in_port_b_type; typedef sc_in in_port_l_type; typedef sc_inout inout_port_b_type; typedef sc_inout inout_port_l_type; private: // constructor explicit sc_sensitive_neg( sc_module* ); // destructor ~sc_sensitive_neg(); public: // changing between process handles sc_sensitive_neg& operator << ( sc_process_handle ); sc_sensitive_neg& operator << ( sc_method_handle ); sc_sensitive_neg& operator << ( sc_thread_handle ); sc_sensitive_neg& operator () ( const in_if_b_type& ); sc_sensitive_neg& operator () ( const in_if_l_type& ); sc_sensitive_neg& operator () ( const in_port_b_type& ); sc_sensitive_neg& operator () ( const in_port_l_type& ); sc_sensitive_neg& operator () ( const inout_port_b_type& ); sc_sensitive_neg& operator () ( const inout_port_l_type& ); sc_sensitive_neg& operator << ( const in_if_b_type& ); sc_sensitive_neg& operator << ( const in_if_l_type& ); sc_sensitive_neg& operator << ( const in_port_b_type& ); sc_sensitive_neg& operator << ( const in_port_l_type& ); sc_sensitive_neg& operator << ( const inout_port_b_type& ); sc_sensitive_neg& operator << ( const inout_port_l_type& ); void reset(); private: sc_module* m_module; enum { SC_NONE_, SC_METHOD_, SC_THREAD_ } m_mode; sc_process_b* m_handle; private: // disabled sc_sensitive_neg(); sc_sensitive_neg( const sc_sensitive_neg& ); sc_sensitive_neg& operator = ( const sc_sensitive_neg& ); }; } // namespace sc_core #endif /***************************************************************************** MODIFICATION LOG - modifiers, enter your name, affiliation, date and changes you are making here. Name, Affiliation, Date: Bishnupriya Bhattacharya, Cadence Design Systems, 25 August, 2003 Description of Modification: Add make_static_sensitivity() methods to enable dynamic method process creation with static sensitivity. *****************************************************************************/ // $Log: sc_sensitive.h,v $ // Revision 1.5 2011/08/26 20:46:10 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.4 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.3 2011/02/13 21:47:38 acg // Andy Goodrich: update copyright notice. // // Revision 1.2 2008/05/22 17:06:26 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.4 2006/04/11 23:13:21 acg // Andy Goodrich: Changes for reduced reset support that only includes // sc_cthread, but has preliminary hooks for expanding to method and thread // processes also. // // Revision 1.3 2006/01/13 18:44:30 acg // Added $Log to record CVS changes into the source. // Taf! systemc-2.3.3/src/sysc/kernel/sc_name_gen.h0000644000175000017500000000516013360325173020532 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_name_gen.h -- Unique name generator. Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #ifndef SC_NAME_GEN #define SC_NAME_GEN #include #include "sysc/utils/sc_hash.h" namespace sc_core{ // ---------------------------------------------------------------------------- // CLASS : sc_name_gen // // Unique name generator class. // ---------------------------------------------------------------------------- class sc_name_gen { public: sc_name_gen(); ~sc_name_gen(); const char* gen_unique_name( const char* basename_, bool preserve_first = false ); private: sc_strhash m_unique_name_map; std::string m_unique_name; private: // disabled sc_name_gen( const sc_name_gen& ); sc_name_gen& operator = ( const sc_name_gen& ); }; } // namespace sc_core // $Log: sc_name_gen.h,v $ // Revision 1.5 2011/08/26 20:46:10 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.4 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.3 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.2 2008/05/22 17:06:26 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.3 2006/01/13 18:44:30 acg // Added $Log to record CVS changes into the source. #endif // Taf! systemc-2.3.3/src/sysc/kernel/sc_main_main.cpp0000644000175000017500000001313313360325173021243 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_main_main.cpp - Wrapper around user's toplevel routine `sc_main'. Original Author: Andy Goodrich, Forte Design Systems CHANGE LOG APPEARS AT THE END OF THE FILE *****************************************************************************/ #define SC_DISABLE_API_VERSION_CHECK // for in-library sc_ver.h inclusion #include "sysc/kernel/sc_cmnhdr.h" #include "sysc/kernel/sc_externs.h" #include "sysc/kernel/sc_except.h" #include "sysc/kernel/sc_ver.h" #include "sysc/utils/sc_report.h" #include "sysc/utils/sc_report_handler.h" #include "sysc/utils/sc_utils_ids.h" #include #include #include #include namespace sc_core { extern void pln(); static int argc_orig; // Original argc value passed to sc_elab_and_sim. static char** argv_orig; // Original argv value passed to sc_elab_and_sim. bool sc_in_action = false; int sc_argc() { return argc_orig; } const char* const* sc_argv() { return argv_orig; } int sc_elab_and_sim( int argc, char* argv[] ) { int status = 1; argc_orig = argc; argv_orig = argv; // Copy argv into a new structure to prevent sc_main from modifying the // result returned from sc_argv. std::vector argv_copy(argc + 1, static_cast(NULL)); for ( int i = 0; i < argc; ++i ) { std::size_t size = std::strlen(argv[i]) + 1; argv_copy[i] = new char[size]; std::copy(argv[i], argv[i] + size, argv_copy[i]); } try { pln(); // Perform initialization here sc_in_action = true; // copy array of pointers to keep allocated pointers for later release std::vector argv_call = argv_copy; status = sc_main( argc, &argv_call[0] ); // Perform cleanup here sc_in_action = false; } catch( const sc_report& x ) { sc_report_handler::get_handler() ( x, sc_report_handler::get_catch_actions() ); } catch( ... ) { // translate other escaping exceptions sc_report* err_p = sc_handle_exception(); if( err_p ) sc_report_handler::get_handler() ( *err_p, sc_report_handler::get_catch_actions() ); delete err_p; } for ( int i = 0; i < argc; ++i ) { delete[] argv_copy[i]; } // IF DEPRECATION WARNINGS WERE ISSUED TELL THE USER HOW TO TURN THEM OFF if ( sc_report_handler::get_count( SC_ID_IEEE_1666_DEPRECATION_ ) > 0 ) { std::stringstream ss; const char MSGNL[] = "\n "; const char CODENL[] = "\n "; ss << "You can turn off warnings about" << MSGNL << "IEEE 1666 deprecated features by placing this method call" << MSGNL << "as the first statement in your sc_main() function:\n" << CODENL << "sc_core::sc_report_handler::set_actions( " << "\"" << SC_ID_IEEE_1666_DEPRECATION_ << "\"," << CODENL << " " /* indent param */ << "sc_core::SC_DO_NOTHING );" << std::endl; SC_REPORT_INFO( SC_ID_IEEE_1666_DEPRECATION_, ss.str().c_str() ); } return status; } } // namespace sc_core // $Log: sc_main_main.cpp,v $ // Revision 1.9 2011/08/26 20:46:10 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.8 2011/05/09 04:07:48 acg // Philipp A. Hartmann: // (1) Restore hierarchy in all phase callbacks. // (2) Ensure calls to before_end_of_elaboration. // // Revision 1.7 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.6 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.5 2010/03/15 18:29:25 acg // Andy Goodrich: Changed the default stack size to 128K from 64K. // // Revision 1.4 2009/10/14 19:06:48 acg // Andy Goodrich: changed the way the "copy" of argv is handled. It is // now passed to sc_main, and the original is referenced via argv_copy. // // Revision 1.3 2008/05/22 17:06:25 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.2 2008/04/11 20:41:28 acg // Andy Goodrich: changed the return value in sc_elab_and_sim() to be 1 // when an exception occurs in sc_main() rather than 0. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.4 2006/01/25 00:31:19 acg // Andy Goodrich: Changed over to use a standard message id of // SC_ID_IEEE_1666_DEPRECATION for all deprecation messages. // // Revision 1.3 2006/01/13 18:44:29 acg // Added $Log to record CVS changes into the source. // systemc-2.3.3/src/sysc/kernel/sc_cor_fiber.cpp0000644000175000017500000001505313360325173021250 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_cor_fiber.cpp -- Coroutine implementation with fibers. Original Author: Martin Janssen, Synopsys, Inc., 2001-12-18 CHANGE LOG APPEARS AT THE END OF THE FILE *****************************************************************************/ #if defined(_WIN32) || defined(WIN32) || defined(WIN64) #ifndef SC_INCLUDE_WINDOWS_H # define SC_INCLUDE_WINDOWS_H // include Windows.h, if needed #endif #include "sysc/kernel/sc_cor_fiber.h" #include "sysc/kernel/sc_simcontext.h" #if defined(__GNUC__) && __USING_SJLJ_EXCEPTIONS__ # if (__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ > 2)) # include # else extern "C" void _Unwind_SjLj_Register (struct SjLj_Function_Context *); extern "C" void _Unwind_SjLj_Unregister (struct SjLj_Function_Context *); # endif #endif namespace sc_core { // ---------------------------------------------------------------------------- // File static variables. // ---------------------------------------------------------------------------- // main coroutine static sc_cor_fiber main_cor; #if defined(__GNUC__) && __USING_SJLJ_EXCEPTIONS__ // current coroutine static sc_cor_fiber* curr_cor; #endif // ---------------------------------------------------------------------------- // CLASS : sc_cor_fiber // // Coroutine class implemented with Windows fibers. // ---------------------------------------------------------------------------- // destructor sc_cor_fiber::~sc_cor_fiber() { if( m_fiber != 0 ) { PVOID cur_fiber = GetCurrentFiber(); if( m_fiber != cur_fiber && this != m_pkg->get_main() ) DeleteFiber( m_fiber ); } } // ---------------------------------------------------------------------------- // CLASS : sc_cor_pkg_fiber // // Coroutine package class implemented with QuickThreads. // ---------------------------------------------------------------------------- int sc_cor_pkg_fiber::instance_count = 0; // constructor sc_cor_pkg_fiber::sc_cor_pkg_fiber( sc_simcontext* simc ) : sc_cor_pkg( simc ) { if( ++ instance_count == 1 ) { // initialize the main coroutine sc_assert( main_cor.m_fiber == 0 ); main_cor.m_fiber = ConvertThreadToFiber( 0 ); main_cor.m_pkg = this; if( !main_cor.m_fiber && GetLastError() == ERROR_ALREADY_FIBER ) { // conversion of current thread to fiber has failed, because // someone else already converted the main thread to a fiber // -> store current fiber main_cor.m_fiber = GetCurrentFiber(); } sc_assert( main_cor.m_fiber != 0 ); # if defined(__GNUC__) && __USING_SJLJ_EXCEPTIONS__ // initialize the current coroutine sc_assert( curr_cor == 0 ); curr_cor = &main_cor; # endif } } // destructor sc_cor_pkg_fiber::~sc_cor_pkg_fiber() { if( -- instance_count == 0 ) { // cleanup the main coroutine main_cor.m_fiber = 0; main_cor.m_pkg = 0; # if defined(__GNUC__) && __USING_SJLJ_EXCEPTIONS__ // cleanup the current coroutine curr_cor = 0; # endif } } // create a new coroutine sc_cor* sc_cor_pkg_fiber::create( std::size_t stack_size, sc_cor_fn* fn, void* arg ) { sc_cor_fiber* cor = new sc_cor_fiber; cor->m_pkg = this; cor->m_stack_size = stack_size; cor->m_fiber = CreateFiberEx( cor->m_stack_size / 2, cor->m_stack_size, 0, (LPFIBER_START_ROUTINE) fn, arg ); return cor; } // yield to the next coroutine void sc_cor_pkg_fiber::yield( sc_cor* next_cor ) { sc_cor_fiber* new_cor = static_cast( next_cor ); # if defined(__GNUC__) && __USING_SJLJ_EXCEPTIONS__ // Switch SJLJ exception handling function contexts _Unwind_SjLj_Register(&curr_cor->m_eh); _Unwind_SjLj_Unregister(&new_cor->m_eh); curr_cor = new_cor; # endif SwitchToFiber( new_cor->m_fiber ); } // abort the current coroutine (and resume the next coroutine) void sc_cor_pkg_fiber::abort( sc_cor* next_cor ) { sc_cor_fiber* new_cor = static_cast( next_cor ); # if defined(__GNUC__) && __USING_SJLJ_EXCEPTIONS__ // Switch SJLJ exception handling function contexts _Unwind_SjLj_Register(&curr_cor->m_eh); _Unwind_SjLj_Unregister(&new_cor->m_eh); curr_cor = new_cor; # endif SwitchToFiber( new_cor->m_fiber ); } // get the main coroutine sc_cor* sc_cor_pkg_fiber::get_main() { return &main_cor; } } // namespace sc_core // $Log: sc_cor_fiber.cpp,v $ // Revision 1.9 2011/09/08 16:12:45 acg // Philipp A. Hartmann: make sure we don't try to make a thread a fiber if // its already a fiber. // // Revision 1.8 2011/08/26 20:46:09 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.7 2011/06/25 17:08:39 acg // Andy Goodrich: Jerome Cornet's changes to use libtool to build the // library. // // Revision 1.6 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.5 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.4 2011/01/19 23:21:50 acg // Andy Goodrich: changes for IEEE 1666 2011 // // Revision 1.3 2009/05/22 16:06:29 acg // Andy Goodrich: process control updates. // // Revision 1.2 2008/05/22 17:06:25 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.3 2006/01/13 18:44:29 acg // Added $Log to record CVS changes into the source. // #endif // Taf! systemc-2.3.3/src/sysc/kernel/sc_module_registry.h0000644000175000017500000000661613360325173022205 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_module_registry.h -- Registry for all modules. FOR INTERNAL USE ONLY. Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #ifndef SC_MODULE_REGISTRY_H #define SC_MODULE_REGISTRY_H namespace sc_core { class sc_module; class sc_simcontext; // ---------------------------------------------------------------------------- // CLASS : sc_module_registry // // Registry for all modules. // FOR INTERNAL USE ONLY! // ---------------------------------------------------------------------------- class sc_module_registry { friend class sc_simcontext; public: void insert( sc_module& ); void remove( sc_module& ); int size() const { return m_module_vec.size(); } private: // constructor explicit sc_module_registry( sc_simcontext& simc_ ); // destructor ~sc_module_registry(); // called when construction is done bool construction_done(); // called when elaboration is done void elaboration_done(); // called before simulation begins void start_simulation(); // called after simulation ends void simulation_done(); private: int m_construction_done; std::vector m_module_vec; sc_simcontext* m_simc; private: // disabled sc_module_registry(); sc_module_registry( const sc_module_registry& ); sc_module_registry& operator = ( const sc_module_registry& ); }; } // namespace sc_core #endif // $Log: sc_module_registry.h,v $ // Revision 1.6 2011/08/26 20:46:10 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.5 2011/05/09 04:07:49 acg // Philipp A. Hartmann: // (1) Restore hierarchy in all phase callbacks. // (2) Ensure calls to before_end_of_elaboration. // // Revision 1.4 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.3 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.2 2008/05/22 17:06:26 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.3 2006/01/13 18:44:30 acg // Added $Log to record CVS changes into the source. // Taf! systemc-2.3.3/src/sysc/kernel/sc_reset.h0000644000175000017500000001707413360325173020112 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_reset.h -- Process reset support. Original Author: Andy Goodrich, Forte Design Systems, 17 June 2003 CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #if !defined(sc_reset_h_INCLUDED) #define sc_reset_h_INCLUDED #include "sysc/communication/sc_writer_policy.h" #if defined(_MSC_VER) && !defined(SC_WIN_DLL_WARN) #pragma warning(push) #pragma warning(disable: 4251) // DLL import for std::vector #endif namespace sc_core { // FORWARD CLASS REFERENCES: template class sc_signal_in_if; template class sc_signal; template class sc_in; template class sc_inout; template class sc_out; template class sc_spawn_reset; class sc_reset; class sc_process_b; //============================================================================== // CLASS sc_reset_target - RESET ENTRY FOR AN sc_process_b TARGET // // This class describes a reset condition associated with an sc_process_b // instance. //============================================================================== class SC_API sc_reset_target { public: bool m_async; // true asynchronous reset, false synchronous. bool m_level; // level for reset. sc_process_b* m_process_p; // process this reset entry is for. }; inline std::ostream& operator << ( std::ostream& os, const sc_reset_target& target ) { os << "["; os << target.m_async << ","; os << target.m_level << ","; os << target.m_process_p << ","; return os; } //============================================================================== // sc_reset_finder - place holder class for a port reset signal until it is // bound and an interface class is available. When the port // has been bound the information in this class will be used // to initialize its sc_reset object instance. //============================================================================== class SC_API sc_reset_finder { friend class sc_reset; friend class sc_simcontext; public: sc_reset_finder( bool async, const sc_in* port_p, bool level, sc_process_b* target_p); sc_reset_finder( bool async, const sc_inout* port_p, bool level, sc_process_b* target_p); sc_reset_finder( bool async, const sc_out* port_p, bool level, sc_process_b* target_p); protected: bool m_async; // True if asynchronous reset. bool m_level; // Level for reset. sc_reset_finder* m_next_p; // Next reset finder in list. const sc_in* m_in_p; // Port for which reset is needed. const sc_inout* m_inout_p; // Port for which reset is needed. const sc_out* m_out_p; // Port for which reset is needed. sc_process_b* m_target_p; // Process to reset. private: // disabled sc_reset_finder( const sc_reset_finder& ); const sc_reset_finder& operator = ( const sc_reset_finder& ); }; //============================================================================== // CLASS sc_reset - RESET INFORMATION FOR A RESET SIGNAL // // See the top of sc_reset.cpp for an explaination of how the reset mechanism // is implemented. //============================================================================== class SC_API sc_reset { friend class sc_cthread_process; friend class sc_method_process; friend class sc_module; friend class sc_process_b; friend class sc_signal; friend class sc_signal; friend class sc_signal; friend class sc_simcontext; template friend class sc_spawn_reset; friend class sc_thread_process; protected: static void reconcile_resets(sc_reset_finder* reset_finder_q); static void reset_signal_is(bool async, const sc_signal_in_if& iface, bool level); static void reset_signal_is( bool async, const sc_in& iface, bool level); static void reset_signal_is( bool async, const sc_inout& iface, bool level); static void reset_signal_is( bool async, const sc_out& iface, bool level); protected: sc_reset( const sc_signal_in_if* iface_p ) : m_iface_p(iface_p), m_targets() {} void notify_processes(); void remove_process( sc_process_b* ); protected: const sc_signal_in_if* m_iface_p; // Interface to read. std::vector m_targets; // List of processes to reset. private: // disabled sc_reset( const sc_reset& ); const sc_reset& operator = ( const sc_reset& ); }; // $Log: sc_reset.h,v $ // Revision 1.11 2011/08/26 20:46:10 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.10 2011/08/24 22:05:51 acg // Torsten Maehne: initialization changes to remove warnings. // // Revision 1.9 2011/04/08 22:38:30 acg // Andy Goodrich: added comment pointing to the description of how the // reset mechanism works that is in sc_reset.cpp. // // Revision 1.8 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.7 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.6 2011/01/06 18:00:32 acg // Andy Goodrich: Removed commented out code. // // Revision 1.5 2010/12/07 20:09:14 acg // Andy Goodrich: removed sc_signal signatures since already have sc_signal_in_if signatures. // // Revision 1.4 2010/11/20 17:10:57 acg // Andy Goodrich: reset processing changes for new IEEE 1666 standard. // // Revision 1.3 2009/05/22 16:06:29 acg // Andy Goodrich: process control updates. // // Revision 1.2 2008/05/22 17:06:26 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.6 2006/12/02 20:58:19 acg // Andy Goodrich: updates from 2.2 for IEEE 1666 support. // // Revision 1.4 2006/04/11 23:13:21 acg // Andy Goodrich: Changes for reduced reset support that only includes // sc_cthread, but has preliminary hooks for expanding to method and thread // processes also. // // Revision 1.3 2006/01/13 18:44:30 acg // Added $Log to record CVS changes into the source. } // namespace sc_core #if defined(_MSC_VER) && !defined(SC_WIN_DLL_WARN) #pragma warning(pop) #endif #endif // !defined(sc_reset_h_INCLUDED) systemc-2.3.3/src/sysc/kernel/sc_cthread_process.h0000644000175000017500000001076013360325173022133 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_cthread_process.h -- Clocked thread declarations Original Author: Andy Goodrich, Forte Design Systems, 4 August 2005 CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #if !defined(sc_cthread_process_h_INCLUDED) #define sc_cthread_process_h_INCLUDED #include "sysc/kernel/sc_thread_process.h" namespace sc_core { // friend function declarations: void SC_API halt( sc_simcontext* ); //============================================================================== // sc_cthread_process - // //============================================================================== class sc_cthread_process : public sc_thread_process { friend class sc_module; friend class sc_process_handle; friend class sc_process_table; friend class sc_thread_process; friend class sc_simcontext; friend void sc_cthread_cor_fn( void* ); friend void halt( sc_simcontext* ); public: sc_cthread_process( const char* name_p, bool free_host, SC_ENTRY_FUNC method_p, sc_process_host* host_p, const sc_spawn_options* opt_p ); virtual void dont_initialize( bool dont ); virtual const char* kind() const { return "sc_cthread_process"; } private: sc_cthread_process( const char* nm, SC_ENTRY_FUNC fn, sc_process_host* host ); // may not be deleted manually (called from sc_process_b) virtual ~sc_cthread_process(); bool eval_watchlist(); bool eval_watchlist_curr_level(); void wait_halt(); }; //------------------------------------------------------------------------------ //"sc_cthread_process::wait_halt" // //------------------------------------------------------------------------------ inline void sc_cthread_process::wait_halt() { m_wait_cycle_n = 0; suspend_me(); throw sc_halt(); } } // namespace sc_core // $Log: sc_cthread_process.h,v $ // Revision 1.8 2011/08/26 20:46:09 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.7 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.6 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.5 2011/02/11 13:25:24 acg // Andy Goodrich: Philipp A. Hartmann's changes: // (1) Removal of SC_CTHREAD method overloads. // (2) New exception processing code. // // Revision 1.4 2011/02/01 21:01:41 acg // Andy Goodrich: removed throw_reset() as it is now handled by the parent // method sc_thread_process::throw_reset(). // // Revision 1.3 2011/01/18 20:10:44 acg // Andy Goodrich: changes for IEEE1666_2011 semantics. // // Revision 1.2 2008/05/22 17:06:25 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.6 2006/05/08 17:57:13 acg // Andy Goodrich: Added David Long's forward declarations for friend functions // to keep the Microsoft C++ compiler happy. // // Revision 1.5 2006/04/20 17:08:16 acg // Andy Goodrich: 3.0 style process changes. // // Revision 1.4 2006/04/11 23:13:20 acg // Andy Goodrich: Changes for reduced reset support that only includes // sc_cthread, but has preliminary hooks for expanding to method and thread // processes also. // // Revision 1.3 2006/01/13 18:44:29 acg // Added $Log to record CVS changes into the source. // #endif // !defined(sc_cthread_process_h_INCLUDED) systemc-2.3.3/src/sysc/kernel/sc_externs.h0000644000175000017500000000422213360325173020447 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_externs.h -- Declaration of `sc_main' and other global variables. Original Author: Stan Y. Liao, Synopsys, Inc. CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #ifndef SC_EXTERNS_H #define SC_EXTERNS_H extern "C" int sc_main( int argc, char* argv[] ); namespace sc_core { extern "C" int sc_elab_and_sim( int argc, char* argv[] ); extern "C" int sc_argc(); extern "C" const char* const* sc_argv(); } // namespace sc_core // $Log: sc_externs.h,v $ // Revision 1.5 2011/08/26 20:46:09 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.4 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.3 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.2 2008/05/22 17:06:25 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.3 2006/01/13 18:44:29 acg // Added $Log to record CVS changes into the source. // #endif systemc-2.3.3/src/sysc/kernel/sc_wait_cthread.h0000644000175000017500000000700213360325173021414 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_wait_cthread.h -- Wait() and related functions for SC_CTHREADs. Original Author: Stan Y. Liao, Synopsys, Inc. Martin Janssen, Synopsys, Inc. CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #ifndef SC_WAIT_CTHREAD_H #define SC_WAIT_CTHREAD_H #include "sysc/kernel/sc_simcontext.h" #include "sysc/datatypes/bit/sc_logic.h" namespace sc_core { template class sc_signal_in_if; // for SC_CTHREADs SC_API extern void halt( sc_simcontext* = sc_get_curr_simcontext() ); SC_API extern void wait( int, sc_simcontext* = sc_get_curr_simcontext() ); extern void at_posedge( const sc_signal_in_if&, sc_simcontext* = sc_get_curr_simcontext() ); extern void at_posedge( const sc_signal_in_if&, sc_simcontext* = sc_get_curr_simcontext() ); extern void at_negedge( const sc_signal_in_if&, sc_simcontext* = sc_get_curr_simcontext() ); extern void at_negedge( const sc_signal_in_if&, sc_simcontext* = sc_get_curr_simcontext() ); } // namespace sc_core /* $Log: sc_wait_cthread.h,v $ Revision 1.6 2011/08/26 20:46:11 acg Andy Goodrich: moved the modification log to the end of the file to eliminate source line number skew when check-ins are done. Revision 1.5 2011/08/24 22:05:51 acg Torsten Maehne: initialization changes to remove warnings. Revision 1.4 2011/02/18 20:27:14 acg Andy Goodrich: Updated Copyrights. Revision 1.3 2011/02/13 21:47:38 acg Andy Goodrich: update copyright notice. Revision 1.2 2008/05/22 17:06:27 acg Andy Goodrich: updated copyright notice to include 2008. Revision 1.1.1.1 2006/12/15 20:20:05 acg SystemC 2.3 Revision 1.2 2006/01/03 23:18:45 acg Changed copyright to include 2006. Revision 1.1.1.1 2005/12/19 23:16:44 acg First check in of SystemC 2.1 into its own archive. Revision 1.10 2005/09/02 19:03:30 acg Changes for dynamic processes. Removal of lambda support. Revision 1.9 2005/04/04 00:16:08 acg Changes for directory name change to sys from systemc. Changes for sc_string going to std::string. Changes for sc_pvector going to std::vector. Changes for reference pools for bit and part selections. Changes for const sc_concatref support. Revision 1.6 2005/01/10 17:52:20 acg Addition of namespace specifications. Revision 1.5 2004/09/27 20:49:10 acg Andy Goodrich, Forte Design Systems, Inc. - Added a $Log comment so that CVS checkin comments appear in the checkout source. */ #endif systemc-2.3.3/src/sysc/kernel/sc_cor_qt.h0000644000175000017500000001013713360325173020250 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_cor_qt.h -- Coroutine implementation with QuickThreads. Original Author: Martin Janssen, Synopsys, Inc., 2001-12-18 CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #ifndef SC_COR_QT_H #define SC_COR_QT_H #if !defined(_WIN32) && !defined(WIN32) && !defined(WIN64) && !defined(SC_USE_PTHREADS) #include "sysc/kernel/sc_cor.h" #include "sysc/packages/qt/qt.h" namespace sc_core { class sc_cor_pkg_qt; typedef sc_cor_pkg_qt sc_cor_pkg_t; // ---------------------------------------------------------------------------- // CLASS : sc_cor_qt // // Coroutine class implemented with QuickThreads. // ---------------------------------------------------------------------------- class sc_cor_qt : public sc_cor { public: // constructor sc_cor_qt() : m_stack_size( 0 ), m_stack( 0 ), m_sp( 0 ), m_pkg( 0 ) {} // destructor virtual ~sc_cor_qt() { delete[] (char*) m_stack; } // switch stack protection on/off virtual void stack_protect( bool enable ); public: std::size_t m_stack_size; // stack size void* m_stack; // stack qt_t* m_sp; // stack pointer sc_cor_pkg_qt* m_pkg; // the creating coroutine package private: // disabled sc_cor_qt( const sc_cor_qt& ); sc_cor_qt& operator = ( const sc_cor_qt& ); }; // ---------------------------------------------------------------------------- // CLASS : sc_cor_pkg_qt // // Coroutine package class implemented with QuickThreads. // ---------------------------------------------------------------------------- class sc_cor_pkg_qt : public sc_cor_pkg { public: // constructor sc_cor_pkg_qt( sc_simcontext* simc ); // destructor virtual ~sc_cor_pkg_qt(); // create a new coroutine virtual sc_cor* create( std::size_t stack_size, sc_cor_fn* fn, void* arg ); // yield to the next coroutine virtual void yield( sc_cor* next_cor ); // abort the current coroutine (and resume the next coroutine) virtual void abort( sc_cor* next_cor ); // get the main coroutine virtual sc_cor* get_main(); private: static int instance_count; private: // disabled sc_cor_pkg_qt(); sc_cor_pkg_qt( const sc_cor_pkg_qt& ); sc_cor_pkg_qt& operator = ( const sc_cor_pkg_qt& ); }; } // namespace sc_core #endif // $Log: sc_cor_qt.h,v $ // Revision 1.6 2011/08/29 18:04:32 acg // Philipp A. Hartmann: miscellaneous clean ups. // // Revision 1.5 2011/08/26 20:46:09 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // // Revision 1.4 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.3 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.2 2008/05/22 17:06:25 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.3 2006/01/13 18:44:29 acg // Added $Log to record CVS changes into the source. // #endif // Taf! systemc-2.3.3/src/sysc/kernel/sc_kernel_ids.h0000644000175000017500000003372613360325173021111 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_kernel_ids.h -- Report ids for the kernel code. Original Author: Martin Janssen, Synopsys, Inc., 2002-01-17 CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #ifndef SC_KERNEL_IDS_H #define SC_KERNEL_IDS_H #include "sysc/utils/sc_report.h" // ---------------------------------------------------------------------------- // Report ids (kernel) // // Report ids in the range of 500-599. // ---------------------------------------------------------------------------- #ifndef SC_DEFINE_MESSAGE #define SC_DEFINE_MESSAGE(id,unused1,unused2) \ namespace sc_core { extern SC_API const char id[]; } namespace sc_core { extern SC_API const char SC_ID_REGISTER_ID_FAILED_[]; // in sc_report_handler.cpp } #endif SC_DEFINE_MESSAGE(SC_ID_NO_BOOL_RETURNED_ , 500, "operator does not return boolean") SC_DEFINE_MESSAGE(SC_ID_NO_INT_RETURNED_ , 501, "operator does not return int") SC_DEFINE_MESSAGE(SC_ID_NO_SC_LOGIC_RETURNED_ , 502, "operator does not return sc_logic") SC_DEFINE_MESSAGE(SC_ID_OPERAND_NOT_SC_LOGIC_ , 503, "operand is not sc_logic") SC_DEFINE_MESSAGE(SC_ID_OPERAND_NOT_BOOL_ , 504, "operand is not bool") SC_DEFINE_MESSAGE(SC_ID_INSTANCE_EXISTS_ , 505, "object already exists") SC_DEFINE_MESSAGE(SC_ID_ILLEGAL_CHARACTERS_ , 506, "illegal characters" ) SC_DEFINE_MESSAGE(SC_ID_VC6_PROCESS_HELPER_ , 507, "internal error: sc_vc6_process_helper" ) SC_DEFINE_MESSAGE(SC_ID_VC6_MAX_PROCESSES_EXCEEDED_ , 508, "maximum number of processes per module exceeded (VC6)" ) SC_DEFINE_MESSAGE(SC_ID_END_MODULE_NOT_CALLED_ , 509, "module construction not properly completed: did " "you forget to add a sc_module_name parameter to " "your module constructor?" ) SC_DEFINE_MESSAGE(SC_ID_HIER_NAME_INCORRECT_ , 510, "hierarchical name as shown may be incorrect due to previous errors" ) SC_DEFINE_MESSAGE(SC_ID_SET_STACK_SIZE_ , 511, "set_stack_size() is only allowed for SC_THREADs and SC_CTHREADs" ) SC_DEFINE_MESSAGE(SC_ID_SC_MODULE_NAME_USE_ , 512, "incorrect use of sc_module_name" ) SC_DEFINE_MESSAGE(SC_ID_SC_MODULE_NAME_REQUIRED_ , 513, "an sc_module_name parameter for your constructor is required" ) SC_DEFINE_MESSAGE(SC_ID_SET_TIME_RESOLUTION_ , 514, "set time resolution failed" ) SC_DEFINE_MESSAGE(SC_ID_SET_DEFAULT_TIME_UNIT_ , 515, "set default time unit failed" ) SC_DEFINE_MESSAGE(SC_ID_DEFAULT_TIME_UNIT_CHANGED_ , 516, "default time unit changed to time resolution" ) SC_DEFINE_MESSAGE(SC_ID_INCONSISTENT_API_CONFIG_ , 517, "inconsistent library configuration detected" ) // available message number 518 SC_DEFINE_MESSAGE(SC_ID_WAIT_NOT_ALLOWED_ , 519, "wait() is only allowed in SC_THREADs and SC_CTHREADs" ) SC_DEFINE_MESSAGE(SC_ID_NEXT_TRIGGER_NOT_ALLOWED_ , 520, "next_trigger() is only allowed in SC_METHODs" ) SC_DEFINE_MESSAGE(SC_ID_IMMEDIATE_NOTIFICATION_ , 521, "immediate notification is not allowed during update phase or elaboration" ) SC_DEFINE_MESSAGE(SC_ID_HALT_NOT_ALLOWED_ , 522, "halt() is only allowed in SC_CTHREADs" ) SC_DEFINE_MESSAGE(SC_ID_WATCHING_NOT_ALLOWED_ , 523, "watching() has been deprecated, use reset_signal_is()" ) SC_DEFINE_MESSAGE(SC_ID_DONT_INITIALIZE_ , 524, "dont_initialize() has no effect for SC_CTHREADs" ) SC_DEFINE_MESSAGE(SC_ID_WAIT_N_INVALID_ , 525, "wait(n) is only valid for n > 0" ) SC_DEFINE_MESSAGE(SC_ID_MAKE_SENSITIVE_ , 526, "make sensitive failed" ) SC_DEFINE_MESSAGE(SC_ID_MAKE_SENSITIVE_POS_ , 527, "make sensitive pos failed" ) SC_DEFINE_MESSAGE(SC_ID_MAKE_SENSITIVE_NEG_ , 528, "make sensitive neg failed" ) SC_DEFINE_MESSAGE(SC_ID_INSERT_MODULE_ , 529, "insert module failed" ) SC_DEFINE_MESSAGE(SC_ID_REMOVE_MODULE_ , 530, "remove module failed" ) SC_DEFINE_MESSAGE(SC_ID_NOTIFY_DELAYED_ , 531, "notify_delayed() cannot be called on events " "that have pending notifications" ) SC_DEFINE_MESSAGE(SC_ID_GEN_UNIQUE_NAME_ , 532, "cannot generate unique name from null string" ) SC_DEFINE_MESSAGE(SC_ID_MODULE_NAME_STACK_EMPTY_ , 533, "module name stack is empty: did you forget to " "add a sc_module_name parameter to your module " "constructor?" ) SC_DEFINE_MESSAGE(SC_ID_NAME_EXISTS_ , 534, "name already exists") SC_DEFINE_MESSAGE( SC_ID_WAIT_NEGATIVE_CYCLES_ , 535, "wait(n) not allowed for n <= 0" ) SC_DEFINE_MESSAGE( SC_ID_IMMEDIATE_SELF_NOTIFICATION_, 536, "immediate self-notification ignored as of IEEE 1666-2011" ) SC_DEFINE_MESSAGE( SC_ID_WAIT_DURING_UNWINDING_ , 537, "wait() not allowed during unwinding" ) SC_DEFINE_MESSAGE(SC_ID_CYCLE_MISSES_EVENTS_ , 538, "the simulation contains timed-events but they are " "ignored by sc_cycle() ==> the simulation will be " "incorrect" ) SC_DEFINE_MESSAGE( SC_ID_RETHROW_UNWINDING_ , 539, "sc_unwind_exception not re-thrown during kill/reset" ) SC_DEFINE_MESSAGE( SC_ID_PROCESS_ALREADY_UNWINDING_ , 540, "kill/reset ignored during unwinding" ) SC_DEFINE_MESSAGE(SC_ID_MODULE_METHOD_AFTER_START_ , 541, "call to SC_METHOD in sc_module while simulation running" ) SC_DEFINE_MESSAGE(SC_ID_MODULE_THREAD_AFTER_START_ , 542, "call to SC_THREAD in sc_module while simulation running" ) SC_DEFINE_MESSAGE(SC_ID_MODULE_CTHREAD_AFTER_START_ , 543, "call to SC_CTHREAD in sc_module while simulation running" ) SC_DEFINE_MESSAGE(SC_ID_SIMULATION_TIME_OVERFLOW_ , 544, "simulation time value overflow, simulation aborted" ) SC_DEFINE_MESSAGE(SC_ID_SIMULATION_STOP_CALLED_TWICE_ , 545, "sc_stop has already been called" ) SC_DEFINE_MESSAGE(SC_ID_SIMULATION_START_AFTER_STOP_ , 546, "sc_start called after sc_stop has been called" ) SC_DEFINE_MESSAGE(SC_ID_STOP_MODE_AFTER_START_ , 547, "attempt to set sc_stop mode after start will be ignored" ) SC_DEFINE_MESSAGE( SC_ID_SIMULATION_START_AFTER_ERROR_, 548, "attempt to restart simulation after error" ) SC_DEFINE_MESSAGE( SC_ID_SIMULATION_UNCAUGHT_EXCEPTION_, 549, "uncaught exception" ) SC_DEFINE_MESSAGE(SC_ID_PHASE_CALLBACKS_UNSUPPORTED_ , 550, "simulation phase callbacks not enabled") SC_DEFINE_MESSAGE(SC_ID_PHASE_CALLBACK_NOT_IMPLEMENTED_, 551, "empty simulation phase callback called" ) SC_DEFINE_MESSAGE(SC_ID_PHASE_CALLBACK_REGISTER_, 552, "register simulation phase callback" ) SC_DEFINE_MESSAGE(SC_ID_PHASE_CALLBACK_FORBIDDEN_, 553, "forbidden action in simulation phase callback" ) SC_DEFINE_MESSAGE( SC_ID_SIMULATION_START_UNEXPECTED_, 554, "sc_start called unexpectedly" ) // available message number 555 SC_DEFINE_MESSAGE(SC_ID_THROW_IT_IGNORED_ , 556, "throw_it on method/non-running process is being ignored " ) SC_DEFINE_MESSAGE(SC_ID_NOT_EXPECTING_DYNAMIC_EVENT_NOTIFY_ , 557, "dynamic event notification encountered when sensitivity is static" ) SC_DEFINE_MESSAGE(SC_ID_DISABLE_WILL_ORPHAN_PROCESS_ , 558, "disable() or dont_initialize() called on process with no static sensitivity, it will be orphaned" ) SC_DEFINE_MESSAGE(SC_ID_PROCESS_CONTROL_CORNER_CASE_ , 559, "Undefined process control interaction" ) SC_DEFINE_MESSAGE(SC_ID_METHOD_TERMINATION_EVENT_ , 560, "Attempt to get terminated event for a method process" ) SC_DEFINE_MESSAGE(SC_ID_JOIN_ON_METHOD_HANDLE_ , 561, "Attempt to register method process with sc_join object" ) SC_DEFINE_MESSAGE(SC_ID_NO_PROCESS_SEMANTICS_ , 563, "Attempt to invoke process with no semantics() method" ) SC_DEFINE_MESSAGE(SC_ID_EVENT_ON_NULL_PROCESS_ , 564, "Attempt to get an event for non-existent process" ) SC_DEFINE_MESSAGE(SC_ID_EVENT_LIST_FAILED_, 565, "invalid use of sc_(and|or)_event_list" ) SC_DEFINE_MESSAGE(SC_ID_UNKNOWN_PROCESS_TYPE_, 566, "Unknown process type" ) SC_DEFINE_MESSAGE(SC_ID_TIME_CONVERSION_FAILED_, 567, "sc_time conversion failed") // available number 568 SC_DEFINE_MESSAGE(SC_ID_BAD_SC_MODULE_CONSTRUCTOR_ , 569, "sc_module(const char*), sc_module(const std::string&) " "have been deprecated, use sc_module(const sc_module_name&)" ) SC_DEFINE_MESSAGE(SC_ID_EMPTY_PROCESS_HANDLE_ , 570, "attempt to use an empty process handle ignored" ) SC_DEFINE_MESSAGE(SC_ID_NO_SC_START_ACTIVITY_ , 571, "no activity or clock movement for sc_start() invocation" ) SC_DEFINE_MESSAGE(SC_ID_KILL_PROCESS_WHILE_UNITIALIZED_ , 572, "a process may not be killed before it is initialized" ) SC_DEFINE_MESSAGE(SC_ID_RESET_PROCESS_WHILE_NOT_RUNNING_ , 573, "a process may not be asynchronously reset while the simulation is not running" ) SC_DEFINE_MESSAGE(SC_ID_THROW_IT_WHILE_NOT_RUNNING_ , 574, "throw_it not allowed unless simulation is running " ) /***************************************************************************** MODIFICATION LOG - modifiers, enter your name, affiliation, date and changes you are making here. Name, Affiliation, Date: Description of Modification: *****************************************************************************/ // $Log: sc_kernel_ids.h,v $ // Revision 1.25 2011/08/26 22:06:34 acg // Torsten Maehne: formating fix. // // Revision 1.24 2011/08/07 19:08:04 acg // Andy Goodrich: moved logs to end of file so line number synching works // better between versions. // // Revision 1.23 2011/07/24 11:15:47 acg // Philipp A. Hartmann: Improvements to error/warning messages related to // process control. // // Revision 1.22 2011/05/09 04:07:48 acg // Philipp A. Hartmann: // (1) Restore hierarchy in all phase callbacks. // (2) Ensure calls to before_end_of_elaboration. // // Revision 1.21 2011/04/19 19:15:41 acg // Andy Goodrich: fix so warning message is always issued for a throw_it() // on a method process. // // Revision 1.20 2011/04/19 15:04:27 acg // Philipp A. Hartmann: clean up SC_ID messages. // // Revision 1.19 2011/04/19 02:39:09 acg // Philipp A. Hartmann: added checks for additional throws during stack unwinds. // // Revision 1.18 2011/04/05 06:23:45 acg // Andy Goodrich: comments for throws while the simulator is not running. // // Revision 1.17 2011/04/01 22:30:39 acg // Andy Goodrich: change hard assertion to warning for trigger_dynamic() // getting called when there is only STATIC sensitivity. This can result // because of sc_process_handle::throw_it(). // // Revision 1.16 2011/03/28 13:02:51 acg // Andy Goodrich: Changes for disable() interactions. // // Revision 1.15 2011/03/07 17:34:21 acg // Andy Goodrich: changed process control corner case message. Added more // place holders for unused message numbers. // // Revision 1.14 2011/03/06 19:57:11 acg // Andy Goodrich: refinements for the illegal suspend - synchronous reset // interaction. // // Revision 1.13 2011/03/06 15:56:29 acg // Andy Goodrich: added process control corner case error message, remove // unused messages. // // Revision 1.12 2011/03/05 19:44:20 acg // Andy Goodrich: changes for object and event naming and structures. // // Revision 1.11 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.10 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.9 2011/02/13 21:29:16 acg // Andy Goodrich: added error messages for throws that occur before // simulator intialization. // // Revision 1.8 2011/02/11 13:25:24 acg // Andy Goodrich: Philipp A. Hartmann's changes: // (1) Removal of SC_CTHREAD method overloads. // (2) New exception processing code. // // Revision 1.7 2011/02/07 19:17:20 acg // Andy Goodrich: changes for IEEE 1666 compatibility. // // Revision 1.6 2011/01/19 23:21:50 acg // Andy Goodrich: changes for IEEE 1666 2011 // // Revision 1.5 2010/07/30 05:21:22 acg // Andy Goodrich: release 2.3 fixes. // // Revision 1.4 2009/02/28 00:26:58 acg // Andy Goodrich: changed boost name space to sc_boost to allow use with // full boost library applications. // // Revision 1.3 2008/11/17 15:57:15 acg // Andy Goodrich: added deprecation message for sc_module(const char*) // // Revision 1.2 2008/05/22 17:06:25 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.7 2006/08/29 23:37:13 acg // Andy Goodrich: Added check for negative time. // // Revision 1.6 2006/04/20 17:08:16 acg // Andy Goodrich: 3.0 style process changes. // // Revision 1.5 2006/01/25 00:31:19 acg // Andy Goodrich: Changed over to use a standard message id of // SC_ID_IEEE_1666_DEPRECATION for all deprecation messages. // // Revision 1.4 2006/01/24 20:49:04 acg // Andy Goodrich: changes to remove the use of deprecated features within the // simulator, and to issue warning messages when deprecated features are used. // // Revision 1.3 2006/01/13 18:44:29 acg // Added $Log to record CVS changes into the source. // #endif // Taf! systemc-2.3.3/src/sysc/kernel/sc_phase_callback_registry.h0000644000175000017500000001635013360325173023630 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_phase_callback_registry.h -- Definition of the simulation phase callbacks The most critical functions are defined inline in this file. Only active, if SC_ENABLE_SIMULATION_PHASE_CALLBACKS[_TRACING] is defined during the SystemC library build. Original Author: Philipp A. Hartmann, OFFIS, 2013-02-15 CHANGE LOG AT END OF FILE *****************************************************************************/ #ifndef SC_PHASE_CALLBACK_REGISTRY_H_INCLUDED_ #define SC_PHASE_CALLBACK_REGISTRY_H_INCLUDED_ #if defined( SC_ENABLE_SIMULATION_PHASE_CALLBACKS ) \ || defined( SC_ENABLE_SIMULATION_PHASE_CALLBACKS_TRACING ) # define SC_HAS_PHASE_CALLBACKS_ 1 #else # define SC_HAS_PHASE_CALLBACKS_ 0 #endif #include "sysc/kernel/sc_simcontext.h" #include "sysc/kernel/sc_object_int.h" #include "sysc/kernel/sc_status.h" #include namespace sc_core { class sc_simcontext; class sc_object; class sc_phase_callback_registry { public: typedef sc_phase_callback_registry this_type; typedef sc_object cb_type; typedef cb_type::phase_cb_mask mask_type; struct entry { cb_type* target; mask_type mask; }; friend class sc_simcontext; friend class sc_object; private: // interface completely internal explicit sc_phase_callback_registry( sc_simcontext& simc ); ~sc_phase_callback_registry(); // --- callback forwarders bool construction_done() const; //< returns false void elaboration_done() const; void initialization_done() const; void start_simulation() const; void evaluation_done() const; void update_done() const; void before_timestep() const; void simulation_paused() const; void simulation_stopped() const; void simulation_done() const; // --- callback registration and implementation mask_type register_callback( cb_type&, mask_type mask ); mask_type unregister_callback( cb_type&, mask_type mask ); // generic caller void do_callback( sc_status ) const; private: typedef std::vector storage_type; typedef std::vector single_storage_type; #if SC_HAS_PHASE_CALLBACKS_ // set and restore simulation status struct scoped_status { scoped_status( sc_status& ref, sc_status s ) : ref_(ref), prev_(ref) { ref_ = s;} ~scoped_status() { ref_ = prev_; } private: sc_status& ref_; sc_status prev_; }; // scoped_status mask_type validate_mask( cb_type&, mask_type, bool warn ); private: sc_simcontext* m_simc; storage_type m_cb_vec; // all callbacks #if 0 single_storage_type m_cb_eval_vec; // - eval cb shortcut #endif single_storage_type m_cb_update_vec; // - update cb shortcut single_storage_type m_cb_timestep_vec; // - timestep cb shortcut #endif // SC_HAS_PHASE_CALLBACKS_ private: // disabled sc_phase_callback_registry( const this_type& ); this_type& operator=(const this_type&); }; // sc_phase_callback_registry // -------------------- callback implementations -------------------- // (empty, if feature is disabled) inline bool sc_phase_callback_registry::construction_done() const { #if SC_HAS_PHASE_CALLBACKS_ do_callback( SC_BEFORE_END_OF_ELABORATION ); #endif return false; } inline void sc_phase_callback_registry::elaboration_done() const { #if SC_HAS_PHASE_CALLBACKS_ do_callback( SC_END_OF_ELABORATION ); #endif } inline void sc_phase_callback_registry::start_simulation() const { #if SC_HAS_PHASE_CALLBACKS_ do_callback( SC_START_OF_SIMULATION ); #endif } inline void sc_phase_callback_registry::initialization_done() const { #if SC_HAS_PHASE_CALLBACKS_ scoped_status scope( m_simc->m_simulation_status , SC_END_OF_INITIALIZATION ); do_callback( SC_END_OF_INITIALIZATION ); #endif } inline void sc_phase_callback_registry::simulation_paused() const { #if SC_HAS_PHASE_CALLBACKS_ do_callback( SC_PAUSED ); #endif } inline void sc_phase_callback_registry::simulation_stopped() const { #if SC_HAS_PHASE_CALLBACKS_ do_callback( SC_STOPPED ); #endif } inline void sc_phase_callback_registry::simulation_done() const { #if SC_HAS_PHASE_CALLBACKS_ do_callback( SC_END_OF_SIMULATION ); #endif } // -------------- specialized callback implementations -------------- #if 0 inline void sc_phase_callback_registry::evaluation_done() const { #if SC_HAS_PHASE_CALLBACKS_ if( !m_cb_eval_vec.size() ) return; typedef single_storage_type::const_iterator it_type; single_storage_type const & vec = m_cb_eval_vec; scoped_status scope( m_simc->m_simulation_status , SC_END_OF_EVALUATION ); for(it_type it = vec.begin(), end = vec.end(); it != end; ++it) (*it)->do_simulation_phase_callback(); #endif } #endif inline void sc_phase_callback_registry::update_done() const { #if SC_HAS_PHASE_CALLBACKS_ if( !m_cb_update_vec.size() ) return; typedef single_storage_type::const_iterator it_type; single_storage_type const & vec = m_cb_update_vec; scoped_status scope( m_simc->m_simulation_status , SC_END_OF_UPDATE ); for(it_type it = vec.begin(), end = vec.end(); it != end; ++it) (*it)->do_simulation_phase_callback(); #endif } inline void sc_phase_callback_registry::before_timestep() const { #if SC_HAS_PHASE_CALLBACKS_ if( !m_cb_timestep_vec.size() ) return; typedef single_storage_type::const_iterator it_type; single_storage_type const & vec = m_cb_timestep_vec; scoped_status scope( m_simc->m_simulation_status , SC_BEFORE_TIMESTEP ); for(it_type it = vec.begin(), end = vec.end(); it != end; ++it) (*it)->do_simulation_phase_callback(); #endif } // ------------------------------------------------------------------ } // namespace sc_core /***************************************************************************** MODIFICATION LOG - modifiers, enter your name, affiliation, date and changes you are making here. Name, Affiliation, Date: Description of Modification: *****************************************************************************/ #endif /* SC_PHASE_CALLBACK_REGISTRY_H_INCLUDED_ */ // Taf! systemc-2.3.3/src/sysc/kernel/sc_method_process.h0000644000175000017500000003566413360325173022013 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_method_process.h -- Method process declarations Original Author: Andy Goodrich, Forte Design Systems, 4 August 2005 CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ // $Log: sc_method_process.h,v $ // Revision 1.23 2011/09/05 21:20:22 acg // Andy Goodrich: result of automake invocation. // // Revision 1.22 2011/08/29 18:04:32 acg // Philipp A. Hartmann: miscellaneous clean ups. // // Revision 1.21 2011/08/26 20:46:10 acg // Andy Goodrich: moved the modification log to the end of the file to // eliminate source line number skew when check-ins are done. // #if !defined(sc_method_process_h_INCLUDED) #define sc_method_process_h_INCLUDED #include "sysc/kernel/sc_process.h" #include "sysc/kernel/sc_spawn_options.h" #include "sysc/kernel/sc_cor.h" #include "sysc/kernel/sc_event.h" #include "sysc/kernel/sc_except.h" // DEBUGGING MACROS: // // DEBUG_MSG(NAME,P,MSG) // MSG = message to print // NAME = name that must match the process for the message to print, or // null if the message should be printed unconditionally. // P = pointer to process message is for, or NULL in which case the // message will not print. #if 0 # include # define DEBUG_NAME "" # define DEBUG_MSG(NAME,P,MSG) \ { \ if ( P && ( (std::strlen(NAME)==0) || !std::strcmp(NAME,P->name())) ) \ std::cout << "**** " << sc_time_stamp() << " (" \ << sc_get_current_process_name("** NONE **") << "): " << MSG \ << " - " << P->name() << std::endl; \ } #else # define DEBUG_MSG(NAME,P,MSG) #endif namespace sc_core { // forward function and class declarations: void sc_method_cor_fn( void* ); void sc_cmethod_cor_fn( void* ); SC_API void sc_set_stack_size( sc_method_handle, std::size_t ); class sc_event; class sc_module; class sc_process_table; class sc_process_handle; class sc_simcontext; class sc_runnable; SC_API void next_trigger( sc_simcontext* ); SC_API void next_trigger( const sc_event&, sc_simcontext* ); SC_API void next_trigger( const sc_event_or_list&, sc_simcontext* ); SC_API void next_trigger( const sc_event_and_list&, sc_simcontext* ); SC_API void next_trigger( const sc_time&, sc_simcontext* ); SC_API void next_trigger( const sc_time&, const sc_event&, sc_simcontext* ); SC_API void next_trigger( const sc_time&, const sc_event_or_list&, sc_simcontext* ); SC_API void next_trigger( const sc_time&, const sc_event_and_list&, sc_simcontext* ); struct sc_invoke_method; //============================================================================== // sc_method_process - // //============================================================================== class sc_method_process : public sc_process_b { friend struct sc_invoke_method; friend void sc_method_cor_fn( void* ); friend void sc_cmethod_cor_fn( void* ); friend void sc_set_stack_size( sc_method_handle, std::size_t ); friend class sc_event; friend class sc_module; friend class sc_process_table; friend class sc_process_handle; friend class sc_simcontext; friend class sc_runnable; friend void next_trigger( sc_simcontext* ); friend void next_trigger( const sc_event&, sc_simcontext* ); friend void next_trigger( const sc_event_or_list&, sc_simcontext* ); friend void next_trigger( const sc_event_and_list&, sc_simcontext* ); friend void next_trigger( const sc_time&, sc_simcontext* ); friend void next_trigger( const sc_time&, const sc_event&, sc_simcontext* ); friend void next_trigger( const sc_time&, const sc_event_or_list&, sc_simcontext* ); friend void next_trigger( const sc_time&, const sc_event_and_list&, sc_simcontext* ); public: sc_method_process( const char* name_p, bool free_host, SC_ENTRY_FUNC method_p, sc_process_host* host_p, const sc_spawn_options* opt_p ); virtual const char* kind() const { return "sc_method_process"; } protected: void check_for_throws(); virtual void disable_process( sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); virtual void enable_process( sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); inline bool run_process(); virtual void kill_process( sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); sc_method_handle next_exist(); sc_method_handle next_runnable(); void clear_trigger(); void next_trigger( const sc_event& ); void next_trigger( const sc_event_or_list& ); void next_trigger( const sc_event_and_list& ); void next_trigger( const sc_time& ); void next_trigger( const sc_time&, const sc_event& ); void next_trigger( const sc_time&, const sc_event_or_list& ); void next_trigger( const sc_time&, const sc_event_and_list& ); virtual void resume_process( sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); void set_next_exist( sc_method_handle next_p ); void set_next_runnable( sc_method_handle next_p ); void set_stack_size( std::size_t size ); virtual void suspend_process( sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); virtual void throw_reset( bool async ); virtual void throw_user( const sc_throw_it_helper& helper, sc_descendant_inclusion_info descendants = SC_NO_DESCENDANTS ); bool trigger_dynamic( sc_event* ); inline void trigger_static(); protected: sc_cor* m_cor; // Thread's coroutine. std::size_t m_stack_size; // Thread stack size. std::vector m_monitor_q; // Thread monitors. private: // may not be deleted manually (called from sc_process_b) virtual ~sc_method_process(); private: // disabled sc_method_process( const sc_method_process& ); const sc_method_process& operator = ( const sc_method_process& ); }; inline void sc_method_process::next_trigger( const sc_event& e ) { clear_trigger(); e.add_dynamic( this ); m_event_p = &e; m_trigger_type = EVENT; } inline void sc_method_process::next_trigger( const sc_event_or_list& el ) { clear_trigger(); el.add_dynamic( this ); m_event_list_p = ⪙ m_trigger_type = OR_LIST; } inline void sc_method_process::next_trigger( const sc_event_and_list& el ) { clear_trigger(); el.add_dynamic( this ); m_event_list_p = ⪙ m_event_count = el.size(); m_trigger_type = AND_LIST; } inline void sc_method_process::next_trigger( const sc_time& t ) { clear_trigger(); m_timeout_event_p->notify_internal( t ); m_timeout_event_p->add_dynamic( this ); m_trigger_type = TIMEOUT; } inline void sc_method_process::next_trigger( const sc_time& t, const sc_event& e ) { clear_trigger(); m_timeout_event_p->notify_internal( t ); m_timeout_event_p->add_dynamic( this ); e.add_dynamic( this ); m_event_p = &e; m_trigger_type = EVENT_TIMEOUT; } inline void sc_method_process::next_trigger( const sc_time& t, const sc_event_or_list& el ) { clear_trigger(); m_timeout_event_p->notify_internal( t ); m_timeout_event_p->add_dynamic( this ); el.add_dynamic( this ); m_event_list_p = ⪙ m_trigger_type = OR_LIST_TIMEOUT; } inline void sc_method_process::next_trigger( const sc_time& t, const sc_event_and_list& el ) { clear_trigger(); m_timeout_event_p->notify_internal( t ); m_timeout_event_p->add_dynamic( this ); el.add_dynamic( this ); m_event_list_p = ⪙ m_event_count = el.size(); m_trigger_type = AND_LIST_TIMEOUT; } inline void sc_method_process::set_next_exist(sc_method_handle next_p) { m_exist_p = next_p; } inline sc_method_handle sc_method_process::next_exist() { return (sc_method_handle)m_exist_p; } inline void sc_method_process::set_next_runnable(sc_method_handle next_p) { m_runnable_p = next_p; } inline sc_method_handle sc_method_process::next_runnable() { return (sc_method_handle)m_runnable_p; } // +---------------------------------------------------------------------------- // |"sc_method_process::run_process" // | // | This method executes this object instance, including fielding exceptions. // | // | Result is false if an unfielded exception occurred, true if not. // +---------------------------------------------------------------------------- inline bool sc_method_process::run_process() { // Execute this object instance's semantics and catch any exceptions that // are generated: bool restart = false; do { try { DEBUG_MSG(DEBUG_NAME,this,"executing method semantics"); semantics(); restart = false; } catch( sc_unwind_exception& ex ) { DEBUG_MSG(DEBUG_NAME,this,"caught unwind exception"); ex.clear(); restart = ex.is_reset(); } catch( ... ) { sc_report* err_p = sc_handle_exception(); simcontext()->set_error( err_p ); return false; } } while( restart ); return true; } //------------------------------------------------------------------------------ //"sc_method_process::trigger_static" // // This inline method adds the current method to the queue of runnable // processes, if required. This is the case if the following criteria // are met: // (1) The process is in a runnable state. // (2) The process is not already on the run queue. // (3) The process is expecting a static trigger, // dynamic event waits take priority. // // // If the triggering process is the same process, the trigger is // ignored as well, unless SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS // is defined. //------------------------------------------------------------------------------ inline void sc_method_process::trigger_static() { if ( (m_state & ps_bit_disabled) || is_runnable() || m_trigger_type != STATIC ) return; #if ! defined( SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS ) if( SC_UNLIKELY_( sc_get_current_process_b() == this ) ) { report_immediate_self_notification(); return; } #endif // SC_ENABLE_IMMEDIATE_SELF_NOTIFICATIONS // If we get here then the method is has satisfied its wait, if its // suspended mark its state as ready to run. If its not suspended then // push it onto the runnable queue. if ( m_state & ps_bit_suspended ) { m_state = m_state | ps_bit_ready_to_run; } else { simcontext()->push_runnable_method(this); } } #undef DEBUG_MSG } // namespace sc_core // Revision 1.20 2011/08/24 22:05:50 acg // Torsten Maehne: initialization changes to remove warnings. // // Revision 1.19 2011/07/29 22:43:15 acg // Andy Goodrich: addition of check_for_throws() method. // // Revision 1.18 2011/07/24 11:18:09 acg // Philipp A. Hartmann: add code to restart a method process after a // self-reset. // // Revision 1.17 2011/05/09 04:07:48 acg // Philipp A. Hartmann: // (1) Restore hierarchy in all phase callbacks. // (2) Ensure calls to before_end_of_elaboration. // // Revision 1.16 2011/04/13 02:41:34 acg // Andy Goodrich: eliminate warning messages generated when the DEBUG_MSG // macro is used. // // Revision 1.15 2011/04/10 22:12:32 acg // Andy Goodrich: adding debugging macros. // // Revision 1.14 2011/04/08 22:31:21 acg // Andy Goodrich: added new inline method run_process() to hide the process // implementation for sc_simcontext. // // Revision 1.13 2011/04/05 20:50:56 acg // Andy Goodrich: // (1) changes to make sure that event(), posedge() and negedge() only // return true if the clock has not moved. // (2) fixes for method self-resumes. // (3) added SC_PRERELEASE_VERSION // (4) removed kernel events from the object hierarchy, added // sc_hierarchy_name_exists(). // // Revision 1.12 2011/04/01 21:24:57 acg // Andy Goodrich: removed unused code. // // Revision 1.11 2011/02/19 08:30:53 acg // Andy Goodrich: Moved process queueing into trigger_static from // sc_event::notify. // // Revision 1.10 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.9 2011/02/17 19:51:34 acg // Andy Goodrich: // (1) Changed the signature of trigger_dynamic back to a bool. // (2) Removed ready_to_run(). // (3) Simplified process control usage. // // Revision 1.8 2011/02/16 22:37:30 acg // Andy Goodrich: clean up to remove need for ps_disable_pending. // // Revision 1.7 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.6 2011/02/01 21:05:05 acg // Andy Goodrich: Changes in trigger_dynamic methods to handle new // process control rules about event sensitivity. // // Revision 1.5 2011/01/18 20:10:44 acg // Andy Goodrich: changes for IEEE1666_2011 semantics. // // Revision 1.4 2009/07/28 01:10:53 acg // Andy Goodrich: updates for 2.3 release candidate. // // Revision 1.3 2009/05/22 16:06:29 acg // Andy Goodrich: process control updates. // // Revision 1.2 2008/05/22 17:06:25 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.7 2006/05/08 17:57:13 acg // Andy Goodrich: Added David Long's forward declarations for friend functions // to keep the Microsoft C++ compiler happy. // // Revision 1.6 2006/04/20 17:08:17 acg // Andy Goodrich: 3.0 style process changes. // // Revision 1.5 2006/04/11 23:13:21 acg // Andy Goodrich: Changes for reduced reset support that only includes // sc_cthread, but has preliminary hooks for expanding to method and thread // processes also. // // Revision 1.4 2006/01/24 20:49:05 acg // Andy Goodrich: changes to remove the use of deprecated features within the // simulator, and to issue warning messages when deprecated features are used. // // Revision 1.3 2006/01/13 18:44:29 acg // Added $Log to record CVS changes into the source. #endif // !defined(sc_method_process_h_INCLUDED) systemc-2.3.3/src/sysc/kernel/sc_process.cpp0000644000175000017500000007033513360325173021000 0ustar carstencarsten/***************************************************************************** Licensed to Accellera Systems Initiative Inc. (Accellera) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. Accellera licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ /***************************************************************************** sc_process.cpp -- Base process implementation. Original Authors: Andy Goodrich, Forte Design Systems, 17 June 2003 Stuart Swan, Cadence Bishnupriya Bhattacharya, Cadence Design Systems, 25 August, 2003 CHANGE LOG AT THE END OF THE FILE *****************************************************************************/ #include "sysc/kernel/sc_name_gen.h" #include "sysc/kernel/sc_cthread_process.h" #include "sysc/kernel/sc_method_process.h" #include "sysc/kernel/sc_thread_process.h" #include "sysc/kernel/sc_sensitive.h" #include "sysc/kernel/sc_process_handle.h" #include "sysc/kernel/sc_event.h" #include namespace sc_core { // sc_process_handle entities that are returned for null pointer instances: // // Note the special name for 'non_event' - this makes sure it does not // appear as a named event. std::vector sc_process_handle::empty_event_vector; std::vector sc_process_handle::empty_object_vector; sc_event sc_process_handle::non_event( sc_event::kernel_event ); // Last process that was created: sc_process_b* sc_process_b::m_last_created_process_p = 0; //------------------------------------------------------------------------------ //"sc_process_b::add_static_event" // // This method adds an event to the list of static events, and sets the // event up to call back this process when it fires. //------------------------------------------------------------------------------ void sc_process_b::add_static_event( const sc_event& e ) { sc_method_handle method_h; // This process as a method. sc_thread_handle thread_h; // This process as a thread. // CHECK TO SEE IF WE ARE ALREADY REGISTERED WITH THE EVENT: for( int i = m_static_events.size() - 1; i >= 0; -- i ) { if( &e == m_static_events[i] ) { return; } } // REMEMBER THE EVENT AND THEN REGISTER OUR OBJECT INSTANCE WITH IT: m_static_events.push_back( &e ); switch ( m_process_kind ) { case SC_THREAD_PROC_: case SC_CTHREAD_PROC_: thread_h = static_cast( this ); e.add_static( thread_h ); break; case SC_METHOD_PROC_: method_h = static_cast( this ); e.add_static( method_h ); break; default: sc_assert( false ); break; } } //------------------------------------------------------------------------------ //"sc_process_b::disconnect_process" // // This method removes this object instance from use. It will be called by // the kill_process() methods of classes derived from it. This object instance // will be removed from any data structures it resides, other than existence. //------------------------------------------------------------------------------ void sc_process_b::disconnect_process() { int mon_n; // monitor queue size. sc_thread_handle thread_h; // This process as a thread. // IF THIS OBJECT IS PINING FOR THE FJORDS WE ARE DONE: if ( m_state & ps_bit_zombie ) return; // IF THIS IS A THREAD SIGNAL ANY MONITORS WAITING FOR IT TO EXIT: switch ( m_process_kind ) { case SC_THREAD_PROC_: case SC_CTHREAD_PROC_: thread_h = static_cast(this); mon_n = thread_h->m_monitor_q.size(); if ( mon_n ) { for ( int mon_i = 0; mon_i < mon_n; mon_i++ ) { thread_h->m_monitor_q[mon_i]->signal( thread_h, sc_process_monitor::spm_exit); } } break; default: break; } // REMOVE EVENT WAITS, AND REMOVE THE PROCESS FROM ITS SC_RESET: remove_dynamic_events(); remove_static_events(); for ( std::vector::size_type rst_i = 0; rst_i < m_resets.size(); rst_i++ ) { m_resets[rst_i]->remove_process( this ); } m_resets.resize(0); // FIRE THE TERMINATION EVENT, MARK AS TERMINATED, AND DECREMENT THE COUNT: // // (1) We wait to set the process kind until after doing the removals // above. // (2) Decrementing the reference count will result in actual object // deletion if we hit zero. m_state = ps_bit_zombie; if ( m_term_event_p ) m_term_event_p->notify(); reference_decrement(); } //------------------------------------------------------------------------------ //"sc_process_b::delete_process" // // This method deletes the current instance, if it is not the running // process. Otherwise, it is put in the simcontext's process deletion // queue. // // The reason for the two step deletion process is that the process from which // reference_decrement() is called may be the running process, so we may need // to wait until it goes idle. //------------------------------------------------------------------------------ void sc_process_b::delete_process() { sc_assert( m_references_n == 0 ); // Immediate deletion: if ( NULL == sc_get_current_process_b() ) { delete this; } // Deferred deletion: note we set the reference count to one for the call // to reference_decrement that occurs in sc_simcontext::crunch(). else { m_references_n = 1; detach(); simcontext()->mark_to_collect_process( this ); } } //------------------------------------------------------------------------------ //"sc_process_b::dont_initialize" // // This virtual method sets the initialization switch for this object instance. //------------------------------------------------------------------------------ void sc_process_b::dont_initialize( bool dont ) { m_dont_init = dont; } //------------------------------------------------------------------------------ //"sc_process_b::dump_state" // // This method returns the process state as a string. //------------------------------------------------------------------------------ std::string sc_process_b::dump_state() const { std::string result; result = "["; if ( m_state == ps_normal ) { result += " normal"; } else { if ( m_state & ps_bit_disabled ) result += "disabled "; if ( m_state & ps_bit_suspended ) result += "suspended "; if ( m_state & ps_bit_ready_to_run ) result += "ready_to_run "; if ( m_state & ps_bit_zombie ) result += "zombie "; } result += "]"; return result; } //------------------------------------------------------------------------------ //"sc_process_b::gen_unique_name" // // This method generates a unique name within this object instance's namespace. //------------------------------------------------------------------------------ const char* sc_process_b::gen_unique_name( const char* basename_, bool preserve_first ) { if ( ! m_name_gen_p ) m_name_gen_p = new sc_name_gen; return m_name_gen_p->gen_unique_name( basename_, preserve_first ); } //------------------------------------------------------------------------------ //"sc_process_b::remove_dynamic_events" // // This method removes this object instance from the events in its dynamic // event lists. // // Arguments: // skip_timeout = skip cleaning up the timeout event, it will be done // by sc_event_notify(). //------------------------------------------------------------------------------ void sc_process_b::remove_dynamic_events( bool skip_timeout ) { sc_method_handle method_h; // This process as a method. sc_thread_handle thread_h; // This process as a thread. m_trigger_type = STATIC; switch ( m_process_kind ) { case SC_THREAD_PROC_: case SC_CTHREAD_PROC_: thread_h = static_cast(this); if ( thread_h->m_timeout_event_p && !skip_timeout ) { thread_h->m_timeout_event_p->remove_dynamic(thread_h); thread_h->m_timeout_event_p->cancel(); } if ( m_event_p ) { m_event_p->remove_dynamic( thread_h ); m_event_p = 0; } if ( m_event_list_p ) { m_event_list_p->remove_dynamic( thread_h, 0 ); m_event_list_p->auto_delete(); m_event_list_p = 0; } break; case SC_METHOD_PROC_: method_h = static_cast(this); if ( method_h->m_timeout_event_p && !skip_timeout ) { method_h->m_timeout_event_p->remove_dynamic(method_h); method_h->m_timeout_event_p->cancel(); } if ( m_event_p ) { m_event_p->remove_dynamic( method_h ); m_event_p = 0; } if ( m_event_list_p ) { m_event_list_p->remove_dynamic( method_h, 0 ); m_event_list_p->auto_delete(); m_event_list_p = 0; } break; default: // Some other type, it needs to clean up itself. // std::cout << "Check " << __FILE__ << ":" << __LINE__ << std::endl; break; } } //------------------------------------------------------------------------------ //"sc_process_b::remove_static_events" // // This method removes this object instance from the events in its static // event list. //------------------------------------------------------------------------------ void sc_process_b::remove_static_events() { sc_method_handle method_h; // This process as a method. sc_thread_handle thread_h; // This process as a thread. switch ( m_process_kind ) { case SC_THREAD_PROC_: case SC_CTHREAD_PROC_: thread_h = static_cast( this ); for( int i = m_static_events.size() - 1; i >= 0; -- i ) { m_static_events[i]->remove_static( thread_h ); } m_static_events.resize(0); break; case SC_METHOD_PROC_: method_h = static_cast( this ); for( int i = m_static_events.size() - 1; i >= 0; -- i ) { m_static_events[i]->remove_static( method_h ); } m_static_events.resize(0); break; default: // Some other type, it needs to clean up itself. // std::cout << "Check " << __FILE__ << ":" << __LINE__ << std::endl; break; } } //------------------------------------------------------------------------------ // "sc_process_b::report_error" // // This method can be used to issue a report from within a process. // The error of the given ID is reported with the given message and // the process' name() appended to the report. //------------------------------------------------------------------------------ void sc_process_b::report_error( const char* msgid, const char* msg ) const { std::stringstream sstr; if( msg && msg[0] ) sstr << msg << ": "; sstr << name(); SC_REPORT_ERROR( msgid, sstr.str().c_str() ); } //------------------------------------------------------------------------------ // "sc_process_b::report_immediate_self_notification" // // This method is used to report an immediate self-notification // that used to trigger the process before the clarification in 1666-2011. // The warning is only reported once. //------------------------------------------------------------------------------ void sc_process_b::report_immediate_self_notification() const { static bool once = false; if( !once ) { SC_REPORT_WARNING( SC_ID_IMMEDIATE_SELF_NOTIFICATION_, name() ); once = true; } } //------------------------------------------------------------------------------ //"sc_process_b::reset_changed" // // This method is called when there is a change in the value of the // signal that was specified via reset_signal_is, or the value of the // m_sticky_reset field. We get called any time m_sticky_reset changes // or a signal value changes since, since we may need to throw an exception // or clear one. Note that this method may be called when there is no // active process, but rather the main simulator is executing so we must // check for that case. // // Arguments: // async = true if this is an asynchronous reset. // asserted = true if reset being asserted, false if being deasserted. //------------------------------------------------------------------------------ void sc_process_b::reset_changed( bool async, bool asserted ) { // Error out on the corner case: if ( !sc_allow_process_control_corners && !async && (m_state & ps_bit_suspended) ) { report_error( SC_ID_PROCESS_CONTROL_CORNER_CASE_, "synchronous reset changed on a suspended process" ); } // IF THIS OBJECT IS PUSHING UP DAISIES WE ARE DONE: if ( m_state & ps_bit_zombie ) return; // Reset is being asserted: if ( asserted ) { // if ( m_reset_event_p ) m_reset_event_p->notify(); if ( async ) { m_active_areset_n++; if ( sc_is_running() ) throw_reset(true); } else { m_active_reset_n++; if ( sc_is_running() ) throw_reset(false); } } // Reset is being deasserted: else { if ( async ) { m_active_areset_n--; } else { m_active_reset_n--; } } // Clear the throw type if there are no active resets. if ( (m_throw_status == THROW_SYNC_RESET || m_throw_status == THROW_ASYNC_RESET) && m_active_areset_n == 0 && m_active_reset_n == 0 && !m_sticky_reset ) { m_throw_status = THROW_NONE; } } //------------------------------------------------------------------------------ //"sc_process_b::reset_event" // // This method returns a reference to the reset event for this object // instance. If no event exists one is allocated. //------------------------------------------------------------------------------ sc_event& sc_process_b::reset_event() { if ( !m_reset_event_p ) { m_reset_event_p = new sc_event( sc_event::kernel_event, "reset_event" ); } return *m_reset_event_p; } //------------------------------------------------------------------------------ //"sc_process_b::reset_process" // // This inline method changes the reset state of this object instance and // conditionally its descendants. // // Notes: // (1) It is called for sync_reset_on() and sync_reset_off(). It is not used // for signal sensitive resets, though all reset flow ends up in // reset_changed(). // // Arguments: // rt = source of the reset: // * reset_asynchronous - sc_process_handle::reset() // * reset_synchronous_off - sc_process_handle::sync_reset_off() // * reset_synchronous_on - sc_process_handle::sync_reset_on() // descendants = indication of how to process descendants. //------------------------------------------------------------------------------ void sc_process_b::reset_process( reset_type rt, sc_descendant_inclusion_info descendants ) { // PROCESS THIS OBJECT INSTANCE'S DESCENDANTS IF REQUESTED TO: if ( descendants == SC_INCLUDE_DESCENDANTS ) { const std::vector children = get_child_objects(); int child_n = children.size(); for ( int child_i = 0; child_i < child_n; child_i++ ) { sc_process_b* child_p = dynamic_cast(children[child_i]); if ( child_p ) child_p->reset_process(rt, descendants); } } // PROCESS THIS OBJECT INSTANCE: switch (rt) { // One-shot asynchronous reset: remove dynamic sensitivity and throw: // // If this is an sc_method only throw if it is active. case reset_asynchronous: if ( sc_get_status() != SC_RUNNING ) { report_error(SC_ID_RESET_PROCESS_WHILE_NOT_RUNNING_); } else { remove_dynamic_events(); throw_reset(true); } break; // Turn on sticky synchronous reset: use standard reset mechanism. case reset_synchronous_on: if ( m_sticky_reset == false ) { m_sticky_reset = true; reset_changed( false, true ); } break; // Turn off sticky synchronous reset: use standard reset mechanism. default: if ( m_sticky_reset == true ) { m_sticky_reset = false; reset_changed( false, false ); } break; } } //------------------------------------------------------------------------------ //"sc_process_b::sc_process_b" // // This is the object instance constructor for this class. //------------------------------------------------------------------------------ sc_process_b::sc_process_b( const char* name_p, bool is_thread, bool free_host, SC_ENTRY_FUNC method_p, sc_process_host* host_p, const sc_spawn_options* /* opt_p */ ) : sc_object( name_p ), file(0), lineno(0), proc_id( simcontext()->next_proc_id()), m_active_areset_n(0), m_active_reset_n(0), m_dont_init( false ), m_dynamic_proc(), m_event_p(0), m_event_count(0), m_event_list_p(0), m_exist_p(0), m_free_host( free_host ), m_has_reset_signal( false ), m_has_stack(false), m_is_thread(is_thread), m_last_report_p(0), m_name_gen_p(0), m_process_kind(SC_NO_PROC_), m_references_n(1), m_resets(), m_reset_event_p(0), m_resume_event_p(0), m_runnable_p(0), m_semantics_host_p( host_p ), m_semantics_method_p ( method_p ), m_state(ps_normal), m_static_events(), m_sticky_reset(false), m_term_event_p(0), m_throw_helper_p(0), m_throw_status( THROW_NONE ), m_timed_out(false), m_timeout_event_p(0), m_trigger_type(STATIC), m_unwinding(false) { // Check spawn phase: m_ready_to_simulate is set *after* elaboration_done() unsigned spawned = SPAWN_ELAB; spawned += simcontext()->elaboration_done(); // -> SPAWN_START, if true spawned += simcontext()->m_ready_to_simulate; // -> SPAWN_SIM, if true m_dynamic_proc = static_cast(spawned); // THIS OBJECT INSTANCE IS NOW THE LAST CREATED PROCESS: m_last_created_process_p = this; m_timeout_event_p = new sc_event( sc_event::kernel_event, "free_event" ); } //------------------------------------------------------------------------------ //"sc_process_b::~sc_process_b" // // This is the object instance destructor for this class. //------------------------------------------------------------------------------ sc_process_b::~sc_process_b() { // REDIRECT ANY CHILDREN AS CHILDREN OF THE SIMULATION CONTEXT: orphan_child_objects(); // DELETE SEMANTICS OBJECTS IF NEED BE: if ( m_free_host ) delete m_semantics_host_p; # if !defined(SC_USE_MEMBER_FUNC_PTR) // Remove invocation object. delete m_semantics_method_p; # endif // REMOVE ANY STRUCTURES THAT MAY HAVE BEEN BUILT: delete m_last_report_p; delete m_name_gen_p; delete m_reset_event_p; delete m_resume_event_p; delete m_term_event_p; delete m_throw_helper_p; delete m_timeout_event_p; } //------------------------------------------------------------------------------ //"sc_process_b::terminated_event" // // This method returns a reference to the terminated event for this object // instance. If no event exists one is allocated. //------------------------------------------------------------------------------ sc_event& sc_process_b::terminated_event() { if ( !m_term_event_p ) { m_term_event_p = new sc_event( sc_event::kernel_event, "term_event" ); } return *m_term_event_p; } // +---------------------------------------------------------------------------- // |"sc_process_b::trigger_reset_event" // | // | This method triggers the notify event. It exists because we can't get // | sc_event context in sc_process.h because the includes would be // | circular... sigh... // +---------------------------------------------------------------------------- void sc_process_b::trigger_reset_event() { if ( m_reset_event_p ) m_reset_event_p->notify(); } //------------------------------------------------------------------------------ //"sc_process_handle::operator sc_cthread_handle" // //------------------------------------------------------------------------------ sc_process_handle::operator sc_cthread_handle() { return dynamic_cast(m_target_p); } //------------------------------------------------------------------------------ //"sc_process_handle::sc_method_handle" // //------------------------------------------------------------------------------ sc_process_handle::operator sc_method_handle() { return dynamic_cast(m_target_p); } //------------------------------------------------------------------------------ //"sc_process_handle::sc_thread_handle" // //------------------------------------------------------------------------------ sc_process_handle::operator sc_thread_handle() { return dynamic_cast(m_target_p); } } // namespace sc_core /***************************************************************************** MODIFICATION LOG - modifiers, enter your name, affiliation, date and changes you are making here. Name, Affiliation, Date: Andy Goodrich, Forte Design Systems, 12 Aug 05 Description of Modification: This is the rewrite of process support. It contains some code from the now-defunct sc_process_b.cpp, as well as the former version of sc_process_b.cpp. Name, Affiliation, Date: Description of Modification: *****************************************************************************/ // $Log: sc_process.cpp,v $ // Revision 1.37 2011/08/24 22:05:51 acg // Torsten Maehne: initialization changes to remove warnings. // // Revision 1.36 2011/08/15 16:43:24 acg // Torsten Maehne: changes to remove unused argument warnings. // // Revision 1.35 2011/08/07 19:08:04 acg // Andy Goodrich: moved logs to end of file so line number synching works // better between versions. // // Revision 1.34 2011/07/29 22:55:01 acg // Philipp A. Hartmann: add missing include. // // Revision 1.33 2011/07/29 22:43:41 acg // Philipp A. Hartmann: changes to handle case where a process control // invocation on a child process causes the list of child processes to change. // // Revision 1.32 2011/07/24 11:20:03 acg // Philipp A. Hartmann: process control error message improvements: // (1) Downgrade error to warning for re-kills of processes. // (2) Add process name to process messages. // (3) drop some superfluous colons in messages. // // Revision 1.31 2011/04/19 15:04:27 acg // Philipp A. Hartmann: clean up SC_ID messages. // // Revision 1.30 2011/04/14 22:33:43 acg // Andy Goodrich: added missing checks for a process being a zombie. // // Revision 1.29 2011/04/13 05:00:43 acg // Andy Goodrich: removed check for method process in termination_event() // since with the new IEEE 1666 2011 its legal. // // Revision 1.28 2011/04/13 02:44:26 acg // Andy Goodrich: added m_unwinding flag in place of THROW_NOW because the // throw status will be set back to THROW_*_RESET if reset is active and // the check for an unwind being complete was expecting THROW_NONE as the // clearing of THROW_NOW. // // Revision 1.27 2011/04/10 22:17:35 acg // Andy Goodrich: added trigger_reset_event() to allow sc_process.h to // contain the run_process() inline method. sc_process.h cannot have // sc_simcontext information because of recursive includes. // // Revision 1.26 2011/04/08 22:33:08 acg // Andy Goodrich: moved the semantics() method to the header file and made // it an inline method. // // Revision 1.25 2011/04/08 18:24:48 acg // Andy Goodrich: moved reset_changed() to .cpp since it needs visibility // to sc_simcontext. // // Revision 1.24 2011/04/05 20:50:57 acg // Andy Goodrich: // (1) changes to make sure that event(), posedge() and negedge() only // return true if the clock has not moved. // (2) fixes for method self-resumes. // (3) added SC_PRERELEASE_VERSION // (4) removed kernel events from the object hierarchy, added // sc_hierarchy_name_exists(). // // Revision 1.23 2011/04/05 06:25:38 acg // Andy Goodrich: new checks for simulation running in reset_process(). // // Revision 1.22 2011/03/20 13:43:23 acg // Andy Goodrich: added async_signal_is() plus suspend() as a corner case. // // Revision 1.21 2011/03/12 21:07:51 acg // Andy Goodrich: changes to kernel generated event support. // // Revision 1.20 2011/03/07 17:38:43 acg // Andy Goodrich: tightening up of checks for undefined interaction between // synchronous reset and suspend. // // Revision 1.19 2011/03/06 23:30:13 acg // Andy Goodrich: refining suspend - sync reset corner case checking so that // the following are error situations: // (1) Calling suspend on a process with a reset_signal_is() specification // or sync_reset_on() is active. // (2) Calling sync_reset_on() on a suspended process. // // Revision 1.18 2011/03/06 19:57:11 acg // Andy Goodrich: refinements for the illegal suspend - synchronous reset // interaction. // // Revision 1.17 2011/03/06 16:47:09 acg // Andy Goodrich: changes for testing sync_reset - suspend corner cases. // // Revision 1.16 2011/03/06 15:57:57 acg // Andy Goodrich: added process control corner case checks. Changes for // named events. // // Revision 1.15 2011/02/18 20:27:14 acg // Andy Goodrich: Updated Copyrights. // // Revision 1.14 2011/02/17 19:52:13 acg // Andy Goodrich: // (1) Simplfied process control usage. // (2) Changed dump_status() to dump_state with new signature. // // Revision 1.13 2011/02/13 21:47:37 acg // Andy Goodrich: update copyright notice. // // Revision 1.12 2011/02/13 21:41:34 acg // Andy Goodrich: get the log messages for the previous check in correct. // // Revision 1.11 2011/02/13 21:32:24 acg // Andy Goodrich: moved sc_process_b::reset_process() from header file // to cpp file. Added dump_status() to print out the status of a // process. // // Revision 1.10 2011/02/04 15:27:36 acg // Andy Goodrich: changes for suspend-resume semantics. // // Revision 1.9 2011/02/01 21:06:12 acg // Andy Goodrich: new layout for the process_state enum. // // Revision 1.8 2011/01/25 20:50:37 acg // Andy Goodrich: changes for IEEE 1666 2011. // // Revision 1.7 2011/01/19 23:21:50 acg // Andy Goodrich: changes for IEEE 1666 2011 // // Revision 1.6 2011/01/18 20:10:45 acg // Andy Goodrich: changes for IEEE1666_2011 semantics. // // Revision 1.5 2010/07/22 20:02:33 acg // Andy Goodrich: bug fixes. // // Revision 1.4 2009/05/22 16:06:29 acg // Andy Goodrich: process control updates. // // Revision 1.3 2008/05/22 17:06:26 acg // Andy Goodrich: updated copyright notice to include 2008. // // Revision 1.2 2007/09/20 20:32:35 acg // Andy Goodrich: changes to the semantics of throw_it() to match the // specification. A call to throw_it() will immediately suspend the calling // thread until all the throwees have executed. At that point the calling // thread will be restarted before the execution of any other threads. // // Revision 1.1.1.1 2006/12/15 20:20:05 acg // SystemC 2.3 // // Revision 1.6 2006/04/20 17:08:17 acg // Andy Goodrich: 3.0 style process changes. // // Revision 1.5 2006/04/11 23:13:21 acg // Andy Goodrich: Changes for reduced reset support that only includes // sc_cthread, but has preliminary hooks for expanding to method and thread // processes also. // // Revision 1.4 2006/01/24 20:49:05 acg // Andy Goodrich: changes to remove the use of deprecated features within the // simulator, and to issue warning messages when deprecated features are used. // // Revision 1.3 2006/01/13 18:44:30 acg // Added $Log to record CVS changes into the source. // systemc-2.3.3/src/sysc/packages/0000755000175000017500000000000013360325173016417 5ustar carstencarstensystemc-2.3.3/src/sysc/packages/qt/0000755000175000017500000000000013360325173017043 5ustar carstencarstensystemc-2.3.3/src/sysc/packages/qt/stp.h0000644000175000017500000000275113360325173020027 0ustar carstencarsten#ifndef STP_H #define STP_H /* * QuickThreads -- Threads-building toolkit. * Copyright (c) 1993 by David Keppel * * Permission to use, copy, modify and distribute this software and * its documentation for any purpose and without fee is hereby * granted, provided that the above copyright notice and this notice * appear in all copies. This software is provided as a * proof-of-concept and for demonstration purposes; there is no * representation about the suitability of this software for any * purpose. */ typedef struct stp_t stp_t; /* Each thread starts by calling a user-supplied function of this type. */ typedef void (stp_userf_t)(void *p0); /* Call this before any other primitives. */ extern void stp_init(); /* When one or more threads are created by the main thread, the system goes multithread when this is called. It is done (no more runable threads) when this returns. */ extern void stp_start (void); /* Create a thread and make it runable. When the thread starts running it will call `f' with arguments `p0' and `p1'. */ extern void stp_create (stp_userf_t *f, void *p0); /* The current thread stops running but stays runable. It is an error to call `stp_yield' before `stp_start' is called or after `stp_start' returns. */ extern void stp_yield (void); /* Like `stp_yield' but the thread is discarded. Any intermediate state is lost. The thread can also terminate by simply returning. */ extern void stp_abort (void); #endif /* ndef STP_H */ systemc-2.3.3/src/sysc/packages/qt/Makefile.base0000644000175000017500000000410013360325173021407 0ustar carstencarsten.SUFFIXES: .c .o .s .E # # Need to include from the current directory because "qt.h" # will include . # CFLAGS = -I. -g # # Fix this to be something meaningful for your system. # DEST = /dev/null DOC = users.tout EXTHDRS = /usr/include/stdio.h HDRS = qt.h \ qtmd.h \ stp.h LDFLAGS = $(CFLAGS) EXTLIBS = LIBS = libstp.a libqt.a LINKER = $(CC) MAKEFILE = Makefile M = Makefile configuration OBJS = qtmdb.o \ meas.o QTOBJS = qt.o qtmds.o qtmdc.o STPOBJS = stp.o PR = -Pps PRINT = pr PROGRAM = run SRCS = meas.c \ qt.c \ qtmdc.c \ qtmds.s \ qtmdb.s TMP_INIT = tmp.init TMP_SWAP = tmp.swap .DEFAULT: co -q $@ .c.E: force $(CC) $(CFLAGS) -E $*.c > $*.E all: libqt.a libstp.a $(PROGRAM) $(M) libqt.a: $(QTOBJS) $(M) ar crv libqt.a $(QTOBJS) ranlib libqt.a libstp.a: $(STPOBJS) $(M) ar crv libstp.a $(STPOBJS) ranlib libstp.a $(PROGRAM): $(OBJS) $(LIBS) $(M) @echo "Loading $(PROGRAM) ... " # ld -o $(PROGRAM) /lib/crt0.o $(OBJS) -lc $(LINKER) $(LDFLAGS) $(OBJS) $(LIBS) $(EXTLIBS) -o $(PROGRAM) @echo "done" clean: rm -f $(OBJS) $(PROGRAM) $(TMP_INIT) $(TMP_SWAP) $(DOC) rm -f libqt.a libstp.a rm -f $(QTOBJS) $(STPOBJS) depend:; @mkmf -f $(MAKEFILE) PROGRAM=$(PROGRAM) DEST=$(DEST) doc: users.ms raw time/assim < raw | grep "^init" | sed 's/^init //' > $(TMP_INIT) time/assim < raw | grep "^swap" | sed 's/^swap //' > $(TMP_SWAP) soelim users.ms | tbl $(PR) | troff -t $(PR) -ms > $(DOC) index:; @ctags -wx $(HDRS) $(SRCS) print:; @$(PRINT) $(HDRS) $(SRCS) program: $(PROGRAM) tags: $(HDRS) $(SRCS); @ctags $(HDRS) $(SRCS) update: $(DEST)/$(PROGRAM) $(DEST)/$(PROGRAM): $(SRCS) $(LIBS) $(HDRS) $(EXTHDRS) @make -f $(MAKEFILE) DEST=$(DEST) install QT_H = qt.h $(QTMD_H) QTMD_H = qtmd.h ### qtmdb.o: $(M) qtmdb.s b.h meas.o: $(M) meas.c /usr/include/stdio.h $(QT_H) b.h stp.h qt.o: $(M) qt.c $(QT_H) stp.o: $(M) stp.c stp.h $(QT_H) qtmds.o: $(M) qtmds.s qtmdc.o: $(M) qtmdc.c $(QT_H) systemc-2.3.3/src/sysc/packages/qt/Makefile.am0000644000175000017500000001004513360325173021077 0ustar carstencarsten## **************************************************************************** ## ## Licensed to Accellera Systems Initiative Inc. (Accellera) under one or ## more contributor license agreements. See the NOTICE file distributed ## with this work for additional information regarding copyright ownership. ## Accellera licenses this file to you under the Apache License, Version 2.0 ## (the "License"); you may not use this file except in compliance with the ## License. You may obtain a copy of the License at ## ## http://www.apache.org/licenses/LICENSE-2.0 ## ## Unless required by applicable law or agreed to in writing, software ## distributed under the License is distributed on an "AS IS" BASIS, ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or ## implied. See the License for the specific language governing ## permissions and limitations under the License. ## ## **************************************************************************** ## ## src/sysc/qt/Makefile.am -- ## Process this file with automake to produce a Makefile.in file. ## ## Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 ## ## **************************************************************************** ## ## MODIFICATION LOG - modifiers, enter your name, affiliation, date and ## changes you are making here. ## ## Name, Affiliation, Date: ## Description of Modification: ## ## **************************************************************************** include $(top_srcdir)/config/Make-rules.sysc NO_H_FILES = \ copyright.h \ qt.h \ qtmd.h \ \ md/aarch64.h \ md/axp.h \ md/hppa.h \ md/i386.h \ md/iX86_64.h \ md/ksr1.h \ md/m88k.h \ md/mips.h \ md/powerpc_mach.h \ md/powerpc_sys5.h \ md/sparc.h \ md/vax.h noinst_HEADERS = \ $(NO_H_FILES) C_FILES = \ qt.c NO_C_FILES = \ md/axp.c \ md/m88k.c \ md/null.c \ md/powerpc.c NO_S_FILES = \ md/aarch64.s \ md/axp_b.s \ md/axp.s \ md/hppa_b.s \ md/hppa.s \ md/i386_b.s \ md/i386.s \ md/iX86_64.s \ md/ksr1_b.s \ md/ksr1.s \ md/m88k_b.s \ md/m88k.s \ md/mips_b.s \ md/mips-irix5.s \ md/mips.s \ md/null.s \ md/powerpc_mach_b.s \ md/powerpc_mach.s \ md/powerpc_sys5_b.s \ md/powerpc_sys5.s \ md/sparc_b.s \ md/sparc.s \ md/vax_b.s \ md/vax.s EXTRA_DIST += \ CHANGES \ config \ INSTALL \ Makefile.base \ README \ README.MISC \ README.PORT \ \ b.h \ meas.c \ stp.c \ stp.h \ \ time/assim \ time/cswap \ time/go \ time/init \ time/prim \ time/raw \ time/README.time \ \ md/axp.1.Makefile \ md/axp.2.Makefile \ md/axp.Makefile \ md/axp.README \ md/default.Makefile \ md/hppa-cnx.Makefile \ md/hppa.Makefile \ md/i386.README \ md/ksr1.Makefile \ md/m88k.Makefile \ md/null.README \ md/powerpc.README \ md/pthreads.Makefile \ md/solaris.README \ \ $(NO_C_FILES) \ $(NO_H_FILES) \ $(NO_S_FILES) CLEANFILES += \ $(QT_ARCH_FILES) \ configuration if WANT_QT_THREADS BUILT_SOURCES = \ configuration noinst_LTLIBRARIES = libqt.la nodist_libqt_la_SOURCES = \ $(QT_ARCH_FILES) libqt_la_SOURCES = \ $(C_FILES) libqt_la_LIBTOOLFLAGS = \ --tag=CC qtmds_o_CCASFLAGS = \ $(AM_CCASFLAGS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) # only add qtmdc.c to QT_ARCH_FILES, if needed for the platform (!=null.c) QT_ARCH_FILES = \ qtmds.s if QT_ARCH_AARCH64 QT_ARCH_IMPL = md/aarch64.s endif if QT_ARCH_X86 QT_ARCH_IMPL = md/i386.s endif if QT_ARCH_X86_64 QT_ARCH_IMPL = md/iX86_64.s endif if QT_ARCH_POWERPC_MACOSX QT_ARCH_FILES+=qtmdc.c QT_ARCH_IMPL = md/powerpc_mach.s md/powerpc.c endif if QT_ARCH_SPARC QT_ARCH_IMPL = md/sparc.s endif if QT_ARCH_HPPA QT_ARCH_IMPL = md/hppa.s endif # ensure to use a working link command in 'config' export LN_S configuration: if SEPARATE_BUILD_TREE # copy arch files to build tree $(AM_V_at)for file in $(QT_ARCH_IMPL); do \ $(MKDIR_P) `dirname "$$file"` ; \ $(INSTALL_DATA) $(srcdir)/$$file ./$$file ; \ done endif # SEPARATE_BUILD_TREE $(AM_V_GEN)$(SHELL) $(srcdir)/config $(QT_ARCH) if SEPARATE_BUILD_TREE CLEANFILES += \ $(QT_ARCH_IMPL) endif # SEPARATE_BUILD_TREE endif # WANT_QT_THREADS ## Taf! systemc-2.3.3/src/sysc/packages/qt/CHANGES0000644000175000017500000000107213360325173020036 0ustar carstencarstenQuickThreads 002: Changes since QuickThreads 001. - Now can be used by C++ programs. - Now *really* works with stacks that grow up. - Supports AXP OSF 2.x cc's varargs. - Supports HP Precision (HP-PA) on workstations and Convex. - Supports assemblers for Intel iX86 ith only '//'-style comments. - Supports Silicon Graphics Irix 5.x with dynamic linking. - Supports System V and Solaris 2.x with no `_' on compiler-generated identifiers; *some* platforms only. Note: not all "./config" arguments are compatible with QT 001. QuickThreads 001: Base version. systemc-2.3.3/src/sysc/packages/qt/meas.c0000644000175000017500000005242513360325173020144 0ustar carstencarsten/* meas.c -- measure qt stuff. */ #include "copyright.h" /* Need this to get assertions under Mach on the Sequent/i386: */ #ifdef __i386__ #define assert(ex) \ do { \ if (!(ex)) { \ fprintf (stderr, "[%s:%d] Assertion " #ex " failed\n", __FILE__, __LINE__); \ abort(); \ } \ } while (0) #else #include #endif /* This really ought to be defined in some ANSI include file (*I* think...), but it's defined here instead, which leads us to another machine dependency. The `iaddr_t' type is an integer representation of a pointer, suited for doing arithmetic on addresses, e.g. to round an address to an alignment boundary. */ typedef unsigned long iaddr_t; #include /* For varargs tryout. */ #include #include "b.h" #include "qt.h" #include "stp.h" extern void exit (int status); extern int atoi (char const *s); extern int fprintf (FILE *out, char const *fmt, ...); extern int fputs (char const *s, FILE *fp); extern void free (void *sto); extern void *malloc (unsigned nbytes); extern void perror (char const *s); void usage (void); void tracer(void); /* Round `v' to be `a'-aligned, assuming `a' is a power of two. */ #define ROUND(v, a) (((v) + (a) - 1) & ~((a)-1)) typedef struct thread_t { qt_t *qt; /* Pointer to thread of function... */ void *stk; void *top; /* Set top of stack if reuse. */ struct thread_t *next; } thread_t; static thread_t * t_alloc (void) { thread_t *t; int ssz = 0x1000; t = malloc (sizeof(thread_t)); if (!t) { perror ("malloc"); exit (1); } assert (ssz > QT_STKBASE); t->stk = malloc (ssz); t->stk = (void *)ROUND (((iaddr_t)t->stk), QT_STKALIGN); if (!t->stk) { perror ("malloc"); exit (1); } assert ((((iaddr_t)t->stk) & (QT_STKALIGN-1)) == 0); t->top = QT_SP (t->stk, ssz - QT_STKBASE); return (t); } static thread_t * t_create (qt_only_t *starter, void *p0, qt_userf_t *f) { thread_t *t; t = t_alloc(); t->qt = QT_ARGS (t->top, p0, t, f, starter); return (t); } static void t_free (thread_t *t) { free (t->stk); free (t); } static void * t_null (qt_t *old, void *p1, void *p2) { /* return (garbage); */ } static void * t_splat (qt_t *old, void *oldp, void *null) { *(qt_t **)oldp = old; /* return (garbage); */ } static char const test01_msg[] = "*QT_SP(sto,sz), QT_ARGS(top,p0,p1,userf,first)"; static char const *test01_descr[] = { "Performs 1 QT_SP and one QT_ARGS per iteration.", NULL }; /* This test gives a guess on how long it takes to initalize a thread. */ static void test01 (int n) { char stack[QT_STKBASE+QT_STKALIGN]; char *stk; qt_t *top; stk = (char *)ROUND (((iaddr_t)stack), QT_STKALIGN); { int i; for (i=0; i0) { /* RETVALUSED */ top = QT_SP (stk, QT_STKBASE); QT_ARGS (top, 0, 0, 0, 0); #ifdef NDEF top = QT_SP (stk, QT_STKBASE); QT_ARGS (top, 0, 0, 0, 0); top = QT_SP (stk, QT_STKBASE); QT_ARGS (top, 0, 0, 0, 0); top = QT_SP (stk, QT_STKBASE); QT_ARGS (top, 0, 0, 0, 0); top = QT_SP (stk, QT_STKBASE); QT_ARGS (top, 0, 0, 0, 0); top = QT_SP (stk, QT_STKBASE); QT_ARGS (top, 0, 0, 0, 0); top = QT_SP (stk, QT_STKBASE); QT_ARGS (top, 0, 0, 0, 0); top = QT_SP (stk, QT_STKBASE); QT_ARGS (top, 0, 0, 0, 0); top = QT_SP (stk, QT_STKBASE); QT_ARGS (top, 0, 0, 0, 0); top = QT_SP (stk, QT_STKBASE); QT_ARGS (top, 0, 0, 0, 0); n -= 10; #else n -= 1; #endif } } static char const test02_msg[] = "QT_BLOCKI (0, 0, test02_aux, t->qt)"; static qt_t *rootthread; static void test02_aux1 (void *pu, void *pt, qt_userf_t *f) { QT_ABORT (t_null, 0, 0, rootthread); } static void * test02_aux2 (qt_t *old, void *farg1, void *farg2) { rootthread = old; /* return (garbage); */ } static void test02 (int n) { thread_t *t; while (n>0) { t = t_create (test02_aux1, 0, 0); QT_BLOCKI (test02_aux2, 0, 0, t->qt); t_free (t); t = t_create (test02_aux1, 0, 0); QT_BLOCKI (test02_aux2, 0, 0, t->qt); t_free (t); t = t_create (test02_aux1, 0, 0); QT_BLOCKI (test02_aux2, 0, 0, t->qt); t_free (t); t = t_create (test02_aux1, 0, 0); QT_BLOCKI (test02_aux2, 0, 0, t->qt); t_free (t); t = t_create (test02_aux1, 0, 0); QT_BLOCKI (test02_aux2, 0, 0, t->qt); t_free (t); n -= 5; } } static char const test03_msg[] = "QT_BLOCKI (...) test vals are right."; /* Called by the thread function when it wants to shut down. Return a value to the main thread. */ static void * test03_aux0 (qt_t *old_is_garbage, void *farg1, void *farg2) { assert (farg1 == (void *)5); assert (farg2 == (void *)6); return ((void *)15); /* Some unlikely value. */ } /* Called during new thread startup by main thread. Since the new thread has never run before, return value is ignored. */ static void * test03_aux1 (qt_t *old, void *farg1, void *farg2) { assert (old != NULL); assert (farg1 == (void *)5); assert (farg2 == (void *)6); rootthread = old; return ((void *)16); /* Different than `15'. */ } static void test03_aux2 (void *pu, void *pt, qt_userf_t *f) { assert (pu == (void *)1); assert (f == (qt_userf_t *)4); QT_ABORT (test03_aux0, (void *)5, (void *)6, rootthread); } static void test03 (int n) { thread_t *t; void *rv; while (n>0) { t = t_create (test03_aux2, (void *)1, (qt_userf_t *)4); rv = QT_BLOCKI (test03_aux1, (void *)5, (void *)6, t->qt); assert (rv == (void *)15); t_free (t); --n; } } static char const test04_msg[] = "stp_start w/ no threads."; static void test04 (int n) { while (n>0) { stp_init(); stp_start(); stp_init(); stp_start(); stp_init(); stp_start(); stp_init(); stp_start(); stp_init(); stp_start(); stp_init(); stp_start(); stp_init(); stp_start(); stp_init(); stp_start(); stp_init(); stp_start(); stp_init(); stp_start(); n -= 10; } } static char const test05_msg[] = "stp w/ 2 yielding thread."; static void test05_aux (void *null) { stp_yield(); stp_yield(); } static void test05 (int n) { while (n>0) { stp_init(); stp_create (test05_aux, 0); stp_create (test05_aux, 0); stp_start(); --n; } } static char const test06_msg[] = "*QT_ARGS(...), QT_BLOCKI one thread"; static char const *test06_descr[] = { "Does a QT_ARGS, QT_BLOCKI to a helper function that saves the", "stack pointer of the main thread, calls an `only' function that", "saves aborts the thread, calling a null helper function.", ":: start/stop = QT_ARGS + QT_BLOCKI + QT_ABORT + 3 procedure calls.", NULL }; /* This test initializes a thread, runs it, then returns to the main program, which reinitializes the thread, runs it again, etc. Each iteration corresponds to 1 init, 1 abort, 1 block. */ static qt_t *test06_sp; static void test06_aux2 (void *null0a, void *null1b, void *null2b, qt_userf_t *null) { QT_ABORT (t_null, 0, 0, test06_sp); } static void * test06_aux3 (qt_t *sp, void *null0c, void *null1c) { test06_sp = sp; /* return (garbage); */ } static void test06 (int n) { thread_t *t; t = t_create (0, 0, 0); while (n>0) { /* RETVALUSED */ QT_ARGS (t->top, 0, 0, 0, test06_aux2); QT_BLOCKI (test06_aux3, 0, 0, t->qt); #ifdef NDEF /* RETVALUSED */ QT_ARGS (t->top, 0, 0, 0, test06_aux2); QT_BLOCKI (test06_aux3, 0, 0, t->qt); /* RETVALUSED */ QT_ARGS (t->top, 0, 0, 0, test06_aux2); QT_BLOCKI (test06_aux3, 0, 0, t->qt); /* RETVALUSED */ QT_ARGS (t->top, 0, 0, 0, test06_aux2); QT_BLOCKI (test06_aux3, 0, 0, t->qt); /* RETVALUSED */ QT_ARGS (t->top, 0, 0, 0, test06_aux2); QT_BLOCKI (test06_aux3, 0, 0, t->qt); n -= 5; #else --n; #endif } } static char test07_msg[] = "*cswap between threads"; static char const *test07_descr[] = { "Build a chain of threads where each thread has a fixed successor.", "There is no scheduling performed. Each thread but one is a loop", "that simply blocks with QT_BLOCKI, calling a helper that saves the", "current stack pointer. The last thread decrements a count, and,", "if zero, aborts back to the main thread. Else it continues with", "the blocking chain. The count is divided by the number of threads", "in the chain, so `n' is the number of integer block operations.", ":: integer cswap = QT_BLOCKI + a procedure call.", NULL }; /* This test repeatedly blocks a bunch of threads. Each iteration corresponds to one block operation. The threads are arranged so that there are TEST07_N-1 of them that run `test07_aux2'. Each one of those blocks saving it's sp to storage owned by the preceding thread; a pointer to that storage is passed in via `mep'. Each thread has a handle on it's own storage for the next thread, referenced by `nxtp', and it blocks by passing control to `*nxtp', telling the helper function to save its state in `*mep'. The last thread in the chain decrements a count and, if it's gone below zero, returns to `test07'; otherwise, it invokes the first thread in the chain. */ static qt_t *test07_heavy; #define TEST07_N (4) static void test07_aux2 (void *null0, void *mep, void *nxtp, qt_userf_t *null) { qt_t *nxt; while (1) { nxt = *(qt_t **)nxtp; #ifdef NDEF printf ("Helper 0x%p\n", nxtp); #endif QT_BLOCKI (t_splat, mep, 0, nxt); } } static void test07_aux3 (void *np, void *mep, void *nxtp, qt_userf_t *null) { int n; n = *(int *)np; while (1) { n -= TEST07_N; if (n<0) { QT_ABORT (t_splat, mep, 0, test07_heavy); } QT_BLOCKI (t_splat, mep, 0, *(qt_t **)nxtp); } } static void test07 (int n) { int i; thread_t *t[TEST07_N]; for (i=0; itop, 0, &t[i]->qt, &t[i+1]->qt, test07_aux2); } /* RETVALUSED */ QT_ARGS (t[i]->top, &n, &t[TEST07_N-1]->qt, &t[0]->qt, test07_aux3); QT_BLOCKI (t_splat, &test07_heavy, 0, t[0]->qt); } static char test08_msg[] = "Floating-point cswap between threads"; static char const *test08_descr[] = { "Measure context switch times including floating-point, use QT_BLOCK.", NULL }; static qt_t *test08_heavy; #define TEST08_N (4) static void test08_aux2 (void *null0, void *mep, void *nxtp, qt_userf_t *null) { qt_t *nxt; while (1) { nxt = *(qt_t **)nxtp; QT_BLOCK (t_splat, mep, 0, nxt); } } static void test08_aux3 (void *np, void *mep, void *nxtp, qt_userf_t *null) { int n; n = *(int *)np; while (1) { n -= TEST08_N; if (n<0) { QT_ABORT (t_splat, mep, 0, test08_heavy); } QT_BLOCK (t_splat, mep, 0, *(qt_t **)nxtp); } } static void test08 (int n) { int i; thread_t *t[TEST08_N]; for (i=0; itop, 0, &t[i]->qt, &t[i+1]->qt, test08_aux2); } /* RETVALUSED */ QT_ARGS (t[i]->top, &n, &t[TEST08_N-1]->qt, &t[0]->qt, test08_aux3); QT_BLOCK (t_splat, &test08_heavy, 0, t[0]->qt); } /* Test the varargs procedure calling. */ char const test09_msg[] = { "Start and run threads using varargs." }; thread_t *test09_t0, *test09_t1, *test09_t2, *test09_main; thread_t * test09_create (qt_startup_t *start, qt_vuserf_t *f, qt_cleanup_t *cleanup, int nbytes, ...) { va_list ap; thread_t *t; t = t_alloc(); va_start (ap, nbytes); t->qt = QT_VARGS (t->top, nbytes, ap, t, start, f, cleanup); va_end (ap); return (t); } static void test09_cleanup (void *pt, void *vuserf_retval) { assert (vuserf_retval == (void *)17); QT_ABORT (t_splat, &((thread_t *)pt)->qt, 0, ((thread_t *)pt)->next->qt); } static void test09_start (void *pt) { } static void * test09_user0 (void) { QT_BLOCKI (t_splat, &test09_t0->qt, 0, test09_t1->qt); return ((void *)17); } static void * test09_user2 (int one, int two) { assert (one == 1); assert (two == 2); QT_BLOCKI (t_splat, &test09_t1->qt, 0, test09_t2->qt); assert (one == 1); assert (two == 2); return ((void *)17); } static void * test09_user10 (int one, int two, int three, int four, int five, int six, int seven, int eight, int nine, int ten) { assert (one == 1); assert (two == 2); assert (three == 3); assert (four == 4); assert (five == 5); assert (six == 6); assert (seven == 7); assert (eight == 8); assert (nine == 9); assert (ten == 10); QT_BLOCKI (t_splat, &test09_t2->qt, 0, test09_main->qt); assert (one == 1); assert (two == 2); assert (three == 3); assert (four == 4); assert (five == 5); assert (six == 6); assert (seven == 7); assert (eight == 8); assert (nine == 9); assert (ten == 10); return ((void *)17); } void test09 (int n) { thread_t main; test09_main = &main; while (--n >= 0) { test09_t0 = test09_create (test09_start, (qt_vuserf_t*)test09_user0, test09_cleanup, 0); test09_t1 = test09_create (test09_start, (qt_vuserf_t*)test09_user2, test09_cleanup, 2 * sizeof(qt_word_t), 1, 2); test09_t2 = test09_create (test09_start, (qt_vuserf_t*)test09_user10, test09_cleanup, 10 * sizeof(qt_word_t), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); /* Chaining used by `test09_cleanup' to determine who is next. */ test09_t0->next = test09_t1; test09_t1->next = test09_t2; test09_t2->next = test09_main; QT_BLOCKI (t_splat, &test09_main->qt, 0, test09_t0->qt); QT_BLOCKI (t_splat, &test09_main->qt, 0, test09_t0->qt); t_free (test09_t0); t_free (test09_t1); t_free (test09_t2); } } /* Test 10/11/12: time the cost of various number of args. */ char const test10_msg[] = { "*Test varargs init & startup w/ 0 args." }; char const *test10_descr[] = { "Start and stop threads that use variant argument lists (varargs).", "Each thread is initialized by calling a routine that calls", "QT_VARARGS. Then runs the thread by calling QT_BLOCKI to hald the", "main thread, a helper that saves the main thread's stack pointer,", "a null startup function, a null user function, a cleanup function", "that calls QT_ABORT and restarts the main thread. Copies no user", "parameters.", ":: varargs start/stop = QT_BLOCKI + QT_ABORT + 6 function calls.", NULL }; /* Helper function to send control back to main. Don't save anything. */ /* Helper function for starting the varargs thread. Save the stack pointer of the main thread so we can get back there eventually. */ /* Startup function for a varargs thread. */ static void test10_startup (void *pt) { } /* User function for a varargs thread. */ static void * test10_run (int arg0, ...) { /* return (garbage); */ } /* Cleanup function for a varargs thread. Send control back to the main thread. Don't save any state from the thread that is halting. */ void test10_cleanup (void *pt, void *vuserf_retval) { QT_ABORT (t_null, 0, 0, ((thread_t *)pt)->qt); } void test10_init (thread_t *new, thread_t *next, int nbytes, ...) { va_list ap; va_start (ap, nbytes); new->qt = QT_VARGS (new->top, nbytes, ap, next, test10_startup, test10_run, test10_cleanup); va_end (ap); } void test10 (int n) { thread_t main; thread_t *t; t = t_alloc(); t->next = &main; while (--n >= 0) { test10_init (t, &main, 0); QT_BLOCKI (t_splat, &main.qt, 0, t->qt); } t_free (t); } char const test11_msg[] = { "*Test varargs init & startup w/ 2 args." }; char const *test11_descr[] = { "Varargs initialization/run. Copies 2 user arguments.", ":: varargs 2 start/stop = QT_VARGS(2 args), QT_BLOCKI, QT_ABORT, 6 f() calls.", NULL }; void test11 (int n) { thread_t main; thread_t *t; t = t_alloc(); t->next = &main; while (--n >= 0) { test10_init (t, &main, 2 * sizeof(int), 2, 1); QT_BLOCKI (t_splat, &main.qt, 0, t->qt); } t_free (t); } char const test12_msg[] = { "*Test varargs init & startup w/ 4 args." }; char const *test12_descr[] = { "Varargs initialization/run. Copies 4 user arguments.", ":: varargs 4 start/stop = QT_VARGS(4 args), QT_BLOCKI, QT_ABORT, 6 f() calls.", NULL }; void test12 (int n) { thread_t main; thread_t *t; t = t_alloc(); t->next = &main; while (--n >= 0) { test10_init (t, &main, 4 * sizeof(int), 4, 3, 2, 1); QT_BLOCKI (t_splat, &main.qt, 0, t->qt); } t_free (t); } char const test13_msg[] = { "*Test varargs init & startup w/ 8 args." }; char const *test13_descr[] = { "Varargs initialization/run. Copies 8 user arguments.", ":: varargs 8 start/stop = QT_VARGS(8 args), QT_BLOCKI, QT_ABORT, 6 f() calls.", NULL }; void test13 (int n) { thread_t main; thread_t *t; t = t_alloc(); t->next = &main; while (--n >= 0) { test10_init (t, &main, 8 * sizeof(int), 8, 7, 6, 5, 4, 3, 2, 1); QT_BLOCKI (t_splat, &main.qt, 0, t->qt); } t_free (t); } char const test14_msg[] = { "*Test varargs initialization w/ 0 args." }; char const *test14_descr[] = { "Varargs initialization without running the thread. Just calls", "QT_VARGS.", ":: varargs 0 init = QT_VARGS()", NULL }; void test14 (int n) { thread_t main; thread_t *t; t = t_alloc(); t->next = &main; while (--n >= 0) { test10_init (t, &main, 0 * sizeof(int)); } t_free (t); } char const test15_msg[] = { "*Test varargs initialization w/ 2 args." }; char const *test15_descr[] = { "Varargs initialization without running the thread. Just calls", "QT_VARGS.", ":: varargs 2 init = QT_VARGS(2 args)", NULL }; void test15 (int n) { thread_t main; thread_t *t; t = t_alloc(); t->next = &main; while (--n >= 0) { test10_init (t, &main, 2 * sizeof(int), 2, 1); } t_free (t); } char const test16_msg[] = { "*Test varargs initialization w/ 4 args." }; char const *test16_descr[] = { "Varargs initialization without running the thread. Just calls", "QT_VARGS.", ":: varargs 4 init = QT_VARGS(4 args)", NULL }; void test16 (int n) { thread_t main; thread_t *t; t = t_alloc(); t->next = &main; while (--n >= 0) { test10_init (t, &main, 4 * sizeof(int), 4, 3, 2, 1); } t_free (t); } char const test17_msg[] = { "*Test varargs initialization w/ 8 args." }; char const *test17_descr[] = { "Varargs initialization without running the thread. Just calls", "QT_VARGS.", ":: varargs 8 init = QT_VARGS(8 args)", NULL }; void test17 (int n) { thread_t main; thread_t *t; t = t_alloc(); t->next = &main; while (--n >= 0) { test10_init (t, &main, 8 * sizeof(int), 8, 7, 6, 5, 4, 3, 2, 1); } t_free (t); } /* Test times for basic machine operations. */ char const test18_msg[] = { "*Call register indirect." }; char const *test18_descr[] = { NULL }; void test18 (int n) { b_call_reg (n); } char const test19_msg[] = { "*Call immediate." }; char const *test19_descr[] = { NULL }; void test19 (int n) { b_call_imm (n); } char const test20_msg[] = { "*Add register-to-register." }; char const *test20_descr[] = { NULL }; void test20 (int n) { b_add (n); } char const test21_msg[] = { "*Load memory to a register." }; char const *test21_descr[] = { NULL }; void test21 (int n) { b_load (n); } /* Driver. */ typedef struct foo_t { char const *msg; /* Message to print for generic help. */ char const **descr; /* A description of what is done by the test. */ void (*f)(int n); } foo_t; static foo_t foo[] = { { "Usage:\n", NULL, (void(*)(int n))usage }, { test01_msg, test01_descr, test01 }, { test02_msg, NULL, test02 }, { test03_msg, NULL, test03 }, { test04_msg, NULL, test04 }, { test05_msg, NULL, test05 }, { test06_msg, test06_descr, test06 }, { test07_msg, test07_descr, test07 }, { test08_msg, test08_descr, test08 }, { test09_msg, NULL, test09 }, { test10_msg, test10_descr, test10 }, { test11_msg, test11_descr, test11 }, { test12_msg, test12_descr, test12 }, { test13_msg, test13_descr, test13 }, { test14_msg, test14_descr, test14 }, { test15_msg, test15_descr, test15 }, { test16_msg, test16_descr, test16 }, { test17_msg, test17_descr, test17 }, { test18_msg, test18_descr, test18 }, { test19_msg, test19_descr, test19 }, { test20_msg, test20_descr, test20 }, { test21_msg, test21_descr, test21 }, { 0, 0 } }; static int tv = 0; void tracer () { fprintf (stderr, "tracer\t%d\n", tv++); fflush (stderr); } void tracer2 (void *val) { fprintf (stderr, "tracer2\t%d val=0x%p", tv++, val); fflush (stderr); } void describe() { int i; FILE *out = stdout; for (i=0; foo[i].msg; ++i) { if (foo[i].descr) { int j; putc ('\n', out); fprintf (out, "[%d]\n", i); for (j=0; foo[i].descr[j]; ++j) { fputs (foo[i].descr[j], out); putc ('\n', out); } } } exit (0); } void usage() { int i; fputs (foo[0].msg, stderr); for (i=1; foo[i].msg; ++i) { fprintf (stderr, "%2d\t%s\n", i, foo[i].msg); } exit (1); } void args (int *which, int *n, int argc, char **argv) { static int nfuncs = 0; if (argc == 2 && argv[1][0] == '-' && argv[1][1] == 'h') { describe(); } if (nfuncs == 0) { for (nfuncs=0; foo[nfuncs].msg; ++nfuncs) ; } if (argc != 2 && argc != 3) { usage(); } *which = atoi (argv[1]); if (*which < 0 || *which >= nfuncs) { usage(); } *n = (argc == 3) ? atoi (argv[2]) : 1; } int main (int argc, char **argv) { int which, n; args (&which, &n, argc, argv); (*(foo[which].f))(n); exit (0); return (0); } systemc-2.3.3/src/sysc/packages/qt/md/0000755000175000017500000000000013360325173017443 5ustar carstencarstensystemc-2.3.3/src/sysc/packages/qt/md/ksr1_b.s0000644000175000017500000000202313360325173021005 0ustar carstencarsten/* * QuickThreads -- Threads-building toolkit. * Copyright (c) 1993 by David Keppel * * Permission to use, copy, modify and distribute this software and * its documentation for any purpose and without fee is hereby * granted, provided that the above copyright notice and this notice * appear in all copies. This software is provided as a * proof-of-concept and for demonstration purposes; there is no * representation about the suitability of this software for any * purpose. */ .file "ksr1_b.s" .def .debug; .endef .globl b_call_reg$TXT .globl b_call_reg .globl b_call_imm$TXT .globl b_call_imm .globl b_add$TXT .globl b_add .globl b_load$TXT .globl b_load b_call_reg: b_call_imm: b_add: b_load: .word b_call_reg$TXT .word qt_error .word qt_error$TXT b_call_reg$TXT: b_call_imm$TXT: b_add$TXT: b_load$TXT: finop ; cxnop finop ; cxnop finop ; ld8 16(%cp),%c4 finop ; ld8 8(%cp),%cp finop ; cxnop finop ; cxnop finop ; jsr %c4,0(%c4) finop ; cxnop finop ; cxnop systemc-2.3.3/src/sysc/packages/qt/md/axp.s0000644000175000017500000000773413360325173020432 0ustar carstencarsten/* * QuickThreads -- Threads-building toolkit. * Copyright (c) 1993 by David Keppel * * Permission to use, copy, modify and distribute this software and * its documentation for any purpose and without fee is hereby * granted, provided that the above copyright notice and this notice * appear in all copies. This software is provided as a * proof-of-concept and for demonstration purposes; there is no * representation about the suitability of this software for any * purpose. */ /* axp.s -- assembly support. */ .text .align 4 .file 2 "axp.s" .globl qt_block .globl qt_blocki .globl qt_abort .globl qt_start .globl qt_vstart /* ** $16: ptr to function to call once curr is suspended ** and control is on r19's stack. ** $17: 1'th arg to (*$16)(...). ** $18: 2'th arg to (*$16)(...). ** $19: sp of thread to resume. ** ** The helper routine returns a value that is passed on as the ** return value from the blocking routine. Since we don't ** touch r0 between the helper's return and the end of ** function, we get this behavior for free. */ .ent qt_blocki qt_blocki: subq $30,80, $30 /* Allocate save area. */ stq $26, 0($30) /* Save registers. */ stq $9, 8($30) stq $10,16($30) stq $11,24($30) stq $12,32($30) stq $13,40($30) stq $14,48($30) stq $15,56($30) stq $29,64($30) .end qt_blocki .ent qt_abort qt_abort: addq $16,$31, $27 /* Put argument function in PV. */ addq $30,$31, $16 /* Save stack ptr in outgoing arg. */ addq $19,$31, $30 /* Set new stack pointer. */ jsr $26,($27),0 /* Call helper function. */ ldq $26, 0($30) /* Restore registers. */ ldq $9, 8($30) ldq $10,16($30) ldq $11,24($30) ldq $12,32($30) ldq $13,40($30) ldq $14,48($30) ldq $15,56($30) ldq $29,64($30) addq $30,80, $30 /* Deallocate save area. */ ret $31,($26),1 /* Return, predict===RET. */ .end qt_abort /* ** Non-varargs thread startup. */ .ent qt_start qt_start: addq $9,$31, $16 /* Load up `qu'. */ addq $10,$31, $17 /* ... user function's `pt'. */ addq $11,$31, $18 /* ... user function's `userf'. */ addq $12,$31, $27 /* ... set procedure value to `only'. */ jsr $26,($27),0 /* Call `only'. */ jsr $26,qt_error /* `only' erroniously returned. */ .end qt_start .ent qt_vstart: qt_vstart: /* Call startup function. */ addq $9,$31, $16 /* Arg0 to `startup'. */ addq $12,$31, $27 /* Set procedure value. */ jsr $26,($27),0 /* Call `startup'. */ /* Call user function. */ ldt $f16, 0($30) /* Load fp arg regs. */ ldt $f17, 8($30) ldt $f18,16($30) ldt $f19,24($30) ldt $f20,32($30) ldt $f21,40($30) ldq $16,48($30) /* And integer arg regs. */ ldq $17,56($30) ldq $18,64($30) ldq $19,72($30) ldq $20,80($30) ldq $21,88($30) addq $30,96 $30 /* Pop 6*2*8 saved arg regs. */ addq $11,$31, $27 /* Set procedure value. */ jsr $26,($27),0 /* Call `vuserf'. */ /* Call cleanup. */ addq $9,$31, $16 /* Arg0 to `cleanup'. */ addq $0,$31, $17 /* Users's return value is arg1. */ addq $10,$31, $27 /* Set procedure value. */ jsr $26,($27),0 /* Call `cleanup'. */ jsr $26,qt_error /* Cleanup erroniously returned. */ .end qt_start /* ** Save calle-save floating-point regs $f2..$f9. ** Also save return pc from whomever called us. ** ** Return value from `qt_block' is the same as the return from ** `qt_blocki'. We get that for free since we don't touch $0 ** between the return from `qt_blocki' and the return from ** `qt_block'. */ .ent qt_block qt_block: subq $30,80, $30 /* Allocate a save space. */ stq $26, 0($30) /* Save registers. */ stt $f2, 8($30) stt $f3,16($30) stt $f4,24($30) stt $f5,32($30) stt $f6,40($30) stt $f7,48($30) stt $f8,56($30) stt $f9,64($30) jsr $26,qt_blocki /* Call helper. */ /* .. who will also restore $gp. */ ldq $26, 0($30) /* restore registers. */ ldt $f2, 8($30) ldt $f3,16($30) ldt $f4,24($30) ldt $f5,32($30) ldt $f6,40($30) ldt $f7,48($30) ldt $f8,56($30) ldt $f9,64($30) addq $30,80, $30 /* Deallcate save space. */ ret $31,($26),1 /* Return, predict===RET. */ .end qt_block systemc-2.3.3/src/sysc/packages/qt/md/m88k_b.s0000644000175000017500000000371613360325173020726 0ustar carstencarsten/* * QuickThreads -- Threads-building toolkit. * Copyright (c) 1993 by David Keppel * * Permission to use, copy, modify and distribute this software and * its documentation for any purpose and without fee is hereby * granted, provided that the above copyright notice and this notice * appear in all copies. This software is provided as a * proof-of-concept and for demonstration purposes; there is no * representation about the suitability of this software for any * purpose. */ .text .globl _b_call_reg .globl _b_call_imm .globl _b_add .globl _b_load _b_null: jmp r1 _b_call_reg: subu r31, r31,8 /* Alloc ret pc save space. */ st r1, r31,32 /* Save ret pc. */ or.u r3, r0,hi16(_b_null) /* Put call addr in a reg. */ or r3, r3,lo16(_b_null) jsr r3 L0: jsr r3 jsr r3 jsr r3 jsr.n r3 subu r2, r2,5 /* Decrement #of iter to go. */ bcnd.n gt0,r2,L0 jsr r3 ld r1, r31,32 jmp r1 _b_call_imm: subu r31, r31,8 /* Alloc ret pc save space. */ st r1, r31,32 /* Save ret pc. */ bsr _b_null L1: bsr _b_null bsr _b_null bsr _b_null bsr.n _b_null subu r2, r2,5 /* Decrement #of iter to go. */ bcnd.n gt0,r2,L1 bsr _b_null ld r1, r31,32 jmp r1 _b_add: add r0, r3,r4 L2: add r3, r4,r5 add r4, r5,r6 add r5, r6,r7 add r8, r9,r0 add r0, r3,r4 add r3, r4,r5 add r4, r5,r6 add r5, r6,r7 add r8, r9,r0 add r0, r3,r4 add r3, r4,r5 add r4, r5,r6 add r5, r6,r7 add r8, r9,r0 add r0, r3,r4 add r3, r4,r5 add r4, r5,r6 add r5, r6,r7 add r8, r9,r0 subu r2, r2,20 /* Decrement #of iter to go. */ bcnd.n gt0,r2,L2 add r0, r3,r4 jmp r1 _b_load: ld r0, r31,0 L3: ld r3, r31,4 ld r4, r31,8 ld r5, r31,12 ld r6, r31,16 ld r0, r31,0 ld r3, r31,4 ld r4, r31,8 ld r5, r31,12 ld r6, r31,16 ld r0, r31,0 ld r3, r31,4 ld r4, r31,8 ld r5, r31,12 ld r6, r31,16 ld r0, r31,0 ld r3, r31,4 ld r4, r31,8 ld r5, r31,12 ld r6, r31,16 subu r2, r2,20 /* Decrement #of iter to go. */ bcnd.n gt0,r2,L3 ld r0, r31,0 jmp r1 systemc-2.3.3/src/sysc/packages/qt/md/i386_b.s0000644000175000017500000000131613360325173020622 0ustar carstencarsten/* // QuickThreads -- Threads-building toolkit. // Copyright (c) 1993 by David Keppel // // Permission to use, copy, modify and distribute this software and // its documentation for any purpose and without fee is hereby // granted, provided that the above copyright notice and this notice // appear in all copies. This software is provided as a // proof-of-concept and for demonstration purposes; there is no // representation about the suitability of this software for any // purpose. */ .globl _b_call_reg .globl b_call_reg .globl _b_call_imm .globl b_call_imm .globl _b_add .globl b_add .globl _b_load .globl b_load _b_call_reg: b_call_reg: _b_call_imm: b_call_imm: _b_add: b_add: _b_load: b_load: hlt systemc-2.3.3/src/sysc/packages/qt/md/m88k.s0000644000175000017500000000760613360325173020427 0ustar carstencarsten/* m88k.s -- assembly support. */ /* * QuickThreads -- Threads-building toolkit. * Copyright (c) 1993 by David Keppel * * Permission to use, copy, modify and distribute this software and * its documentation for any purpose and without fee is hereby * granted, provided that the above copyright notice and this notice * appear in all copies. This software is provided as a * proof-of-concept and for demonstration purposes; there is no * representation about the suitability of this software for any * purpose. */ /* Callee-save r14..r25, r31(sp), r30(fp). r1 === return pc. * Argument registers r2..r9, return value r2..r3. * * On startup, restore regs so retpc === call to a function to start. * * We're going to call a function (r2) from within the context switch * routine. Call it on the new thread's stack on behalf of the old * thread. */ .globl _qt_block .globl _qt_blocki .globl _qt_abort .globl _qt_start .globl _qt_vstart /* ** r2: ptr to function to call once curr is suspended ** and control is on r5's stack. ** r3: 1'th arg to *r2. ** r4: 2'th arg to *r2. ** r5: sp of thread to suspend. ** ** The helper routine returns a value that is passed on as the ** return value from the blocking routine. Since we don't ** touch r2 between the helper's return and the end of ** function, we get this behavior for free. ** ** Same entry for integer-only and floating-point, since there ** are no separate integer and floating-point registers. ** ** Each procedure call sets aside a ``home region'' of 8 regs ** for r2-r9 for varargs. For context switches we don't use ** the ``home region'' for varargs so use it to save regs. ** Allocate 64 bytes of save space -- use 32 bytes of register ** save area passed in to us plus 32 bytes we allcated, use ** the other 32 bytes for save area for a save area to call ** the helper function. */ _qt_block: _qt_blocki: sub r31, r31,64 /* Allocate reg save space. */ st r1, r31,8+32 /* Save callee-save registers. */ st r14, r31,12+32 st.d r15, r31,16+32 st.d r17, r31,24+32 st.d r19, r31,32+32 st.d r21, r31,40+32 st.d r23, r31,48+32 st r25, r31,56+32 st r30, r31,60+32 _qt_abort: addu r14, r31,0 /* Remember old sp. */ addu r31, r5,0 /* Set new sp. */ jsr.n r2 /* Call helper. */ addu r2, r14,0 /* Pass old sp as an arg0 to helper. */ ld r1, r31,8+32 /* Restore callee-save registers. */ ld r14, r31,12+32 ld.d r15, r31,16+32 ld.d r17, r31,24+32 ld.d r19, r31,32+32 ld.d r21, r31,40+32 ld.d r23, r31,48+32 ld r25, r31,56+32 ld r30, r31,60+32 jmp.n r1 /* Return to new thread's caller. */ addu r31, r31,64 /* Free register save space. */ /* ** Non-varargs thread startup. ** See `m88k.h' for register use conventions. */ _qt_start: addu r2, r14,0 /* Set user arg `pu'. */ addu r3, r15,0 /* ... user function pt. */ jsr.n r17 /* Call `only'. */ addu r4, r16,0 /* ... user function userf. */ bsr _qt_error /* `only' erroniously returned. */ /* ** Varargs thread startup. ** See `m88k.h' for register use conventions. ** ** Call the `startup' function with just argument `pt'. ** Then call `vuserf' with 8 register args plus any ** stack args. ** Then call `cleanup' with `pt' and the return value ** from `vuserf'. */ _qt_vstart: addu r18, r30,0 /* Remember arg7 to `vuserf'. */ addu r30, r0,0 /* Null-terminate call chain. */ jsr.n r17 /* Call `startup'. */ addu r2, r15,0 /* `pt' is arg0 to `startup'. */ addu r2, r19,0 /* Set arg0. */ addu r3, r20,0 /* Set arg1. */ addu r4, r21,0 /* Set arg2. */ addu r5, r22,0 /* Set arg3. */ addu r6, r23,0 /* Set arg4. */ addu r7, r24,0 /* Set arg5. */ addu r8, r25,0 /* Set arg6. */ jsr.n r16 /* Call `vuserf'. */ addu r9, r18,0 /* Set arg7. */ addu r3, r2,0 /* Ret. value is arg1 to `cleanup'. */ jsr.n r14 /* Call `cleanup'. */ addu r2, r15,0 /* `pt' is arg0 to `cleanup'. */ bsr _qt_error /* `cleanup' erroniously returned. */ systemc-2.3.3/src/sysc/packages/qt/md/mips-irix5.s0000644000175000017500000001323613360325173021642 0ustar carstencarsten/* mips.s -- assembly support. */ /* * QuickThreads -- Threads-building toolkit. * Copyright (c) 1993 by David Keppel * * Permission to use, copy, modify and distribute this software and * its documentation for any purpose and without fee is hereby * granted, provided that the above copyright notice and this notice * appear in all copies. This software is provided as a * proof-of-concept and for demonstration purposes; there is no * representation about the suitability of this software for any * purpose. */ /* Callee-save $16-$23, $30-$31. * * $25 is used as a procedure value pointer, used to discover constants * in a callee. Thus, each caller here sets $25 before the call. * * On startup, restore regs so retpc === call to a function to start. * We're going to call a function ($4) from within this routine. * We're passing 3 args, therefore need to allocate 12 extra bytes on * the stack for a save area. The start routine needs a like 16-byte * save area. Must be doubleword aligned (_mips r3000 risc * architecture_, gerry kane, pg d-23). */ /* * Modified by Assar Westerlund to support Irix 5.x * calling conventions for dynamically-linked code. */ /* Make this position-independent code. */ .option pic2 .globl qt_block .globl qt_blocki .globl qt_abort .globl qt_start .globl qt_vstart /* ** $4: ptr to function to call once curr is suspended ** and control is on $7's stack. ** $5: 1'th arg to $4. ** $6: 2'th arg to $4 ** $7: sp of thread to suspend. ** ** Totally gross hack: The MIPS calling convention reserves ** 4 words on the stack for a0..a3. This routine "ought" to ** allocate space for callee-save registers plus 4 words for ** the helper function, but instead we use the 4 words ** provided by the function that called us (we don't need to ** save our argument registers). So what *appears* to be ** allocating only 40 bytes is actually allocating 56, by ** using the caller's 16 bytes. ** ** The helper routine returns a value that is passed on as the ** return value from the blocking routine. Since we don't ** touch $2 between the helper's return and the end of ** function, we get this behavior for free. */ qt_blocki: sub $sp,$sp,40 /* Allocate reg save space. */ sw $16, 0+16($sp) sw $17, 4+16($sp) sw $18, 8+16($sp) sw $19,12+16($sp) sw $20,16+16($sp) sw $21,20+16($sp) sw $22,24+16($sp) sw $23,28+16($sp) sw $30,32+16($sp) sw $31,36+16($sp) add $2, $sp,$0 /* $2 <= old sp to pass to func@$4. */ qt_abort: add $sp, $7,$0 /* $sp <= new sp. */ .set noreorder add $25, $4,$0 /* Set helper function procedure value. */ jal $31,$25 /* Call helper func@$4 . */ add $4, $2,$0 /* $a0 <= pass old sp as a parameter. */ .set reorder lw $31,36+16($sp) /* Restore callee-save regs... */ lw $30,32+16($sp) lw $23,28+16($sp) lw $22,24+16($sp) lw $21,20+16($sp) lw $20,16+16($sp) lw $19,12+16($sp) lw $18, 8+16($sp) lw $17, 4+16($sp) lw $16, 0+16($sp) /* Restore callee-save */ add $sp,$sp,40 /* Deallocate reg save space. */ j $31 /* Return to caller. */ /* ** Non-varargs thread startup. ** Note: originally, 56 bytes were allocated on the stack. ** The thread restore routine (_blocki/_abort) removed 40 ** of them, which means there is still 16 bytes for the ** argument area required by the MIPS calling convention. */ qt_start: add $4, $16,$0 /* Load up user function pu. */ add $5, $17,$0 /* ... user function pt. */ add $6, $18,$0 /* ... user function userf. */ add $25, $19,$0 /* Set `only' procedure value. */ jal $31,$25 /* Call `only'. */ la $25,qt_error /* Set `qt_error' procedure value. */ j $25 /* ** Save calle-save floating-point regs $f20-$f30 ** See comment in `qt_block' about calling conventinos and ** reserved space. Use the same trick here, but here we ** actually have to allocate all the bytes since we have to ** leave 4 words leftover for `qt_blocki'. ** ** Return value from `qt_block' is the same as the return from ** `qt_blocki'. We get that for free since we don't touch $2 ** between the return from `qt_blocki' and the return from ** `qt_block'. */ qt_block: sub $sp, $sp,56 /* 6 8-byte regs, saved ret pc, aligned. */ swc1 $f20, 0+16($sp) swc1 $f22, 8+16($sp) swc1 $f24, 16+16($sp) swc1 $f26, 24+16($sp) swc1 $f28, 32+16($sp) swc1 $f30, 40+16($sp) sw $31, 48+16($sp) jal qt_blocki lwc1 $f20, 0+16($sp) lwc1 $f22, 8+16($sp) lwc1 $f24, 16+16($sp) lwc1 $f26, 24+16($sp) lwc1 $f28, 32+16($sp) lwc1 $f30, 40+16($sp) lw $31, 48+16($sp) add $sp, $sp,56 j $31 /* ** First, call `startup' with the `pt' argument. ** ** Next, call the user's function with all arguments. ** Note that we don't know whether args were passed in ** integer regs, fp regs, or on the stack (See Gerry Kane ** "MIPS R2000 RISC Architecture" pg D-22), so we reload ** all the registers, possibly with garbage arguments. ** ** Finally, call `cleanup' with the `pt' argument and with ** the return value from the user's function. It is an error ** for `cleanup' to return. */ qt_vstart: add $4, $17,$0 /* `pt' is arg0 to `startup'. */ add $25, $18,$0 /* Set `startup' procedure value. */ jal $31, $25 /* Call `startup'. */ add $sp, $sp,16 /* Free extra save space. */ lw $4, 0($sp) /* Load up args. */ lw $5, 4($sp) lw $6, 8($sp) lw $7, 12($sp) lwc1 $f12, 0($sp) /* Load up fp args. */ lwc1 $f14, 8($sp) add $25, $19,$0 /* Set `userf' procedure value. */ jal $31,$25 /* Call `userf'. */ add $4, $17,$0 /* `pt' is arg0 to `cleanup'. */ add $5, $2,$0 /* Ret. val is arg1 to `cleanup'. */ add $25, $16,$0 /* Set `cleanup' procedure value. */ jal $31, $25 /* Call `cleanup'. */ la $25,qt_error /* Set `qt_error' procedure value. */ j $25 systemc-2.3.3/src/sysc/packages/qt/md/sparc.h0000644000175000017500000000735013360325173020731 0ustar carstencarsten/* * QuickThreads -- Threads-building toolkit. * Copyright (c) 1993 by David Keppel * * Permission to use, copy, modify and distribute this software and * its documentation for any purpose and without fee is hereby * granted, provided that the above copyright notice and this notice * appear in all copies. This software is provided as a * proof-of-concept and for demonstration purposes; there is no * representation about the suitability of this software for any * purpose. */ #ifndef QUICKTHREADS_SPARC_H #define QUICKTHREADS_SPARC_H typedef unsigned long qt_word_t; /* Stack layout on the sparc: non-varargs: +--- | | %o7 == return address -> qt_start | %i7 | %i6 == frame pointer -> 0 (NULL-terminated stack frame chain) | %i5 -> only | %i4 -> userf | %i3 | %i2 -> pt | %i1 -> pu | %i0 | %l7 | %l6 | %l5 | %l4 | %l3 | %l2 | %l1 | %l0 <--- qt_t.sp +--- varargs: | : | : | argument list | one-word aggregate return pointer +--- | | %o7 == return address -> qt_vstart | %i7 | %i6 == frame pointer -> 0 (NULL-terminated stack frame chain) | %i5 -> startup | %i4 -> userf | %i3 -> cleanup | %i2 -> pt | %i1 | %i0 | %l7 | %l6 | %l5 | %l4 | %l3 | %l2 | %l1 | %l0 <--- qt_t.sp +--- */ /* What to do to start a thread running. */ extern void qt_start (void); extern void qt_vstart (void); /* Hold 17 saved registers + 1 word for alignment. */ #define QUICKTHREADS_STKBASE (18 * 4) #define QUICKTHREADS_VSTKBASE QUICKTHREADS_STKBASE /* Stack must be doubleword aligned. */ #define QUICKTHREADS_STKALIGN (8) /* Doubleword aligned. */ #define QUICKTHREADS_ONLY_INDEX (QUICKTHREADS_I5) #define QUICKTHREADS_USER_INDEX (QUICKTHREADS_I4) #define QUICKTHREADS_ARGT_INDEX (QUICKTHREADS_I2) #define QUICKTHREADS_ARGU_INDEX (QUICKTHREADS_I1) #define QUICKTHREADS_VSTARTUP_INDEX (QUICKTHREADS_I5) #define QUICKTHREADS_VUSERF_INDEX (QUICKTHREADS_I4) #define QUICKTHREADS_VCLEANUP_INDEX (QUICKTHREADS_I3) #define QUICKTHREADS_VARGT_INDEX (QUICKTHREADS_I2) #define QUICKTHREADS_O7 (16) #define QUICKTHREADS_I6 (14) #define QUICKTHREADS_I5 (13) #define QUICKTHREADS_I4 (12) #define QUICKTHREADS_I3 (11) #define QUICKTHREADS_I2 (10) #define QUICKTHREADS_I1 ( 9) /* The thread will ``return'' to the `qt_start' routine to get things going. The normal return sequence takes us to QUICKTHREADS_O7+8, so we pre-subtract 8. The frame pointer chain is 0-terminated to prevent the trap handler from chasing off in to random memory when flushing stack windows. */ #define QUICKTHREADS_ARGS_MD(top) \ (QUICKTHREADS_SPUT ((top), QUICKTHREADS_O7, ((void *)(((int)qt_start)-8))), \ QUICKTHREADS_SPUT ((top), QUICKTHREADS_I6, 0)) /* The varargs startup routine always reads 6 words of arguments (6 argument registers) from the stack, offset by one word to allow for an aggregate return area pointer. If the varargs routine actually pushed fewer words than that, qt_vstart could read off the top of the stack. To prevent errors, we always allocate 8 words. The space is often just wasted. */ #define QUICKTHREADS_VARGS_MD0(sp, vabytes) \ ((qt_t *)(((char *)(sp)) - 8*4 - QUICKTHREADS_STKROUNDUP(vabytes))) #define QUICKTHREADS_VARGS_MD1(sp) \ (QUICKTHREADS_SPUT (sp, QUICKTHREADS_O7, ((void *)(((int)qt_vstart)-8)))) /* The SPARC has wierdo calling conventions which stores a hidden parameter for returning aggregate values, so the rest of the parameters are shoved up the stack by one place. */ #define QUICKTHREADS_VARGS_ADJUST(sp) (((char *)sp)+4) #define QUICKTHREADS_VARGS_DEFAULT #define QUICKTHREADS_GROW_DOWN #endif /* ndef QUICKTHREADS_SPARC_H */ systemc-2.3.3/src/sysc/packages/qt/md/powerpc_sys5.s0000644000175000017500000004321613360325173022277 0ustar carstencarsten/* powerpc-sys5.s -- assembly support. */ /* * QuickThreads -- Threads-building toolkit. * Copyright (c) 1993 by David Keppel * * Permission to use, copy, modify and distribute this software and * its documentation for any purpose and without fee is hereby * granted, provided that the above copyright notice and this notice * appear in all copies. This software is provided as a * proof-of-concept and for demonstration purposes; there is no * representation about the suitability of this software for any * purpose. * PowerPC-System V thread switching module. * * This software is largely based on the original PowerPC-Linux porting * developed by Ken Aaker * * Marco Bucci * December 2002 * */ /* * * PowerPC Register convections: * * r0 volatile * r1 SP * r2 system reserved * r3-r4 volatile for parameter passing and function return * r5-r10 volatile for parameter passing * r11-r12 volatile * r13-r14 non volatile registers * f0 volatile * f1 volatile for parameter passing and function return * f2-f13 volatile for parameter passing * f14-f31 non volatile * * cr2-cr4 non volatile * * * See on the heather file for more documentation. * * * * IMPLEMENTATION NOTES * * * 1) Condition register saving * On most machines, the condition code register is caller-save. * On the PPC, the condition code register is callee-save, so the * thread context switch must preserve it. * * * 2) Floating point registers saving * On resuming a thread, floating point registers are or not restored just * depending on which block routine suspended the thread (i.e. regardless * whether "qt_block", "qt_blocki" or "qt_abort" is used to resume it). * This behaviour is obtained by implementing "qt_block" by means af a nested * call to "qt_blocki". As a result, the blocking of a thread always goes * and returns through "qt_blocki and, if a thread was blocked by "qt_block", * its execution resumes from the floating point restoring code on exit * of "qt_block". * * Thanks to David Keppel that explained me this "simple" trick. * * * 3) C languace code debugging * The original version of this software was developed and debugged under * MacOS X using the Metrowerks Code Warrior PPC integrated assembler. * It could be still used with a C inline assembler by means of a suitable * file to include it. * In order to avoid "copy and paste" bugs, and make easyer the maintaining, * I made the minimal changes, so you can find some strange code as: * * #if 0 * .if 0 * C code here * .endif * #endif * * This is just to embed some C code that is needed by the Code Warrior * integrated assembler. * * * 4) Assembly constants generation * Constants used in the assembly code are generated by running * the C code in the sequel (commented). It uses the C macros declared in * the C heather in order to guarantee that the C interface and the assebly * code are "aligned". I avoided the use of an assebler preprocessor since * they are not so standard and moreover using macro espressions makes the * assembly debugging more difficult. * * #include #include "powerpc_sys5.h" int main() { using namespace std; int i; cout << ".set LR_SAVE, " << PPC_LR_SAVE << endl; cout << ".set BLOCKI_FSIZE, " << QUICKTHREADS_BLOCKI_FRAME_SIZE << endl; cout << ".set BLOCKI_CR_SAVE, " << QUICKTHREADS_BLOCKI_CR_SAVE << endl; cout << ".set BLOCK_FSIZE, " << QUICKTHREADS_BLOCK_FRAME_SIZE << endl; cout << endl; for(i=0; i<12; i++) cout << ".set PAR_" << i << ", " << PPC_PAR(i) << endl; cout << endl; i = 13; cout << ".set GPR_SAVE_" << i << ", " << QUICKTHREADS_BLOCKI_GPR_SAVE(i) << endl; cout << endl; for(i=31; i>13; i--) cout << ".set FPR_SAVE_" << i << ", " << QUICKTHREADS_BLOCK_FPR_SAVE(i) << endl; cout << endl; cout << ".set VARGS_BKOFF, " << QUICKTHREADS_VARGS_BKOFF << endl; cout << endl << endl << endl; for(i=31; i>13; i--) cout << "\tstfd\tf" << i << ",FPR_SAVE_" << i << "(%r1)" << endl; cout << endl; for(i=31; i>13; i--) cout << "\tlfd \tf" << i << ",FPR_SAVE_" << i << "(%r1)" << endl; cout << endl << endl << endl; return 0; } * * * */ #if 0 .text .align 4 .globl qt_block .globl _qt_block .globl qt_blocki .globl _qt_blocki .globl qt_abort .globl _qt_abort .globl qt_start .globl _qt_start .globl qt_vstart .globl _qt_vstart .set LR_SAVE, 4 .set BLOCKI_FSIZE, 96 .set BLOCKI_CR_SAVE, 8 /* CR is saved into the callee's stack frame */ .set BLOCK_FSIZE, 160 .set PAR_0, 8 .set PAR_1, 12 .set PAR_2, 16 .set PAR_3, 20 .set PAR_4, 24 .set PAR_5, 28 .set PAR_6, 32 .set PAR_7, 36 .set PAR_8, 40 .set PAR_9, 44 .set PAR_10, 48 .set PAR_11, 52 .set GPR_SAVE_13, 20 .set FPR_SAVE_31, 152 .set FPR_SAVE_30, 144 .set FPR_SAVE_29, 136 .set FPR_SAVE_28, 128 .set FPR_SAVE_27, 120 .set FPR_SAVE_26, 112 .set FPR_SAVE_25, 104 .set FPR_SAVE_24, 96 .set FPR_SAVE_23, 88 .set FPR_SAVE_22, 80 .set FPR_SAVE_21, 72 .set FPR_SAVE_20, 64 .set FPR_SAVE_19, 56 .set FPR_SAVE_18, 48 .set FPR_SAVE_17, 40 .set FPR_SAVE_16, 32 .set FPR_SAVE_15, 24 .set FPR_SAVE_14, 16 /* various offsets used by "qt_varg" */ .set P_T, PAR_0 .set P_STARTUP, PAR_1 .set P_USERF, PAR_2 .set P_CLEANUP, PAR_3 /* the offset used to move back the linkage area to be adiacent to * the variant argument list before calling "userf(...). * Skip "t", "startup", "userf", "cleanup" and first * 8 parameters (since they are passed via registers) */ .set VARGS_BKOFF, 48 /* location where "t" and "cleanup" are saved (with respect of * the stack frame base) */ .set P_T_SAVE, -4 .set P_CLEANUP_SAVE, -8 #endif /* Block the current thread saving all integer non volatile registers and * start a new thread. */ #if 0 .if 0 #endif void *qt_blocki (void *helper, void *a0, void *a1, void *newthread); asm void *qt_blocki (void *helper, void *a0, void *a1, void *newthread) { #if 0 .endif #endif #if 0 qt_blocki: _qt_blocki: #endif /* prolog code */ stwu %r1,-BLOCKI_FSIZE(%r1) /* allocate the stack frame */ mflr %r0 /* return addr in r0 */ mfcr %r11 /* CR in r11 */ stw %r0,LR_SAVE+BLOCKI_FSIZE(%r1) /* save return addr in the stack */ stw %r11,BLOCKI_CR_SAVE(%r1) /* save CR in the stack */ stmw %r13,GPR_SAVE_13(%r1) /* save non-volatile reg */ /* call helper(qt_t *old, void *a0, void *a1) */ mtlr %r3 /* "helper" addr in the link reg */ mr %r3,%r1 /* current thread (i.e. the SP) in arg "old" */ mr %r1,%r6 /* swap to the new thread (i.e. to its SP) */ blrl /* jump to "helper" */ /* the "helper" return value is returned (since r3 is not changed) */ /* epilog code: return to the new thread's "qt_blocki" caller */ lmw %r13,GPR_SAVE_13(%r1) /* restore non-volatile reg */ lwz %r0,LR_SAVE+BLOCKI_FSIZE(%r1) /* recover return addr */ lwz %r11,BLOCKI_CR_SAVE(%r1) /* recover CR */ mtlr %r0 /* return address in the link reg */ mtcr %r11 /* restore CR */ addi %r1,%r1,BLOCKI_FSIZE /* free the stack frame */ blr /* return */ #if 0 .if 0 #endif } #if 0 .endif #endif /* Abort the current thread and start a new thread. */ #if 0 .if 0 #endif void qt_abort (void *helper, void *a0, void *a1, void *newthread); asm void qt_abort (void *helper, void *a0, void *a1, void *newthread) { #if 0 .endif #endif #if 0 qt_abort: _qt_abort: #endif /* prolog code */ /* there is no prolog. It will never come back */ /* call helper(qt_t *old, void *a0, void *a1) */ mtlr %r3 /* "helper" addr in the link reg */ mr %r1,%r6 /* swap to the new thread (i.e. to its SP) */ /* we don't need to set "old", we can pass just garbage. Actually, since r3 is not changed, "old" is set to "helper" (don't care) */ blrl /* call "helper" */ /* the "helper" return value is returned (since r3 is not changed) */ /* epilog code: return to the new thread's "qt_blocki" caller */ lmw %r13,GPR_SAVE_13(%r1) /* restore non-volatile reg */ lwz %r0,LR_SAVE+BLOCKI_FSIZE(%r1) /* recover return addr */ lwz %r11,BLOCKI_CR_SAVE(%r1) /* recover CR */ mtlr %r0 /* return address in the link reg */ mtcr %r11 /* restore CR */ addi %r1,%r1,BLOCKI_FSIZE /* free the stack frame */ blr /* return */ #if 0 .if 0 #endif } #if 0 .endif #endif /* Block the current thread saving all non volatile registers and start * a new thread. */ #if 0 .if 0 #endif void *qt_block (void *helper, void *a0, void *a1, void *newthread); asm void *qt_block (void *helper, void *a0, void *a1, void *newthread) { #if 0 .endif #endif # if 0 qt_block: _qt_block: #endif /* prolog code */ stwu %r1,-BLOCK_FSIZE(%r1) /* allocate the stack frame */ mflr %r0 /* return addr in r0 */ stw %r0,LR_SAVE+BLOCK_FSIZE(%r1) /* save return addr in the stack */ /* save non-volatile fp reg */ stfd %f31,FPR_SAVE_31(%r1) stfd %f30,FPR_SAVE_30(%r1) stfd %f29,FPR_SAVE_29(%r1) stfd %f28,FPR_SAVE_28(%r1) stfd %f27,FPR_SAVE_27(%r1) stfd %f26,FPR_SAVE_26(%r1) stfd %f25,FPR_SAVE_25(%r1) stfd %f24,FPR_SAVE_24(%r1) stfd %f23,FPR_SAVE_23(%r1) stfd %f22,FPR_SAVE_22(%r1) stfd %f21,FPR_SAVE_21(%r1) stfd %f20,FPR_SAVE_20(%r1) stfd %f19,FPR_SAVE_19(%r1) stfd %f18,FPR_SAVE_18(%r1) stfd %f17,FPR_SAVE_17(%r1) stfd %f16,FPR_SAVE_16(%r1) stfd %f15,FPR_SAVE_15(%r1) stfd %f14,FPR_SAVE_14(%r1) /* block the thread */ bl qt_blocki /* the thread is going to be resumed */ /* restore non-volatile fp reg */ lfd %f31,FPR_SAVE_31(%r1) lfd %f30,FPR_SAVE_30(%r1) lfd %f29,FPR_SAVE_29(%r1) lfd %f28,FPR_SAVE_28(%r1) lfd %f27,FPR_SAVE_27(%r1) lfd %f26,FPR_SAVE_26(%r1) lfd %f25,FPR_SAVE_25(%r1) lfd %f24,FPR_SAVE_24(%r1) lfd %f23,FPR_SAVE_23(%r1) lfd %f22,FPR_SAVE_22(%r1) lfd %f21,FPR_SAVE_21(%r1) lfd %f20,FPR_SAVE_20(%r1) lfd %f19,FPR_SAVE_19(%r1) lfd %f18,FPR_SAVE_18(%r1) lfd %f17,FPR_SAVE_17(%r1) lfd %f16,FPR_SAVE_16(%r1) lfd %f15,FPR_SAVE_15(%r1) lfd %f14,FPR_SAVE_14(%r1) lwz %r0,LR_SAVE+BLOCK_FSIZE(%r1) /* recover return addr */ mtlr %r0 /* return address in the link reg */ addi %r1,%r1,BLOCK_FSIZE /* free the stack frame */ blr /* return */ #if 0 .if 0 #endif } #if 0 .endif #endif /* Start a single argument thread using parameters preloaded in the stack * during thread initialization (see comments on stack initialization in the * heather file). * * Executes: * * only(u, t, userf); */ #if 0 .if 0 #endif void qt_start(void); asm void qt_start(void) { #if 0 .endif #endif #if 0 qt_start: _qt_start: #endif lwz %r3,PAR_0(%r1) /* "u" in r3 */ lwz %r4,PAR_1(%r1) /* "t" in r4 */ lwz %r5,PAR_2(%r1) /* "userf" in r5 */ lwz %r6,PAR_3(%r1) /* "only" in r6 */ mtlr %r6 /* "only" address in the link reg */ /* call only(u, t, userf) */ blrl /* jump to "only" */ /* error if it returns */ b qt_error /* dead code (some inline asm "wants" the epilog, or they genetare it) */ blr #if 0 .if 0 #endif } #if 0 .endif #endif /* Start a variant argument thread using parameters preloaded in the stack * during thread initialization (see comments on stack initialization in the * heather file). * * Executes: * * startup(t); * userf_return = userf(...); * cleanup(pt, userf_return); * ***** Stack layout on start ***** backchain -> STACK BOTTOM (higher address) +==========================+ backchain - 4 -> | | + LOCAL VARIABLES AREA + .............. + + | | +--------------------------+ | | + ALIGNMEBNT PAD + .............. + (if needed) + | | +--------------------------+ | | arg(n) + + | | + VARIABLE ARGUMENT LIST + .............. + for userf call + SP + PAR(5) -> | | arg(1) + + SP + PAR(4) -> | | arg(0) +--------------------------+ SP + PAR(3) -> | | cleanup par + + SP + PAR(2) -> | | userf par + PARAMETER AREA + SP + PAR(1) -> | | startup par + + SP + PAR(0) -> | | t par +--------------------------+ | | + LINKAGE AREA + SP -> | | +==========================+ STACK TOP (lower address) Stack grows down | V ***** Stack layout before call userf ***** backchain -> STACK BOTTOM (higher address) +==========================+ backchain - 4 -> | | + LOCAL VARIABLES AREA + .............. + + | | +--------------------------+ | | + ALIGNMEBNT PAD + .............. + (if needed) + | | +--------------------------+ | | arg(n) + + | | + VARIABLE ARGUMENT LIST + .............. + for userf call + SP + PAR(1) -> | | arg(1) + + SP + PAR(0) -> | | arg(0) +--------------------------+ | | + LINKAGE AREA + SP -> | | +==========================+ STACK TOP (lower address) Stack grows down | V * To call "userf(...)", the argument list must be adiacent to the linkage * area. Instead of copy the argument list, we move back the linkage area * (actually, we just increase the SP and copy the backchain). "t" and * "cleanup" are saved in a local variable area in order to call * cleanup(pt, userf_return). */ #if 0 .if 0 #endif void qt_vstart(void); asm void qt_vstart(void) { #if 0 .endif #endif #if 0 qt_vstart: _qt_vstart: #endif /* NOTICE: the callee routines could save parameter registers in the caller's * stack parameter area. We put "t" in PAR(0) in such a way, if startup(t) * will save "t", it will be saved on the same location thus not delething * any other parameter. */ /* since we will move back the linckage area (to make it adiacent to the * parameter list), we need to save "t" and "cleanup". We have made room for * this on the bottom of the stack frame. */ /* save parameters in the local variable area */ lwz %r11,0(%r1) /* get the backchain */ lwz %r3,P_T(%r1) lwz %r4,P_CLEANUP(%r1) stw %r3,P_T_SAVE(%r11) /* save "pt" */ stw %r4,P_CLEANUP_SAVE(%r11) /* save "cleanup" */ /* call startup(t) */ lwz %r5,P_STARTUP(%r1) mtlr %r5 blrl /* call "startup" */ /* call userf(...) */ lwz %r11,0(%r1) /* reload backchain (r11 is volatile) */ lwz %r4,P_USERF(%r1) /* load "userf" */ mtlr %r4 /* first eight parameter of the variant list must be copyed in * GPR3-GPR10. There is a four places offset due to "t", "startup", * userf" and "cleanup" */ lwz %r3,PAR_4(%r1) lwz %r4,PAR_5(%r1) lwz %r5,PAR_6(%r1) lwz %r6,PAR_7(%r1) lwz %r7,PAR_8(%r1) lwz %r8,PAR_9(%r1) lwz %r9,PAR_10(%r1) lwz %r10,PAR_11(%r1) /* move the linkage area to be adiacent to the argument list */ stw %r11,VARGS_BKOFF(%r1) /* copy backchain */ addi %r1,%r1,VARGS_BKOFF /* move back the stack */ blrl /* call "userf" */ /* call qt_cleanup(void *pt, void *vuserf_return) */ lwz %r11,0(%r1) /* reload backchain (r11 is volatile) */ mr %r4,%r3 /* push "userf" return as 2nd parameter */ lwz %r3,P_T_SAVE(%r11) /* reload "pt" */ lwz %r5,P_CLEANUP_SAVE(%r11) /* reload "cleanup" */ mtlr %r5 blrl b qt_error /* dead code (some inline asm "wants" the epilog, or they genetare it) */ blr #if 0 .if 0 #endif } #if 0 .endif #endif systemc-2.3.3/src/sysc/packages/qt/md/ksr1.s0000644000175000017500000002760613360325173020522 0ustar carstencarsten/* * QuickThreads -- Threads-building toolkit. * Copyright (c) 1993 by David Keppel * * Permission to use, copy, modify and distribute this software and * its documentation for any purpose and without fee is hereby * granted, provided that the above copyright notice and this notice * appear in all copies. This software is provided as a * proof-of-concept and for demonstration purposes; there is no * representation about the suitability of this software for any * purpose. */ .file "ksr1.s" .def .debug; .endef .align 128 .globl qt_blocki .globl qt_blocki$TXT .globl qt_block .globl qt_block$TXT .globl qt_start$TXT .globl qt_start .globl qt_abort$TXT .globl qt_abort .globl qt_vstart .globl qt_vstart$TXT # # KSR convention: on procedure calls, load both the procedure address # and a pointer to a constant block. The address of function `f' is # `f$TXT', and the constant block address is `f'. The constant block # has several reserved values: # # 8 bytes fpu register save mask # 4 bytes ipu register save mask # 4 bytes ceu register save mask # f: f$TXT # ... whatever you want ... (not quite...read on) # # Note, by the way, that a pointer to a function is passed as a # pointer to the constant area, and the constant area has the text # address. # # # Procedures that do not return structures prefix their code with # # proc$TXT: # finop; cxnop # finop; cxnop # # # Calls to those procedures branch to a 16 byte offset (4 instrs) in # to the procedure to skip those instructions. # # Procedures that return structures use a different code prefix: # # proc$TXT: # finop; beq.qt %rc, %rc, 24 # return value entry # finop; cxnop # finop; movi8 0, %rc # no return value entry # # # Calls that want the returned structure branch directly to the # procedure address. Callers that don't want (or aren't expecting) a # return value branche 16 bytes in to the procedure, which will zero # %rc, telling the called procedure not to return a structure. # # # On entry: # %i2 -- control block of helper function to run # (dereference to get helper) # %i3 -- a1 # %i4 -- a2 # %i5 -- sp of new to run # .data .half 0x0, 0x0, 0x7ffff000, 0x7fff8000 qt_blocki: qt_abort: .word qt_blocki$TXT .word qt_restore$TXT .text qt_abort$TXT: qt_blocki$TXT: finop ; cxnop # entry prefix finop ; cxnop # entry prefix add8.ntr 75,%i31,%i31 ; movi8 512,%c5 # ICR; stk adjust finop ; ssub8.ntr 0,%sp,%c5,%sp finop ; st8 %fp,504(%sp) # Save caller's fp finop ; st8 %cp,496(%sp) # Save caller's cp finop ; ld8 8(%c10),%c5 # ld qt_restore$TXT finop ; st8 %c14,0(%sp) # Save special ret addr finop ; mov8_8 %c10, %cp # Our cp finop ; sadd8.ntr 0,%sp,%c5,%fp # Our frame ptr finop ; st8 %c5,8(%sp) # st qt_restore$TXT # # CEU registers %c15-%c24, %c26-%c30 (%c14 we restore later) # finop ; st8 %c15,456(%sp) finop ; st8 %c16,448(%sp) finop ; st8 %c17,440(%sp) finop ; st8 %c18,432(%sp) finop ; st8 %c19,424(%sp) finop ; st8 %c20,416(%sp) finop ; st8 %c21,408(%sp) finop ; st8 %c22,400(%sp) finop ; st8 %c23,392(%sp) finop ; st8 %c24,384(%sp) # # %c25 is the Enclosing Frame Pointer (EFP) -- since C doesn't # use nested procedures, we ignore it (leaving a gap, though) # finop ; st8 %c26,368(%sp) finop ; st8 %c27,360(%sp) finop ; st8 %c28,352(%sp) finop ; st8 %c29,344(%sp) finop ; st8 %c30,336(%sp) # # IPU registers %i12-%i30 # finop ; st8 %i12,328(%sp) finop ; st8 %i13,320(%sp) finop ; st8 %i14,312(%sp) finop ; st8 %i15,304(%sp) # (gap to get alignment for st64) # -- Doesn't work on version 1.1.3 of the OS # finop ; st64 %i16,256(%sp) finop ; st8 %i16,256(%sp) finop ; st8 %i17,248(%sp) finop ; st8 %i18,240(%sp) finop ; st8 %i19,232(%sp) finop ; st8 %i20,224(%sp) finop ; st8 %i21,216(%sp) finop ; st8 %i22,208(%sp) finop ; st8 %i23,200(%sp) finop ; st8 %i24,192(%sp) finop ; st8 %i25,184(%sp) finop ; st8 %i26,176(%sp) finop ; st8 %i27,168(%sp) finop ; st8 %i28,160(%sp) finop ; st8 %i29,152(%sp) finop ; st8 %i30,144(%sp) # # FPU already saved, or saving not necessary # # # Switch to the stack passed in as fourth argument to the block # routine (%i5) and call the helper routine passed in as the first # argument (%i2). Note that the address of the helper's constant # block is passed in, so we must derefence it to get the helper's text # address. # finop ; movb8_8 %i2,%c10 # helper's ConstBlock finop ; cxnop # Delay slot, fill w/ finop ; cxnop # .. 2 st8 from above finop ; ld8 0(%c10),%c4 # load addr of helper finop ; movb8_8 %sp, %i2 # 1st arg to helper # is this stack; other # args remain in regs finop ; movb8_8 %i5,%sp # switch stacks finop ; jsr %c14,16(%c4) # call helper movi8 3, %i0 ; movi8 0,%c8 # nargs brain dmg finop ; cxnop finop ; cxnop # # Here is where behavior differs for threads being restored and threads # being started. Blocked threads have a pointer to qt_restore$TXT on # the top of their stacks; manufactured stacks have a pointer to qt_start$TXT # on the top of their stacks. With this setup, starting threads # skip the (unecessary) restore operations. # # We jump to an offset of 16 to either (1) skip past the two noop pairs # at the start of qt_start$TXT, or (2) skip past the two noop pairs # after qt_restore$TXT. # finop ; ld8 8(%sp),%c4 finop ; cxnop finop ; cxnop finop ; jmp 16(%c4) qt_restore$TXT: finop ; cxnop finop ; cxnop # # Point of Restore: # # The helper funtion will return here. Any result it has placed in # a return register (most likely %i0) will not get overwritten below # and will consequently be the return value of the blocking routine. # # # CEU registers %c15-%c24, %c26-%c30 (%c14 we restore later) # finop ; ld8 456(%sp),%c15 finop ; ld8 448(%sp),%c16 finop ; ld8 440(%sp),%c17 finop ; ld8 432(%sp),%c18 finop ; ld8 424(%sp),%c19 finop ; ld8 416(%sp),%c20 finop ; ld8 408(%sp),%c21 finop ; ld8 400(%sp),%c22 finop ; ld8 392(%sp),%c23 finop ; ld8 384(%sp),%c24 # # %c25 is the Enclosing Frame Pointer (EFP) -- since C doesn't # use nested procedures, we ignore it (leaving a gap, though) # finop ; ld8 368(%sp),%c26 finop ; ld8 360(%sp),%c27 finop ; ld8 352(%sp),%c28 finop ; ld8 344(%sp),%c29 finop ; ld8 336(%sp),%c30 # # IPU registers %i12-%i30 # finop ; ld8 328(%sp),%i12 finop ; ld8 320(%sp),%i13 finop ; ld8 312(%sp),%i14 finop ; ld8 304(%sp),%i15 # (gap to get alignment for ld64) # -- Doesn't work on version 1.1.3 of the OS # finop ; ld64 256(%sp),%i16 finop ; ld8 256(%sp),%i16 finop ; ld8 248(%sp),%i17 finop ; ld8 240(%sp),%i18 finop ; ld8 232(%sp),%i19 finop ; ld8 224(%sp),%i20 finop ; ld8 216(%sp),%i21 finop ; ld8 208(%sp),%i22 finop ; ld8 200(%sp),%i23 finop ; ld8 192(%sp),%i24 finop ; ld8 184(%sp),%i25 finop ; ld8 176(%sp),%i26 finop ; ld8 168(%sp),%i27 finop ; ld8 160(%sp),%i28 finop ; ld8 152(%sp),%i29 finop ; ld8 144(%sp),%i30 # # FPU registers don't need to be loaded, or will be loaded by an # enclosing scope (e.g., if this is called by qt_block). # # # Load the special registers. We don't load the stack ptr because # the new stack is passed in as an argument, we don't load the EFP # because we don't use it, and we load the return address specially # off the top of the stack. # finop ; ld8 0(%sp),%c14 # return addr finop ; ld8 496(%sp),%cp finop ; ld8 504(%sp),%fp finop ; jmp 32(%c14) # jump back to thread finop ; movi8 512,%c5 # stack adjust finop ; sadd8.ntr 0,%sp,%c5,%sp .data .half 0x0, 0x0, 0x7ffff000, 0x7fff8000 qt_block: .word qt_block$TXT .word qt_error .word qt_error$TXT .word qt_blocki # # Handle saving and restoring the FPU regs, relying on qt_blocki # to save and restore the remaining registers. # .text qt_block$TXT: finop ; cxnop # entry prefix finop ; cxnop # entry prefix add8.ntr 29,%i31,%i31 ; movi8 512,%c5 # ICR; stk adjust finop ; ssub8.ntr 0,%sp,%c5,%sp finop ; st8 %fp,504(%sp) # Save caller's fp finop ; st8 %cp,496(%sp) # Save caller's cp finop ; st8 %c14,488(%sp) # store ret addr finop ; sadd8.ntr 0,%sp,%c5,%fp # Our frame ptr finop ; mov8_8 %c10, %cp # Our cp # # Store 8 registers at once...destination must be a multiple of 64 # finop ; st64 %f16,384(%sp) finop ; st64 %f24,320(%sp) finop ; st64 %f32,256(%sp) finop ; st64 %f40,192(%sp) finop ; st64 %f48,128(%sp) finop ; st64 %f56,64(%sp) # # Call the integer blocking routine, passing the arguments passed to us # finop ; ld8 24(%cp), %c10 finop ; cxnop finop ; jsr %c14, qt_blocki$TXT finop ; cxnop finop ; cxnop movi8 4,%i0 ; movi8 0,%c8 # nargs brain dmg # # Load 8 registers at once...source must be a multiple of 64 # finop ; ld64 64(%sp),%f56 finop ; ld64 128(%sp),%f48 finop ; ld64 192(%sp),%f40 finop ; ld64 256(%sp),%f32 finop ; ld64 320(%sp),%f24 finop ; ld64 384(%sp),%f16 finop ; ld8 488(%sp),%c14 finop ; ld8 496(%sp),%cp finop ; ld8 504(%sp),%fp finop ; jmp 32(%c14) # jump back to thread finop ; movi8 512,%c5 # stack adjust finop ; sadd8.ntr 0,%sp,%c5,%sp .data .half 0x0, 0x0, 0x7ffff000, 0x7fff8000 qt_start: .word qt_start$TXT # # A new thread is set up to "appear" as if it were executing code at # the beginning of qt_start and then it called a blocking routine # (qt_blocki). So when a new thread starts to run, it gets unblocked # by the code above and "returns" to `qt_start$TXT' in the # restore step of the switch. Blocked threads jump to 16(qt_restore$TXT), # and starting threads jump to 16(qt_start$TXT). # .text qt_start$TXT: finop ; cxnop # finop ; cxnop # finop ; ld8 40(%sp),%c10 # `only' constant block finop ; ld8 32(%sp),%i4 # `userf' arg. finop ; ld8 24(%sp),%i3 # `t' arg. finop ; ld8 0(%c10),%c4 # `only' text location finop ; ld8 16(%sp),%i2 # `u' arg. finop ; cxnop finop ; jsr %c14,16(%c4) # call `only' # # Pop the frame used to store the thread's initial data # finop ; sadd8.ntr 0,%sp,128,%sp finop ; cxnop movi8 2,%i0 ; movi8 0,%c8 # nargs brain dmg # # If we ever return, it's an error. # finop ; jmp qt_error$TXT finop ; cxnop finop ; cxnop movi8 0,%i0 ; movi8 0,%c8 # nargs brain dmg # # This stuff is broken # .data .half 0x0, 0x0, 0x7ffff000, 0x7fff8000 qt_vstart: .word qt_vstart$TXT .text qt_vstart$TXT: finop ; cxnop # entry prefix finop ; cxnop # entry prefix finop ; cxnop finop ; cxnop add8.ntr 11,%i31,%i31 ; movi8 512,%c5 finop ; ssub8.ntr 0,%sp,%c5,%sp # fix stack finop ; ld8 8(%sp),%i2 # load `t' as arg to finop ; cxnop # `startup' finop ; cxnop finop ; ld8 16(%sp),%c10 # `startup' const block finop ; cxnop finop ; cxnop finop ; ld8 0(%c10),%c4 # `startup' text loc. finop ; cxnop finop ; cxnop finop ; jsr %c14,16(%c4) # call `startup' finop ; cxnop finop ; cxnop movi8 1, %i0 ; movi8 0,%c8 # nargs brain dmg # # finop ; sadd 0,%sp,128,%sp # alter stack # finop ; ld8 8(%sp),%i2 # load `t' as arg to finop ; ld8 8(%sp),%i2 # load `t' as arg to finop ; ld8 8(%sp),%i2 # load `t' as arg to finop ; ld8 8(%sp),%i2 # load `t' as arg to finop ; ld8 32(%sp),%c10 # `only' constant block finop ; ld8 8(%sp),%i2 # `u' arg. finop ; ld8 16(%sp),%i3 # `t' arg. finop ; ld8 0(%c10),%c4 # `only' text location finop ; ld8 24(%sp),%i4 # `userf' arg. finop ; cxnop finop ; jsr %c4,16(%c4) # call `only' finop ; cxnop finop ; cxnop # # If the callee ever calls `nargs', the following instruction (pair) # will be executed. However, we don't know when we compile this code # how many args are being passed. So we give our best guess: 0. # movi8 0,%i0 ; movi8 0,%c8 # nargs brain dmg # # If we ever return, it's an error. # finop ; jmp qt_error$TXT finop ; cxnop finop ; cxnop movi8 0,%i0 ; movi8 0,%c8 # nargs brain dmg systemc-2.3.3/src/sysc/packages/qt/md/vax_b.s0000644000175000017500000000247013360325173020731 0ustar carstencarsten/* * QuickThreads -- Threads-building toolkit. * Copyright (c) 1993 by David Keppel * * Permission to use, copy, modify and distribute this software and * its documentation for any purpose and without fee is hereby * granted, provided that the above copyright notice and this notice * appear in all copies. This software is provided as a * proof-of-concept and for demonstration purposes; there is no * representation about the suitability of this software for any * purpose. */ .text .globl _b_call_reg .globl _b_call_imm .globl _b_add .globl _b_load _b_null: .word 0x0 ret _b_call_reg: .word 0x0 movl 4(ap),r0 moval _b_null,r1 L0: calls $0,(r1) calls $0,(r1) calls $0,(r1) calls $0,(r1) calls $0,(r1) subl2 $5,r0 bgtr L0 ret _b_call_imm: .word 0x0 movl 4(ap),r0 L1: calls $0,_b_null calls $0,_b_null calls $0,_b_null calls $0,_b_null calls $0,_b_null subl2 $5,r0 bgtr L1 ret _b_add: .word 0x0 movl 4(ap),r0 L2: subl2 $1,r0 subl2 $1,r0 subl2 $1,r0 subl2 $1,r0 subl2 $1,r0 subl2 $1,r0 subl2 $1,r0 subl2 $1,r0 subl2 $1,r0 subl2 $1,r0 bgtr L2 ret _b_load: .word 0x0 movl 4(ap),r0 L3: movl 0(sp),r1 movl 4(sp),r1 movl 8(sp),r1 movl 12(sp),r1 movl 16(sp),r1 movl 20(sp),r1 movl 24(sp),r1 movl 28(sp),r1 movl 32(sp),r1 movl 36(sp),r1 subl2 $1,r0 bgtr L3 ret systemc-2.3.3/src/sysc/packages/qt/md/ksr1.h0000644000175000017500000001314613360325173020501 0ustar carstencarsten/* * QuickThreads -- Threads-building toolkit. * Copyright (c) 1993 by David Keppel * * Permission to use, copy, modify and distribute this software and * its documentation for any purpose and without fee is hereby * granted, provided that the above copyright notice and this notice * appear in all copies. This software is provided as a * proof-of-concept and for demonstration purposes; there is no * representation about the suitability of this software for any * purpose. */ #ifndef QUICKTHREADS_KSR1_H #define QUICKTHREADS_KSR1_H /* Stack layout: Registers are saved in strictly low to high order, FPU regs first (only if qt_block is called), CEU regs second, IPU regs next, with no padding between the groups. Callee-save: f16..f63; c15..c30; i12..i30. Args passed in i2..i5. Note: c31 is a private data pointer. It is not changed on thread swaps with the assumption that it represents per-processor rather than per-thread state. Note: i31 is an instruction count register that is updated by the context switch routines. Like c31, it is not changed on context switches. This is what we want on startup: +------ <-- BOS: Bottom of stack (grows down) | 80 (128 - 48) bytes of padding to a 128-byte boundary +--- | only | userf | t | u | qt_start$TXT | (empty) <-- qt.sp +------ <-- (BOS - 128) This is why we want this on startup: A thread begins running when the restore procedure switches thread stacks and pops a return address off of the top of the new stack (see below for the reason why we explicitly store qt_start$TXT). The block procedure pushes two jump addresses on a thread's stack before it switches stacks. The first is the return address for the block procedure, and the second is a restore address. The return address is used to jump back to the thread that has been switched to; the restore address is a jump within the block code to restore the registers. Normally, this is just a jump to the next address. However, on thread startup, this is a jump to qt_start$TXT. (The block procedure stores the restore address at an offset of 8 bytes from the top of the stack, which is also the offset at which qt_start$TXT is stored on the stacks of new threads. Hence, when the block procedure switches to a new thread stack, it will initially jump to qt_start$TXT; thereafter, it jumps to the restore code.) qt_start$TXT, after it has read the initial data on the new thread's stack and placed it in registers, pops the initial stack frame and gives the thread the entire stack to use for execution. The KSR runtime system has an unusual treatment of pointers to functions. From C, taking the `name' of a function yields a pointer to a _constant block_ and *not* the address of the function. The zero'th entry in the constant block is a pointer to the function. We have to be careful: the restore procedure expects a return address on the top of the stack (pointed to by qt.sp). This is not a problem when restoring a thread that has run before, since the block routine would have stored the return address on top of the stack. However, when ``faking up'' a thread start (bootstrapping a thread stack frame), the top of the stack needs to contain a pointer to the code that will start the thread running. The pointer to the startup code is *not* `qt_start'. It is the word *pointed to* by `qt_start'. Thus, we dereference `qt_start', see QUICKTHREADS_ARGS_MD below. On varargs startup (still unimplemented): | padding to 128 byte boundary | varargs <-- padded to a 128-byte-boundary +--- | caller's frame, 16 bytes | 80 bytes of padding (frame padded to a 128-byte boundary) +--- | cleanup | vuserf | startup | t +--- | qt_start <-- qt.sp +--- Of a suspended thread: +--- | caller's frame, 16 bytes | fpu registers 47 regs * 8 bytes/reg 376 bytes | ceu registers 16 regs * 8 bytes/reg 128 bytes | ipu registers 19 regs * 8 bytes/reg 152 bytes | : | 80 bytes of padding | : | qt_restore <-- qt.sp +--- */ #define QUICKTHREADS_STKALIGN 128 #define QUICKTHREADS_GROW_DOWN typedef unsigned long qt_word_t; #define QUICKTHREADS_STKBASE QUICKTHREADS_STKALIGN #define QUICKTHREADS_VSTKBASE QUICKTHREADS_STKBASE extern void qt_start(void); /* * See the discussion above for what indexing into a procedure ptr * does for us (it's lovely, though, isn't it?). * * This assumes that the address of a procedure's code is the * first word in a procedure's constant block. That's how the manual * says it will be arranged. */ #define QUICKTHREADS_ARGS_MD(sp) (QUICKTHREADS_SPUT (sp, 1, ((qt_word_t *)qt_start)[0])) /* * The *index* (positive offset) of where to put each value. * See the picture of the stack above that explains the offsets. */ #define QUICKTHREADS_ONLY_INDEX (5) #define QUICKTHREADS_USER_INDEX (4) #define QUICKTHREADS_ARGT_INDEX (3) #define QUICKTHREADS_ARGU_INDEX (2) #define QUICKTHREADS_VARGS_DEFAULT #define QUICKTHREADS_VARGS(sp, nb, vargs, pt, startup, vuserf, cleanup) \ (qt_vargs (sp, nbytes, &vargs, pt, startup, vuserf, cleanup)) #define QUICKTHREADS_VARGS_MD0(sp, vabytes) \ ((qt_t *)(((char *)(sp)) - 4*8 - QUICKTHREADS_STKROUNDUP(vabytes))) extern void qt_vstart(void); #define QUICKTHREADS_VARGS_MD1(sp) (QUICKTHREADS_SPUT (sp, 0, ((qt_word_t *)qt_vstart)[0])) #define QUICKTHREADS_VCLEANUP_INDEX (4) #define QUICKTHREADS_VUSERF_INDEX (3) #define QUICKTHREADS_VSTARTUP_INDEX (2) #define QUICKTHREADS_VARGT_INDEX (1) #endif /* def QUICKTHREADS_KSR1_H */ systemc-2.3.3/src/sysc/packages/qt/md/aarch64.h0000644000175000017500000000322113360325173021042 0ustar carstencarsten#ifndef QUICKTHREADS_AARCH_64_H #define QUICKTHREADS_AARCH_64_H // For QUICKTHREADS_SPUT in qt.h typedef unsigned long qt_word_t; extern void qt_start(void); extern void qt_vstart(void); extern void qt_error(void); extern void qt_align(void); // Stack must be 16-byte aligned at all times. #define QUICKTHREADS_STKALIGN (16) #define QUICKTHREADS_STKBASE (20 * sizeof(qt_word_t)) #define QUICKTHREADS_VSTKBASE (5 * sizeof(qt_word_t)) #define QUICKTHREADS_GROW_DOWN #define QUICKTHREADS_ADJ(sp) (((char *)sp) - QUICKTHREADS_STKBASE) // Initialize a single-argument thread. // // Set up link index to point to the true initializer, qt_start, // which will call only(pu, pt, userf) read from the stack. // // (*helper)(old_sp, a0, a1) will be called in between on the current // stack, so FRAME_INDEX needs to be correct and the other values // appropriately stored. #define QUICKTHREADS_ARGS(sp, pu, pt, userf, only) \ (QUICKTHREADS_SPUT(sp, QUICKTHREADS_LINK_INDEX, qt_start), \ QUICKTHREADS_SPUT(sp, QUICKTHREADS_FRAME_INDEX, sp), \ QUICKTHREADS_SPUT(sp, QUICKTHREADS_ONLY_INDEX, only), \ QUICKTHREADS_SPUT(sp, QUICKTHREADS_USER_INDEX, userf), \ QUICKTHREADS_SPUT(sp, QUICKTHREADS_ARGT_INDEX, pt), \ QUICKTHREADS_SPUT(sp, QUICKTHREADS_ARGU_INDEX, pu), \ sp) #define QUICKTHREADS_LINK_INDEX -1 // x30; standard #define QUICKTHREADS_FRAME_INDEX -2 // x29; standard #define QUICKTHREADS_ONLY_INDEX -3 // x28; arbitrary #define QUICKTHREADS_USER_INDEX -4 // x27; arbitrary #define QUICKTHREADS_ARGT_INDEX -5 // x26; arbitrary #define QUICKTHREADS_ARGU_INDEX -6 // x25; arbitrary #endif // QUICKTHREADS_AARCH_64_H systemc-2.3.3/src/sysc/packages/qt/md/powerpc.README0000644000175000017500000000117713360325173022007 0ustar carstencarsten PowerPC assembly support 1) MacOS X, Darwin, MKLinux and other systems based on Mach kernel ABI: - Configuration command: ./config powerpc-darwin - See documentation inside powerpc_mach.h, powerpc_mach.s, powerpc.c. 2) LinuxPPC, and other systems based on System V ABI: - Configuration command: ./config powerpc - See documentation inside powerpc_sys5.h, powerpc_sys5.s, powerpc.c. Marco Bucci December 2002 * This software is largely based on the original PowerPC-Linux porting * developed by Ken Aaker * * Marco Bucci * December 2002 systemc-2.3.3/src/sysc/packages/qt/md/hppa.s0000644000175000017500000001757613360325173020577 0ustar carstencarsten; pa-risc.s -- assembly support. ; QuickThreads -- Threads-building toolkit. ; Copyright (c) 1993 by David Keppel ; ; Permission to use, copy, modify and distribute this software and ; its documentation for any purpose and without fee is hereby ; granted, provided that the above copyright notice and this notice ; appear in all copies. This software is provided as a ; proof-of-concept and for demonstration purposes; there is no ; representation about the suitability of this software for any ; purpose. ; This file (pa-risc.s) is part of the port of QuickThreads for ; PA-RISC 1.1 architecture. This file implements context switches ; and thread startup. It was written in 1994 by Uwe Reder ; (`uereder@cip.informatik.uni-erlangen.de') for the Operating ; Systems Department (IMMD4) at the University of Erlangen/Nuernberg ; Germany. ; Callee saves general registers gr3..gr18, ; floating-point registers fr12..fr21. .CODE .IMPORT $$dyncall, MILLICODE .IMPORT qt_error, CODE .EXPORT qt_blocki, ENTRY .EXPORT qt_block, ENTRY .EXPORT qt_abort, ENTRY .EXPORT qt_start, ENTRY .EXPORT qt_vstart, ENTRY ; arg0: ptr to function (helper) to call once curr is suspended ; and control is on arg3's stack. ; arg1: 1'th arg to *arg0. ; arg2: 2'th arg to *arg0. ; arg3: sp of new thread. qt_blocki .PROC .CALLINFO CALLER, FRAME=0, SAVE_RP, ENTRY_GR=18 .ENTRY stw %rp,-20(%sp) ; save rp to old frame-marker stwm %r3,128(%sp) ; save callee-saves general registers stw %r4,-124(%sp) stw %r5,-120(%sp) stw %r6,-116(%sp) stw %r7,-112(%sp) stw %r8,-108(%sp) stw %r9,-104(%sp) stw %r10,-100(%sp) stw %r11,-96(%sp) stw %r12,-92(%sp) stw %r13,-88(%sp) stw %r14,-84(%sp) stw %r15,-80(%sp) stw %r16,-76(%sp) stw %r17,-72(%sp) stw %r18,-68(%sp) qt_abort copy %arg0,%r22 ; helper to be called by $$dyncall copy %sp,%arg0 ; pass current sp as arg0 to helper copy %arg3,%sp ; set new sp .CALL bl $$dyncall,%mrp ; call helper copy %mrp,%rp ldw -68(%sp),%r18 ; restore general registers ldw -72(%sp),%r17 ldw -76(%sp),%r16 ldw -80(%sp),%r15 ldw -84(%sp),%r14 ldw -88(%sp),%r13 ldw -92(%sp),%r12 ldw -96(%sp),%r11 ldw -100(%sp),%r10 ldw -104(%sp),%r9 ldw -108(%sp),%r8 ldw -112(%sp),%r7 ldw -116(%sp),%r6 ldw -120(%sp),%r5 ldw -124(%sp),%r4 ldw -148(%sp),%rp ; restore return-pointer bv %r0(%rp) ; return to caller ldwm -128(%sp),%r3 .EXIT .PROCEND qt_block .PROC .CALLINFO CALLER, FRAME=0, SAVE_RP, ENTRY_FR=21 .ENTRY stw %rp,-20(%sp) ; save rp to old frame-marker fstds,ma %fr12,8(%sp) ; save callee-saves float registers fstds,ma %fr13,8(%sp) fstds,ma %fr14,8(%sp) fstds,ma %fr15,8(%sp) fstds,ma %fr16,8(%sp) fstds,ma %fr17,8(%sp) fstds,ma %fr18,8(%sp) fstds,ma %fr19,8(%sp) fstds,ma %fr20,8(%sp) fstds,ma %fr21,8(%sp) .CALL bl qt_blocki,%rp ldo 48(%sp),%sp ldo -48(%sp),%sp fldds,mb -8(%sp),%fr21 ; restore callee-saves float registers fldds,mb -8(%sp),%fr20 fldds,mb -8(%sp),%fr19 fldds,mb -8(%sp),%fr18 fldds,mb -8(%sp),%fr17 fldds,mb -8(%sp),%fr16 fldds,mb -8(%sp),%fr15 fldds,mb -8(%sp),%fr14 fldds,mb -8(%sp),%fr13 ldw -28(%sp),%rp ; restore return-pointer bv %r0(%rp) ; return to caller. fldds,mb -8(%sp),%fr12 .EXIT .PROCEND qt_start .PROC .CALLINFO CALLER, FRAME=0 .ENTRY copy %r18,%arg0 ; set user arg `pu'. copy %r17,%arg1 ; ... user function pt. copy %r16,%arg2 ; ... user function userf. ; %r22 is a caller-saves register copy %r15,%r22 ; function to be called by $$dyncall .CALL ; in=%r22 bl $$dyncall,%mrp ; call `only'. copy %mrp,%rp bl,n qt_error,%r0 ; `only' erroniously returned. .EXIT .PROCEND ; Varargs ; ; First, call `startup' with the `pt' argument. ; ; Next, call the user's function with all arguments. ; We don't know whether arguments are integers, 32-bit floating-points or ; even 64-bit floating-points, so we reload all the registers, possibly ; with garbage arguments. The thread creator provided non-garbage for ; the arguments that the callee actually uses, so the callee never gets ; garbage. ; ; -48 -44 -40 -36 -32 ; | arg3 | arg2 | arg1 | arg0 | ; ----------------------------- ; integers: arg3 arg2 arg1 arg0 ; 32-bit fps: farg3 farg2 farg1 farg0 ; 64-bit fps: <---farg3--> <---farg1--> ; ; Finally, call `cleanup' with the `pt' argument and with the return value ; from the user's function. It is an error for `cleanup' to return. qt_vstart .PROC .CALLINFO CALLER, FRAME=0 .ENTRY ; Because the startup function may damage the fixed arguments ; on the stack (PA-RISC Procedure Calling Conventions Reference ; Manual, 2.4 Fixed Arguments Area), we allocate a seperate ; stack frame for it. ldo 64(%sp),%sp ; call: void startup(void *pt) copy %r15,%arg0 ; `pt' is arg0 to `startup'. copy %r16,%r22 .CALL bl $$dyncall,%mrp ; Call `startup'. copy %mrp,%rp ldo -64(%sp),%sp ; call: void *qt_vuserf_t(...) ldw -36(%sp),%arg0 ; Load args to integer registers. ldw -40(%sp),%arg1 ldw -44(%sp),%arg2 ldw -48(%sp),%arg3 ; Index of fld[w|d]s only ranges from -16 to 15, so we ; take r22 to be our new base register. ldo -32(%sp),%r22 fldws -4(%r22),%farg0 ; Load args to floating-point registers. fldds -8(%r22),%farg1 fldws -12(%r22),%farg2 fldds -16(%r22),%farg3 copy %r17,%r22 .CALL bl $$dyncall,%mrp ; Call `userf'. copy %mrp,%rp ; call: void cleanup(void *pt, void *vuserf_return) copy %r15,%arg0 ; `pt' is arg0 to `cleanup'. copy %ret0,%arg1 ; Return-value is arg1 to `cleanup'. copy %r18,%r22 .CALL bl $$dyncall,%mrp ; Call `cleanup'. copy %mrp,%rp bl,n qt_error,%r0 .EXIT .PROCEND systemc-2.3.3/src/sysc/packages/qt/md/powerpc_sys5_b.s0000644000175000017500000000644513360325173022603 0ustar carstencarsten/* speed test for basic CPU operations */ /* Marco Bucci */ /* This code was developed with the Code Warrior integrate ppc assembler. * Macros are use to hide illegal constructs whether you are using a * "normal" assembler or the "C integrated" assembler. */ #if 0 .text .align 4 .globl b_call_reg .globl _b_call_reg .globl b_call_imm .globl _b_call_imm .globl b_add .globl _b_add .globl b_load .globl _b_load .set fsize, 64 .set lrsave, 4 #else #define fsize 64 #define lrsave 4 #endif #if 0 .if 0 #endif asm void b_null(void) { #if 0 .endif #endif #if 0 b_null: #endif blr #if 0 .if 0 #endif } #if 0 .endif #endif /* actually the same as the following. How to get "b_null" address? * I didnt find the right sintax or the right way. * I should take the current PC, then the difference to "b_null" * (making the difference beween the labels), perform the sum and go?! */ #if 0 .if 0 #endif asm void b_call_reg(long n) { #if 0 .endif #endif #if 0 b_call_reg: _b_call_reg: #endif mflr %r0 stw %r31,-4(%r1) stw %r30,-8(%r1) stw %r0,lrsave(%r1) stwu %r1,-fsize(%r1) mr %r30,%r3 li %r31,0 b L1 L0: bl b_null bl b_null bl b_null bl b_null bl b_null addi %r31,%r31,5 L1: cmpw %r31,%r30 blt L0 lwz %r0,lrsave+fsize(%r1) mtlr %r0 lwz %r31,-4+fsize(%r1) lwz %r30,-8+fsize(%r1) addi %r1,%r1,fsize blr #if 0 .if 0 #endif } #if 0 .endif #endif #if 0 .if 0 #endif asm void b_call_imm(long n) { #if 0 .endif #endif #if 0 b_call_imm: _b_call_imm: #endif mflr %r0 stw %r31,-4(%r1) stw %r30,-8(%r1) stw %r0,lrsave(%r1) stwu %r1,-fsize(%r1) mr %r30,%r3 li %r31,0 b L3 L2: bl b_null bl b_null bl b_null bl b_null bl b_null addi %r31,%r31,5 L3: cmpw %r31,%r30 blt L2 lwz %r0,lrsave+fsize(%r1) mtlr %r0 lwz %r31,-4+fsize(%r1) lwz %r30,-8+fsize(%r1) addi %r1,%r1,fsize blr #if 0 .if 0 #endif } #if 0 .endif #endif #if 0 .if 0 #endif asm void b_add(long n) { #if 0 .endif #endif #if 0 b_add: _b_add: #endif mflr %r0 stw %r31,-4(%r1) stw %r30,-8(%r1) stw %r0,lrsave(%r1) stwu %r1,-fsize(%r1) mr %r30,%r3 li %r31,0 b L5 L4: addi %r3,%r3,5 addi %r4,%r4,5 addi %r5,%r5,5 addi %r6,%r6,5 addi %r7,%r7,5 addi %r3,%r3,5 addi %r4,%r4,5 addi %r5,%r5,5 addi %r6,%r6,5 addi %r7,%r7,5 addi %r31,%r31,10 L5: cmpw %r31,%r30 blt L4 lwz %r0,lrsave+fsize(%r1) mtlr %r0 lwz %r31,-4+fsize(%r1) lwz %r30,-8+fsize(%r1) addi %r1,%r1,fsize blr #if 0 .if 0 #endif } #if 0 .endif #endif #if 0 .if 0 #endif asm void b_load(long n) { #if 0 .endif #endif #if 0 b_load: _b_load: #endif mflr %r0 stw %r31,-4(%r1) stw %r30,-8(%r1) stw %r0,lrsave(%r1) stwu %r1,-fsize(%r1) mr %r30,%r3 li %r31,0 b L7 L6: lwz %r3,4(%r1) lwz %r4,8(%r1) lwz %r5,12(%r1) lwz %r6,16(%r1) lwz %r7,20(%r1) lwz %r3,24(%r1) lwz %r4,28(%r1) lwz %r5,32(%r1) lwz %r6,36(%r1) lwz %r7,40(%r1) addi %r31,%r31,10 L7: cmpw %r31,%r30 blt L6 lwz %r0,lrsave+fsize(%r1) mtlr %r0 lwz %r31,-4+fsize(%r1) lwz %r30,-8+fsize(%r1) addi %r1,%r1,fsize blr #if 0 .if 0 #endif } #if 0 .endif #endif systemc-2.3.3/src/sysc/packages/qt/md/axp.1.Makefile0000644000175000017500000000016513360325173022033 0ustar carstencarsten # # Compiling for the DEC AXP (alpha) with GNU CC or version 1.x of OSF. # CC = cc -std1 -D__AXP__ -D__OSF1__ systemc-2.3.3/src/sysc/packages/qt/md/m88k.Makefile0000644000175000017500000000015413360325173021671 0ustar carstencarsten # # Hosted compilers for 88k for Meerkat. # CC = gcc88 -Dm88k -ansi -pedantic -Wall -fno-builtin AS = as88 systemc-2.3.3/src/sysc/packages/qt/md/null.c0000644000175000017500000000115713360325173020565 0ustar carstencarsten/* * QuickThreads -- Threads-building toolkit. * Copyright (c) 1993 by David Keppel * * Permission to use, copy, modify and distribute this software and * its documentation for any purpose and without fee is hereby * granted, provided that the above copyright notice and this notice * appear in all copies. This software is provided as a * proof-of-concept and for demonstration purposes; there is no * representation about the suitability of this software for any * purpose. */ char const qtmd_rcsid[] = "$Header: /Users/acg/CVSROOT/systemc-2.3/src/sysc/qt/md/null.c,v 1.1.1.1 2006/12/15 20:20:06 acg Exp $"; systemc-2.3.3/src/sysc/packages/qt/md/i386.h0000644000175000017500000000731713360325173020315 0ustar carstencarsten/* * QuickThreads -- Threads-building toolkit. * Copyright (c) 1993 by David Keppel * * Permission to use, copy, modify and distribute this software and * its documentation for any purpose and without fee is hereby * granted, provided that the above copyright notice and this notice * appear in all copies. This software is provided as a * proof-of-concept and for demonstration purposes; there is no * representation about the suitability of this software for any * purpose. */ #ifndef QUICKTHREADS_386_H #define QUICKTHREADS_386_H typedef unsigned long qt_word_t; /* Thread's initial stack layout on the i386: non-varargs: +--- | arg[2] === `userf' on startup | arg[1] === `pt' on startup | arg[0] === `pu' on startup +--- | ret pc === qt_error +--- | ret pc === `only' on startup +--- | %ebp | %esi | %edi | %ebx <--- qt_t.sp +--- When a non-varargs thread is started, it ``returns'' directly to the client's `only' function. varargs: +--- | arg[n-1] | .. | arg[0] +--- | ret pc === `qt_vstart' +--- | %ebp === `startup' | %esi === `cleanup' | %edi === `pt' | %ebx === `vuserf' <--- qt_t.sp +--- When a varargs thread is started, it ``returns'' to the `qt_vstart' startup code. The startup code calls the appropriate functions. */ /* What to do to start a varargs thread running. */ extern void qt_vstart (void); /* Hold 4 saved regs plus two return pcs (qt_error, qt_start) plus three args. */ #define QUICKTHREADS_STKBASE (13 * 4) /* Hold 4 saved regs plus one return pc (qt_vstart). */ #define QUICKTHREADS_VSTKBASE (5 * 4) /* Stack must be 16-byte aligned at function call instr. (SSE data support) */ #define QUICKTHREADS_STKALIGN (16) /* Where to place various arguments. */ #define QUICKTHREADS_ONLY_INDEX (QUICKTHREADS_PC) #define QUICKTHREADS_USER_INDEX (QUICKTHREADS_ARG2) #define QUICKTHREADS_ARGT_INDEX (QUICKTHREADS_ARG1) #define QUICKTHREADS_ARGU_INDEX (QUICKTHREADS_ARG0) #define QUICKTHREADS_VSTARTUP_INDEX (QUICKTHREADS_EBP) #define QUICKTHREADS_VUSERF_INDEX (QUICKTHREADS_EBX) #define QUICKTHREADS_VCLEANUP_INDEX (QUICKTHREADS_ESI) #define QUICKTHREADS_VARGT_INDEX (QUICKTHREADS_EDI) #define QUICKTHREADS_EBX 0 #define QUICKTHREADS_EDI 1 #define QUICKTHREADS_ESI 2 #define QUICKTHREADS_EBP 3 #define QUICKTHREADS_POP0 4 #define QUICKTHREADS_POP1 5 #define QUICKTHREADS_POP2 6 #define QUICKTHREADS_PC 7 /* The following are defined only for non-varargs. */ #define QUICKTHREADS_POPE 8 #define QUICKTHREADS_ARG0 9 #define QUICKTHREADS_ARG1 10 #define QUICKTHREADS_ARG2 11 #define QUICKTHREADS_RPC 12 /* Stack grows down. The top of the stack is the first thing to pop off (preincrement, postdecrement). */ #define QUICKTHREADS_GROW_DOWN extern void qt_error (void); /* For correct 16-byte stack alignment (auto-relocatable functions) */ extern void qt_tramp (void); extern void qt_align (void); /* Push on the error return address and the alignment/trampoline functions. */ #define QUICKTHREADS_ARGS_MD(sto) \ (QUICKTHREADS_SPUT (sto, QUICKTHREADS_POP0, qt_align), \ QUICKTHREADS_SPUT (sto, QUICKTHREADS_POP1, qt_align), \ QUICKTHREADS_SPUT (sto, QUICKTHREADS_POP2, qt_align), \ QUICKTHREADS_SPUT (sto, QUICKTHREADS_POPE, qt_tramp), \ QUICKTHREADS_SPUT (sto, QUICKTHREADS_RPC, qt_error)) /* When varargs are pushed, allocate space for all the args. */ #define QUICKTHREADS_VARGS_MD0(sto, nbytes) \ ((qt_t *)(((char *)(sto)) - QUICKTHREADS_STKROUNDUP(nbytes))) #define QUICKTHREADS_VARGS_MD1(sto) \ (QUICKTHREADS_SPUT (sto, QUICKTHREADS_PC, qt_vstart)) #define QUICKTHREADS_VARGS_DEFAULT #endif /* QUICKTHREADS_386_H */ systemc-2.3.3/src/sysc/packages/qt/md/axp.README0000644000175000017500000000072513360325173021116 0ustar carstencarstenThe handling of varargs is platform-dependent. Assar Westerlund stared at the problem for a while and deduces the following table: vers / compiler cc gcc ---------------------------------------------------------------------- 1.3 a0, offset __base, __offset 2.0 _a0, _offset __base, __offset The current code should handle both cc and gcc versions, provided you configure for the correct compiler. systemc-2.3.3/src/sysc/packages/qt/md/powerpc_mach.h0000644000175000017500000006444613360325173022301 0ustar carstencarsten/* + * QuickThreads -- Threads-building toolkit. + * Copyright (c) 1993 by David Keppel + * + * Permission to use, copy, modify and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice and this notice + * appear in all copies. This software is provided as a + * proof-of-concept and for demonstration purposes; there is no + * representation about the suitability of this software for any + * purpose. + * + * PowerPC-Mach thread switching module. + * + * This software is largely based on the original PowerPC-Linux porting + * developed by Ken Aaker + * + * Marco Bucci + * December 2002 + * + */ #ifndef QUICKTHREADS_POWERPC_H #define QUICKTHREADS_POWERPC_H /***************************************************************************** * * DESCRIPTION * * This is the QuickThreads switching module implementation for PowerPC * running under Mach kernel. It was developed and tested under MacOS X, that * is under Darwin (the UNIX-BSD fundation of MacOS X). * * Notice that the Mach PowerPC ABI (Application Binary Interface) [1] is * not the same than System V ABI [2] used by most of the LINUX PowerPC * implementations. * * IMPLEMENTATION NOTES * * 1) Porting on System V ABI * Excluding the variant argument calling convention, Mach and System V ABI * are enough similar and it could be possible to use some simple macro, to * adapt the code for both the ABIs. Actually, the only relevant difference * is in the linkage area structure and in the position where the Link and * the Condition registers are saved. As to the calling conventions, there * are differences with floating points argument passing and with variant * argument lists. Notice that, on Mach, the caller's stack frame allocates * space to hold all arguments ([1] p.51), while on System V, the caller's * stack frame allocates space to hold just the arguments that don't fit into * registers ([2] p.3.18). * * 2) Variant argument list implementation * Variant argument calling on a RISC machine is not easy to implement since * parameters are passed via registers instead of via stack. In a general * variant argument implementation, the caller's stack must map the whole * parameter list following the rules related to the use of the GPR and FPR * parameter registers and the stack alignment ([1] p.54). * This implementation is quite simple and not general. It works under the * hypothesis that arguments are 4-bytes aligned integers. * * 3) This heather file organisation * I preferred to not make confusion between macros that are needed (i.e. * directly used) by QuickThreads and internal "implementation" macros. You * will find QuickThreds macros in the end of this header. Sometime they just * refer to an analogous "internal" macro. On the top, there are the macros * that I used to make more clean (I hope) the implementation. I could include * some system heather (as to stack layout definitions, prologs and epilogs, * etc.), but I preferred to have a self-contained heather in order to make * all more clear for mantaining and for possible porting on another ABI. * * * REFERENCES * * [1] - Mach-O Runtime Architecture * Runtime Concepts and Conventions for Mac OS X Programs * Preliminary July 2002 * * [2] - SYSTEM V APPLICATION BINARY INTERFACE * PowerPC Processor Supplement * September 1995 * * On MacOS X, more documentation is available by installing the "Developer * Tools". Useful macros and documentation can be found in the system headers * files such as asm.h, asm_help.h etc. (see /usr/architecture/ppc/ or * /System/Library/Frameworks/Kernel.framework/Headers/architecture/ppc/). *****************************************************************************/ /***************************************************************************** * * PowerPC Mach-O Stack frame (see [1]) * ................ + + | | reserved + CALLER'S LINKAGE AREA + | | Caller's LR + + | | Caller's CR + + backchain -> | | Caller's backchain +==========================+ | | FPR31 + FPR SAVE AREA + .............. + + | | FPRn +--------------------------+ | | GPR31 + GPR SAVE AREA + .............. + + | | GPRn +--------------------------+ | | + ALIGNMEBNT PAD + .............. + (if needed) + | | +--------------------------+ | | + LOCAL VARIABLES AREA + .............. + + | | +--------------------------+ | | PAR(n) + + | | + PARAMETER AREA + .............. + for FUTURE call + | | PAR(1) + + SP + 24 -> | | PAR(0) +--------------------------+ SP + 20 -> | | Caller's TOC + + SP + 16 -> | | reserved + + SP + 12 -> | | reserved + LINKAGE AREA + SP + 8 -> | | LR callee-save for FUTURE call + + SP + 4 -> | | CR callee-save for FUTURE call + + SP -> | | backchain +==========================+ STACK TOP (lower address) Stack grows down | V * NOTE: * * 1) Parameter are allocated in the CALLER's parameter area. This area must * be large enough to hold all parameters regardless if they are or not passed * in registers. * * The caller parameter area is used: * - by the caller, to store parameters to the callee that cannot fit in * registers (no more parameter registers are available); * - by the callee, to save parameter registers (for istance because they are * needed for a further call). * * Obviously, the callee saves parameter registers, in the location in which * they are mapped on the caller's stack frame. So, be aware that, if * something else is stored in that location, it could be deleted after a call. * * 2) The callee saves LR and CR in the caller's linkage area. All other * callee's state are saved in its own stack frame. * *****************************************************************************/ /***************************************************************************** * * Stack initialization for a single argument thread * top + QUICKTHREADS_STKBASE -> STACK BOTTOM (higher address) +==========================+ | | + + .............. + + | | +--------------------------+ top + QUICKTHREADS_ONLY_INDEX * 4 -> | only param | PAR(3) + + top + QUICKTHREADS_USER_INDEX * 4 -> | userf param | PAR(2) + + top + QUICKTHREADS_ARGT_INDEX * 4 -> | t param | PAR(1) + + top + QUICKTHREADS_ARGU_INDEX * 4 -> | u param | PAR(0) +--------------------------+ | | + + .............. + + top + QUICKTHREADS_RETURN_INDEX * 4 -> | qt_start | LR save + + .............. + + top + QUICKTHREADS_BLOCKI_FRAME_SIZE -> | top + QUICKTHREADS_STKBASE | backchain +==========================+ | | + + .............. + + | | +--------------------------+ | | + + .............. + + top -> |top + QUICKTHREADS_BLOCKI_FRAME_SIZE| backchain +==========================+ STACK TOP (lower address) Stack grows down | V ***************************************************************************** * * Stack initialization for a variant argument thread * bottom -> STACK BOTTOM (higher address) +==========================+ | | + + .............. + + top + QUICKTHREADS_VSTKBASE -> | arg(0) | PAR(4) +--------------------------+ top + QUICKTHREADS_CLEANUP_INDEX * 4 -> | cleanup param | PAR(3) + + top + QUICKTHREADS_USER_INDEX * 4 -> | userf param | PAR(2) + + top + QUICKTHREADS_VSTARTUP_INDEX * 4 ->| startup param | PAR(1) + + top + QUICKTHREADS_ARGT_INDEX * 4 -> | t param | PAR(0) +--------------------------+ | | + + .............. + + top + QUICKTHREADS_RETURN_INDEX * 4 -> | qt_start | LR save + + .............. top + QUICKTHREADS_BLOCKI_FRAME_SIZE -> | top + QUICKTHREADS_STKBASE | backchain +==========================+ | | + + .............. + + | | +--------------------------+ | | + + .............. + + top -> |top + QUICKTHREADS_BLOCKI_FRAME_SIZE| backchain +==========================+ STACK TOP (lower address) Stack grows down | V * NOTE: * * Parameters are passed to "qt_start" or to "qt_vstart" putting them into * the stack frames of "qt_start" or "qt_vstart" themselves. This not a * conventional parameter passing because parameters should be put into the * caller's stack, not into the callee's one. Actually we must consider * that as a preload of the parameter area that "qt_start" or "qt_vstart" * will use for their own calls. * Be aware of the fact that, during a call, the caller's parameter area is, * in a certain sense, volatile. In facts, the callee can save parameter * registers on the caller's parameter area. * *****************************************************************************/ /***************************************************************************** Define PowerPC Mach-O related macros *****************************************************************************/ typedef unsigned long PPC_W; /* Stack pointer must always be a multiple of 16 */ #define PPC_STACK_INCR 16 #define PPC_ROUND_STACK(length) \ (((length)+PPC_STACK_INCR-1) & ~(PPC_STACK_INCR-1)) #define PPC_LINKAGE_AREA 24 #define PPC_CR_SAVE 4 #define PPC_LR_SAVE 8 #define PPC_PARAM_AREA(n) (4*(n)) #define PPC_GPR_SAVE_AREA (4*19) /* GPR13-GPR31 must be saved */ #define PPC_FPR_SAVE_AREA (8*18) /* FPR14-FPR31 must be saved */ /* Define parameter offset on the stack. * NOTICE: Parameters are numbered 0, 1, ..., n. */ #define PPC_PAR(i) (PPC_LINKAGE_AREA+(i)*4) /***************************************************************************** Define stack frames *****************************************************************************/ /* Define the "qt_blocki" and "qt_abort" stack frame. We use the same stack * frame for both. * top + S -> +==========================+ top + S - 4 -> | | GPR31 + GPR SAVE AREA + .............. + + top + S - 19 * 4 -> | | GPR13 +--------------------------+ | | + ALIGNMEBNT PAD + .............. + (if needed) + | | +--------------------------+ | | + + | | + PARAMETER AREA + | | + + top + 24 -> | | +--------------------------+ | | + LINKAGE AREA + top -> | | +==========================+ */ #define QUICKTHREADS_BLOCKI_FRAME_SIZE \ PPC_ROUND_STACK(PPC_LINKAGE_AREA+PPC_PARAM_AREA(4)+PPC_GPR_SAVE_AREA) /* Offset to the base of the GPR save area. Save from GPR13 to GPR31 * increasing address. */ #define QUICKTHREADS_BLOCKI_GPR_SAVE(i) (QUICKTHREADS_BLOCKI_FRAME_SIZE-4+(i-31)*4) /* Define the "qt_block" stack frame. Notice that since "qt_black" calls * "qt_blocki", GPR registers are saved into "qt_blocki" stack frame. * top + S -> +==========================+ top + S - 8 -> | | FPR31 + FPR SAVE AREA + .............. + + top + S - 18 * 8 -> | | FPR14 +--------------------------+ | | + ALIGNMEBNT PAD + .............. + (if needed) + | | +--------------------------+ | | + + | | + PARAMETER AREA + | | + + top + 24 -> | | +--------------------------+ | | + LINKAGE AREA + top -> | | +==========================+ */ #define QUICKTHREADS_BLOCK_FRAME_SIZE \ PPC_ROUND_STACK(PPC_LINKAGE_AREA+PPC_PARAM_AREA(4)+PPC_FPR_SAVE_AREA) /* Offset to the location where registers are saved. */ #define QUICKTHREADS_BLOCK_FPR_SAVE(i) (QUICKTHREADS_BLOCK_FRAME_SIZE-8+(i-31)*8) /* Define the "qt_start" frame size. It consists just of the linkage area and * the parameter area. * +==========================+ | | + ALIGNMEBNT PAD + .............. + (if needed) + | | +--------------------------+ | | only par + + | | userf par + PARAMETER AREA + | | t par + + top + 24 -> | | u par +--------------------------+ | | + LINKAGE AREA + top -> | | +==========================+ */ #define QUICKTHREADS_START_FRAME_SIZE PPC_ROUND_STACK(PPC_LINKAGE_AREA+PPC_PARAM_AREA(4)) /* Define the "qt_vstart" frame. It consists of the linkage area, the fix parameter * area, the variant argument list and a local variable area used in "qt_vstart" * implementation. * backchain -> +==========================+ backchain - 4 -> | | + LOCAL VARIABLES AREA + .............. + + | | +--------------------------+ | | + ALIGNMEBNT PAD + .............. + (if needed) + | | +--------------------------+ | | arg(n) + + | | + VARIABLE ARGUMENT LIST + .............. + for userf call + | | arg(1) + + top + 24 + 16 -> | | arg(0) +--------------------------+ | | cleanup par + + | | userf par + PARAMETER AREA + | | startup par + + top + 24 -> | | t par +--------------------------+ | | + LINKAGE AREA + top -> | | +==========================+ */ #define QUICKTHREADS_VARGS_LOCAL_AREA (4*4) /* local variable area */ /* The offset the stack will be moved back before to call "userf(...)". * The linckage area must be moved to be adiacent to the part of the variant * argument list that is in the stack. */ #define QUICKTHREADS_VARGS_BKOFF PPC_PARAM_AREA(4) #define QUICKTHREADS_VSTART_FRAME_SIZE(varbytes) \ PPC_ROUND_STACK(PPC_LINKAGE_AREA+PPC_PARAM_AREA(4)+(varbytes)+ \ QUICKTHREADS_VARGS_LOCAL_AREA) /* Offset to the base of the varian argument list */ #define QUICKTHREADS_VSTART_LIST_BASE (PPC_LINKAGE_AREA+PPC_PARAM_AREA(4)) /* Notice that qt_start and qt_vstart have no parameters, actually their * parameters are written in their stack frame during thread initialization */ extern void qt_start(void); extern void qt_vstart(void); /* Offset (in words) of the location where the block routine saves its return * address (i.e. LR). SP points the top of the block routine stack and, * following ppc calling conventions, the return address is saved in the * previous (caller's) stack frame. */ #define QUICKTHREADS_RETURN_INDEX ((QUICKTHREADS_BLOCKI_FRAME_SIZE+PPC_LR_SAVE)/sizeof(PPC_W)) /* static variable used to get the stack bottom in "VARGS" initialization */ /* static void *qt_sp_bottom_save; */ #define QUICKTHREADS_ARG_INDEX(i) ((QUICKTHREADS_BLOCKI_FRAME_SIZE+PPC_PAR(i))/sizeof(PPC_W)) /***************************************************************************** QuickThreads needed definitions *****************************************************************************/ #define QUICKTHREADS_GROW_DOWN #define QUICKTHREADS_STKALIGN PPC_STACK_INCR typedef PPC_W qt_word_t; /* This macro is used by "QUICKTHREADS_ARGS" to initialize a single argument thread. * - set "qt_start" as the "qt_block" or "qt_blocki" return address; * - set the top of the stack backchain; * - set the next backchain (not needed, but just to be "clean"). */ #define QUICKTHREADS_ARGS_MD(sp) \ (QUICKTHREADS_SPUT (sp, QUICKTHREADS_RETURN_INDEX, qt_start), \ QUICKTHREADS_SPUT (sp, 0, sp+QUICKTHREADS_BLOCKI_FRAME_SIZE), \ QUICKTHREADS_SPUT (sp, QUICKTHREADS_BLOCKI_FRAME_SIZE/sizeof(PPC_W), \ sp+QUICKTHREADS_BLOCKI_FRAME_SIZE+QUICKTHREADS_START_FRAME_SIZE)) /* This macro is used by "QUICKTHREADS_VARGS" to initialize a variant argument thread. * It returns the pointer to the top of the argument list. * We also use it to get the stack bottom via a static variable. This is a bit * "dirty", it could be better to do it in "qt_vargs", but we don't want change * anything out of this file. * We need the stack bottom to allocate a local variable area used by * "qt_vstart". */ #define QUICKTHREADS_VARGS_MD0(sp, varbytes) \ ((qt_sp_bottom_save = sp), \ ((qt_t *)(((char *)(sp)) - \ (QUICKTHREADS_VSTART_FRAME_SIZE(varbytes)-QUICKTHREADS_VSTART_LIST_BASE)))) /* This macro is used by "QUICKTHREADS_VARGS" to initialize a variant argument thread. * - set "qt_start" as the "qt_block" or "qt_blocki" return address; * - set the top of the stackback chain; * - set the next backchain (it points the stack botton). */ #define QUICKTHREADS_VARGS_MD1(sp) \ (QUICKTHREADS_SPUT (sp, QUICKTHREADS_RETURN_INDEX, qt_vstart), \ QUICKTHREADS_SPUT (sp, 0, sp+QUICKTHREADS_BLOCKI_FRAME_SIZE), \ QUICKTHREADS_SPUT (sp, (QUICKTHREADS_BLOCKI_FRAME_SIZE)/sizeof(PPC_W), \ qt_sp_bottom_save)) /* Activate "qt_vargs" as the initialization routine for the variant * argument threads */ #define QUICKTHREADS_VARGS_DEFAULT /* Override "qt_vargs" with "qt_vargs_stdarg". * On LinuxPPC "qt_vargs" doesn't work, "qt_vargs_stdarg" uses a more * standard way to retrieve arguments from the variant list. */ #define QUICKTHREADS_VARGS(sp, nbytes, vargs, pt, startup, vuserf, cleanup) \ ((qt_t *)qt_vargs_stdarg (sp, nbytes, vargs, pt, startup, vuserf, cleanup)) /* This macro is used by "QUICKTHREADS_ADJ(sp)" to get the stack top form the stack * bottom during a single argument thread initialization. * It is the space we need to allocate for a single argument thread: the stack * frame for the block routine ("qt_block" or "qt_blocki") and for "qt_start". */ #define QUICKTHREADS_STKBASE \ (QUICKTHREADS_BLOCKI_FRAME_SIZE+QUICKTHREADS_START_FRAME_SIZE) /* This macro is used by "QUICKTHREADS_VADJ(sp)" to get the stack top from the base * of the variant argument list during a variant argument thread initialization. */ #define QUICKTHREADS_VSTKBASE (QUICKTHREADS_BLOCKI_FRAME_SIZE+QUICKTHREADS_VSTART_LIST_BASE) /* The *index* (positive offset) of where to put each value. */ #define QUICKTHREADS_ARGU_INDEX QUICKTHREADS_ARG_INDEX(0) #define QUICKTHREADS_ARGT_INDEX QUICKTHREADS_ARG_INDEX(1) #define QUICKTHREADS_USER_INDEX QUICKTHREADS_ARG_INDEX(2) #define QUICKTHREADS_ONLY_INDEX QUICKTHREADS_ARG_INDEX(3) #define QUICKTHREADS_VARGT_INDEX QUICKTHREADS_ARG_INDEX(0) #define QUICKTHREADS_VSTARTUP_INDEX QUICKTHREADS_ARG_INDEX(1) #define QUICKTHREADS_VUSERF_INDEX QUICKTHREADS_ARG_INDEX(2) #define QUICKTHREADS_VCLEANUP_INDEX QUICKTHREADS_ARG_INDEX(3) #endif /* ndef QUICKTHREADS_POWERPC_H */ systemc-2.3.3/src/sysc/packages/qt/md/hppa-cnx.Makefile0000644000175000017500000000063013360325173022617 0ustar carstencarsten# This file (cnx_spp.Makefile) is part of the port of QuickThreads for # PA-RISC 1.1 architecture on a Convex SPP. This file is a machine dependent # makefile for QuickThreads. It was written in 1994 by Uwe Reder # (`uereder@cip.informatik.uni-erlangen.de') for the Operating Systems # Department (IMMD4) at the University of Erlangen/Nuernberg Germany. # `Normal' configuration. CC = /usr/convex/bin/cc systemc-2.3.3/src/sysc/packages/qt/md/axp.c0000644000175000017500000000743013360325173020403 0ustar carstencarsten/* * QuickThreads -- Threads-building toolkit. * Copyright (c) 1993 by David Keppel * * Permission to use, copy, modify and distribute this software and * its documentation for any purpose and without fee is hereby * granted, provided that the above copyright notice and this notice * appear in all copies. This software is provided as a * proof-of-concept and for demonstration purposes; there is no * representation about the suitability of this software for any * purpose. */ #include #include "qt.h" /* Varargs is harder on the AXP. Parameters are saved on the stack as something like (stack grows down to low memory; low at bottom of picture): | : | arg6 +--- | iarg5 | : | iarg3 <-- va_list._a0 + va_list._offset | : | iarg0 <-- va_list._a0 +--- | farg5 | : | farg0 +--- When some of the arguments have known type, there is no need to save all of them in the struct. So, for example, if the routine is called zork (int a0, float a1, int a2, ...) { va_list ap; va_start (ap, a2); qt_vargs (... &ap ...); } then offset is set to 3 * 8 (8 === sizeof machine word) = 24. What this means for us is that the user's routine needs to be called with an arg list where some of the words in the `any type' parameter list have to be split and moved up in to the int/fp region. Ways in which this can fail: - The user might not know the size of the pushed arguments anyway. - Structures have funny promotion rules. - Probably lots of other things. All in all, we never promised varargs would work reliably. */ #define QUICKTHREADS_VADJ(sp) (((char *)sp) - QUICKTHREADS_VSTKBASE) #define QUICKTHREADS_VARGS_MD0(sp, vabytes) \ ((qt_t *)(((char *)(sp)) - 6*2*8 - QUICKTHREADS_STKROUNDUP(vabytes))) extern void qt_vstart(void); #define QUICKTHREADS_VARGS_MD1(sp) (QUICKTHREADS_SPUT (sp, QUICKTHREADS_R26, qt_vstart)) /* Different machines use different implementations for varargs. Unfortunately, the code below ``looks in to'' the varargs structure, `va_list', and thus depends on the conventions. The following #defines try to deal with it but don't catch everything. */ #ifdef __GNUC__ #define _a0 __base #define _offset __offset #else #ifdef __OSF1__ #define _a0 a0 #define _offset offset #endif #endif /* def __GNUC__ */ struct qt_t * qt_vargs (struct qt_t *qsp, int nbytes, struct va_list *vargs, void *pt, qt_function_t *startup, qt_function_t *vuserf, qt_function_t *cleanup) { va_list ap; int i; int max; /* Maximum *words* of args to copy. */ int tmove; /* *Words* of args moved typed->typed. */ qt_word_t *sp; ap = *(va_list *)vargs; qsp = QUICKTHREADS_VARGS_MD0 (qsp, nbytes); sp = (qt_word_t *)qsp; tmove = 6 - ap._offset/sizeof(qt_word_t); /* Copy from one typed area to the other. */ for (i=0; i