diff --git a/.cproject b/.cproject
index 5484523..6826073 100644
--- a/.cproject
+++ b/.cproject
@@ -28,10 +28,9 @@
-
-
+
+
-
@@ -64,10 +63,9 @@
-
-
+
+
-
@@ -99,12 +97,47 @@
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -117,10 +150,12 @@
+
+
diff --git a/.gitignore b/.gitignore
index af81461..ffab976 100644
--- a/.gitignore
+++ b/.gitignore
@@ -47,3 +47,4 @@
/.direnv/
/.venv/
/.cache
+/CMakeUserPresets.json
diff --git a/.gitmodules b/.gitmodules
index 6211793..1ddda03 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,6 @@
[submodule "scc"]
path = scc
url = https://github.com/Minres/SystemC-Components.git
+[submodule "cmake-conan"]
+ path = cmake-conan
+ url = https://github.com/conan-io/cmake-conan.git
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 808a583..30fb7c7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -8,11 +8,9 @@ option(FULL_TEST_SUITE "enable also long-running tests" OFF)
option(ENABLE_SCV "Enable use of SCV" OFF)
option(ENABLE_CLANG_TIDY "Enable clang-tidy checks" OFF)
-include(ConanInline)
include(GNUInstallDirs)
include(BuildType)
-set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
@@ -20,14 +18,6 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON)
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-march=native" COMPILER_SUPPORTS_MARCH_NATIVE)
-if(COMPILER_SUPPORTS_MARCH_NATIVE)
- if("${CMAKE_BUILD_TYPE}" STREQUAL "")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native")
- elseif(NOT(${CMAKE_BUILD_TYPE} STREQUAL "RelWithDebInfo"))
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native")
- endif()
-endif()
-
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
set(warnings "-Wall -Wextra -Werror")
set(CMAKE_CXX_FLAG_RELEASE "-O3 -DNDEBUG")
@@ -39,11 +29,10 @@ endif()
if(ENABLE_COVERAGE)
include(CodeCoverage)
append_coverage_compiler_flags()
- set(COVERAGE_EXCLUDES "osci-lib/scc/*" "/engr/dev/tools/*")
endif()
-find_program(CLANG_TIDY_EXE NAMES "clang-tidy")
if(ENABLE_CLANG_TIDY)
+ find_program(CLANG_TIDY_EXE NAMES "clang-tidy")
if(CLANG_TIDY_EXE)
message(STATUS "clang-tidy found: ${CLANG_TIDY_EXE}")
#set(CLANG_TIDY_CHECKS "-*,modernize-*,-modernize-use-trailing-return-type,clang-analyzer-core.*,clang-analyzer-cplusplus.*")
@@ -54,17 +43,8 @@ if(ENABLE_CLANG_TIDY)
endif()
endif()
-set(CLANG_FORMAT_EXCLUDE_PATTERNS "/third_party/")
+set(CLANG_FORMAT_EXCLUDE_PATTERNS "/third_party/" "/build/")
find_package(ClangFormat)
-
-set(CONAN_CMAKE_SILENT_OUTPUT ON)
-conan_check()
-conan_configure(REQUIRES jsoncpp/1.9.5 yaml-cpp/0.6.3 spdlog/1.9.2 fmt/8.0.1 boost/1.85.0 gsl-lite/0.37.0 systemc/2.3.4 catch2/3.1.0 zlib/1.2.11 lz4/1.9.4
- GENERATORS cmake_find_package
- OPTIONS fmt:header_only=True spdlog:header_only=True
- )
-conan_install()
-
find_package(ZLIB)
find_package(lz4)
# This line finds the boost lib and headers.
diff --git a/CMakePresets.json b/CMakePresets.json
new file mode 100644
index 0000000..86840c3
--- /dev/null
+++ b/CMakePresets.json
@@ -0,0 +1,40 @@
+{
+ "version": 3,
+ "vendor": {
+ "conan": {}
+ },
+ "cmakeMinimumRequired": {
+ "major": 3,
+ "minor": 24,
+ "patch": 0
+ },
+ "configurePresets": [
+ {
+ "name": "Debug",
+ "cacheVariables": {
+ "CMAKE_POLICY_DEFAULT_CMP0091": "NEW",
+ "CMAKE_BUILD_TYPE": "Debug",
+ "CMAKE_CXX_STANDARD": "17",
+ "CMAKE_PROJECT_TOP_LEVEL_INCLUDES": "cmake-conan/conan_provider.cmake"
+ }
+ },
+ {
+ "name": "RelWithDebInfo",
+ "cacheVariables": {
+ "CMAKE_POLICY_DEFAULT_CMP0091": "NEW",
+ "CMAKE_BUILD_TYPE": "RelWithDebInfo",
+ "CMAKE_CXX_STANDARD": "17",
+ "CMAKE_PROJECT_TOP_LEVEL_INCLUDES": "cmake-conan/conan_provider.cmake"
+ }
+ },
+ {
+ "name": "Release",
+ "cacheVariables": {
+ "CMAKE_POLICY_DEFAULT_CMP0091": "NEW",
+ "CMAKE_BUILD_TYPE": "Release",
+ "CMAKE_CXX_STANDARD": "17",
+ "CMAKE_PROJECT_TOP_LEVEL_INCLUDES": "cmake-conan/conan_provider.cmake"
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Jenkinsfile b/Jenkinsfile
index fa67378..d9dbfe3 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -29,18 +29,12 @@ void checkout_project() {
])
}
-void setup_conan() {
- sh'''
- pip3 install --user "conan<2.0" pyucis
- conan profile new default --detect --force
- conan remote list | grep minres > /dev/null
- [ $? ] || conan remote add minres https://git.minres.com/api/packages/Tooling/conan
- '''
-}
-
void build_n_test_project() {
sh'''
- cmake -S . -B build
+ python3 -mvenv .venv
+ . .venv/bin/activate
+ pip3 install -r requirements.txt
+ cmake -S . -B build --preset Release
cmake --build build -j12
cmake --build build --target test
'''
@@ -57,47 +51,30 @@ pipeline {
stages {
stage('SCC test pipeline') {
parallel {
- stage('U22.04') {
+ stage('ubuntu-22.04') {
agent {docker { image 'ubuntu-22.04' } }
stages {
stage('Checkout') { steps { checkout_project() }}
- stage('Setup') { steps { setup_conan() }}
stage('Build & test') { steps { build_n_test_project() }}
}
}
- stage('U20.04') {
- agent {docker { image 'ubuntu-20.04' } }
- stages {
- stage('Checkout') { steps { checkout_project() }}
- stage('Setup') { steps { setup_conan() }}
- stage('Build & test') { steps { build_n_test_project() }}
- }
- }
- stage('COS7') {
- agent {docker { image 'centos7' } }
- stages {
- stage('Checkout') { steps { checkout_project() }}
- stage('Setup') { steps { setup_conan() }}
- stage('Build & test') { steps { build_n_test_project() }}
- }
- }
- stage('RCK8') {
+ stage('rockylinux8') {
agent {docker { image 'rockylinux8' } }
stages {
stage('Checkout') { steps { checkout_project() }}
- stage('Setup') { steps { setup_conan() }}
stage('Build & test') { steps { build_n_test_project() }}
}
}
- //
stage('Format check') {
- agent {docker { image 'ubuntu-riscv' } }
+ agent {docker { image 'ubuntu-22.04' } }
stages {
stage('Checkout') { steps { checkout_project() }}
- stage('Setup') { steps { setup_conan() }}
stage('Build & check format') { steps {
sh'''
- cmake -S . -B build
+ python3 -mvenv .venv
+ . .venv/bin/activate
+ pip3 install -r requirements.txt
+ cmake -S . -B build --preset Release
cmake --build build --target format-check
'''
}}
diff --git a/Modulefile b/Modulefile
index 5d602fb..4891e78 100644
--- a/Modulefile
+++ b/Modulefile
@@ -13,5 +13,5 @@ if { $distro == "CentOS" && ![info exists ::env(PROJECT)] && ![info exists ::env
}
module load tools/utilities
-module load tools/cmake
+module load tools/cmake/3.28
module load tools/clang/14.0
diff --git a/README.md b/README.md
index 171f11e..98bb81b 100644
--- a/README.md
+++ b/README.md
@@ -12,9 +12,10 @@ In Console:
module load ./Modulefile
python3 -mvenv .venv
. .venv/bin/activate
- pip3 install conan==1.59.0
- cmake -S . -B build
+ pip3 install -r requirements.txt
+ cmake -S . -B build --preset Release
cmake --build build -j30
+ cmake --build build --target test
\ No newline at end of file
diff --git a/cmake-conan b/cmake-conan
new file mode 160000
index 0000000..c22bbf0
--- /dev/null
+++ b/cmake-conan
@@ -0,0 +1 @@
+Subproject commit c22bbf0af0b73d5f0def24a9cdf4ce503ae79e5d
diff --git a/conanfile.txt b/conanfile.txt
new file mode 100644
index 0000000..80c687f
--- /dev/null
+++ b/conanfile.txt
@@ -0,0 +1,44 @@
+[requires]
+jsoncpp/1.9.5
+yaml-cpp/0.6.3
+spdlog/1.9.2
+fmt/8.0.1
+boost/1.85.0
+gsl-lite/0.37.0
+systemc/2.3.4
+catch2/3.1.0
+zlib/1.2.11
+lz4/1.9.4
+rapidjson/cci.20230929
+
+[options]
+boost/*:fPIC=True
+boost/*:header_only=False
+boost/*:without_contract=True
+boost/*:without_fiber=True
+boost/*:without_graph=True
+boost/*:without_graph_parallel=True
+boost/*:without_iostreams=True
+boost/*:without_json=True
+boost/*:without_locale=True
+boost/*:without_log=True
+boost/*:without_math=True
+boost/*:without_mpi=True
+boost/*:without_nowide=True
+boost/*:without_python=True
+boost/*:without_random=True
+boost/*:without_regex=True
+boost/*:without_stacktrace=True
+boost/*:without_test=True
+boost/*:without_timer=True
+boost/*:without_type_erasure=True
+boost/*:without_wave=True
+systemc/*:shared=False
+systemc/*:disable_virtual_bind=False
+
+[generators]
+CMakeDeps
+CMakeToolchain
+
+[layout]
+cmake_layout
diff --git a/examples/ahb_bfm/sc_main.cpp b/examples/ahb_bfm/sc_main.cpp
deleted file mode 100644
index b01ad27..0000000
--- a/examples/ahb_bfm/sc_main.cpp
+++ /dev/null
@@ -1,148 +0,0 @@
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-using namespace sc_core;
-using namespace scc;
-
-class testbench : public sc_module, public scc::traceable {
-public:
- enum { WIDTH = 64 };
- tlm::scc::initiator_mixin> isck{"isck"};
- ahb::pin::initiator intor{"intor"};
- sc_core::sc_clock HCLK{"HCLK", 10_ns};
- sc_core::sc_signal HRESETn{"HRESETn"};
- sc_core::sc_signal> HADDR{"HADDR"};
- sc_core::sc_signal> HBURST{"HBURST"};
- sc_core::sc_signal HMASTLOCK{"HMASTLOCK"};
- sc_core::sc_signal> HPROT{"HPROT"};
- sc_core::sc_signal> HSIZE{"HSIZE"};
- sc_core::sc_signal> HTRANS{"HTRANS"};
- sc_core::sc_signal> HWDATA{"HWDATA"};
- sc_core::sc_signal HWRITE{"HWRITE"};
- sc_core::sc_signal> HRDATA{"HRDATA"};
- sc_core::sc_signal HREADY{"HREADY"};
- sc_core::sc_signal HRESP{"HRESP"};
- sc_core::sc_signal HSEL{"HSEL"};
-
- ahb::pin::target target{"target"};
- tlm::scc::target_mixin> tsck{"tsck"};
-
- testbench(sc_module_name nm)
- : sc_module(nm) {
- SC_HAS_PROCESS(testbench);
- isck(intor.tsckt);
- intor.HCLK_i(HCLK);
- intor.HRESETn_i(HRESETn);
- intor.HADDR_o(HADDR);
- intor.HBURST_o(HBURST);
- intor.HMASTLOCK_o(HMASTLOCK);
- intor.HPROT_o(HPROT);
- intor.HSIZE_o(HSIZE);
- intor.HTRANS_o(HTRANS);
- intor.HWDATA_o(HWDATA);
- intor.HWRITE_o(HWRITE);
- intor.HRDATA_i(HRDATA);
- intor.HREADY_i(HREADY);
- intor.HRESP_i(HRESP);
- target.HCLK_i(HCLK);
- target.HRESETn_i(HRESETn);
- target.HADDR_i(HADDR);
- target.HBURST_i(HBURST);
- target.HMASTLOCK_i(HMASTLOCK);
- target.HPROT_i(HPROT);
- target.HSIZE_i(HSIZE);
- target.HTRANS_i(HTRANS);
- target.HWDATA_i(HWDATA);
- target.HWRITE_i(HWRITE);
- target.HSEL_i(HSEL);
- target.HRDATA_o(HRDATA);
- target.HREADY_o(HREADY);
- target.HRESP_o(HRESP);
- target.isckt(tsck);
- SC_THREAD(run);
- tsck.register_b_transport([this](tlm::tlm_generic_payload& gp, sc_time& delay) {
- gp.set_response_status(tlm::TLM_OK_RESPONSE);
- if(gp.is_write()) {
- SCCINFO(SCMOD) << "Received write access to addr 0x" << std::hex << gp.get_address();
- } else {
- memset(gp.get_data_ptr(), 0x55, gp.get_data_length());
- SCCINFO(SCMOD) << "Received read access from addr 0x" << std::hex << gp.get_address();
- }
- });
- }
-
- void run() {
- HRESETn.write(false);
- for(size_t i = 0; i < 10; ++i)
- wait(HCLK.posedge_event());
- HRESETn.write(true);
- wait(HCLK.posedge_event());
- HSEL.write(true);
- tlm::tlm_generic_payload gp;
- uint8_t data[8];
- data[0] = 2;
- data[1] = 4;
- gp.set_address(0x1000);
- gp.set_data_length(8);
- gp.set_data_ptr(data);
- gp.set_streaming_width(8);
- gp.set_command(tlm::TLM_WRITE_COMMAND);
- sc_time delay;
- isck->b_transport(gp, delay);
- gp.set_address(0x1020);
- gp.set_data_length(8);
- gp.set_data_ptr(data);
- gp.set_streaming_width(8);
- gp.set_command(tlm::TLM_READ_COMMAND);
- delay = SC_ZERO_TIME;
- isck->b_transport(gp, delay);
- for(size_t i = 0; i < 10; ++i)
- wait(HCLK.posedge_event());
- sc_stop();
- }
-};
-
-int sc_main(int argc, char* argv[]) {
- sc_core::sc_report_handler::set_actions("/IEEE_Std_1666/deprecated", sc_core::SC_DO_NOTHING);
- sc_report_handler::set_actions(SC_ID_MORE_THAN_ONE_SIGNAL_DRIVER_, SC_DO_NOTHING);
- ///////////////////////////////////////////////////////////////////////////
- // configure logging
- ///////////////////////////////////////////////////////////////////////////
- scc::init_logging(scc::log::DEBUG);
- ///////////////////////////////////////////////////////////////////////////
- // set up configuration and tracing
- ///////////////////////////////////////////////////////////////////////////
- scc::configurer cfg("ahb_bfm.json");
- scc::configurable_tracer trace("ahb_bfm", tracer::TEXT, true, true);
- ///////////////////////////////////////////////////////////////////////////
- // create modules/channels and trace
- ///////////////////////////////////////////////////////////////////////////
- testbench tb("tb");
- trace.add_control();
- {
- std::ofstream of{"ahb_test.default.json"};
- if(of.is_open())
- cfg.dump_configuration(of);
- }
- cfg.configure();
- ///////////////////////////////////////////////////////////////////////////
- // run the simulation
- ///////////////////////////////////////////////////////////////////////////
- try {
- sc_core::sc_start(1_us);
- if(!sc_core::sc_end_of_simulation_invoked())
- sc_core::sc_stop();
- } catch(sc_core::sc_report& rep) {
- sc_core::sc_report_handler::get_handler()(rep, sc_core::SC_DISPLAY | sc_core::SC_STOP);
- }
- return 0;
-}
diff --git a/requirements.txt b/requirements.txt
index f5ad00c..b7d8b70 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1 +1,3 @@
-conan<2.0
+conan>=2.0
+cmake
+clang-format==14.0
\ No newline at end of file
diff --git a/scc b/scc
index 4f27c76..bccc926 160000
--- a/scc
+++ b/scc
@@ -1 +1 @@
-Subproject commit 4f27c76e0631da96cfdf421e91c2cd983c3f4253
+Subproject commit bccc9269ff84181d1287dd6021ab5eb52f8909d0
diff --git a/src/factory.h b/src/factory.h
index 2c57fce..09e8cb3 100644
--- a/src/factory.h
+++ b/src/factory.h
@@ -25,7 +25,7 @@ public:
add(const std::string& name, Args&&... args);
};
- template static T& get(const std::string& name = "");
+ template static T& get(const std::string& name = typeid(T).name());
void create();
@@ -50,7 +50,7 @@ private:
std::map m_objects;
};
-template factory::add::add(Args&&... args) { add("", args...); }
+template factory::add::add(Args&&... args) { add(typeid(T).name(), args...); }
template factory::add::add(const std::string& name, Args&&... args) {
factory::get_instance().add_object(name, [args...]() -> object {
diff --git a/src/sc_main.cpp b/src/sc_main.cpp
index 6ff5088..b1fe425 100644
--- a/src/sc_main.cpp
+++ b/src/sc_main.cpp
@@ -24,11 +24,14 @@ void ABRThandler(int sig) { longjmp(abrt, 1); }
int sc_main(int argc, char* argv[]) {
signal(SIGABRT, ABRThandler);
auto my_name = util::split(argv[0], '/').back();
- scc::init_logging(LogConfig().logLevel(getenv("SCC_TEST_VERBOSE") ? log::TRACE : log::FATAL).logAsync(false).msgTypeFieldWidth(35));
+ auto level = getenv("SCC_TEST_VERBOSE");
+ auto log_lvl = level ? static_cast(std::min(strtoul(level, nullptr, 10) + 4, 7UL)) : log::FATAL;
+ scc::init_logging(LogConfig().logLevel(log_lvl).logAsync(false).msgTypeFieldWidth(35));
// create tracer if environment variable SCC_TEST_TRACE is defined
std::unique_ptr tracer;
- if(getenv("SCC_TEST_TRACE"))
- tracer = std::make_unique(my_name, scc::tracer::NONE, scc::tracer::ENABLE);
+ if(auto* test_trace = getenv("SCC_TEST_TRACE")) {
+ tracer = std::make_unique(my_name, scc::tracer::ENABLE, scc::tracer::ENABLE);
+ }
int result = -1;
if(setjmp(abrt) == 0) {
// instantiate design(s)
@@ -37,6 +40,7 @@ int sc_main(int argc, char* argv[]) {
result = Catch::Session().run(argc, argv);
// destroy design(s)
sc_stop();
+ SCCTRACE() << "Test sequence finished";
factory::get_instance().destroy();
}
return result;
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 5e98656..7004527 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -1,11 +1,14 @@
add_subdirectory(io-redirector)
add_subdirectory(ordered_semaphore)
add_subdirectory(cci_param_restricted)
+add_subdirectory(apb_pin_level)
add_subdirectory(ahb_pin_level)
add_subdirectory(axi4_pin_level)
add_subdirectory(ace_pin_level)
add_subdirectory(configuration)
add_subdirectory(configurer)
+add_subdirectory(sc_fixed_tracing)
+add_subdirectory(cxs_tlm)
if(FULL_TEST_SUITE)
add_subdirectory(sim_performance)
endif()
diff --git a/tests/apb_pin_level/CMakeLists.txt b/tests/apb_pin_level/CMakeLists.txt
new file mode 100644
index 0000000..bd52313
--- /dev/null
+++ b/tests/apb_pin_level/CMakeLists.txt
@@ -0,0 +1,9 @@
+project (apb_pin_level)
+
+add_executable(${PROJECT_NAME}
+ bus_test.cpp
+ ${test_util_SOURCE_DIR}/sc_main.cpp
+)
+target_link_libraries (${PROJECT_NAME} PUBLIC test_util)
+
+catch_discover_tests(${PROJECT_NAME})
diff --git a/tests/apb_pin_level/bus_test.cpp b/tests/apb_pin_level/bus_test.cpp
new file mode 100644
index 0000000..3cdff2f
--- /dev/null
+++ b/tests/apb_pin_level/bus_test.cpp
@@ -0,0 +1,255 @@
+
+#include "testbench.h"
+#include
+#include
+#undef CHECK
+#include
+#include
+
+using namespace sc_core;
+using namespace ahb;
+
+factory::add tb;
+bool is_equal(tlm::tlm_generic_payload const& a, tlm::tlm_generic_payload const& b) {
+ auto ret = true;
+ ret &= a.get_command() == b.get_command();
+ ret &= a.get_address() == b.get_address();
+ ret &= a.get_data_length() == b.get_data_length();
+ for(auto i = 0u; i < a.get_data_length(); ++i)
+ ret &= a.get_data_ptr()[i] == b.get_data_ptr()[i];
+ // if(a.get_byte_enable_ptr() && b.get_byte_enable_ptr()) {
+ // ret &= a.get_byte_enable_length() == b.get_byte_enable_length();
+ // for(auto i=0u; i tlm::tlm_generic_payload* prepare_trans(uint64_t start_address, unsigned len, unsigned width) {
+ static unsigned id{0};
+ auto trans = tlm::scc::tlm_mm<>::get().allocate(len);
+ trans->set_address(start_address);
+ tlm::scc::setId(*trans, ++id);
+ auto ext = trans->get_extension();
+ trans->set_data_length(len);
+ trans->set_streaming_width(len);
+ ext->set_instruction();
+ return trans;
+}
+
+inline void randomize(tlm::tlm_generic_payload& gp) {
+ static uint8_t req_cnt{0};
+ for(size_t i = 0; i < gp.get_data_length(); ++i) {
+ *(gp.get_data_ptr() + i) = i % 2 ? i : req_cnt;
+ }
+ req_cnt++;
+}
+
+template unsigned run_scenario(STATE& state, unsigned wait_states = 0) {
+ auto& dut = factory::get();
+ dut.register_b_transport([&state, wait_states](tlm::tlm_base_protocol_types::tlm_payload_type& trans, sc_core::sc_time& d) {
+ if(trans.is_read()) {
+ for(size_t i = 0; i < trans.get_data_length(); ++i) {
+ *(trans.get_data_ptr() + i) = i % 2 ? i : (state.resp_cnt + 128);
+ }
+ state.read_tx.second.emplace_back(&trans);
+ }
+ if(trans.is_write())
+ state.write_tx.second.emplace_back(&trans);
+ SCCDEBUG(__FUNCTION__) << "RX: " << trans;
+ for(unsigned i = 0; i < wait_states; ++i)
+ sc_core::wait(factory::get().clk.posedge_event());
+ state.resp_cnt++;
+ trans.set_response_status(tlm::TLM_OK_RESPONSE);
+ });
+
+ dut.rst_n.write(false);
+ sc_start(state.ResetCycles * dut.clk.period());
+ dut.rst_n.write(true);
+ sc_start(dut.clk.period());
+ sc_start(dut.clk.period());
+
+ auto run1 = sc_spawn([&dut, &state]() {
+ unsigned int StartAddr{0x0};
+ for(int i = 0; i < state.NumberOfIterations; ++i) {
+ tlm::scc::tlm_gp_shared_ptr trans =
+ prepare_trans(StartAddr, state.BurstLengthByte, state.BurstSizeBytes);
+ trans->set_command(tlm::TLM_READ_COMMAND);
+ SCCDEBUG(__FUNCTION__) << "task run1, iteration " << i << " TX: " << *trans;
+ sc_core::sc_time d;
+ dut.isck->b_transport(*trans, d);
+ state.read_tx.first.emplace_back(trans);
+ StartAddr += state.BurstSizeBytes;
+ }
+ SCCDEBUG(__FUNCTION__) << "task run1 finished";
+ });
+ auto run2 = sc_spawn([&dut, &state]() {
+ unsigned int StartAddr{0x2000};
+ for(int i = 0; i < state.NumberOfIterations; ++i) {
+ tlm::scc::tlm_gp_shared_ptr trans =
+ prepare_trans(StartAddr, state.BurstLengthByte, state.BurstSizeBytes);
+ trans->set_command(tlm::TLM_WRITE_COMMAND);
+ randomize(*trans);
+ SCCDEBUG(__FUNCTION__) << "task run2, iteration " << i << " TX: " << *trans;
+ sc_core::sc_time d;
+ dut.isck->b_transport(*trans, d);
+ state.write_tx.first.emplace_back(trans);
+ StartAddr += state.BurstSizeBytes;
+ }
+ SCCDEBUG(__FUNCTION__) << "task run2 finished";
+ });
+ auto run3 = sc_spawn([&dut, &state]() {
+ unsigned int StartAddr{0x1000};
+ for(int i = 0; i < state.NumberOfIterations; ++i) {
+ tlm::scc::tlm_gp_shared_ptr trans =
+ prepare_trans(StartAddr, state.BurstLengthByte, state.BurstSizeBytes);
+ trans->set_command(tlm::TLM_READ_COMMAND);
+ SCCDEBUG(__FUNCTION__) << "task run3, iteration " << i << " TX: " << *trans;
+ sc_core::sc_time d;
+ dut.isck->b_transport(*trans, d);
+ state.read_tx.first.emplace_back(trans);
+ StartAddr += state.BurstSizeBytes;
+ }
+ SCCDEBUG(__FUNCTION__) << "task run3 finished";
+ });
+ auto run4 = sc_spawn([&dut, &state]() {
+ unsigned int StartAddr{0x3000};
+ for(int i = 0; i < state.NumberOfIterations; ++i) {
+ tlm::scc::tlm_gp_shared_ptr trans =
+ prepare_trans(StartAddr, state.BurstLengthByte, state.BurstSizeBytes);
+ trans->set_command(tlm::TLM_WRITE_COMMAND);
+ randomize(*trans);
+ SCCDEBUG(__FUNCTION__) << "task run4, iteration " << i << " TX: " << *trans;
+ sc_core::sc_time d;
+ dut.isck->b_transport(*trans, d);
+ state.write_tx.first.emplace_back(trans);
+ StartAddr += state.BurstSizeBytes;
+ }
+ SCCDEBUG(__FUNCTION__) << "task run4 finished";
+ });
+
+ unsigned cycles{0};
+ while(cycles < 1000 && !(run1.terminated() && run2.terminated() && run3.terminated() && run4.terminated())) {
+ sc_start(10 * dut.clk.period());
+ cycles += 10;
+ }
+ return cycles;
+}
+
+TEST_CASE("apb_read_write", "[APB][pin-level]") {
+ struct {
+ unsigned int ResetCycles{4};
+ unsigned int BurstLengthByte{4};
+ unsigned int BurstSizeBytes{4};
+ unsigned int NumberOfIterations{1};
+ std::pair, std::vector> read_tx;
+ std::pair, std::vector> write_tx;
+ unsigned resp_cnt{0};
+ } state;
+
+ auto cycles = run_scenario(state);
+
+ REQUIRE(cycles < 1000);
+ REQUIRE(sc_report_handler::get_count(SC_ERROR) == 0);
+ REQUIRE(sc_report_handler::get_count(SC_WARNING) == 0);
+
+ REQUIRE(state.resp_cnt == 4 * state.NumberOfIterations);
+ {
+ auto& e = state.write_tx;
+ auto const& send_tx = e.first;
+ auto const& recv_tx = e.second;
+ REQUIRE(send_tx.size() == recv_tx.size());
+ for(auto i = 0; i < send_tx.size(); ++i) {
+ REQUIRE(send_tx[i]->get_response_status() == tlm::TLM_OK_RESPONSE);
+ CHECK(is_equal(*send_tx[i], *recv_tx[i]));
+ }
+ }
+ {
+ auto& e = state.read_tx;
+ auto const& send_tx = e.first;
+ auto const& recv_tx = e.second;
+ REQUIRE(send_tx.size() == recv_tx.size());
+ for(auto i = 0; i < send_tx.size(); ++i) {
+ REQUIRE(send_tx[i]->get_response_status() == tlm::TLM_OK_RESPONSE);
+ CHECK(is_equal(*send_tx[i], *recv_tx[i]));
+ }
+ }
+}
+
+TEST_CASE("apb_narrow_read_write", "[APB][pin-level]") {
+ struct {
+ unsigned int ResetCycles{4};
+ unsigned int BurstLengthByte{1};
+ unsigned int BurstSizeBytes{1};
+ unsigned int NumberOfIterations{8};
+ std::pair, std::vector> read_tx;
+ std::pair, std::vector> write_tx;
+ unsigned resp_cnt{0};
+ } state;
+
+ auto cycles = run_scenario(state);
+
+ REQUIRE(cycles < 1000);
+ REQUIRE(sc_report_handler::get_count(SC_ERROR) == 0);
+ REQUIRE(sc_report_handler::get_count(SC_WARNING) == 0);
+
+ REQUIRE(state.resp_cnt == 4 * state.NumberOfIterations);
+ {
+ auto& e = state.write_tx;
+ auto const& send_tx = e.first;
+ auto const& recv_tx = e.second;
+ REQUIRE(send_tx.size() == recv_tx.size());
+ for(auto i = 0; i < send_tx.size(); ++i)
+ CHECK(is_equal(*send_tx[i], *recv_tx[i]));
+ }
+ {
+ auto& e = state.read_tx;
+ auto const& send_tx = e.first;
+ auto const& recv_tx = e.second;
+ REQUIRE(send_tx.size() == recv_tx.size());
+ // Narrow reads cannot be checked as they arrive a word read at the target
+ // for(auto i = 0; i < send_tx.size(); ++i)
+ // CHECK(is_equal(*send_tx[i], *recv_tx[i]));
+ }
+}
+
+TEST_CASE("apb_delayed_read_write", "[APB][pin-level]") {
+ struct {
+ unsigned int ResetCycles{4};
+ unsigned int BurstLengthByte{4};
+ unsigned int BurstSizeBytes{4};
+ unsigned int NumberOfIterations{2};
+ std::pair, std::vector> read_tx;
+ std::pair, std::vector> write_tx;
+ unsigned resp_cnt{0};
+ } state;
+
+ auto cycles = run_scenario(state, 2);
+
+ REQUIRE(cycles < 1000);
+ REQUIRE(sc_report_handler::get_count(SC_ERROR) == 0);
+ REQUIRE(sc_report_handler::get_count(SC_WARNING) == 0);
+
+ REQUIRE(state.resp_cnt == 4 * state.NumberOfIterations);
+ {
+ auto& e = state.write_tx;
+ auto const& send_tx = e.first;
+ auto const& recv_tx = e.second;
+ REQUIRE(send_tx.size() == recv_tx.size());
+ for(auto i = 0; i < send_tx.size(); ++i) {
+ REQUIRE(send_tx[i]->get_response_status() == tlm::TLM_OK_RESPONSE);
+ CHECK(is_equal(*send_tx[i], *recv_tx[i]));
+ }
+ }
+ {
+ auto& e = state.read_tx;
+ auto const& send_tx = e.first;
+ auto const& recv_tx = e.second;
+ REQUIRE(send_tx.size() == recv_tx.size());
+ for(auto i = 0; i < send_tx.size(); ++i) {
+ REQUIRE(send_tx[i]->get_response_status() == tlm::TLM_OK_RESPONSE);
+ CHECK(is_equal(*send_tx[i], *recv_tx[i]));
+ }
+ }
+}
diff --git a/tests/apb_pin_level/testbench.h b/tests/apb_pin_level/testbench.h
new file mode 100644
index 0000000..bb14d26
--- /dev/null
+++ b/tests/apb_pin_level/testbench.h
@@ -0,0 +1,89 @@
+#ifndef _TESTBENCH_H_
+#define _TESTBENCH_H_
+
+#include
+#include
+#include
+
+using namespace sc_core;
+
+class testbench : public sc_core::sc_module {
+public:
+ enum { DATA_WIDTH = 32, ADDR_WIDTH = 32 };
+ using addr_t = typename apb::pin::initiator::addr_t;
+ using data_t = apb::pin::initiator::data_t;
+ using strb_t = sc_dt::sc_uint;
+ sc_core::sc_time clk_period{10, sc_core::SC_NS};
+ sc_core::sc_clock clk{"clk", clk_period, 0.5, sc_core::SC_ZERO_TIME, true};
+ sc_core::sc_signal rst_n{"rst_n"};
+ // initiator side
+ tlm::scc::initiator_mixin> isck{"isck"};
+ apb::pin::initiator intor_bfm{"intor_bfm"};
+ // signal accurate bus
+ sc_core::sc_signal PADDR{"PADDR"};
+ sc_core::sc_signal> PPROT{"PPROT"};
+ sc_core::sc_signal PNSE{"PNSE"};
+ sc_core::sc_signal PSELx{"PSELx"};
+ sc_core::sc_signal PENABLE{"PENABLE"};
+ sc_core::sc_signal PWRITE{"PWRITE"};
+ sc_core::sc_signal PWDATA{"PWDATA"};
+ sc_core::sc_signal PSTRB{"PSTRB"};
+ sc_core::sc_signal PREADY{"PREADY"};
+ sc_core::sc_signal PRDATA{"PRDATA"};
+ sc_core::sc_signal PSLVERR{"PSLVERR"};
+ sc_core::sc_signal PWAKEUP{"PWAKEUP"};
+ // target side
+ apb::pin::target tgt_bfm{"tgt_bfm"};
+ tlm::scc::target_mixin> tsck{"tsck"};
+
+public:
+ SC_HAS_PROCESS(testbench);
+ testbench()
+ : testbench("testbench") {}
+ testbench(sc_core::sc_module_name nm)
+ : sc_core::sc_module(nm) {
+ intor_bfm.PCLK_i(clk);
+ tgt_bfm.PCLK_i(clk);
+ // bfm to signals
+ isck(intor_bfm.tsckt);
+ intor_bfm.PRESETn_i(rst_n);
+ intor_bfm.PADDR_o(PADDR);
+ intor_bfm.PPROT_o(PPROT);
+ intor_bfm.PNSE_o(PNSE);
+ intor_bfm.PSELx_o(PSELx);
+ intor_bfm.PENABLE_o(PENABLE);
+ intor_bfm.PWRITE_o(PWRITE);
+ intor_bfm.PWDATA_o(PWDATA);
+ intor_bfm.PSTRB_o(PSTRB);
+ intor_bfm.PREADY_i(PREADY);
+ intor_bfm.PRDATA_i(PRDATA);
+ intor_bfm.PSLVERR_i(PSLVERR);
+ intor_bfm.PWAKEUP_o(PWAKEUP);
+
+ tgt_bfm.PRESETn_i(rst_n);
+ tgt_bfm.PADDR_i(PADDR);
+ tgt_bfm.PPROT_i(PPROT);
+ tgt_bfm.PNSE_i(PNSE);
+ tgt_bfm.PSELx_i(PSELx);
+ tgt_bfm.PENABLE_i(PENABLE);
+ tgt_bfm.PWRITE_i(PWRITE);
+ tgt_bfm.PWDATA_i(PWDATA);
+ tgt_bfm.PSTRB_i(PSTRB);
+ tgt_bfm.PREADY_o(PREADY);
+ tgt_bfm.PRDATA_o(PRDATA);
+ tgt_bfm.PSLVERR_o(PSLVERR);
+ tgt_bfm.PWAKEUP_i(PWAKEUP);
+
+ tgt_bfm.isckt(tsck);
+ tsck.register_b_transport([this](tlm::tlm_base_protocol_types::tlm_payload_type& trans, sc_core::sc_time& d) {
+ if(cb_delegate)
+ cb_delegate(trans, d);
+ });
+ }
+
+ void run1() {}
+ void register_b_transport(std::function cb) { cb_delegate = cb; }
+ std::function cb_delegate;
+};
+
+#endif // _TESTBENCH_H_
diff --git a/tests/axi4_pin_level/CMakeLists.txt b/tests/axi4_pin_level/CMakeLists.txt
index ffcfa7b..53ff21a 100644
--- a/tests/axi4_pin_level/CMakeLists.txt
+++ b/tests/axi4_pin_level/CMakeLists.txt
@@ -1,7 +1,7 @@
project (axi4_pin_level)
add_executable(${PROJECT_NAME}
- narrow_burst_test.cpp
+ burst_test.cpp
${test_util_SOURCE_DIR}/sc_main.cpp
)
target_link_libraries (${PROJECT_NAME} PUBLIC test_util)
diff --git a/tests/axi4_pin_level/narrow_burst_test.cpp b/tests/axi4_pin_level/burst_test.cpp
similarity index 56%
rename from tests/axi4_pin_level/narrow_burst_test.cpp
rename to tests/axi4_pin_level/burst_test.cpp
index 3119369..2315ec8 100644
--- a/tests/axi4_pin_level/narrow_burst_test.cpp
+++ b/tests/axi4_pin_level/burst_test.cpp
@@ -7,9 +7,59 @@
#include
using namespace sc_core;
+using tlm_gp_shared_ptr_vec = std::vector;
factory::add tb;
+//// DataTransfer()
+//// ==============
+// void DataTransfer(uint64_t Start_Address, unsigned axsize, unsigned axlen, unsigned Data_Bus_Bytes, axi::burst_e Mode, bool IsWrite) {
+// auto Number_Bytes = 2u<= Upper_Wrap_Boundary) addr = Lower_Wrap_Boundary;
+// }
+// } else {
+// addr = Aligned_Address + Number_Bytes;
+// aligned = true; // All transfers after the first are aligned
+// }
+// }
+// }
+// return;
+// }
bool is_equal(tlm::tlm_generic_payload const& a, tlm::tlm_generic_payload const& b) {
auto ret = true;
ret &= a.get_command() == b.get_command();
@@ -38,7 +88,9 @@ tlm::tlm_generic_payload* prepare_trans(uint64_t start_address, unsigned addr_in
ext->set_size(scc::ilog2(width));
sc_assert(len < (bus_cfg::BUSWIDTH / 8) || len % (bus_cfg::BUSWIDTH / 8) == 0);
auto length = (len * 8 - 1) / (8 * width);
- if(width == (bus_cfg::BUSWIDTH / 8) && start_address % (bus_cfg::BUSWIDTH / 8))
+ // if(width == (bus_cfg::BUSWIDTH / 8) && start_address % (bus_cfg::BUSWIDTH / 8))
+ // length++;
+ if(start_address % (bus_cfg::BUSWIDTH / 8) + width > (bus_cfg::BUSWIDTH / 8))
length++;
ext->set_length(length);
// ext->set_burst(len * 8 > bus_cfg::buswidth ? axi::burst_e::INCR : axi::burst_e::FIXED);
@@ -81,51 +133,55 @@ template unsigned run_scenario(STATE& state) {
unsigned int StartAddr{0x0};
for(int i = 0; i < state.NumberOfIterations; ++i) {
tlm::scc::tlm_gp_shared_ptr trans =
- prepare_trans(StartAddr, 4, state.BurstLengthByte, state.BurstSizeBytes, 1);
+ prepare_trans(StartAddr + (state.unaligned ? 2 : 0), 4, state.BurstLengthByte, state.BurstSizeBytes, 1);
trans->set_command(tlm::TLM_READ_COMMAND);
- SCCDEBUG(__FUNCTION__) << "run1, iteration " << i << " TX: " << *trans;
+ SCCDEBUG("run1") << "iteration " << i << " TX: " << *trans;
dut.intor_pe.transport(*trans, false);
state.read_tx[axi::get_axi_id(*trans)].first.emplace_back(trans);
StartAddr += state.BurstSizeBytes;
}
+ SCCDEBUG("run1") << "finished " << state.NumberOfIterations << " iterations";
});
auto run2 = sc_spawn([&dut, &state]() {
unsigned int StartAddr{0x2000};
for(int i = 0; i < state.NumberOfIterations; ++i) {
tlm::scc::tlm_gp_shared_ptr trans =
- prepare_trans(StartAddr, 4, state.BurstLengthByte, state.BurstSizeBytes, 2);
+ prepare_trans(StartAddr + (state.unaligned ? 2 : 0), 4, state.BurstLengthByte, state.BurstSizeBytes, 2);
trans->set_command(tlm::TLM_WRITE_COMMAND);
randomize(*trans);
- SCCDEBUG(__FUNCTION__) << "run2, iteration " << i << " TX: " << *trans;
+ SCCDEBUG("run2") << "iteration " << i << " TX: " << *trans;
dut.intor_pe.transport(*trans, false);
state.write_tx[axi::get_axi_id(*trans)].first.emplace_back(trans);
StartAddr += state.BurstSizeBytes;
}
+ SCCDEBUG("run2") << "finished " << state.NumberOfIterations << " iterations";
});
auto run3 = sc_spawn([&dut, &state]() {
unsigned int StartAddr{0x1000};
for(int i = 0; i < state.NumberOfIterations; ++i) {
tlm::scc::tlm_gp_shared_ptr trans =
- prepare_trans(StartAddr, 4, state.BurstLengthByte, state.BurstSizeBytes, 3);
+ prepare_trans(StartAddr + (state.unaligned ? 2 : 0), 4, state.BurstLengthByte, state.BurstSizeBytes, 3);
trans->set_command(tlm::TLM_READ_COMMAND);
- SCCDEBUG(__FUNCTION__) << "run3, iteration " << i << " TX: " << *trans;
+ SCCDEBUG("run3") << "iteration " << i << " TX: " << *trans;
dut.intor_pe.transport(*trans, false);
state.read_tx[axi::get_axi_id(*trans)].first.emplace_back(trans);
StartAddr += state.BurstSizeBytes;
}
+ SCCDEBUG("run3") << "finished " << state.NumberOfIterations << " iterations";
});
auto run4 = sc_spawn([&dut, &state]() {
unsigned int StartAddr{0x3000};
for(int i = 0; i < state.NumberOfIterations; ++i) {
tlm::scc::tlm_gp_shared_ptr trans =
- prepare_trans(StartAddr, 4, state.BurstLengthByte, state.BurstSizeBytes, 4);
+ prepare_trans(StartAddr + (state.unaligned ? 2 : 0), 4, state.BurstLengthByte, state.BurstSizeBytes, 4);
trans->set_command(tlm::TLM_WRITE_COMMAND);
randomize(*trans);
- SCCDEBUG(__FUNCTION__) << "run4, iteration " << i << " TX: " << *trans;
+ SCCDEBUG("run4") << "iteration " << i << " TX: " << *trans;
dut.intor_pe.transport(*trans, false);
state.write_tx[axi::get_axi_id(*trans)].first.emplace_back(trans);
StartAddr += state.BurstSizeBytes;
}
+ SCCDEBUG("run4") << "finished " << state.NumberOfIterations << " iterations";
});
unsigned cycles{0};
@@ -136,21 +192,23 @@ template unsigned run_scenario(STATE& state) {
return cycles;
}
-void axi4_burst_alignment(bool pipelined_wrreq, bool write_bp) {
+void axi4_burst_alignment(bool pipelined_wrreq, bool write_bp, bool unaligned = false) {
+ SCCINFO(__FUNCTION__) << "starting with pipelined_wrreq=" << pipelined_wrreq << " and write_bp=" << write_bp;
struct {
unsigned int ResetCycles{4};
unsigned int BurstLengthByte{16};
unsigned int BurstSizeBytes{8};
unsigned int NumberOfIterations{8};
- std::unordered_map, std::vector>> read_tx;
- std::unordered_map, std::vector>>
- write_tx;
+ std::unordered_map> read_tx;
+ std::unordered_map> write_tx;
unsigned resp_cnt{0};
+ bool unaligned{false};
} state;
+ state.unaligned = unaligned;
auto& dut = factory::get();
dut.intor_bfm.pipelined_wrreq = pipelined_wrreq;
- dut.tgt_pe.wr_data_accept_delay.value = write_bp ? 1 : 0;
+ dut.tgt_pe.wr_data_accept_delay.set_value(write_bp ? 1 : 0);
auto cycles = run_scenario(state);
REQUIRE(cycles < 1000);
@@ -172,27 +230,39 @@ void axi4_burst_alignment(bool pipelined_wrreq, bool write_bp) {
auto const& recv_tx = e.second.second;
REQUIRE(send_tx.size() == recv_tx.size());
for(auto i = 0; i < send_tx.size(); ++i) {
+ auto addr = send_tx[i]->get_address();
+ if(addr % (testbench::bus_cfg::ADDRWIDTH / 8)) {
+ CHECK(send_tx[i]->get_data_length() <= recv_tx[i]->get_data_length());
+ CHECK(send_tx[i]->get_byte_enable_length() <= recv_tx[i]->get_byte_enable_length());
+ // adjust the length of the read due to misalignment
+ recv_tx[i]->set_data_length(send_tx[i]->get_data_length());
+ recv_tx[i]->set_byte_enable_length(send_tx[i]->get_byte_enable_length());
+ recv_tx[i]->set_streaming_width(send_tx[i]->get_streaming_width());
+ }
REQUIRE(send_tx[i]->get_response_status() == tlm::TLM_OK_RESPONSE);
CHECK(is_equal(*send_tx[i], *recv_tx[i]));
}
}
}
-void axi4_narrow_burst(bool pipelined_wrreq, bool write_bp) {
+void axi4_narrow_burst(bool pipelined_wrreq, bool write_bp, bool unaligned = false) {
+ SCCINFO(__FUNCTION__) << "starting with pipelined_wrreq=" << pipelined_wrreq << ", write_bp = " << write_bp
+ << " and unaligned=" << unaligned;
struct {
unsigned int ResetCycles{4};
unsigned int BurstLengthByte{16};
unsigned int BurstSizeBytes{4};
unsigned int NumberOfIterations{8};
- std::unordered_map, std::vector>> read_tx;
- std::unordered_map, std::vector>>
- write_tx;
+ std::unordered_map> read_tx;
+ std::unordered_map> write_tx;
unsigned resp_cnt{0};
+ bool unaligned{false};
} state;
+ state.unaligned = unaligned;
auto& dut = factory::get();
dut.intor_bfm.pipelined_wrreq = pipelined_wrreq;
- dut.tgt_pe.wr_data_accept_delay.value = write_bp ? 1 : 0;
+ dut.tgt_pe.wr_data_accept_delay.set_value(write_bp ? 1 : 0);
auto cycles = run_scenario(state);
REQUIRE(cycles < 1000);
@@ -218,16 +288,32 @@ void axi4_narrow_burst(bool pipelined_wrreq, bool write_bp) {
TEST_CASE("axi4_burst_alignment", "[AXI][pin-level]") { axi4_burst_alignment(false, false); }
+TEST_CASE("axi4_burst_alignment_unaligned_addr", "[AXI][pin-level]") { axi4_burst_alignment(false, false, true); }
+
TEST_CASE("axi4_narrow_burst", "[AXI][pin-level]") { axi4_narrow_burst(false, false); }
+// TEST_CASE("axi4_narrow_burst_unaligned_addr", "[AXI][pin-level]") { axi4_narrow_burst(false, false, true); }
+
TEST_CASE("axi4_burst_alignment_with_bp", "[AXI][pin-level]") { axi4_burst_alignment(false, true); }
+TEST_CASE("axi4_burst_alignment_with_bp_unaligned_addr", "[AXI][pin-level]") { axi4_burst_alignment(false, true, true); }
+
TEST_CASE("axi4_narrow_burst_with_bp", "[AXI][pin-level]") { axi4_narrow_burst(false, true); }
+// TEST_CASE("axi4_narrow_burst_with_bp_unaligned_addr", "[AXI][pin-level]") { axi4_narrow_burst(false, true, true); }
+
TEST_CASE("axi4_burst_alignment_pipelined_write", "[AXI][pin-level]") { axi4_burst_alignment(true, false); }
+TEST_CASE("axi4_burst_alignment_pipelined_write_unaligned_addr", "[AXI][pin-level]") { axi4_burst_alignment(true, false, true); }
+
TEST_CASE("axi4_narrow_burst_pipelined_write", "[AXI][pin-level]") { axi4_narrow_burst(true, false); }
+// TEST_CASE("axi4_narrow_burst_pipelined_write_unaligned_addr", "[AXI][pin-level]") { axi4_narrow_burst(true, false, true); }
+
TEST_CASE("axi4_burst_alignment_pipelined_write_with_bp", "[AXI][pin-level]") { axi4_burst_alignment(true, true); }
+TEST_CASE("axi4_burst_alignment_pipelined_write_with_bp_unaligned_addr", "[AXI][pin-level]") { axi4_burst_alignment(true, true, true); }
+
TEST_CASE("axi4_narrow_burst_pipelined_write_with_bp", "[AXI][pin-level]") { axi4_narrow_burst(true, true); }
+
+// TEST_CASE("axi4_narrow_burst_pipelined_write_with_bp_unaligned_addr", "[AXI][pin-level]") { axi4_narrow_burst(true, true, true); }
diff --git a/tests/axi4_pin_level/waves.gtkw b/tests/axi4_pin_level/waves.gtkw
new file mode 100644
index 0000000..222c184
--- /dev/null
+++ b/tests/axi4_pin_level/waves.gtkw
@@ -0,0 +1,116 @@
+[*]
+[*] GTKWave Analyzer v3.3.118 (w)1999-2023 BSI
+[*] Wed Jan 8 16:33:12 2025
+[*]
+[dumpfile] "/scratch/eyck/workarea/MINRES/SystemC-Components-Test/axi4_pin_level.fst"
+[dumpfile_mtime] "Wed Jan 8 16:32:32 2025"
+[dumpfile_size] 7261
+[savefile] "/scratch/eyck/workarea/MINRES/SystemC-Components-Test/tests/axi4_pin_level/waves.gtkw"
+[timestart] 0
+[size] 2560 1288
+[pos] -1 -1
+*-20.062529 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+[treeopen] testbench.
+[sst_width] 304
+[signals_width] 243
+[sst_expanded] 1
+[sst_vpaned_height] 396
+@28
+testbench.clk
+testbench.rst
+@800200
+-ar
+@28
+testbench.ar_valid
+testbench.ar_ready
+@22
+testbench.ar_addr[31:0]
+@28
+testbench.ar_burst[1:0]
+@22
+testbench.ar_cache[3:0]
+testbench.ar_id[3:0]
+testbench.ar_len[7:0]
+@28
+testbench.ar_lock
+testbench.ar_prot[2:0]
+@22
+testbench.ar_qos[3:0]
+testbench.ar_region[3:0]
+@28
+testbench.ar_size[2:0]
+testbench.ar_user
+@1000200
+-ar
+@800200
+-r
+@28
+testbench.r_valid
+testbench.r_ready
+testbench.r_last
+@22
+testbench.r_data[63:0]
+testbench.r_id[3:0]
+@28
+testbench.r_resp[1:0]
+testbench.r_trace
+testbench.r_user
+@1000200
+-r
+@800200
+-aw
+@28
+testbench.aw_valid
+testbench.aw_ready
+@22
+testbench.aw_id[3:0]
+testbench.aw_addr[31:0]
+@28
+testbench.aw_burst[1:0]
+@22
+testbench.aw_cache[3:0]
+testbench.aw_len[7:0]
+@28
+testbench.aw_lock
+testbench.aw_prot[2:0]
+@22
+testbench.aw_qos[3:0]
+testbench.aw_region[3:0]
+@28
+testbench.aw_size[2:0]
+testbench.aw_user
+@1000200
+-aw
+@800200
+-w
+@29
+testbench.w_valid
+testbench.w_ready
+testbench.w_ack
+@23
+testbench.w_data[63:0]
+testbench.w_id[3:0]
+@29
+testbench.w_last
+@23
+testbench.w_strb[7:0]
+@29
+testbench.w_trace
+testbench.w_user
+@1000200
+-w
+@800200
+-b
+@28
+testbench.b_valid
+testbench.b_ready
+@22
+testbench.b_id[3:0]
+@28
+testbench.b_resp[1:0]
+testbench.b_trace
+testbench.b_user
+@1000200
+-b
+[pattern_trace] 1
+[pattern_trace] 0
diff --git a/tests/cci_param_restricted/test.cpp b/tests/cci_param_restricted/test.cpp
index 925edbc..63d6d63 100644
--- a/tests/cci_param_restricted/test.cpp
+++ b/tests/cci_param_restricted/test.cpp
@@ -2,12 +2,12 @@
#define SC_INCLUDE_DYNAMIC_PROCESSES
#include
#endif
+#include
#include
#include
#include
#include
#include
-
using namespace sc_core;
struct top : public sc_core::sc_module {
diff --git a/tests/configuration/sc_main.cpp b/tests/configuration/sc_main.cpp
index f4886a0..d00620a 100644
--- a/tests/configuration/sc_main.cpp
+++ b/tests/configuration/sc_main.cpp
@@ -33,7 +33,6 @@
#include "top_module.h"
#include
-#include
#include
/**
diff --git a/tests/cxs_tlm/CMakeLists.txt b/tests/cxs_tlm/CMakeLists.txt
new file mode 100644
index 0000000..ede8eff
--- /dev/null
+++ b/tests/cxs_tlm/CMakeLists.txt
@@ -0,0 +1,8 @@
+project (cxs_tlm)
+add_executable(${PROJECT_NAME}
+ csx_packet_test.cpp
+ ${test_util_SOURCE_DIR}/sc_main.cpp
+)
+target_link_libraries (${PROJECT_NAME} PUBLIC scc::busses test_util)
+
+catch_discover_tests(${PROJECT_NAME})
diff --git a/tests/cxs_tlm/csx_packet_test.cpp b/tests/cxs_tlm/csx_packet_test.cpp
new file mode 100644
index 0000000..8bfdcf3
--- /dev/null
+++ b/tests/cxs_tlm/csx_packet_test.cpp
@@ -0,0 +1,171 @@
+
+#include "testbench.h"
+#include
+#include
+#undef CHECK
+#include
+#include
+#include
+
+using namespace sc_core;
+namespace cxs {
+factory::add> tb8;
+factory::add> tb9;
+factory::add> tb10;
+
+template unsigned run_scenario(STATE& state, unsigned burst_factor = 0) {
+ auto& dut = factory::get>();
+ if(burst_factor)
+ dut.tx.burst_len.set_value(burst_factor);
+ dut.rst.write(true);
+ sc_start(state.reset_cycles * dut.clk.period());
+ dut.rst.write(false);
+ sc_start(dut.clk.period());
+
+ auto run1 = sc_spawn([&dut, &state]() {
+ auto burst_cnt{0};
+ std::deque expected_pkt;
+ for(auto size : state.packet_sizes) {
+ cxs_pkt_shared_ptr tx_pkt = cxs_pkt_mm::get().allocate();
+ tx_pkt->get_data().resize(size);
+ SCCDEBUG("run_scenario") << "Transmitting packet with size " << size;
+ auto phase{tlm::nw::REQUEST};
+ sc_core::sc_time t = sc_core::SC_ZERO_TIME;
+ auto status = dut.isck->nb_transport_fw(*tx_pkt, phase, t);
+ expected_pkt.emplace_back(tx_pkt);
+ tx_pkt = nullptr;
+ REQUIRE(status == tlm::TLM_UPDATED);
+ REQUIRE(phase == tlm::nw::CONFIRM);
+ if(++burst_cnt == state.granularity) {
+ auto rec_cnt = 0u;
+ while(rec_cnt < burst_cnt) {
+ ::sc_core::wait(dut.recv.data_written_event());
+ while(!dut.recv.empty()) {
+ auto recv_pkt = dut.recv.front();
+ dut.recv.pop_front();
+ tx_pkt = expected_pkt.front();
+ expected_pkt.pop_front();
+ REQUIRE(tx_pkt == recv_pkt);
+ REQUIRE(recv_pkt->get_data().size() == state.packet_sizes[state.resp_cnt]);
+ state.resp_cnt++;
+ rec_cnt++;
+ SCCDEBUG("run_scenario") << "Received packet with size " << recv_pkt->get_data().size()
+ << ", total number of packets is " << state.resp_cnt;
+ }
+ }
+ burst_cnt = 0;
+ }
+ }
+ });
+
+ unsigned cycles{0};
+ while(cycles < state.max_cycles && !(run1.terminated())) {
+ // while(cycles<1000 && !(run5.terminated())){
+ sc_start(10 * dut.clk.period());
+ cycles += 10;
+ }
+ return cycles;
+}
+
+template unsigned run_scenario(int width, STATE& state, unsigned burst_factor = 0) {
+ switch(width) {
+ case 8:
+ case 256:
+ return run_scenario<256>(state);
+ case 9:
+ case 512:
+ return run_scenario<512>(state);
+ case 10:
+ case 1024:
+ return run_scenario<1024>(state);
+ }
+ return 0;
+}
+
+TEST_CASE("single-packet", "[CXS][tlm-level]") {
+ struct {
+ unsigned int reset_cycles{4};
+ unsigned int max_cycles = 5000;
+ std::vector packet_sizes;
+ unsigned granularity{1};
+ unsigned resp_cnt{0};
+ } state;
+
+ state.packet_sizes.assign({4, 8, 16, 32, 64, 128, 256, 1024});
+ for(auto width = 8; width < 11; ++width) {
+ state.resp_cnt = 0;
+ auto cycles = run_scenario(width, state);
+
+ REQUIRE(cycles < state.max_cycles);
+ REQUIRE(sc_report_handler::get_count(SC_ERROR) == 0);
+ REQUIRE(sc_report_handler::get_count(SC_WARNING) == 0);
+
+ REQUIRE(state.resp_cnt == state.packet_sizes.size());
+ }
+}
+
+TEST_CASE("multi-packet", "[CXS][tlm-level]") {
+ struct {
+ unsigned int reset_cycles{4};
+ unsigned int max_cycles = 5000;
+ std::vector packet_sizes;
+ unsigned granularity{2};
+ unsigned resp_cnt{0};
+ } state;
+
+ state.packet_sizes.assign({4, 8, 16, 32, 16, 64, 16, 128, 16, 256, 16, 1024});
+ for(auto width = 8; width < 11; ++width) {
+ state.resp_cnt = 0;
+ auto cycles = run_scenario(width, state);
+
+ REQUIRE(cycles < state.max_cycles);
+ REQUIRE(sc_report_handler::get_count(SC_ERROR) == 0);
+ REQUIRE(sc_report_handler::get_count(SC_WARNING) == 0);
+
+ REQUIRE(state.resp_cnt == state.packet_sizes.size());
+ }
+}
+TEST_CASE("single-packet-burst2", "[CXS][tlm-level]") {
+ struct {
+ unsigned int reset_cycles{4};
+ unsigned int max_cycles = 5000;
+ std::vector packet_sizes;
+ unsigned granularity{1};
+ unsigned resp_cnt{0};
+ } state;
+
+ state.packet_sizes.assign({4, 8, 16, 32, 64, 128, 256, 1024});
+ for(auto width = 8; width < 11; ++width) {
+ state.resp_cnt = 0;
+ auto cycles = run_scenario(width, state, 2);
+
+ REQUIRE(cycles < state.max_cycles);
+ REQUIRE(sc_report_handler::get_count(SC_ERROR) == 0);
+ REQUIRE(sc_report_handler::get_count(SC_WARNING) == 0);
+
+ REQUIRE(state.resp_cnt == state.packet_sizes.size());
+ }
+}
+
+TEST_CASE("multi-packet-burst2", "[CXS][tlm-level]") {
+ struct {
+ unsigned int reset_cycles{4};
+ unsigned int max_cycles = 5000;
+ std::vector packet_sizes;
+ unsigned granularity{2};
+ unsigned resp_cnt{0};
+ } state;
+
+ state.packet_sizes.assign({4, 8, 16, 32, 16, 64, 16, 128, 16, 256, 16, 1024});
+ for(auto width = 8; width < 11; ++width) {
+ state.resp_cnt = 0;
+ auto cycles = run_scenario(width, state, 2);
+
+ REQUIRE(cycles < state.max_cycles);
+ REQUIRE(sc_report_handler::get_count(SC_ERROR) == 0);
+ REQUIRE(sc_report_handler::get_count(SC_WARNING) == 0);
+
+ REQUIRE(state.resp_cnt == state.packet_sizes.size());
+ }
+}
+} // namespace cxs
diff --git a/tests/cxs_tlm/testbench.h b/tests/cxs_tlm/testbench.h
new file mode 100644
index 0000000..00d99b9
--- /dev/null
+++ b/tests/cxs_tlm/testbench.h
@@ -0,0 +1,77 @@
+#ifndef _TESTBENCH_H_
+#define _TESTBENCH_H_
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+using namespace sc_core;
+using namespace sc_dt;
+using namespace std;
+namespace cxs {
+
+const char* sc_gen_unique_name(const char*, bool preserve_first);
+template struct testbench : public sc_core::sc_module {
+
+ using transaction_type = cxs_packet_types::tlm_payload_type;
+ using phase_type = cxs_packet_types::tlm_phase_type;
+
+ sc_core::sc_clock clk{"clk", 1_ns};
+ sc_core::sc_signal rst{"rst"};
+ tlm::nw::initiator_mixin, cxs_packet_types> isck{"isck"};
+ cxs_transmitter tx{"tx"};
+ cxs_channel cxs_chan{"cxs_chan"};
+ cxs_receiver rx{"rx"};
+ tlm::nw::target_mixin, cxs_packet_types> tsck{"tsck"};
+
+ testbench()
+ : testbench(sc_core::sc_gen_unique_name("testbench", false)) {}
+
+ testbench(sc_core::sc_module_name const& nm)
+ : sc_module(nm) {
+ isck.register_nb_transport_bw(
+ [this](transaction_type& trans, phase_type& phase, sc_core::sc_time& t) { return this->nb_transport_fw(trans, phase, t); });
+ tsck.register_nb_transport_fw(
+ [this](transaction_type& trans, phase_type& phase, sc_core::sc_time& t) { return this->nb_transport_fw(trans, phase, t); });
+ isck(tx.tsck);
+ tx.clk_i(clk);
+ tx.rst_i(rst);
+ tx.isck(cxs_chan.tsck);
+ cxs_chan.isck(rx.tsck);
+ rx.clk_i(clk);
+ rx.rst_i(rst);
+ rx.isck(tsck);
+ cxs_chan.channel_delay.set_value(100_ns);
+ rx.max_credit.set_value(15);
+ }
+
+ tlm::tlm_sync_enum nb_transport_fw(transaction_type& trans, phase_type& phase, sc_core::sc_time& t) {
+ if(phase == tlm::nw::REQUEST) {
+ SCCINFO(SCMOD) << "Received non-blocking transaction with phase " << phase.get_name();
+ recv.push_back(&trans);
+ phase = tlm::nw::CONFIRM;
+ return tlm::TLM_UPDATED;
+ }
+ throw std::runtime_error("illegal request in forward path");
+ }
+
+ tlm::tlm_sync_enum nb_transport_bw(transaction_type& trans, phase_type& phase, sc_core::sc_time& t) {
+ if(phase == tlm::nw::CONFIRM) {
+ confirmation_evt.notify(sc_core::SC_ZERO_TIME);
+ return tlm::TLM_ACCEPTED;
+ }
+ throw std::runtime_error("illegal response in backward path");
+ }
+
+ sc_core::sc_event confirmation_evt;
+ scc::fifo_w_cb recv;
+};
+} // namespace cxs
+#endif // _TESTBENCH_H_
diff --git a/tests/sc_fixed_tracing/CMakeLists.txt b/tests/sc_fixed_tracing/CMakeLists.txt
new file mode 100644
index 0000000..8dcb049
--- /dev/null
+++ b/tests/sc_fixed_tracing/CMakeLists.txt
@@ -0,0 +1,3 @@
+add_executable (sc_fixed_tracing sc_main.cpp)
+target_link_libraries (sc_fixed_tracing LINK_PUBLIC scc-sysc)
+add_test(NAME sc_fixed_tracing_test COMMAND sc_fixed_tracing )
\ No newline at end of file
diff --git a/tests/sc_fixed_tracing/sc_main.cpp b/tests/sc_fixed_tracing/sc_main.cpp
new file mode 100644
index 0000000..769b18f
--- /dev/null
+++ b/tests/sc_fixed_tracing/sc_main.cpp
@@ -0,0 +1,82 @@
+#define SC_INCLUDE_FX
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+using namespace sc_dt;
+using namespace std;
+
+struct testbench : public sc_core::sc_module {
+ scc::sc_variable> a{"a", sc_dt::sc_fixed<6, 4>()};
+ scc::sc_variable> b_sc_sat{"b_sc_sat", 0};
+ scc::sc_variable> a_qant{"a_qant", 0};
+ scc::sc_variable> b_sc_rnd{"b_sc_rnd", 0};
+ scc::sc_variable> b_sc_trn{"b_sc_trn", 0};
+ sc_fixed<5, 3> a_fixed;
+ sc_dt::sc_fix a_fix{5, 3};
+ sc_fxtype_params params{5, 4};
+ sc_fxtype_context context{params};
+ // becase we do not specify in b_fix constructor anything
+ // the parameters are taken form the latest created context
+ sc_fix b_fix;
+ sc_fix c_fix{5, 3};
+
+ testbench(sc_core::sc_module_name const& nm)
+ : sc_module(nm) {
+ SC_HAS_PROCESS(testbench);
+ SC_THREAD(run);
+ }
+
+ void trace(sc_core::sc_trace_file* trf) const override {
+ a.trace(trf);
+ scc::sc_trace(trf, a_fixed, std::string(name()) + ".a_fixed");
+ scc::sc_trace(trf, a_fix, std::string(name()) + ".a_fix");
+ scc::sc_trace(trf, b_fix, std::string(name()) + ".b_fix");
+ scc::sc_trace(trf, c_fix, std::string(name()) + ".c_fix");
+ }
+
+ void run() {
+ wait(1_ns);
+ init();
+ wait(1_ns);
+ test_overflow_modes();
+ wait(1_ns);
+ test_quantization_modes();
+ wait(1_ns);
+ this->a = 2;
+ wait(1_ps);
+ sc_core::sc_stop();
+ }
+
+ void init() {
+ a_fixed = 1.75;
+ a_fix = 1.75;
+ b_fix = 1.75;
+ c_fix = 1.75;
+ }
+ void test_overflow_modes() {
+ a = -7;
+ b_sc_sat = *a;
+ }
+
+ void test_quantization_modes() {
+ a_qant = -2.3125;
+ b_sc_rnd = *a_qant;
+ b_sc_trn = *a_qant;
+ }
+};
+
+int sc_main(int sc_argc, char* sc_argv[]) {
+ scc::init_logging(scc::log::INFO);
+ scc::configurer cfg("");
+ scc::tracer trc("sc_fixed_tracing");
+ testbench tb("tb");
+ sc_core::sc_start();
+ SCCINFO("sc_main") << "End Simulation.";
+
+ return sc_core::sc_report_handler::get_count(sc_core::SC_ERROR) + sc_core::sc_report_handler::get_count(sc_core::SC_WARNING);
+} // End of 'sc_main'