From 262f093eb54b7533efe0b0a9cb1608593f9e077a Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Fri, 30 Nov 2018 11:08:08 +0100 Subject: [PATCH] Started from SystemC-Quickstart --- .cproject | 120 +++++++++++ .gitignore | 1 + .gitmodules | 0 .project | 34 +++ .pydevproject | 6 + .settings/language.settings.xml | 29 +++ .../org.eclipse.cdt.managedbuilder.core.prefs | 13 ++ CMakeLists.txt | 35 +++ LICENSE | 201 ++++++++++++++++++ README.md | 28 +++ cmake/Conan.cmake | 45 ++++ components/components.h | 18 ++ components/initiator.cpp | 136 ++++++++++++ components/initiator.h | 36 ++++ components/logging.cpp | 115 ++++++++++ components/logging.h | 42 ++++ components/router.h | 133 ++++++++++++ components/router_example.cpp | 18 ++ components/target.cpp | 102 +++++++++ components/target.h | 46 ++++ components/top.h | 33 +++ components/tx_example.cpp | 44 ++++ components/tx_example_mods.cpp | 140 ++++++++++++ components/tx_example_mods.h | 136 ++++++++++++ components/txtop.cpp | 49 +++++ components/txtop.h | 31 +++ conanfile.txt | 11 + router_example.py | 36 ++++ 28 files changed, 1638 insertions(+) create mode 100644 .cproject create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 .project create mode 100644 .pydevproject create mode 100644 .settings/language.settings.xml create mode 100644 .settings/org.eclipse.cdt.managedbuilder.core.prefs create mode 100644 CMakeLists.txt create mode 100644 LICENSE create mode 100644 README.md create mode 100644 cmake/Conan.cmake create mode 100644 components/components.h create mode 100644 components/initiator.cpp create mode 100644 components/initiator.h create mode 100644 components/logging.cpp create mode 100644 components/logging.h create mode 100644 components/router.h create mode 100644 components/router_example.cpp create mode 100644 components/target.cpp create mode 100644 components/target.h create mode 100644 components/top.h create mode 100644 components/tx_example.cpp create mode 100644 components/tx_example_mods.cpp create mode 100644 components/tx_example_mods.h create mode 100644 components/txtop.cpp create mode 100644 components/txtop.h create mode 100644 conanfile.txt create mode 100644 router_example.py diff --git a/.cproject b/.cproject new file mode 100644 index 0000000..e3c80bb --- /dev/null +++ b/.cproject @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84c048a --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/build/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..e69de29 diff --git a/.project b/.project new file mode 100644 index 0000000..21905b2 --- /dev/null +++ b/.project @@ -0,0 +1,34 @@ + + + PySysC-SC + + + PySysC + + + + org.python.pydev.PyDevBuilder + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.core.ccnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + org.python.pydev.pythonNature + + diff --git a/.pydevproject b/.pydevproject new file mode 100644 index 0000000..37ae0d1 --- /dev/null +++ b/.pydevproject @@ -0,0 +1,6 @@ + + +PySysC Python 3.6.3 +python interpreter +3.6 + diff --git a/.settings/language.settings.xml b/.settings/language.settings.xml new file mode 100644 index 0000000..fa7a16b --- /dev/null +++ b/.settings/language.settings.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.settings/org.eclipse.cdt.managedbuilder.core.prefs b/.settings/org.eclipse.cdt.managedbuilder.core.prefs new file mode 100644 index 0000000..10e755f --- /dev/null +++ b/.settings/org.eclipse.cdt.managedbuilder.core.prefs @@ -0,0 +1,13 @@ +eclipse.preferences.version=1 +environment/buildEnvironmentInclude/cdt.managedbuild.toolchain.gnu.base.1318364290/CPATH/delimiter=\: +environment/buildEnvironmentInclude/cdt.managedbuild.toolchain.gnu.base.1318364290/CPATH/operation=remove +environment/buildEnvironmentInclude/cdt.managedbuild.toolchain.gnu.base.1318364290/CPLUS_INCLUDE_PATH/delimiter=\: +environment/buildEnvironmentInclude/cdt.managedbuild.toolchain.gnu.base.1318364290/CPLUS_INCLUDE_PATH/operation=remove +environment/buildEnvironmentInclude/cdt.managedbuild.toolchain.gnu.base.1318364290/C_INCLUDE_PATH/delimiter=\: +environment/buildEnvironmentInclude/cdt.managedbuild.toolchain.gnu.base.1318364290/C_INCLUDE_PATH/operation=remove +environment/buildEnvironmentInclude/cdt.managedbuild.toolchain.gnu.base.1318364290/append=true +environment/buildEnvironmentInclude/cdt.managedbuild.toolchain.gnu.base.1318364290/appendContributed=true +environment/buildEnvironmentLibrary/cdt.managedbuild.toolchain.gnu.base.1318364290/LIBRARY_PATH/delimiter=\: +environment/buildEnvironmentLibrary/cdt.managedbuild.toolchain.gnu.base.1318364290/LIBRARY_PATH/operation=remove +environment/buildEnvironmentLibrary/cdt.managedbuild.toolchain.gnu.base.1318364290/append=true +environment/buildEnvironmentLibrary/cdt.managedbuild.toolchain.gnu.base.1318364290/appendContributed=true diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..e7a5be4 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,35 @@ +project(TransactionExample CXX) +cmake_minimum_required(VERSION 3.9) +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake) + +include(Conan) +setup_conan() + +conan_basic_setup(TARGETS) + +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +add_library(components SHARED + components/tx_example_mods.cpp + components/initiator.cpp + components/target.cpp + components/logging.cpp) +target_link_libraries(components PUBLIC CONAN_PKG::SystemC) +target_link_libraries(components PUBLIC CONAN_PKG::SystemCVerification) + +add_executable(TransactionExample + components/tx_example.cpp + components/txtop.cpp) +target_link_libraries(TransactionExample components) + +add_executable(router_example + components/router_example.cpp) +target_link_libraries(router_example components) + +# CTest is a testing tool that can be used to test your project. +# enable_testing() +# add_test(NAME example +# WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/bin +# COMMAND example) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8dada3e --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed 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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..8291405 --- /dev/null +++ b/README.md @@ -0,0 +1,28 @@ +# PySysC-SC + +A simple C++/SystemC/CMake project to test pysysc + +# How to build + +> Currently only Linux and MacOS are tested + + +``` +pip install conan +conan remote add minres https://api.bintray.com/conan/minres/conan-repo +cd PySysC-SC +mkdir build +cd build +conan install .. --build=missing +cmake .. +cmake --build . +``` + +## Notes + +If you encounter issues when linking wrt. c++11 symbols you might have run into GCC ABI incompatibility introduced from GCC 5.0 onwards. You can fix this by adding '-s compiler.libcxx=libstdc++11' to the conan call or changing compiler.libcxx to +``` +compiler.libcxx=libstdc++11 +``` +in $HOME/.conan/profiles/default + diff --git a/cmake/Conan.cmake b/cmake/Conan.cmake new file mode 100644 index 0000000..5bd9930 --- /dev/null +++ b/cmake/Conan.cmake @@ -0,0 +1,45 @@ +macro(setup_conan) + find_program(conan conan) + if(NOT EXISTS ${conan}) + message(FATAL_ERROR "Conan is required. Please see README.md") + return() + endif() + + if(${CMAKE_HOST_SYSTEM_NAME} STREQUAL Darwin) + set(os Macos) + else() + set(os ${CMAKE_HOST_SYSTEM_NAME}) + endif() + + if(${CMAKE_CXX_COMPILER_ID} STREQUAL GNU) + set(compiler gcc) + elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL AppleClang) + set(compiler apple-clang) + else() + message(FATAL_ERROR "Unknown compiler: ${CMAKE_CXX_COMPILER_ID}") + endif() + + string(SUBSTRING ${CMAKE_CXX_COMPILER_VERSION} 0 3 compiler_version) + + set(conanfile ${CMAKE_SOURCE_DIR}/conanfile.txt) + set(conanfile_cmake ${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) + set(compiler_libcxx libstdc++11) + + if("${CMAKE_BUILD_TYPE}" STREQUAL "") + set(CONAN_BUILD_TYPE Debug) + elseif("${CMAKE_BUILD_TYPE}" STREQUAL "RelWithDebInfo") + set(CONAN_BUILD_TYPE Release) + else() + set(CONAN_BUILD_TYPE ${CMAKE_BUILD_TYPE}) + endif() + + execute_process(COMMAND ${conan} install --build=missing + -s build_type=${CONAN_BUILD_TYPE} -s compiler.libcxx=${compiler_libcxx} + ${CMAKE_SOURCE_DIR} RESULT_VARIABLE return_code) + if(NOT ${return_code} EQUAL 0) + message(FATAL_ERROR "conan install command failed.") + endif() + + include(${conanfile_cmake}) + conan_basic_setup() +endmacro() diff --git a/components/components.h b/components/components.h new file mode 100644 index 0000000..88f8131 --- /dev/null +++ b/components/components.h @@ -0,0 +1,18 @@ +/* + * components.h + * + * Created on: 02.12.2018 + * Author: eyck + */ + +#ifndef COMPONENTS_H_ +#define COMPONENTS_H_ + +//#include "tx_example_mods.h" +#include +#include "logging.h" +#include "initiator.h" +#include "router.h" +#include "target.h" + +#endif /* COMPONENTS_H_ */ diff --git a/components/initiator.cpp b/components/initiator.cpp new file mode 100644 index 0000000..01019d5 --- /dev/null +++ b/components/initiator.cpp @@ -0,0 +1,136 @@ +/* + * initiator.cpp + * + * Created on: 02.12.2018 + * Author: eyck + */ + +#include "initiator.h" +#include "logging.h" + + +Initiator::Initiator(::sc_core::sc_module_name nm) +: socket("socket") // Construct and name socket +, dmi_ptr_valid(false) +{ + // Register callbacks for incoming interface method calls + socket.register_invalidate_direct_mem_ptr(this, &Initiator::invalidate_direct_mem_ptr); + + SC_THREAD(thread_process); +} + +void Initiator::thread_process() { + { + // TLM-2 generic payload transaction, reused across calls to b_transport, DMI and debug + tlm::tlm_generic_payload* trans = new tlm::tlm_generic_payload; + sc_time delay = sc_time(10, SC_NS); + + // Generate a random sequence of reads and writes + for (int i = 256-64; i < 256+64; i += 4) + { + int data; + tlm::tlm_command cmd = static_cast(rand() % 2); + if (cmd == tlm::TLM_WRITE_COMMAND) data = 0xFF000000 | i; + + // Use DMI if it is available + if (dmi_ptr_valid && sc_dt::uint64(i) >= dmi_data.get_start_address() + && sc_dt::uint64(i) <= dmi_data.get_end_address()) + { + // Bypass transport interface and use direct memory interface + // Implement target latency + if ( cmd == tlm::TLM_READ_COMMAND ) + { + assert( dmi_data.is_read_allowed() ); + memcpy(&data, dmi_data.get_dmi_ptr() + i - dmi_data.get_start_address(), 4); + wait( dmi_data.get_read_latency() ); + } + else if ( cmd == tlm::TLM_WRITE_COMMAND ) + { + assert( dmi_data.is_write_allowed() ); + memcpy(dmi_data.get_dmi_ptr() + i - dmi_data.get_start_address(), &data, 4); + wait( dmi_data.get_write_latency() ); + } + + LOG_INFO << "DMI = { " << (cmd ? 'W' : 'R') << ", " << hex << i + << " } , data = " << hex << data << " at time " << sc_time_stamp(); + } + else + { + trans->set_command( cmd ); + trans->set_address( i ); + trans->set_data_ptr( reinterpret_cast(&data) ); + trans->set_data_length( 4 ); + trans->set_streaming_width( 4 ); // = data_length to indicate no streaming + trans->set_byte_enable_ptr( 0 ); // 0 indicates unused + trans->set_dmi_allowed( false ); // Mandatory initial value + trans->set_response_status( tlm::TLM_INCOMPLETE_RESPONSE ); // Mandatory initial value + + +#ifdef INJECT_ERROR + if (i > 90) trans->set_streaming_width(2); +#endif + + // Other fields default: byte enable = 0, streaming width = 0, DMI_hint = false, no extensions + + socket->b_transport( *trans, delay ); // Blocking transport call + + // Initiator obliged to check response status + if ( trans->is_response_error() ) + { + // Print response string + char txt[100]; + sprintf(txt, "Error from b_transport, response status = %s", + trans->get_response_string().c_str()); + SC_REPORT_ERROR("TLM-2", txt); + + } + + // Check DMI hint + if ( trans->is_dmi_allowed() ) + { + // ********************************************* + // Re-use transaction object for DMI. Reset the address because it could + // have been modified by the interconnect on the previous transport call + // ********************************************* + + trans->set_address( i ); + dmi_ptr_valid = socket->get_direct_mem_ptr( *trans, dmi_data ); + } + + LOG_INFO << "trans = { " << (cmd ? 'W' : 'R') << ", " << hex << i + << " } , data = " << hex << data << " at time " << sc_time_stamp(); + } + } + + // Use debug transaction interface to dump memory contents, reusing same transaction object + sc_dt::uint64 A = 128; + trans->set_address(A); + trans->set_read(); + trans->set_data_length(256); + + unsigned char* data = new unsigned char[256]; + trans->set_data_ptr(data); + + unsigned int n_bytes = socket->transport_dbg( *trans ); + + for (unsigned int i = 0; i < n_bytes; i += 4) + { + LOG_INFO << "mem[" << (A + i) << "] = " + << *(reinterpret_cast( &data[i] )); + } + + A = 256; + trans->set_address(A); + trans->set_data_length(128); + + n_bytes = socket->transport_dbg( *trans ); + + for (unsigned int i = 0; i < n_bytes; i += 4) + { + LOG_INFO << "mem[" << (A + i) << "] = " + << *(reinterpret_cast( &data[i] )); + } + } +} + + diff --git a/components/initiator.h b/components/initiator.h new file mode 100644 index 0000000..b47d11f --- /dev/null +++ b/components/initiator.h @@ -0,0 +1,36 @@ +#ifndef INITIATOR_H +#define INITIATOR_H + +#include "systemc" +using namespace sc_core; +using namespace sc_dt; +using namespace std; + +#include "tlm.h" +#include "tlm_utils/simple_initiator_socket.h" + + +// Initiator module generating generic payload transactions + +struct Initiator: sc_module +{ + // TLM-2 socket, defaults to 32-bits wide, base protocol + tlm_utils::simple_initiator_socket socket; + + SC_HAS_PROCESS(Initiator); + + Initiator( ::sc_core::sc_module_name ); + + void thread_process(); + + // TLM-2 backward DMI method + void invalidate_direct_mem_ptr(sc_dt::uint64 start_range, sc_dt::uint64 end_range){ + // Ignore range and invalidate all DMI pointers regardless + dmi_ptr_valid = false; + } + + bool dmi_ptr_valid; + tlm::tlm_dmi dmi_data; +}; + +#endif diff --git a/components/logging.cpp b/components/logging.cpp new file mode 100644 index 0000000..dc5fcdc --- /dev/null +++ b/components/logging.cpp @@ -0,0 +1,115 @@ +/* + * logging.cpp + * + * Created on: 24.12.2018 + * Author: eyck + */ + + +#include "logging.h" +#include +#include +#include +#include +#include + +using namespace sc_core; + +enum log_level {NONE, FATAL, ERROR, WARNING, INFO, DEBUG, TRACE}; + +namespace { + +static std::deque msg_buf; + +inline log_level verbosity2log(int verb) { + if (verb >= sc_core::SC_FULL) return TRACE; + if (verb >= sc_core::SC_HIGH) return DEBUG; + return INFO; +} + +std::string time2string(const sc_core::sc_time &t) { + const std::array time_units{"fs", "ps", "ns", "us", "ms", "s "}; + const std::array multiplier{1ULL, + 1000ULL, + 1000ULL * 1000, + 1000ULL * 1000 * 1000, + 1000ULL * 1000 * 1000 * 1000, + 1000ULL * 1000 * 1000 * 1000 * 1000}; + std::ostringstream oss; + const sc_core::sc_time_tuple tt{t}; + const auto val = tt.value(); + if (!val) { + oss << "0 s"; + } else { + const unsigned scale = tt.unit(); + const auto fs_val = val * multiplier[scale]; + for (int j = multiplier.size() - 1; j >= scale; --j) { + if (fs_val > multiplier[j]) { + const auto i = val / multiplier[j - scale]; + const auto f = val % multiplier[j - scale]; + oss << i << '.' << std::setw(3 * (j - scale)) << std::setfill('0') << std::left << f << ' ' + << time_units[j]; + break; + } + } + } + return oss.str(); +} + +const std::string compose_message(const sc_report &rep) { + std::stringstream os; + os << "[" << std::setw(20) << time2string(sc_core::sc_time_stamp()) << "] "; + if (rep.get_id() >= 0) + os << "(" + << "IWEF"[rep.get_severity()] << rep.get_id() << ") "; + os << rep.get_msg_type(); + if (*rep.get_msg()) os << ": " << rep.get_msg(); + if (rep.get_severity() > SC_INFO) { + std::array line_number_str; + os << " [FILE:" << rep.get_file_name() << ":" << rep.get_line_number() << "]"; + sc_simcontext *simc = sc_get_curr_simcontext(); + if (simc && sc_is_running()) { + const char *proc_name = rep.get_process_name(); + if (proc_name) os << "[PROCESS:" << proc_name << "]"; + } + } + return os.str(); +} + +void report_handler(const sc_report &rep, const sc_actions &actions) { + std::array map = {{INFO, WARNING, ERROR, FATAL}}; + if (actions & SC_DISPLAY) { + auto level = rep.get_severity() > sc_core::SC_INFO ? map[rep.get_severity()] : verbosity2log(rep.get_verbosity()); + msg_buf.push_back(compose_message(rep)); + } + if (actions & SC_STOP) sc_stop(); + if (actions & SC_ABORT) abort(); + if (actions & SC_THROW) throw rep; +} +} + +bool has_output(){ + return !msg_buf.empty(); +} + +std::string get_output(){ + std::string ret = msg_buf.front(); + msg_buf.pop_front(); + return ret; +} + +void init_logging(unsigned level) { + const std::array verbosity = {SC_NONE, // Logging::NONE + SC_LOW, // Logging::FATAL + SC_LOW, // Logging::ERROR + SC_LOW, // Logging::WARNING + SC_MEDIUM, // Logging::INFO + SC_HIGH, // logging::DEBUG + SC_FULL, // logging::TRACE + SC_DEBUG}; // logging::TRACE+1 + sc_report_handler::set_verbosity_level(verbosity[level]); + sc_report_handler::set_handler(report_handler); +} + + + diff --git a/components/logging.h b/components/logging.h new file mode 100644 index 0000000..20defd8 --- /dev/null +++ b/components/logging.h @@ -0,0 +1,42 @@ +/* + * logging.h + * + * Created on: 24.12.2018 + * Author: eyck + */ + +#ifndef LOGGING_H_ +#define LOGGING_H_ + +#include +#include +#include + +bool has_output(); +std::string get_output(); +void init_logging(unsigned level); + +class Log { +public: + Log(const char* file, int line):messageLevel(sc_core::SC_INFO), file(file), line(line){}; + Log(const Log&) = delete; + Log& operator =(const Log&) = delete; + virtual ~Log(){ + ::sc_core::sc_report_handler::report(messageLevel, "", os.str().c_str(), file, line ); + } + std::ostringstream& Get(sc_core::sc_severity level = sc_core::SC_INFO){ + messageLevel = level; + return os; + } +protected: + std::ostringstream os; + sc_core::sc_severity messageLevel; + const char* file; + int line; +}; + +#define LOG(level) Log(__FILE__, __LINE__).Get(level) +#define LOG_INFO Log(__FILE__, __LINE__).Get(sc_core::SC_INFO) +#define LOG_WARN Log(__FILE__, __LINE__).Get(sc_core::SC_WARNING) +#define LOG_ERR Log(__FILE__, __LINE__).Get(sc_core::SC_ERROR) +#endif /* LOGGING_H_ */ diff --git a/components/router.h b/components/router.h new file mode 100644 index 0000000..3b9ebaa --- /dev/null +++ b/components/router.h @@ -0,0 +1,133 @@ +#ifndef ROUTER_H +#define ROUTER_H + +#include "systemc" +using namespace sc_core; +using namespace sc_dt; +using namespace std; + +#include "tlm.h" +#include "tlm_utils/simple_initiator_socket.h" +#include "tlm_utils/simple_target_socket.h" + + +// ********************************************* +// Generic payload blocking transport router +// ********************************************* + +template +struct Router: sc_module +{ + // TLM-2 socket, defaults to 32-bits wide, base protocol + tlm_utils::simple_target_socket target_socket; + + // ********************************************* + // Use tagged sockets to be able to distinguish incoming backward path calls + // ********************************************* + + sc_core::sc_vector> initiator_socket; + + SC_CTOR(Router) + : target_socket("target_socket") + , initiator_socket("socket", N_TARGETS) + { + // Register callbacks for incoming interface method calls + target_socket.register_b_transport( this, &Router::b_transport); + target_socket.register_get_direct_mem_ptr(this, &Router::get_direct_mem_ptr); + target_socket.register_transport_dbg( this, &Router::transport_dbg); + + for (unsigned int i = 0; i < N_TARGETS; i++) + { + char txt[20]; + sprintf(txt, "socket_%d", i); + + // ********************************************* + // Register callbacks for incoming interface method calls, including tags + // ********************************************* + initiator_socket[i].register_invalidate_direct_mem_ptr(this, &Router::invalidate_direct_mem_ptr, i); + } + } + + // **************** + // FORWARD PATH + // **************** + + // TLM-2 blocking transport method + virtual void b_transport( tlm::tlm_generic_payload& trans, sc_time& delay ) + { + sc_dt::uint64 address = trans.get_address(); + sc_dt::uint64 masked_address; + unsigned int target_nr = decode_address( address, masked_address); + + // Modify address within transaction + trans.set_address( masked_address ); + + // Forward transaction to appropriate target + initiator_socket[target_nr]->b_transport( trans, delay ); + } + + // TLM-2 forward DMI method + virtual bool get_direct_mem_ptr(tlm::tlm_generic_payload& trans, + tlm::tlm_dmi& dmi_data) + { + sc_dt::uint64 masked_address; + unsigned int target_nr = decode_address( trans.get_address(), masked_address ); + trans.set_address( masked_address ); + + bool status = initiator_socket[target_nr]->get_direct_mem_ptr( trans, dmi_data ); + + // Calculate DMI address of target in system address space + dmi_data.set_start_address( compose_address( target_nr, dmi_data.get_start_address() )); + dmi_data.set_end_address ( compose_address( target_nr, dmi_data.get_end_address() )); + + return status; + } + + // TLM-2 debug transaction method + virtual unsigned int transport_dbg(tlm::tlm_generic_payload& trans) + { + sc_dt::uint64 masked_address; + unsigned int target_nr = decode_address( trans.get_address(), masked_address ); + trans.set_address( masked_address ); + + // Forward debug transaction to appropriate target + return initiator_socket[target_nr]->transport_dbg( trans ); + } + + // **************** + // BACKWARD PATH + // **************** + + // ************************** + // Tagged backward DMI method + // ************************** + + virtual void invalidate_direct_mem_ptr(int id, + sc_dt::uint64 start_range, + sc_dt::uint64 end_range) + { + // Reconstruct address range in system memory map + sc_dt::uint64 bw_start_range = compose_address( id, start_range ); + sc_dt::uint64 bw_end_range = compose_address( id, end_range ); + target_socket->invalidate_direct_mem_ptr(bw_start_range, bw_end_range); + } + + // **************** + // ROUTER INTERNALS + // **************** + + // Simple fixed address decoding + inline unsigned int decode_address( sc_dt::uint64 address, sc_dt::uint64& masked_address ) + { + unsigned int target_nr = static_cast( (address >> 8) & 0x3 ); + masked_address = address & 0xFF; + return target_nr; + } + + inline sc_dt::uint64 compose_address( unsigned int target_nr, sc_dt::uint64 address) + { + return (target_nr << 8) | (address & 0xFF); + } +}; + +#endif diff --git a/components/router_example.cpp b/components/router_example.cpp new file mode 100644 index 0000000..7dc6f5b --- /dev/null +++ b/components/router_example.cpp @@ -0,0 +1,18 @@ +/* + * router_example.cpp + * + * Created on: 02.12.2018 + * Author: eyck + */ + + +#include "top.h" + +int sc_main(int argc, char* argv[]) +{ + Top top("top"); + sc_start(); + return 0; +} + + diff --git a/components/target.cpp b/components/target.cpp new file mode 100644 index 0000000..ffeb36b --- /dev/null +++ b/components/target.cpp @@ -0,0 +1,102 @@ +/* + * target.cpp + * + * Created on: 02.12.2018 + * Author: eyck + */ + +#include "target.h" + +void Memory::b_transport(tlm::tlm_generic_payload& trans, sc_time& delay) { + tlm::tlm_command cmd = trans.get_command(); + sc_dt::uint64 adr = trans.get_address() / 4; + unsigned char* ptr = trans.get_data_ptr(); + unsigned int len = trans.get_data_length(); + unsigned char* byt = trans.get_byte_enable_ptr(); + unsigned int wid = trans.get_streaming_width(); + + // Obliged to check address range and check for unsupported features, + // i.e. byte enables, streaming, and bursts + // Can ignore extensions + + // Generate the appropriate error response + if (adr >= SIZE) { + trans.set_response_status( tlm::TLM_ADDRESS_ERROR_RESPONSE ); + return; + } + if (byt != 0) { + trans.set_response_status( tlm::TLM_BYTE_ENABLE_ERROR_RESPONSE ); + return; + } + if (len > 4 || wid < len) { + trans.set_response_status( tlm::TLM_BURST_ERROR_RESPONSE ); + return; + } + + wait(delay); + delay = SC_ZERO_TIME; + + // Obliged to implement read and write commands + if ( cmd == tlm::TLM_READ_COMMAND ) + memcpy(ptr, &mem[adr], len); + else if ( cmd == tlm::TLM_WRITE_COMMAND ) + memcpy(&mem[adr], ptr, len); + + // Set DMI hint to indicated that DMI is supported + trans.set_dmi_allowed(true); + + // Obliged to set response status to indicate successful completion + trans.set_response_status( tlm::TLM_OK_RESPONSE ); + } + +bool Memory::get_direct_mem_ptr(tlm::tlm_generic_payload& trans, + tlm::tlm_dmi& dmi_data) +{ + // Permit read and write access + dmi_data.allow_read_write(); + + // Set other details of DMI region + dmi_data.set_dmi_ptr( reinterpret_cast( &mem[0] ) ); + dmi_data.set_start_address( 0 ); + dmi_data.set_end_address( SIZE*4-1 ); + dmi_data.set_read_latency( LATENCY ); + dmi_data.set_write_latency( LATENCY ); + + return true; +} + +Memory::Memory(sc_core::sc_module_name nm) +: socket("socket"), LATENCY(10, SC_NS) +{ + // Register callbacks for incoming interface method calls + socket.register_b_transport( this, &Memory::b_transport); + socket.register_get_direct_mem_ptr(this, &Memory::get_direct_mem_ptr); + socket.register_transport_dbg( this, &Memory::transport_dbg); + + // Initialize memory with random data + for (int i = 0; i < SIZE; i++) + mem[i] = 0xAA000000 | (mem_nr << 20) | (rand() % 256); + + ++mem_nr; +} + +// TLM-2 debug transaction method +unsigned int Memory::transport_dbg(tlm::tlm_generic_payload& trans) +{ + tlm::tlm_command cmd = trans.get_command(); + sc_dt::uint64 adr = trans.get_address() / 4; + unsigned char* ptr = trans.get_data_ptr(); + unsigned int len = trans.get_data_length(); + + // Calculate the number of bytes to be actually copied + unsigned int num_bytes = (len < (SIZE - adr) * 4) ? len : (SIZE - adr) * 4; + + if ( cmd == tlm::TLM_READ_COMMAND ) + memcpy(ptr, &mem[adr], num_bytes); + else if ( cmd == tlm::TLM_WRITE_COMMAND ) + memcpy(&mem[adr], ptr, num_bytes); + + return num_bytes; +} + + diff --git a/components/target.h b/components/target.h new file mode 100644 index 0000000..8f9d85e --- /dev/null +++ b/components/target.h @@ -0,0 +1,46 @@ +#ifndef TARGET_H +#define TARGET_H + +// Needed for the simple_target_socket +#define SC_INCLUDE_DYNAMIC_PROCESSES + +#include "systemc" +using namespace sc_core; +using namespace sc_dt; +using namespace std; + +#include "tlm.h" +#include "tlm_utils/simple_target_socket.h" + + +// Target module representing a simple memory + +struct Memory: sc_module +{ + // TLM-2 socket, defaults to 32-bits wide, base protocol + tlm_utils::simple_target_socket socket; + + enum { SIZE = 256 }; + const sc_time LATENCY; + + SC_HAS_PROCESS(Memory); + + Memory(sc_core::sc_module_name nm); + +protected: + // TLM-2 blocking transport method + void b_transport( tlm::tlm_generic_payload& trans, sc_time& delay ); + + // TLM-2 forward DMI method + bool get_direct_mem_ptr(tlm::tlm_generic_payload& trans, + tlm::tlm_dmi& dmi_data); + // TLM-2 debug transaction method + unsigned int transport_dbg(tlm::tlm_generic_payload& trans); + + int mem[SIZE]; + static unsigned int mem_nr; +}; + +unsigned int Memory::mem_nr = 0; + +#endif diff --git a/components/top.h b/components/top.h new file mode 100644 index 0000000..a4b995d --- /dev/null +++ b/components/top.h @@ -0,0 +1,33 @@ +#ifndef TOP_H +#define TOP_H + +#include "initiator.h" +#include "target.h" +#include "router.h" + +SC_MODULE(Top) +{ + Initiator* initiator; + Router<4>* router; + Memory* memory[4]; + + SC_CTOR(Top) + { + // Instantiate components + initiator = new Initiator("initiator"); + router = new Router<4>("router"); + for (int i = 0; i < 4; i++) + { + char txt[20]; + sprintf(txt, "memory_%d", i); + memory[i] = new Memory(txt); + } + + // Bind sockets + initiator->socket.bind( router->target_socket ); + for (int i = 0; i < 4; i++) + router->initiator_socket[i].bind( memory[i]->socket ); + } +}; + +#endif diff --git a/components/tx_example.cpp b/components/tx_example.cpp new file mode 100644 index 0000000..27642ed --- /dev/null +++ b/components/tx_example.cpp @@ -0,0 +1,44 @@ +// -*- C++ -*- +/***************************************************************************** + + 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. + + *****************************************************************************/ +// this code compiles and runs with our latest prototype for this specification + +#include "txtop.h" + +int sc_main (int argc , char *argv[]) +{ + scv_startup(); + + scv_tr_text_init(); + scv_tr_db db("transaction_example.txlog"); + scv_tr_db::set_default_db(&db); + + tx_top top("top"); + + // Accellera SystemC >=2.2 got picky about multiple drivers. + // Disable check for bus simulation. + sc_report_handler::set_actions(SC_ID_MORE_THAN_ONE_SIGNAL_DRIVER_, SC_DO_NOTHING); + // run the simulation + sc_start(1.0, SC_MS); + + return 0; +} + diff --git a/components/tx_example_mods.cpp b/components/tx_example_mods.cpp new file mode 100644 index 0000000..d7d746a --- /dev/null +++ b/components/tx_example_mods.cpp @@ -0,0 +1,140 @@ +// -*- C++ -*- +/***************************************************************************** + + 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. + + *****************************************************************************/ +// this code compiles and runs with our latest prototype for this specification + +#include "tx_example_mods.h" + +rw_task_if::data_t rw_pipelined_transactor::read(const rw_task_if::addr_t* +addr) { + addr_phase.lock(); + scv_tr_handle h = read_gen.begin_transaction(*addr); + + scv_tr_handle h1 = addr_gen.begin_transaction(*addr,"addr_phase",h); + wait(clk->posedge_event()); + bus_addr = *addr; + addr_req = 1; + wait(addr_ack->posedge_event()); + wait(clk->negedge_event()); + addr_req = 0; + wait(addr_ack->negedge_event()); + addr_gen.end_transaction(h1); + addr_phase.unlock(); + + data_phase.lock(); + scv_tr_handle h2 = data_gen.begin_transaction("data_phase",h); + wait(data_rdy->posedge_event()); + data_t data = bus_data.read(); + wait(data_rdy->negedge_event()); + data_gen.end_transaction(h2); + read_gen.end_transaction(h,data); + data_phase.unlock(); + + return data; +} + +void rw_pipelined_transactor::write(const write_t * req) { + scv_tr_handle h = write_gen.begin_transaction(req->addr); + // ... + write_gen.end_transaction(h,req->data); +} + +void test::main() { + // simple sequential tests + for (int i=0; i<3; i++) { + rw_task_if::addr_t addr = i; + rw_task_if::data_t data = transactor->read(&addr); + cout << "at time " << sc_time_stamp() << ": "; + cout << "received data : " << data << endl; + } + + scv_smart_ptr addr; + for (int i=0; i<3; i++) { + + addr->next(); + rw_task_if::data_t data = transactor->read( addr->get_instance() ); + cout << "data for address " << *addr << " is " << data << endl; + } + + scv_smart_ptr write; + for (int i=0; i<3; i++) { + write->next(); + transactor->write( write->get_instance() ); + cout << "send data : " << write->data << endl; + } + + scv_smart_ptr data; + scv_bag distribution; + distribution.push(1,40); + distribution.push(2,60); + data->set_mode(distribution); + for (int i=0;i<3; i++) { data->next(); process(data); } +} + +void design::addr_phase() { + while (1) { + while (addr_req.read() != 1) { + wait(addr_req->value_changed_event()); + } + sc_uint<8> _addr = bus_addr.read(); + bool _rw = rw.read(); + + int cycle = rand() % 10 + 1; + while (cycle-- > 0) { + wait(clk->posedge_event()); + } + + addr_ack = 1; + wait(clk->posedge_event()); + addr_ack = 0; + + outstandingAddresses.push_back(_addr); + outstandingType.push_back(_rw); + cout << "at time " << sc_time_stamp() << ": "; + cout << "received request for memory address " << _addr << endl; + } +} + +void design::data_phase() { + while (1) { + while (outstandingAddresses.empty()) { + wait(clk->posedge_event()); + } + int cycle = rand() % 10 + 1; + while (cycle-- > 0) { + wait(clk->posedge_event()); + } + if (outstandingType.front() == 0) { + cout << "reading memory address " << outstandingAddresses.front() + << " with value " << memory[outstandingAddresses.front().to_ulong()] << endl; + bus_data = memory[outstandingAddresses.front().to_ulong()]; + data_rdy = 1; + wait(clk->posedge_event()); + data_rdy = 0; + + } else { + cout << "not implemented yet" << endl; + } + outstandingAddresses.pop_front(); + outstandingType.pop_front(); + } +} + diff --git a/components/tx_example_mods.h b/components/tx_example_mods.h new file mode 100644 index 0000000..341c5cf --- /dev/null +++ b/components/tx_example_mods.h @@ -0,0 +1,136 @@ +// -*- C++ -*- +/***************************************************************************** + + 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. + + *****************************************************************************/ +// this code compiles and runs with our latest prototype for this specification + +#include +#include + +// hack to fake a true fifo_mutex +#define fifo_mutex sc_mutex + +const unsigned ram_size = 256; + +class rw_task_if : virtual public sc_interface { +public: + typedef sc_uint<8> addr_t; + typedef sc_uint<8> data_t; + struct write_t { + addr_t addr; + data_t data; + }; + + virtual data_t read(const addr_t*) = 0; + virtual void write(const write_t*) = 0; +}; + +SCV_EXTENSIONS(rw_task_if::write_t) { +public: + scv_extensions addr; + scv_extensions data; + SCV_EXTENSIONS_CTOR(rw_task_if::write_t) { + SCV_FIELD(addr); + SCV_FIELD(data); + } +}; + +class pipelined_bus_ports : public sc_module { +public: + sc_in< bool > clk; + sc_inout< bool > rw; + sc_inout< bool > addr_req; + sc_inout< bool > addr_ack; + sc_inout< sc_uint<8> > bus_addr; + sc_inout< bool > data_rdy; + sc_inout< sc_uint<8> > bus_data; + + SC_CTOR(pipelined_bus_ports) + : clk("clk"), rw("rw"), + addr_req("addr_req"), + addr_ack("addr_ack"), bus_addr("bus_addr"), + data_rdy("data_rdy"), bus_data("bus_data") {} +}; + +class rw_pipelined_transactor + : public rw_task_if, + public pipelined_bus_ports { + + fifo_mutex addr_phase; + fifo_mutex data_phase; + + scv_tr_stream pipelined_stream; + scv_tr_stream addr_stream; + scv_tr_stream data_stream; + scv_tr_generator, sc_uint<8> > read_gen; + scv_tr_generator, sc_uint<8> > write_gen; + scv_tr_generator > addr_gen; + scv_tr_generator > data_gen; + +public: + rw_pipelined_transactor(sc_module_name nm) : + pipelined_bus_ports(nm), + addr_phase("addr_phase"), + data_phase("data_phase"), + pipelined_stream("pipelined_stream", "transactor"), + addr_stream("addr_stream", "transactor"), + data_stream("data_stream", "transactor"), + read_gen("read",pipelined_stream,"addr","data"), + write_gen("write",pipelined_stream,"addr","data"), + addr_gen("addr",addr_stream,"addr"), + data_gen("data",data_stream,"data") + {} + virtual data_t read(const addr_t* p_addr); + virtual void write(const write_t * req); +}; +class test : public sc_module { +public: + sc_port< rw_task_if > transactor; + SC_CTOR(test) { + SC_THREAD(main); + } + void main(); +}; + +class write_constraint : virtual public scv_constraint_base { +public: + scv_smart_ptr write; + SCV_CONSTRAINT_CTOR(write_constraint) { + SCV_CONSTRAINT( write->addr() <= ram_size ); + SCV_CONSTRAINT( write->addr() != write->data() ); + } +}; + +inline void process(scv_smart_ptr data) {} +class design : public pipelined_bus_ports { + std::list< sc_uint<8> > outstandingAddresses; + std::list< bool > outstandingType; + sc_uint<8> memory[ram_size]; + +public: + SC_HAS_PROCESS(design); + design(sc_module_name nm) : pipelined_bus_ports(nm) { + for (unsigned i=0; i + +class tx_top: public sc_core::sc_module { +public: + tx_top(sc_core::sc_module_name nm); + virtual ~tx_top(); + sc_core::sc_clock clk; + sc_core::sc_signal< bool > rw; + sc_core::sc_signal< bool > addr_req; + sc_core::sc_signal< bool > addr_ack; + sc_core::sc_signal< sc_dt::sc_uint<8> > bus_addr; + sc_core::sc_signal< bool > data_rdy; + sc_core::sc_signal< sc_dt::sc_uint<8> > bus_data; + test t; + rw_pipelined_transactor tr; + design duv; + +}; + +#endif /* TXTOP_H_ */ diff --git a/conanfile.txt b/conanfile.txt new file mode 100644 index 0000000..d9c11e0 --- /dev/null +++ b/conanfile.txt @@ -0,0 +1,11 @@ +[requires] +SystemC/2.3.2@minres/stable +SystemCVerification/2.0.1@minres/stable + +[generators] +cmake + +[options] +SystemC:stdcxx=11 +SystemC:shared=True +SystemCVerification:stdcxx=11 diff --git a/router_example.py b/router_example.py new file mode 100644 index 0000000..1755406 --- /dev/null +++ b/router_example.py @@ -0,0 +1,36 @@ +import os.path +import cppyy +from cppyy import gbl as cpp +import pysysc as scpy +############################################################################### +# setup and load +############################################################################### +myDir = os.path.dirname( os.path.realpath(__file__)) +conan_err = scpy.read_config_from_conan(os.path.join(myDir, 'conanfile.txt')) +scpy.load_systemc() +scpy.add_include_path(os.path.join(myDir, 'components')) +scpy.add_library('components.h', os.path.join(myDir, 'build/Debug/lib/libcomponents.so')) +############################################################################### +# configure +############################################################################### +cpp.init_logging(5) +cpp.sc_core.sc_report_handler.set_actions(cpp.sc_core.SC_ID_MORE_THAN_ONE_SIGNAL_DRIVER_, cpp.sc_core.SC_DO_NOTHING); +############################################################################### +# instantiate +############################################################################### +initiator = cpp.Initiator(cpp.sc_core.sc_module_name("initiator")) +memories = [cpp.Memory(cpp.sc_core.sc_module_name(name)) for name in ["mem0", "mem1", "mem2", "mem3"]] +router = cpp.Router[4](cpp.sc_core.sc_module_name("router")) +############################################################################### +# connect it +############################################################################### +initiator.socket.bind(router.target_socket) +for idx,m in enumerate(memories): + router.initiator_socket.at(idx).bind(m.socket) +############################################################################### +# run if it is standalone +############################################################################### +if __name__ == "__main__": + cpp.sc_core.sc_in_action=True + cpp.sc_core.sc_start() + print("Done")