add test case focusing on simulation kernel performance

This commit is contained in:
Eyck Jentzsch 2020-07-14 10:49:06 +02:00
parent 954bbed352
commit 61c33fdcc3
14 changed files with 552 additions and 49 deletions

View File

@ -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(ENABLE_CLANG_TIDY FALSE CACHE BOOL "Enable clang-tidy checks")
include(GitFunctions)
get_branch_from_git()
@ -60,6 +61,7 @@ if(ENABLE_COVERAGE)
endif()
find_program(CLANG_TIDY_EXE NAMES "clang-tidy-9")
if(ENABLE_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.*")
@ -71,6 +73,7 @@ else()
message(AUTHOR_WARNING "clang-tidy not found!")
set(CMAKE_CXX_CLANG_TIDY "" CACHE STRING "" FORCE) # delete it
endif()
endif()
setup_conan()

View File

@ -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

View File

@ -1,3 +1,3 @@
add_subdirectory(io-redirector)
#add_subdirectory(sim_performance)
add_subdirectory(sim_performance)
add_subdirectory(ordered_semaphore)

View File

@ -1,7 +1,8 @@
cmake_minimum_required(VERSION 3.12)
add_executable (sim_performance
sc_main.cpp
blocks.cpp
pkt_sender.cpp
pkt_switch.cpp
top.cpp
)
target_link_libraries (sim_performance LINK_PUBLIC scc)

View File

@ -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_ */

View File

@ -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();
}
}

View File

@ -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_ */

View File

@ -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;
}

View File

@ -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_ */

View File

@ -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;
}

View File

@ -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();
}

View File

@ -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_ */

View File

@ -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_ */