From 7364acfc758a30f81aa75844f6b96b1e4e19990a Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 8 Dec 2018 01:58:26 -0800 Subject: systemc: Initial import of TLM headers from Accellera. These headers will need to be cleaned up and have some Accellera specific quirks ironed out of them, but I'll do that in a later change to make it clear what those changes are. Change-Id: Ia4e08633ab552b4c616c66c9b7e2bbd78ebfe7b9 Reviewed-on: https://gem5-review.googlesource.com/c/15055 Reviewed-by: Anthony Gutierrez Maintainer: Anthony Gutierrez --- src/systemc/ext/tlm | 33 + src/systemc/ext/tlm.h | 22 + src/systemc/ext/tlm_core/Makefile.am | 97 ++ src/systemc/ext/tlm_core/Makefile.in | 799 ++++++++++++++ src/systemc/ext/tlm_core/tlm_1/README.txt | 97 ++ .../ext/tlm_core/tlm_1/tlm_analysis/tlm_analysis.h | 33 + .../tlm_1/tlm_analysis/tlm_analysis_fifo.h | 54 + .../tlm_core/tlm_1/tlm_analysis/tlm_analysis_if.h | 39 + .../tlm_1/tlm_analysis/tlm_analysis_port.h | 84 ++ .../tlm_1/tlm_analysis/tlm_analysis_triple.h | 53 + .../ext/tlm_core/tlm_1/tlm_analysis/tlm_write_if.h | 42 + .../tlm_req_rsp/tlm_1_interfaces/tlm_core_ifs.h | 149 +++ .../tlm_req_rsp/tlm_1_interfaces/tlm_fifo_ifs.h | 85 ++ .../tlm_1_interfaces/tlm_master_slave_ifs.h | 73 ++ .../tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_tag.h | 31 + .../tlm_1/tlm_req_rsp/tlm_adapters/tlm_adapters.h | 105 ++ .../tlm_channels/tlm_fifo/circular_buffer.h | 268 +++++ .../tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo.h | 263 +++++ .../tlm_channels/tlm_fifo/tlm_fifo_peek.h | 98 ++ .../tlm_channels/tlm_fifo/tlm_fifo_put_get.h | 140 +++ .../tlm_channels/tlm_fifo/tlm_fifo_resize.h | 93 ++ .../tlm_req_rsp_channels/tlm_put_get_imp.h | 114 ++ .../tlm_req_rsp_channels/tlm_req_rsp_channels.h | 155 +++ .../tlm_1/tlm_req_rsp/tlm_ports/tlm_event_finder.h | 76 ++ .../tlm_req_rsp/tlm_ports/tlm_nonblocking_port.h | 91 ++ .../ext/tlm_core/tlm_1/tlm_req_rsp/tlm_req_rsp.h | 37 + src/systemc/ext/tlm_core/tlm_2/README.txt | 111 ++ .../tlm_2/tlm_2_interfaces/tlm_2_interfaces.h | 27 + .../ext/tlm_core/tlm_2/tlm_2_interfaces/tlm_dmi.h | 114 ++ .../tlm_2/tlm_2_interfaces/tlm_fw_bw_ifs.h | 223 ++++ .../tlm_core/tlm_2/tlm_generic_payload/tlm_array.h | 126 +++ .../tlm_2/tlm_generic_payload/tlm_endian_conv.h | 791 ++++++++++++++ .../tlm_generic_payload/tlm_generic_payload.h | 29 + .../tlm_core/tlm_2/tlm_generic_payload/tlm_gp.h | 402 +++++++ .../tlm_2/tlm_generic_payload/tlm_helpers.h | 80 ++ .../tlm_core/tlm_2/tlm_generic_payload/tlm_phase.h | 108 ++ .../tlm_2/tlm_quantum/tlm_global_quantum.h | 82 ++ .../ext/tlm_core/tlm_2/tlm_quantum/tlm_quantum.h | 25 + .../tlm_2/tlm_sockets/tlm_base_socket_if.h | 56 + .../tlm_2/tlm_sockets/tlm_initiator_socket.h | 240 +++++ .../ext/tlm_core/tlm_2/tlm_sockets/tlm_sockets.h | 26 + .../tlm_core/tlm_2/tlm_sockets/tlm_target_socket.h | 255 +++++ src/systemc/ext/tlm_core/tlm_2/tlm_version.h | 180 ++++ src/systemc/ext/tlm_utils/Makefile.am | 62 ++ src/systemc/ext/tlm_utils/Makefile.in | 731 +++++++++++++ src/systemc/ext/tlm_utils/README.txt | 85 ++ .../ext/tlm_utils/convenience_socket_bases.h | 77 ++ .../ext/tlm_utils/instance_specific_extensions.h | 124 +++ .../tlm_utils/instance_specific_extensions_int.h | 174 +++ .../tlm_utils/multi_passthrough_initiator_socket.h | 286 +++++ .../tlm_utils/multi_passthrough_target_socket.h | 328 ++++++ src/systemc/ext/tlm_utils/multi_socket_bases.h | 440 ++++++++ .../ext/tlm_utils/passthrough_target_socket.h | 477 +++++++++ src/systemc/ext/tlm_utils/peq_with_cb_and_phase.h | 301 ++++++ src/systemc/ext/tlm_utils/peq_with_get.h | 94 ++ .../ext/tlm_utils/simple_initiator_socket.h | 316 ++++++ src/systemc/ext/tlm_utils/simple_target_socket.h | 1132 ++++++++++++++++++++ src/systemc/ext/tlm_utils/tlm_quantumkeeper.h | 172 +++ .../tlm_core/tlm_2/tlm_generic_payload/tlm_gp.cpp | 367 +++++++ .../tlm_2/tlm_generic_payload/tlm_phase.cpp | 113 ++ .../tlm_2/tlm_quantum/tlm_global_quantum.cpp | 49 + src/systemc/tlm_utils/convenience_socket_bases.cpp | 84 ++ .../tlm_utils/instance_specific_extensions.cpp | 249 +++++ 63 files changed, 11667 insertions(+) create mode 100644 src/systemc/ext/tlm create mode 100644 src/systemc/ext/tlm.h create mode 100644 src/systemc/ext/tlm_core/Makefile.am create mode 100644 src/systemc/ext/tlm_core/Makefile.in create mode 100644 src/systemc/ext/tlm_core/tlm_1/README.txt create mode 100644 src/systemc/ext/tlm_core/tlm_1/tlm_analysis/tlm_analysis.h create mode 100644 src/systemc/ext/tlm_core/tlm_1/tlm_analysis/tlm_analysis_fifo.h create mode 100644 src/systemc/ext/tlm_core/tlm_1/tlm_analysis/tlm_analysis_if.h create mode 100644 src/systemc/ext/tlm_core/tlm_1/tlm_analysis/tlm_analysis_port.h create mode 100644 src/systemc/ext/tlm_core/tlm_1/tlm_analysis/tlm_analysis_triple.h create mode 100644 src/systemc/ext/tlm_core/tlm_1/tlm_analysis/tlm_write_if.h create mode 100644 src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_core_ifs.h create mode 100644 src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_fifo_ifs.h create mode 100644 src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_master_slave_ifs.h create mode 100644 src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_tag.h create mode 100644 src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_adapters/tlm_adapters.h create mode 100644 src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/circular_buffer.h create mode 100644 src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo.h create mode 100644 src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_peek.h create mode 100644 src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_put_get.h create mode 100644 src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_resize.h create mode 100644 src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_req_rsp_channels/tlm_put_get_imp.h create mode 100644 src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_req_rsp_channels/tlm_req_rsp_channels.h create mode 100644 src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_ports/tlm_event_finder.h create mode 100644 src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_ports/tlm_nonblocking_port.h create mode 100644 src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_req_rsp.h create mode 100644 src/systemc/ext/tlm_core/tlm_2/README.txt create mode 100644 src/systemc/ext/tlm_core/tlm_2/tlm_2_interfaces/tlm_2_interfaces.h create mode 100644 src/systemc/ext/tlm_core/tlm_2/tlm_2_interfaces/tlm_dmi.h create mode 100644 src/systemc/ext/tlm_core/tlm_2/tlm_2_interfaces/tlm_fw_bw_ifs.h create mode 100644 src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_array.h create mode 100644 src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_endian_conv.h create mode 100644 src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_generic_payload.h create mode 100644 src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_gp.h create mode 100644 src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_helpers.h create mode 100644 src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_phase.h create mode 100644 src/systemc/ext/tlm_core/tlm_2/tlm_quantum/tlm_global_quantum.h create mode 100644 src/systemc/ext/tlm_core/tlm_2/tlm_quantum/tlm_quantum.h create mode 100644 src/systemc/ext/tlm_core/tlm_2/tlm_sockets/tlm_base_socket_if.h create mode 100644 src/systemc/ext/tlm_core/tlm_2/tlm_sockets/tlm_initiator_socket.h create mode 100644 src/systemc/ext/tlm_core/tlm_2/tlm_sockets/tlm_sockets.h create mode 100644 src/systemc/ext/tlm_core/tlm_2/tlm_sockets/tlm_target_socket.h create mode 100644 src/systemc/ext/tlm_core/tlm_2/tlm_version.h create mode 100644 src/systemc/ext/tlm_utils/Makefile.am create mode 100644 src/systemc/ext/tlm_utils/Makefile.in create mode 100644 src/systemc/ext/tlm_utils/README.txt create mode 100644 src/systemc/ext/tlm_utils/convenience_socket_bases.h create mode 100644 src/systemc/ext/tlm_utils/instance_specific_extensions.h create mode 100644 src/systemc/ext/tlm_utils/instance_specific_extensions_int.h create mode 100644 src/systemc/ext/tlm_utils/multi_passthrough_initiator_socket.h create mode 100644 src/systemc/ext/tlm_utils/multi_passthrough_target_socket.h create mode 100644 src/systemc/ext/tlm_utils/multi_socket_bases.h create mode 100644 src/systemc/ext/tlm_utils/passthrough_target_socket.h create mode 100644 src/systemc/ext/tlm_utils/peq_with_cb_and_phase.h create mode 100644 src/systemc/ext/tlm_utils/peq_with_get.h create mode 100644 src/systemc/ext/tlm_utils/simple_initiator_socket.h create mode 100644 src/systemc/ext/tlm_utils/simple_target_socket.h create mode 100644 src/systemc/ext/tlm_utils/tlm_quantumkeeper.h create mode 100644 src/systemc/tlm_core/tlm_2/tlm_generic_payload/tlm_gp.cpp create mode 100644 src/systemc/tlm_core/tlm_2/tlm_generic_payload/tlm_phase.cpp create mode 100644 src/systemc/tlm_core/tlm_2/tlm_quantum/tlm_global_quantum.cpp create mode 100644 src/systemc/tlm_utils/convenience_socket_bases.cpp create mode 100644 src/systemc/tlm_utils/instance_specific_extensions.cpp diff --git a/src/systemc/ext/tlm b/src/systemc/ext/tlm new file mode 100644 index 000000000..b4fb9fe70 --- /dev/null +++ b/src/systemc/ext/tlm @@ -0,0 +1,33 @@ +/***************************************************************************** + + 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_HEADER__ +#define __TLM_HEADER__ + +#include // main SystemC header + +#include "tlm_core/tlm_2/tlm_version.h" +#include "tlm_core/tlm_1/tlm_analysis/tlm_analysis.h" +#include "tlm_core/tlm_1/tlm_req_rsp/tlm_req_rsp.h" +#include "tlm_core/tlm_2/tlm_2_interfaces/tlm_2_interfaces.h" +#include "tlm_core/tlm_2/tlm_generic_payload/tlm_generic_payload.h" +#include "tlm_core/tlm_2/tlm_sockets/tlm_sockets.h" +#include "tlm_core/tlm_2/tlm_quantum/tlm_quantum.h" + +#endif /* TLM_HEADER_INCLUDED_ */ diff --git a/src/systemc/ext/tlm.h b/src/systemc/ext/tlm.h new file mode 100644 index 000000000..36d6263ea --- /dev/null +++ b/src/systemc/ext/tlm.h @@ -0,0 +1,22 @@ +/***************************************************************************** + + 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" diff --git a/src/systemc/ext/tlm_core/Makefile.am b/src/systemc/ext/tlm_core/Makefile.am new file mode 100644 index 000000000..38098a88f --- /dev/null +++ b/src/systemc/ext/tlm_core/Makefile.am @@ -0,0 +1,97 @@ +## **************************************************************************** +## +## 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 + +localincludedir = $(includedir)/tlm_core +nobase_localinclude_HEADERS = $(H_FILES) + +noinst_LTLIBRARIES = libtlm_core.la +libtlm_core_la_SOURCES = $(NO_H_FILES) $(CXX_FILES) diff --git a/src/systemc/ext/tlm_core/Makefile.in b/src/systemc/ext/tlm_core/Makefile.in new file mode 100644 index 000000000..0202a6b90 --- /dev/null +++ b/src/systemc/ext/tlm_core/Makefile.in @@ -0,0 +1,799 @@ +# 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 + +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 + +.MAKE: install-am install-strip + +.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-nobase_localincludeHEADERS + + +# 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: diff --git a/src/systemc/ext/tlm_core/tlm_1/README.txt b/src/systemc/ext/tlm_core/tlm_1/README.txt new file mode 100644 index 000000000..c7e1c5e1f --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_1/README.txt @@ -0,0 +1,97 @@ +TLM-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) diff --git a/src/systemc/ext/tlm_core/tlm_1/tlm_analysis/tlm_analysis.h b/src/systemc/ext/tlm_core/tlm_1/tlm_analysis/tlm_analysis.h new file mode 100644 index 000000000..777f7141a --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_1/tlm_analysis/tlm_analysis.h @@ -0,0 +1,33 @@ +/***************************************************************************** + + 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 + + diff --git a/src/systemc/ext/tlm_core/tlm_1/tlm_analysis/tlm_analysis_fifo.h b/src/systemc/ext/tlm_core/tlm_1/tlm_analysis/tlm_analysis_fifo.h new file mode 100644 index 000000000..1f01b2a8e --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_1/tlm_analysis/tlm_analysis_fifo.h @@ -0,0 +1,54 @@ +/***************************************************************************** + + 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 diff --git a/src/systemc/ext/tlm_core/tlm_1/tlm_analysis/tlm_analysis_if.h b/src/systemc/ext/tlm_core/tlm_1/tlm_analysis/tlm_analysis_if.h new file mode 100644 index 000000000..bc24fee54 --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_1/tlm_analysis/tlm_analysis_if.h @@ -0,0 +1,39 @@ +/***************************************************************************** + + 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 diff --git a/src/systemc/ext/tlm_core/tlm_1/tlm_analysis/tlm_analysis_port.h b/src/systemc/ext/tlm_core/tlm_1/tlm_analysis/tlm_analysis_port.h new file mode 100644 index 000000000..999092538 --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_1/tlm_analysis/tlm_analysis_port.h @@ -0,0 +1,84 @@ +/***************************************************************************** + + 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 + + diff --git a/src/systemc/ext/tlm_core/tlm_1/tlm_analysis/tlm_analysis_triple.h b/src/systemc/ext/tlm_core/tlm_1/tlm_analysis/tlm_analysis_triple.h new file mode 100644 index 000000000..f65a25a2e --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_1/tlm_analysis/tlm_analysis_triple.h @@ -0,0 +1,53 @@ +/***************************************************************************** + + 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 diff --git a/src/systemc/ext/tlm_core/tlm_1/tlm_analysis/tlm_write_if.h b/src/systemc/ext/tlm_core/tlm_1/tlm_analysis/tlm_write_if.h new file mode 100644 index 000000000..b66a591bc --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_1/tlm_analysis/tlm_write_if.h @@ -0,0 +1,42 @@ +/***************************************************************************** + + 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 diff --git a/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_core_ifs.h b/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_core_ifs.h new file mode 100644 index 000000000..4c1340338 --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_core_ifs.h @@ -0,0 +1,149 @@ +/***************************************************************************** + + 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 diff --git a/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_fifo_ifs.h b/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_fifo_ifs.h new file mode 100644 index 000000000..d9b2b985b --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_fifo_ifs.h @@ -0,0 +1,85 @@ +/***************************************************************************** + + 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 + diff --git a/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_master_slave_ifs.h b/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_master_slave_ifs.h new file mode 100644 index 000000000..5bac3c877 --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_master_slave_ifs.h @@ -0,0 +1,73 @@ +/***************************************************************************** + + 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 diff --git a/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_tag.h b/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_tag.h new file mode 100644 index 000000000..230b77d17 --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_1_interfaces/tlm_tag.h @@ -0,0 +1,31 @@ +/***************************************************************************** + + 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 diff --git a/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_adapters/tlm_adapters.h b/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_adapters/tlm_adapters.h new file mode 100644 index 000000000..13207187a --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_adapters/tlm_adapters.h @@ -0,0 +1,105 @@ +/***************************************************************************** + + 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 diff --git a/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/circular_buffer.h b/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/circular_buffer.h new file mode 100644 index 000000000..50309e31b --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/circular_buffer.h @@ -0,0 +1,268 @@ +/***************************************************************************** + + 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 + diff --git a/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo.h b/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo.h new file mode 100644 index 000000000..7b44a32ee --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo.h @@ -0,0 +1,263 @@ +/***************************************************************************** + + 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 + diff --git a/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_peek.h b/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_peek.h new file mode 100644 index 000000000..e856c5657 --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_peek.h @@ -0,0 +1,98 @@ +/***************************************************************************** + + 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 diff --git a/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_put_get.h b/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_put_get.h new file mode 100644 index 000000000..2728e0394 --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_put_get.h @@ -0,0 +1,140 @@ +/***************************************************************************** + + 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 diff --git a/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_resize.h b/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_resize.h new file mode 100644 index 000000000..39932fea1 --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_resize.h @@ -0,0 +1,93 @@ +/***************************************************************************** + + 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 diff --git a/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_req_rsp_channels/tlm_put_get_imp.h b/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_req_rsp_channels/tlm_put_get_imp.h new file mode 100644 index 000000000..36dbd21d6 --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_req_rsp_channels/tlm_put_get_imp.h @@ -0,0 +1,114 @@ +/***************************************************************************** + + 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 : + private virtual tlm_put_if< PUT_DATA > , + private 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 diff --git a/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_req_rsp_channels/tlm_req_rsp_channels.h b/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_req_rsp_channels/tlm_req_rsp_channels.h new file mode 100644 index 000000000..7bd5652f7 --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_channels/tlm_req_rsp_channels/tlm_req_rsp_channels.h @@ -0,0 +1,155 @@ +/***************************************************************************** + + 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 diff --git a/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_ports/tlm_event_finder.h b/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_ports/tlm_event_finder.h new file mode 100644 index 000000000..4ca042857 --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_ports/tlm_event_finder.h @@ -0,0 +1,76 @@ +/***************************************************************************** + + 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_ diff --git a/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_ports/tlm_nonblocking_port.h b/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_ports/tlm_nonblocking_port.h new file mode 100644 index 000000000..0af1e3487 --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_ports/tlm_nonblocking_port.h @@ -0,0 +1,91 @@ +/***************************************************************************** + + 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 diff --git a/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_req_rsp.h b/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_req_rsp.h new file mode 100644 index 000000000..88f1d0e8c --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_1/tlm_req_rsp/tlm_req_rsp.h @@ -0,0 +1,37 @@ +/***************************************************************************** + + 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__ */ diff --git a/src/systemc/ext/tlm_core/tlm_2/README.txt b/src/systemc/ext/tlm_core/tlm_2/README.txt new file mode 100644 index 000000000..cb02af2d8 --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_2/README.txt @@ -0,0 +1,111 @@ +TLM-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 ) diff --git a/src/systemc/ext/tlm_core/tlm_2/tlm_2_interfaces/tlm_2_interfaces.h b/src/systemc/ext/tlm_core/tlm_2/tlm_2_interfaces/tlm_2_interfaces.h new file mode 100644 index 000000000..8a0c543c8 --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_2/tlm_2_interfaces/tlm_2_interfaces.h @@ -0,0 +1,27 @@ +/***************************************************************************** + + 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 + diff --git a/src/systemc/ext/tlm_core/tlm_2/tlm_2_interfaces/tlm_dmi.h b/src/systemc/ext/tlm_core/tlm_2/tlm_2_interfaces/tlm_dmi.h new file mode 100644 index 000000000..d7c3304eb --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_2/tlm_2_interfaces/tlm_dmi.h @@ -0,0 +1,114 @@ +/***************************************************************************** + + 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 */ diff --git a/src/systemc/ext/tlm_core/tlm_2/tlm_2_interfaces/tlm_fw_bw_ifs.h b/src/systemc/ext/tlm_core/tlm_2/tlm_2_interfaces/tlm_fw_bw_ifs.h new file mode 100644 index 000000000..59e81c658 --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_2/tlm_2_interfaces/tlm_fw_bw_ifs.h @@ -0,0 +1,223 @@ +/***************************************************************************** + + 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__ */ diff --git a/src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_array.h b/src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_array.h new file mode 100644 index 000000000..1a49b0895 --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_array.h @@ -0,0 +1,126 @@ +/***************************************************************************** + + 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_ */ diff --git a/src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_endian_conv.h b/src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_endian_conv.h new file mode 100644 index 000000000..cf17a1ffb --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_endian_conv.h @@ -0,0 +1,791 @@ +/***************************************************************************** + + 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 + diff --git a/src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_generic_payload.h b/src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_generic_payload.h new file mode 100644 index 000000000..3e25e56f2 --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_generic_payload.h @@ -0,0 +1,29 @@ +/***************************************************************************** + + 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 + diff --git a/src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_gp.h b/src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_gp.h new file mode 100644 index 000000000..99bb1e969 --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_gp.h @@ -0,0 +1,402 @@ +/***************************************************************************** + + 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_ */ diff --git a/src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_helpers.h b/src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_helpers.h new file mode 100644 index 000000000..da3abb4f9 --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_helpers.h @@ -0,0 +1,80 @@ +/***************************************************************************** + + 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__ */ diff --git a/src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_phase.h b/src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_phase.h new file mode 100644 index 000000000..a06ccc443 --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_2/tlm_generic_payload/tlm_phase.h @@ -0,0 +1,108 @@ +/***************************************************************************** + + 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! diff --git a/src/systemc/ext/tlm_core/tlm_2/tlm_quantum/tlm_global_quantum.h b/src/systemc/ext/tlm_core/tlm_2/tlm_quantum/tlm_global_quantum.h new file mode 100644 index 000000000..5c08acf28 --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_2/tlm_quantum/tlm_global_quantum.h @@ -0,0 +1,82 @@ +/***************************************************************************** + + 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_ diff --git a/src/systemc/ext/tlm_core/tlm_2/tlm_quantum/tlm_quantum.h b/src/systemc/ext/tlm_core/tlm_2/tlm_quantum/tlm_quantum.h new file mode 100644 index 000000000..f06a4633a --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_2/tlm_quantum/tlm_quantum.h @@ -0,0 +1,25 @@ +/***************************************************************************** + + 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_ diff --git a/src/systemc/ext/tlm_core/tlm_2/tlm_sockets/tlm_base_socket_if.h b/src/systemc/ext/tlm_core/tlm_2/tlm_sockets/tlm_base_socket_if.h new file mode 100644 index 000000000..c847835d7 --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_2/tlm_sockets/tlm_base_socket_if.h @@ -0,0 +1,56 @@ +/***************************************************************************** + + 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_ diff --git a/src/systemc/ext/tlm_core/tlm_2/tlm_sockets/tlm_initiator_socket.h b/src/systemc/ext/tlm_core/tlm_2/tlm_sockets/tlm_initiator_socket.h new file mode 100644 index 000000000..b703ec210 --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_2/tlm_sockets/tlm_initiator_socket.h @@ -0,0 +1,240 @@ +/***************************************************************************** + + 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_ diff --git a/src/systemc/ext/tlm_core/tlm_2/tlm_sockets/tlm_sockets.h b/src/systemc/ext/tlm_core/tlm_2/tlm_sockets/tlm_sockets.h new file mode 100644 index 000000000..013e29286 --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_2/tlm_sockets/tlm_sockets.h @@ -0,0 +1,26 @@ +/***************************************************************************** + + 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__ */ diff --git a/src/systemc/ext/tlm_core/tlm_2/tlm_sockets/tlm_target_socket.h b/src/systemc/ext/tlm_core/tlm_2/tlm_sockets/tlm_target_socket.h new file mode 100644 index 000000000..030643294 --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_2/tlm_sockets/tlm_target_socket.h @@ -0,0 +1,255 @@ +/***************************************************************************** + + 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_ diff --git a/src/systemc/ext/tlm_core/tlm_2/tlm_version.h b/src/systemc/ext/tlm_core/tlm_2/tlm_version.h new file mode 100644 index 000000000..3cf230077 --- /dev/null +++ b/src/systemc/ext/tlm_core/tlm_2/tlm_version.h @@ -0,0 +1,180 @@ +/***************************************************************************** + + 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 4 ///< version patch level ( numeric ) +#define TLM_VERSION_ORIGINATOR "Accellera" ///< TLM creator string +#define TLM_VERSION_SEPARATOR "." ///< version string separator + +#define TLM_IS_PRERELEASE 0 ///< 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 "2017" ///< release year ( YYYY ) +#define TLM_VERSION_RELEASE_MONTH "10" ///< release month ( MM ) +#define TLM_VERSION_RELEASE_DAY "12" ///< 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__ */ diff --git a/src/systemc/ext/tlm_utils/Makefile.am b/src/systemc/ext/tlm_utils/Makefile.am new file mode 100644 index 000000000..cd9e960a1 --- /dev/null +++ b/src/systemc/ext/tlm_utils/Makefile.am @@ -0,0 +1,62 @@ +## **************************************************************************** +## +## 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) diff --git a/src/systemc/ext/tlm_utils/Makefile.in b/src/systemc/ext/tlm_utils/Makefile.in new file mode 100644 index 000000000..6c1469c4a --- /dev/null +++ b/src/systemc/ext/tlm_utils/Makefile.in @@ -0,0 +1,731 @@ +# 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 + +.MAKE: install-am install-strip + +.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-nobase_localincludeHEADERS + + +# 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: diff --git a/src/systemc/ext/tlm_utils/README.txt b/src/systemc/ext/tlm_utils/README.txt new file mode 100644 index 000000000..8be587bdf --- /dev/null +++ b/src/systemc/ext/tlm_utils/README.txt @@ -0,0 +1,85 @@ + +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. diff --git a/src/systemc/ext/tlm_utils/convenience_socket_bases.h b/src/systemc/ext/tlm_utils/convenience_socket_bases.h new file mode 100644 index 000000000..81efaac09 --- /dev/null +++ b/src/systemc/ext/tlm_utils/convenience_socket_bases.h @@ -0,0 +1,77 @@ +/***************************************************************************** + + 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_ diff --git a/src/systemc/ext/tlm_utils/instance_specific_extensions.h b/src/systemc/ext/tlm_utils/instance_specific_extensions.h new file mode 100644 index 000000000..5d9f66b13 --- /dev/null +++ b/src/systemc/ext/tlm_utils/instance_specific_extensions.h @@ -0,0 +1,124 @@ +/***************************************************************************** + + 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_ diff --git a/src/systemc/ext/tlm_utils/instance_specific_extensions_int.h b/src/systemc/ext/tlm_utils/instance_specific_extensions_int.h new file mode 100644 index 000000000..192a600ba --- /dev/null +++ b/src/systemc/ext/tlm_utils/instance_specific_extensions_int.h @@ -0,0 +1,174 @@ +/***************************************************************************** + + 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_ diff --git a/src/systemc/ext/tlm_utils/multi_passthrough_initiator_socket.h b/src/systemc/ext/tlm_utils/multi_passthrough_initiator_socket.h new file mode 100644 index 000000000..0a0dd6993 --- /dev/null +++ b/src/systemc/ext/tlm_utils/multi_passthrough_initiator_socket.h @@ -0,0 +1,286 @@ +/***************************************************************************** + + 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_ diff --git a/src/systemc/ext/tlm_utils/multi_passthrough_target_socket.h b/src/systemc/ext/tlm_utils/multi_passthrough_target_socket.h new file mode 100644 index 000000000..0b759d4aa --- /dev/null +++ b/src/systemc/ext/tlm_utils/multi_passthrough_target_socket.h @@ -0,0 +1,328 @@ +/***************************************************************************** + + 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 unbound = (binders.size() == 1 && m_export_callback_created); + // no call to get_base_interface has consumed the export - ignore + if (unbound) 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_ diff --git a/src/systemc/ext/tlm_utils/multi_socket_bases.h b/src/systemc/ext/tlm_utils/multi_socket_bases.h new file mode 100644 index 000000000..d937511dc --- /dev/null +++ b/src/systemc/ext/tlm_utils/multi_socket_bases.h @@ -0,0 +1,440 @@ +/***************************************************************************** + + 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_ diff --git a/src/systemc/ext/tlm_utils/passthrough_target_socket.h b/src/systemc/ext/tlm_utils/passthrough_target_socket.h new file mode 100644 index 000000000..b2c97aed5 --- /dev/null +++ b/src/systemc/ext/tlm_utils/passthrough_target_socket.h @@ -0,0 +1,477 @@ +/***************************************************************************** + + 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_ diff --git a/src/systemc/ext/tlm_utils/peq_with_cb_and_phase.h b/src/systemc/ext/tlm_utils/peq_with_cb_and_phase.h new file mode 100644 index 000000000..60f96e6bd --- /dev/null +++ b/src/systemc/ext/tlm_utils/peq_with_cb_and_phase.h @@ -0,0 +1,301 @@ +/***************************************************************************** + + 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__ diff --git a/src/systemc/ext/tlm_utils/peq_with_get.h b/src/systemc/ext/tlm_utils/peq_with_get.h new file mode 100644 index 000000000..5c85f25d5 --- /dev/null +++ b/src/systemc/ext/tlm_utils/peq_with_get.h @@ -0,0 +1,94 @@ +/***************************************************************************** + + 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 diff --git a/src/systemc/ext/tlm_utils/simple_initiator_socket.h b/src/systemc/ext/tlm_utils/simple_initiator_socket.h new file mode 100644 index 000000000..0cf9c5649 --- /dev/null +++ b/src/systemc/ext/tlm_utils/simple_initiator_socket.h @@ -0,0 +1,316 @@ +/***************************************************************************** + + 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_ diff --git a/src/systemc/ext/tlm_utils/simple_target_socket.h b/src/systemc/ext/tlm_utils/simple_target_socket.h new file mode 100644 index 000000000..7e4c3a197 --- /dev/null +++ b/src/systemc/ext/tlm_utils/simple_target_socket.h @@ -0,0 +1,1132 @@ +/***************************************************************************** + + 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_ diff --git a/src/systemc/ext/tlm_utils/tlm_quantumkeeper.h b/src/systemc/ext/tlm_utils/tlm_quantumkeeper.h new file mode 100644 index 000000000..ed211665f --- /dev/null +++ b/src/systemc/ext/tlm_utils/tlm_quantumkeeper.h @@ -0,0 +1,172 @@ +/***************************************************************************** + + 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 diff --git a/src/systemc/tlm_core/tlm_2/tlm_generic_payload/tlm_gp.cpp b/src/systemc/tlm_core/tlm_2/tlm_generic_payload/tlm_gp.cpp new file mode 100644 index 000000000..6843db312 --- /dev/null +++ b/src/systemc/tlm_core/tlm_2/tlm_generic_payload/tlm_gp.cpp @@ -0,0 +1,367 @@ +/***************************************************************************** + + 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 diff --git a/src/systemc/tlm_core/tlm_2/tlm_generic_payload/tlm_phase.cpp b/src/systemc/tlm_core/tlm_2/tlm_generic_payload/tlm_phase.cpp new file mode 100644 index 000000000..5f3fb25e0 --- /dev/null +++ b/src/systemc/tlm_core/tlm_2/tlm_generic_payload/tlm_phase.cpp @@ -0,0 +1,113 @@ +/***************************************************************************** + + 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! diff --git a/src/systemc/tlm_core/tlm_2/tlm_quantum/tlm_global_quantum.cpp b/src/systemc/tlm_core/tlm_2/tlm_quantum/tlm_global_quantum.cpp new file mode 100644 index 000000000..8ac09cc9b --- /dev/null +++ b/src/systemc/tlm_core/tlm_2/tlm_quantum/tlm_global_quantum.cpp @@ -0,0 +1,49 @@ +/***************************************************************************** + + 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 diff --git a/src/systemc/tlm_utils/convenience_socket_bases.cpp b/src/systemc/tlm_utils/convenience_socket_bases.cpp new file mode 100644 index 000000000..5d03fd23f --- /dev/null +++ b/src/systemc/tlm_utils/convenience_socket_bases.cpp @@ -0,0 +1,84 @@ +/***************************************************************************** + + 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 diff --git a/src/systemc/tlm_utils/instance_specific_extensions.cpp b/src/systemc/tlm_utils/instance_specific_extensions.cpp new file mode 100644 index 000000000..9406dc8da --- /dev/null +++ b/src/systemc/tlm_utils/instance_specific_extensions.cpp @@ -0,0 +1,249 @@ +/***************************************************************************** + + 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 -- cgit v1.2.3