add test case focusing on simulation kernel performance
This commit is contained in:
parent
954bbed352
commit
61c33fdcc3
|
@ -9,6 +9,7 @@ set(ENABLE_SHARED TRUE CACHE BOOL "Build shared libraries")
|
||||||
|
|
||||||
set(NO_SUBMODULE_CHECK FALSE CACHE BOOL "Disable the submodule check")
|
set(NO_SUBMODULE_CHECK FALSE CACHE BOOL "Disable the submodule check")
|
||||||
|
|
||||||
|
set(ENABLE_CLANG_TIDY FALSE CACHE BOOL "Enable clang-tidy checks")
|
||||||
include(GitFunctions)
|
include(GitFunctions)
|
||||||
get_branch_from_git()
|
get_branch_from_git()
|
||||||
|
|
||||||
|
@ -60,6 +61,7 @@ if(ENABLE_COVERAGE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_program(CLANG_TIDY_EXE NAMES "clang-tidy-9")
|
find_program(CLANG_TIDY_EXE NAMES "clang-tidy-9")
|
||||||
|
if(ENABLE_CLANG_TIDY)
|
||||||
if(CLANG_TIDY_EXE)
|
if(CLANG_TIDY_EXE)
|
||||||
message(STATUS "clang-tidy found: ${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.*")
|
set(CLANG_TIDY_CHECKS "-*,modernize-*,-modernize-use-trailing-return-type,clang-analyzer-core.*,clang-analyzer-cplusplus.*")
|
||||||
|
@ -71,6 +73,7 @@ else()
|
||||||
message(AUTHOR_WARNING "clang-tidy not found!")
|
message(AUTHOR_WARNING "clang-tidy not found!")
|
||||||
set(CMAKE_CXX_CLANG_TIDY "" CACHE STRING "" FORCE) # delete it
|
set(CMAKE_CXX_CLANG_TIDY "" CACHE STRING "" FORCE) # delete it
|
||||||
endif()
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
setup_conan()
|
setup_conan()
|
||||||
|
|
||||||
|
|
|
@ -1,45 +0,0 @@
|
||||||
macro(setup_conan)
|
|
||||||
find_program(conan conan PATHS /usr/bin /usr/local/bin)
|
|
||||||
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()
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit ffa9b526d7f64f7233720d139e7202aaba61895c
|
Subproject commit 3192c9cc2169b18ee7e1cd2c9fbb92d04887e7ac
|
|
@ -1,3 +1,3 @@
|
||||||
add_subdirectory(io-redirector)
|
add_subdirectory(io-redirector)
|
||||||
#add_subdirectory(sim_performance)
|
add_subdirectory(sim_performance)
|
||||||
add_subdirectory(ordered_semaphore)
|
add_subdirectory(ordered_semaphore)
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
cmake_minimum_required(VERSION 3.12)
|
cmake_minimum_required(VERSION 3.12)
|
||||||
add_executable (sim_performance
|
add_executable (sim_performance
|
||||||
sc_main.cpp
|
sc_main.cpp
|
||||||
blocks.cpp
|
pkt_sender.cpp
|
||||||
|
pkt_switch.cpp
|
||||||
top.cpp
|
top.cpp
|
||||||
)
|
)
|
||||||
target_link_libraries (sim_performance LINK_PUBLIC scc)
|
target_link_libraries (sim_performance LINK_PUBLIC scc)
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* packet.h
|
||||||
|
*
|
||||||
|
* Created on: 04.05.2020
|
||||||
|
* Author: eyck
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SIM_PERFORMANCE_PACKET_H_
|
||||||
|
#define _SIM_PERFORMANCE_PACKET_H_
|
||||||
|
|
||||||
|
#include <tlm>
|
||||||
|
|
||||||
|
struct packet {
|
||||||
|
std::vector<uint8_t> routing;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct packet_ext: public tlm::tlm_extension<packet_ext>, public packet {
|
||||||
|
|
||||||
|
packet_ext() = default;
|
||||||
|
|
||||||
|
packet_ext& operator=(packet_ext const& o) = default;
|
||||||
|
|
||||||
|
tlm_extension_base* clone() const override {
|
||||||
|
return new packet_ext(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void copy_from(tlm_extension_base const & o) override {
|
||||||
|
auto* ext = dynamic_cast<packet_ext const*>(&o);
|
||||||
|
if(ext)
|
||||||
|
this->routing=ext->routing;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _SIM_PERFORMANCE_PACKET_H_ */
|
|
@ -0,0 +1,99 @@
|
||||||
|
/*
|
||||||
|
* blocks.cpp
|
||||||
|
*
|
||||||
|
* Created on: 04.05.2020
|
||||||
|
* Author: eyck
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "pkt_sender.h"
|
||||||
|
#include "types.h"
|
||||||
|
#include <scc/report.h>
|
||||||
|
#include <tlm/tlm_mm.h>
|
||||||
|
|
||||||
|
using namespace sc_core;
|
||||||
|
|
||||||
|
pkt_sender::pkt_sender(const sc_core::sc_module_name &nm, unsigned dim, unsigned pos_x, unsigned pos_y)
|
||||||
|
: sc_module(nm)
|
||||||
|
, bw_peq("bw_peq")
|
||||||
|
, fw_peq("fw_peq")
|
||||||
|
, my_pos{pos_x,pos_y}
|
||||||
|
, dim{dim}
|
||||||
|
{
|
||||||
|
SCCDEBUG(SCMOD)<<"instantiating sender "<<pos_x<<"/"<<pos_y;
|
||||||
|
SC_HAS_PROCESS(pkt_sender);
|
||||||
|
isck.register_nb_transport_bw([this](tlm::tlm_generic_payload &gp, tlm::tlm_phase &phase, sc_core::sc_time &delay)->tlm::tlm_sync_enum{
|
||||||
|
return this->nb_bw(gp, phase, delay);
|
||||||
|
});
|
||||||
|
tsck.register_nb_transport_fw([this](tlm::tlm_generic_payload &gp, tlm::tlm_phase &phase, sc_core::sc_time &delay)->tlm::tlm_sync_enum{
|
||||||
|
return this->nb_fw(gp, phase, delay);
|
||||||
|
});
|
||||||
|
SC_METHOD(received);
|
||||||
|
sensitive<<fw_peq.get_event();
|
||||||
|
dont_initialize();
|
||||||
|
SC_THREAD(run);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pkt_sender::gen_routing(std::vector<uint8_t> &route_vec) {
|
||||||
|
if(std::get<0>(my_pos)==0){
|
||||||
|
for(auto i=0; i<dim; ++i)
|
||||||
|
route_vec.push_back(RIGHT);
|
||||||
|
} else if(std::get<0>(my_pos)==dim+1){
|
||||||
|
for(auto i=0; i<dim; ++i)
|
||||||
|
route_vec.push_back(LEFT);
|
||||||
|
} else if(std::get<1>(my_pos)==0){
|
||||||
|
for(auto i=0; i<dim; ++i)
|
||||||
|
route_vec.push_back(BOTTOM);
|
||||||
|
} else if(std::get<1>(my_pos)==dim+1){
|
||||||
|
for(auto i=0; i<dim; ++i)
|
||||||
|
route_vec.push_back(TOP);
|
||||||
|
} else
|
||||||
|
SCCERR(SCMOD)<<"WTF!?!";
|
||||||
|
}
|
||||||
|
|
||||||
|
void pkt_sender::run() {
|
||||||
|
wait(clk_i.posedge_event());
|
||||||
|
for(auto i=0U; i<1000; i++){
|
||||||
|
tlm::tlm_generic_payload* gp = tlm::tlm_mm<>::get().allocate<packet_ext>();
|
||||||
|
gen_routing(gp->get_extension<packet_ext>()->routing);
|
||||||
|
tlm::tlm_phase phase{tlm::BEGIN_REQ};
|
||||||
|
sc_time delay;
|
||||||
|
gp->acquire();
|
||||||
|
auto sync = isck->nb_transport_fw(*gp, phase, delay);
|
||||||
|
sc_assert(sync==tlm::TLM_UPDATED && phase==tlm::END_REQ);
|
||||||
|
tlm::tlm_generic_payload* ret{nullptr};
|
||||||
|
while(!(ret=bw_peq.get_next_transaction())){
|
||||||
|
wait(bw_peq.get_event());
|
||||||
|
}
|
||||||
|
sc_assert(gp==ret);
|
||||||
|
ret->release();
|
||||||
|
wait(clk_i.posedge_event());
|
||||||
|
}
|
||||||
|
finish_evt.notify(SC_ZERO_TIME);
|
||||||
|
}
|
||||||
|
|
||||||
|
tlm::tlm_sync_enum pkt_sender::nb_bw(tlm::tlm_generic_payload &gp, tlm::tlm_phase &phase, sc_core::sc_time &delay) {
|
||||||
|
sc_assert(phase==tlm::BEGIN_RESP);
|
||||||
|
bw_peq.notify(gp, delay);
|
||||||
|
phase=tlm::END_RESP;
|
||||||
|
return tlm::TLM_COMPLETED;
|
||||||
|
}
|
||||||
|
|
||||||
|
tlm::tlm_sync_enum pkt_sender::nb_fw(tlm::tlm_generic_payload &gp, tlm::tlm_phase &phase, sc_core::sc_time &delay) {
|
||||||
|
sc_assert(phase==tlm::BEGIN_REQ);
|
||||||
|
auto ext = gp.get_extension<packet_ext>();
|
||||||
|
sc_assert(ext->routing.size()==0);
|
||||||
|
gp.acquire();
|
||||||
|
fw_peq.notify(gp, delay);
|
||||||
|
phase=tlm::END_REQ;
|
||||||
|
return tlm::TLM_UPDATED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pkt_sender::received() {
|
||||||
|
if(auto gp = fw_peq.get_next_transaction()){
|
||||||
|
tlm::tlm_phase phase{tlm::BEGIN_RESP};
|
||||||
|
sc_time delay;
|
||||||
|
auto sync = tsck->nb_transport_bw(*gp, phase, delay);
|
||||||
|
sc_assert(sync==tlm::TLM_COMPLETED && phase==tlm::END_RESP);
|
||||||
|
gp->release();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* blocks.h
|
||||||
|
*
|
||||||
|
* Created on: 04.05.2020
|
||||||
|
* Author: eyck
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SIM_PERFORMANCE_PKT_SENDER_H_
|
||||||
|
#define _SIM_PERFORMANCE_PKT_SENDER_H_
|
||||||
|
|
||||||
|
#include <systemc>
|
||||||
|
#include "packet.h"
|
||||||
|
#include <scc/initiator_mixin.h>
|
||||||
|
#include <scc/target_mixin.h>
|
||||||
|
|
||||||
|
|
||||||
|
class pkt_sender : sc_core::sc_module {
|
||||||
|
public:
|
||||||
|
sc_core::sc_in<bool> clk_i{"clk_i"};
|
||||||
|
scc::initiator_mixin<tlm::tlm_initiator_socket<32>> isck;
|
||||||
|
scc::target_mixin<tlm::tlm_target_socket<32>> tsck;
|
||||||
|
pkt_sender(sc_core::sc_module_name const&, unsigned dim, unsigned pos_x, unsigned pos_y);
|
||||||
|
virtual ~pkt_sender() = default;
|
||||||
|
sc_core::sc_event const& get_finish_event(){return finish_evt;}
|
||||||
|
private:
|
||||||
|
void run();
|
||||||
|
void gen_routing(std::vector<uint8_t>& route_vec);
|
||||||
|
void received();
|
||||||
|
tlm_utils::peq_with_get<tlm::tlm_generic_payload> bw_peq, fw_peq;
|
||||||
|
tlm::tlm_sync_enum nb_fw(tlm::tlm_generic_payload&, tlm::tlm_phase&, sc_core::sc_time&);
|
||||||
|
tlm::tlm_sync_enum nb_bw(tlm::tlm_generic_payload&, tlm::tlm_phase&, sc_core::sc_time&);
|
||||||
|
sc_core::sc_event finish_evt;
|
||||||
|
std::pair<unsigned, unsigned> my_pos;
|
||||||
|
const unsigned dim;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _SIM_PERFORMANCE_PKT_SENDER_H_ */
|
|
@ -0,0 +1,97 @@
|
||||||
|
/*
|
||||||
|
* blocks.cpp
|
||||||
|
*
|
||||||
|
* Created on: 04.05.2020
|
||||||
|
* Author: eyck
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SC_INCLUDE_DYNAMIC_PROCESSES // needed for sc_spawn
|
||||||
|
#define SC_INCLUDE_DYNAMIC_PROCESSES
|
||||||
|
#endif
|
||||||
|
#include "pkt_switch.h"
|
||||||
|
#include "types.h"
|
||||||
|
#include <tlm/tlm_mm.h>
|
||||||
|
#include <scc/report.h>
|
||||||
|
|
||||||
|
using namespace sc_core;
|
||||||
|
|
||||||
|
pkt_switch::pkt_switch(const sc_core::sc_module_name &nm):sc_module(nm) {
|
||||||
|
SC_HAS_PROCESS(pkt_switch);
|
||||||
|
auto index = 0U;
|
||||||
|
for(auto& s:isck){
|
||||||
|
s.register_nb_transport_bw([this](unsigned id, tlm::tlm_generic_payload &gp, tlm::tlm_phase &phase, sc_core::sc_time &delay)->tlm::tlm_sync_enum{
|
||||||
|
return this->nb_bw(id, gp, phase, delay);
|
||||||
|
}, index++);
|
||||||
|
}
|
||||||
|
index = 0U;
|
||||||
|
for(auto& s:tsck){
|
||||||
|
s.register_nb_transport_fw([this](unsigned id, tlm::tlm_generic_payload &gp, tlm::tlm_phase &phase, sc_core::sc_time &delay)->tlm::tlm_sync_enum{
|
||||||
|
return this->nb_fw(id, gp, phase, delay);
|
||||||
|
}, index++);
|
||||||
|
}
|
||||||
|
SC_METHOD(clock_cb);
|
||||||
|
sensitive<<clk_i.pos();
|
||||||
|
dont_initialize();
|
||||||
|
for(auto i=0U; i<SIDES; ++i){
|
||||||
|
sc_core::sc_spawn_options opts;
|
||||||
|
opts.spawn_method();
|
||||||
|
opts.set_sensitivity(&out_fifo[i].data_written_event());
|
||||||
|
sc_core::sc_spawn([this, i]()->void {this->output_cb(i);}, sc_core::sc_gen_unique_name("out_peq"), &opts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tlm::tlm_sync_enum pkt_switch::nb_fw(unsigned id, tlm::tlm_generic_payload &gp, tlm::tlm_phase &phase, sc_core::sc_time &delay) {
|
||||||
|
in_tx[id].write(&gp);
|
||||||
|
if(phase==tlm::BEGIN_REQ) phase=tlm::END_REQ;
|
||||||
|
else SCCERR(SCMOD)<<"WTF!?!";
|
||||||
|
return tlm::TLM_UPDATED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pkt_switch::clock_cb() {
|
||||||
|
std::array<std::vector<unsigned>, SIDES> routing{};
|
||||||
|
bool nothing_todo=true;
|
||||||
|
for(auto i=0U; i<SIDES; ++i){
|
||||||
|
if(auto gp = in_tx[i].read()){
|
||||||
|
auto ext = gp->get_extension<packet_ext>();
|
||||||
|
sc_assert(ext);
|
||||||
|
routing[ext->routing.back()].push_back(i);
|
||||||
|
nothing_todo = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(nothing_todo) return;
|
||||||
|
for(auto i=0U; i<SIDES; ++i){
|
||||||
|
if(routing[i].size()){
|
||||||
|
auto selected_input=routing[i].front();
|
||||||
|
auto* gp = in_tx[selected_input].read();
|
||||||
|
if(out_fifo[i].nb_write(gp)){
|
||||||
|
auto ext = gp->get_extension<packet_ext>();
|
||||||
|
ext->routing.pop_back();
|
||||||
|
gp->acquire();
|
||||||
|
tlm::tlm_phase phase{tlm::BEGIN_RESP};
|
||||||
|
sc_core::sc_time delay;
|
||||||
|
auto res = tsck[selected_input]->nb_transport_bw(*gp, phase, delay);
|
||||||
|
if(res!=tlm::TLM_COMPLETED && !(res==tlm::TLM_UPDATED && phase==tlm::END_RESP))
|
||||||
|
SCCERR(SCMOD)<<"WTF!?!";
|
||||||
|
in_tx[selected_input].clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void pkt_switch::output_cb(unsigned id) {
|
||||||
|
|
||||||
|
if(out_fifo[id].num_available()){
|
||||||
|
auto* gp = out_fifo[id].read();
|
||||||
|
tlm::tlm_phase phase{tlm::BEGIN_REQ};
|
||||||
|
sc_time delay;
|
||||||
|
auto sync = isck[id]->nb_transport_fw(*gp, phase, delay);
|
||||||
|
sc_assert(sync==tlm::TLM_UPDATED && phase==tlm::END_REQ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tlm::tlm_sync_enum pkt_switch::nb_bw(unsigned id, tlm::tlm_generic_payload &gp, tlm::tlm_phase &phase, sc_core::sc_time &delay) {
|
||||||
|
gp.release();
|
||||||
|
sc_assert(phase==tlm::BEGIN_RESP);
|
||||||
|
phase=tlm::END_RESP;
|
||||||
|
return tlm::TLM_COMPLETED;
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* blocks.h
|
||||||
|
*
|
||||||
|
* Created on: 04.05.2020
|
||||||
|
* Author: eyck
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SIM_PERFORMANCE_PKT_SWITCH_H_
|
||||||
|
#define _SIM_PERFORMANCE_PKT_SWITCH_H_
|
||||||
|
|
||||||
|
#include <systemc>
|
||||||
|
#include "packet.h"
|
||||||
|
#include <scc/tagged_initiator_mixin.h>
|
||||||
|
#include <scc/tagged_target_mixin.h>
|
||||||
|
#include <scc/sc_owning_signal.h>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
|
||||||
|
class pkt_switch : sc_core::sc_module {
|
||||||
|
public:
|
||||||
|
enum {NONE=std::numeric_limits<unsigned>::max()};
|
||||||
|
sc_core::sc_in<bool> clk_i{"clk_i"};
|
||||||
|
sc_core::sc_vector<scc::tagged_target_mixin<tlm::tlm_target_socket<32>>> tsck{"tsck",4};
|
||||||
|
sc_core::sc_vector<scc::tagged_initiator_mixin<tlm::tlm_initiator_socket<32>>> isck{"isck",4};
|
||||||
|
pkt_switch(sc_core::sc_module_name const&);
|
||||||
|
virtual ~pkt_switch() = default;
|
||||||
|
private:
|
||||||
|
void clock_cb();
|
||||||
|
void output_cb(unsigned);
|
||||||
|
tlm::tlm_sync_enum nb_fw(unsigned, tlm::tlm_generic_payload&, tlm::tlm_phase&, sc_core::sc_time&);
|
||||||
|
tlm::tlm_sync_enum nb_bw(unsigned, tlm::tlm_generic_payload&, tlm::tlm_phase&, sc_core::sc_time&);
|
||||||
|
sc_core::sc_vector<scc::sc_owning_signal<tlm::tlm_generic_payload>> in_tx{"in_sig", 4};
|
||||||
|
sc_core::sc_vector<sc_core::sc_fifo<tlm::tlm_generic_payload*>> out_fifo{"out_peq", 4};
|
||||||
|
std::array<unsigned, 4> last_sel_inp{NONE, NONE, NONE, NONE};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _SIM_PERFORMANCE_PKT_SWITCH_H_ */
|
|
@ -0,0 +1,102 @@
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Copyright 2017 eyck@minres.com
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/*
|
||||||
|
* sc_main.cpp
|
||||||
|
*
|
||||||
|
* Created on: 17.09.2017
|
||||||
|
* Author: eyck@minres.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "top.h"
|
||||||
|
#include <scc/perf_estimator.h>
|
||||||
|
#include <scc/report.h>
|
||||||
|
#include <scc/scv_tr_db.h>
|
||||||
|
#include <scc/tracer.h>
|
||||||
|
#include <boost/program_options.hpp>
|
||||||
|
|
||||||
|
using namespace scc;
|
||||||
|
namespace po = boost::program_options;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
const size_t ERROR_IN_COMMAND_LINE = 1;
|
||||||
|
const size_t SUCCESS = 0;
|
||||||
|
const size_t ERROR_UNHANDLED_EXCEPTION = 2;
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
int sc_main(int argc, char *argv[]) {
|
||||||
|
sc_core::sc_report_handler::set_actions( "/IEEE_Std_1666/deprecated", sc_core::SC_DO_NOTHING );
|
||||||
|
sc_core::sc_report_handler::set_actions(sc_core::SC_ID_MORE_THAN_ONE_SIGNAL_DRIVER_, sc_core::SC_DO_NOTHING);
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// CLI argument parsing
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
po::options_description desc("Options");
|
||||||
|
// clang-format off
|
||||||
|
desc.add_options()
|
||||||
|
("help,h", "Print help message")
|
||||||
|
("debug,d", "set debug level")
|
||||||
|
("trace,t", "trace SystemC signals");
|
||||||
|
// clang-format on
|
||||||
|
po::variables_map vm;
|
||||||
|
try {
|
||||||
|
po::store(po::parse_command_line(argc, argv, desc), vm); // can throw
|
||||||
|
// --help option
|
||||||
|
if (vm.count("help")) {
|
||||||
|
std::cout << "JIT-ISS simulator for AVR" << std::endl << desc << std::endl;
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
po::notify(vm); // throws on error, so do after help in case
|
||||||
|
// there are any problems
|
||||||
|
} catch (po::error &e) {
|
||||||
|
std::cerr << "ERROR: " << e.what() << std::endl << std::endl;
|
||||||
|
std::cerr << desc << std::endl;
|
||||||
|
return ERROR_IN_COMMAND_LINE;
|
||||||
|
}
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// configure logging
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
scc::init_logging(vm.count("debug")?scc::log::DEBUG:scc::log::INFO);
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// set up tracing & transaction recording
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
//tracer trace("simple_system", tracer::TEXT, vm.count("trace"));
|
||||||
|
// todo: fix displayed clock period in VCD
|
||||||
|
try {
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// instantiate top level
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
perf_estimator estimator;
|
||||||
|
top i_top("i_top", 89);
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// run simulation
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
sc_start(sc_core::sc_time(1, sc_core::SC_MS));
|
||||||
|
if(sc_is_running()) {
|
||||||
|
SCCERR() << "simulation timed out"; // calls sc_stop
|
||||||
|
sc_core::sc_stop();
|
||||||
|
}
|
||||||
|
} catch(sc_report& e) {
|
||||||
|
SCCERR() << "Caught sc_report exception during simulation: " << e.what() << ":" << e.get_msg();
|
||||||
|
} catch(std::exception& e) {
|
||||||
|
SCCERR() << "Caught exception during simulation: " << e.what();
|
||||||
|
} catch(...) {
|
||||||
|
SCCERR() << "Caught unspecified exception during simulation";
|
||||||
|
}
|
||||||
|
auto errcnt = sc_report_handler::get_count(SC_ERROR);
|
||||||
|
auto warncnt = sc_report_handler::get_count(SC_WARNING);
|
||||||
|
SCCINFO() << "simulation finished, " << errcnt << " error" << (errcnt == 1 ? "" : "s") << " and " << warncnt << " warning"
|
||||||
|
<< (warncnt == 1 ? "" : "s");
|
||||||
|
return errcnt + warncnt;
|
||||||
|
}
|
|
@ -0,0 +1,96 @@
|
||||||
|
/*
|
||||||
|
* top.cpp
|
||||||
|
*
|
||||||
|
* Created on: 04.05.2020
|
||||||
|
* Author: eyck
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "top.h"
|
||||||
|
#include <scc/utilities.h>
|
||||||
|
#include <scc/report.h>
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
using namespace sc_core;
|
||||||
|
using namespace fmt;
|
||||||
|
|
||||||
|
top::top(sc_core::sc_module_name const& nm, unsigned dimension) :sc_module(nm){
|
||||||
|
sc_assert(dimension>0);
|
||||||
|
SC_HAS_PROCESS(top);
|
||||||
|
for(auto yidx=0U; yidx<dimension; ++yidx){
|
||||||
|
for(auto xidx=0U; xidx<dimension; ++xidx){
|
||||||
|
auto name = format("sw_{}_{}", xidx, yidx);
|
||||||
|
SCCDEBUG(SCMOD)<<"instantiating switch "<<xidx<<"/"<<yidx;
|
||||||
|
switches.push_back(scc::make_unique<pkt_switch>(sc_module_name(name.c_str())));
|
||||||
|
switches.back()->clk_i(clk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(auto yidx=0U; yidx<dimension; ++yidx){
|
||||||
|
for(auto xidx=0U; xidx<dimension; ++xidx){
|
||||||
|
auto& sw = switches[yidx*dimension+xidx];
|
||||||
|
if(xidx<dimension-1) {
|
||||||
|
auto& swr = switches[yidx*dimension+(xidx+1)];
|
||||||
|
sw->isck[RIGHT](swr->tsck[LEFT]);
|
||||||
|
swr->isck[LEFT](sw->tsck[RIGHT]);
|
||||||
|
}
|
||||||
|
if(yidx<dimension-1){
|
||||||
|
auto& swb = switches[(yidx+1)*dimension+xidx];
|
||||||
|
sw->isck[BOTTOM](swb->tsck[TOP]);
|
||||||
|
swb->isck[TOP](sw->tsck[BOTTOM]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto yidx = 0U;
|
||||||
|
auto xidx = 0U;
|
||||||
|
for(xidx=0U; xidx<dimension; ++xidx){
|
||||||
|
auto name = format("snd_{}_{}", xidx+1, 0);
|
||||||
|
senders[TOP].push_back(scc::make_unique<pkt_sender>(sc_module_name(name.c_str()), dimension, xidx+1, 0));
|
||||||
|
auto& snd = senders[TOP].back();
|
||||||
|
snd->clk_i(clk);
|
||||||
|
auto& sw = switches[yidx*dimension+xidx];
|
||||||
|
snd->isck(sw->tsck[TOP]);
|
||||||
|
sw->isck[TOP](snd->tsck);
|
||||||
|
}
|
||||||
|
yidx=dimension-1;
|
||||||
|
for(xidx=0U; xidx<dimension; ++xidx){
|
||||||
|
auto name = format("snd_{}_{}", xidx+1, dimension+1);
|
||||||
|
senders[BOTTOM].push_back(scc::make_unique<pkt_sender>(sc_module_name(name.c_str()), dimension, xidx+1, dimension+1));
|
||||||
|
auto& snd = senders[BOTTOM].back();
|
||||||
|
snd->clk_i(clk);
|
||||||
|
auto& sw = switches[yidx*dimension+xidx];
|
||||||
|
snd->isck(sw->tsck[BOTTOM]);
|
||||||
|
sw->isck[BOTTOM](snd->tsck);
|
||||||
|
}
|
||||||
|
xidx=0U;
|
||||||
|
for(yidx=0U; yidx<dimension; ++yidx){
|
||||||
|
auto name = format("snd_{}_{}", 0, yidx+1);
|
||||||
|
senders[LEFT].push_back(scc::make_unique<pkt_sender>(sc_module_name(name.c_str()), dimension, 0, yidx+1));
|
||||||
|
auto& snd = senders[LEFT].back();
|
||||||
|
snd->clk_i(clk);
|
||||||
|
auto& sw = switches[yidx*dimension+xidx];
|
||||||
|
snd->isck(sw->tsck[LEFT]);
|
||||||
|
sw->isck[LEFT](snd->tsck);
|
||||||
|
}
|
||||||
|
xidx=dimension-1;
|
||||||
|
for(yidx=0U; yidx<dimension; ++yidx){
|
||||||
|
auto name = format("snd_{}_{}", dimension+1, yidx+1);
|
||||||
|
senders[RIGHT].push_back(scc::make_unique<pkt_sender>(sc_module_name(name.c_str()), dimension, dimension+1, yidx+1));
|
||||||
|
auto& snd = senders[RIGHT].back();
|
||||||
|
snd->clk_i(clk);
|
||||||
|
auto& sw = switches[yidx*dimension+xidx];
|
||||||
|
snd->isck(sw->tsck[RIGHT]);
|
||||||
|
sw->isck[RIGHT](snd->tsck);
|
||||||
|
}
|
||||||
|
SC_THREAD(run);
|
||||||
|
}
|
||||||
|
|
||||||
|
void top::run() {
|
||||||
|
sc_event_and_list evt_list;
|
||||||
|
for(auto& sides:senders) {
|
||||||
|
for(auto& sender:sides){
|
||||||
|
evt_list&=sender->get_finish_event();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wait(evt_list);
|
||||||
|
sc_stop();
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* top.h
|
||||||
|
*
|
||||||
|
* Created on: 04.05.2020
|
||||||
|
* Author: eyck
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SIM_PERFORMANCE_TOP_H_
|
||||||
|
#define _SIM_PERFORMANCE_TOP_H_
|
||||||
|
|
||||||
|
#include <systemc>
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
#include "pkt_sender.h"
|
||||||
|
#include "pkt_switch.h"
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
class top: public sc_core::sc_module {
|
||||||
|
public:
|
||||||
|
top(sc_core::sc_module_name const&, unsigned);
|
||||||
|
virtual ~top() = default;
|
||||||
|
private:
|
||||||
|
void run();
|
||||||
|
sc_core::sc_clock clk;
|
||||||
|
std::array<std::vector<std::unique_ptr<pkt_sender>>, SIDES> senders;
|
||||||
|
std::vector<std::unique_ptr<pkt_switch>> switches;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* TESTS_SIM_PERFORMANCE_TOP_H_ */
|
|
@ -0,0 +1,13 @@
|
||||||
|
/*
|
||||||
|
* types.h
|
||||||
|
*
|
||||||
|
* Created on: 12.07.2020
|
||||||
|
* Author: eyck
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TESTS_SIM_PERFORMANCE_TYPES_H_
|
||||||
|
#define TESTS_SIM_PERFORMANCE_TYPES_H_
|
||||||
|
|
||||||
|
enum {TOP=0, RIGHT=1, BOTTOM=2, LEFT=3, SIDES=4};
|
||||||
|
|
||||||
|
#endif /* TESTS_SIM_PERFORMANCE_TYPES_H_ */
|
Loading…
Reference in New Issue