Commit 72725bda authored by Ralf Stemmer's avatar Ralf Stemmer

First public release

parent 18308e2c
*.o
*~
model
How To Build
============
1. Setup
--------
Open build.sh and check if the path to the SystemC installation is valid.
I have installed SystemC in /opt/systemc - If your path is different, just change the path in the HEADER and LIBS variables accordingly.
I also use the LLVM C++ Compler clang++. When you want to use the GCC C++ compiler, just replace clang++ by g++.
2. Compile
----------
Just execute the build.sh script.
It compiles all cpp-files in this directroy and sub directories.
Then the objectfiles get linked to a binary called model.
Save simulated iteration delays
Optional parameters:
-i (--iterations): Limit the amount of iterations that get simulated. Default is 1 million.
-s (--skip): Skip n iterations.
./model -i 1000 -s 20000 # Simulate iteration 1000 .. 2000
./model > results.txt # save results in a text file
File added
/*
* sobel_filter.h
*
* Created on: 10.12.2015
* Author: Christof Schlaak
* Refactored: Ralf Stemmer on 16.05.2018
*/
#ifndef SOBEL_FILTER_H_
#define SOBEL_FILTER_H_
#include <sdf.h>
void GetPixel(token_t tokensOut[]);
void GX(token_t tokensIn[], token_t tokensOut[]);
void GY(token_t tokensIn[], token_t tokensOut[]);
token_t ABS(token_t tokensIn1[], token_t tokensIn2[]);
#endif /* SOBEL_FILTER_H_ */
#!/usr/bin/env bash
Instances=20
Experiment=jpeg3
TotalSamples=1000000
ExperimentDirectory=./results/${Host}/${Experiment}
Host="$(hostname)"
SamplesPerInstance=$(( TotalSamples / Instances))
echo "Samples Per Instance: $SamplesPerInstance"
mkdir -p $ExperimentDirectory
date | tee $ExperimentDirectory/begin.txt
for i in $(seq 0 $(( Instances - 1 ))) ; do
Offset=$(( SamplesPerInstance * i ))
ResultPath=$ExperimentDirectory/$(printf "%02d" $i).txt
./$Experiment --iterations $SamplesPerInstance --skip $Offset 2> /dev/null > $ResultPath &
done
# Wait until all processes finish
wait
date | tee $ExperimentDirectory/end.txt
# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
#!/usr/bin/env bash
#source ../scripts/settings.sh
SOURCEPATH="../PlatformV2/lib/src/sobel"
INSTALLPATH="./apps/"
BUILDPATH="./build-sobel"
INCLUDEPATHS="-I$SOURCEPATH -I./"
SHARED_CFLAGS="-O0 -c"
GCC=gcc
AR=ar
# 1st argument: libname "jpeg-ef" for example
# 2nd argument: CFLAGS
function Build
{
LIBNAME="$1"
CFLAGS="$2"
SOURCES=$(find $SOURCEPATH -type f -name "*.c")
for s in $SOURCES ;
do
echo -e -n "\e[1;34m - $s\e[0m "
FILENAME="${s##*/}"
OBJFILE="${FILENAME%.*}.o"
$GCC $CFLAGS $INCLUDEPATHS -I$SOURCEPATH -c -o "$BUILDPATH/$OBJFILE" $s
if [ $? -ne 0 ] ; then
echo -e "\e[1;31m$GCC FAILED!\e[0m"
exit 1
else
echo -e "\e[1;32m✔\e[0m"
fi
done
$AR rv $INSTALLPATH/lib${LIBNAME}.a $BUILDPATH/*.o
rm $BUILDPATH/*.o
}
# Build Libraries
mkdir -p $BUILDPATH
rm $INSTALLPATH/libsobel.a
Build sobel $SHARED_CFLAGS
cp $SOURCEPATH/*.h $INSTALLPATH/.
# Make Clean
rmdir $BUILDPATH
#!/usr/bin/env bash
SOURCE=$(find . -type f -name "*.cpp")
SYSTEMC="/opt/systemc"
APPS="./apps"
HEADER="-I. -I$SYSTEMC/include -I$APPS"
LIBS="-L$SYSTEMC/lib-linux64 -lsystemc $(pkg-config --libs gsl) -L$APPS -lsobel"
CPP="clang++"
CPPFLAGS="-g3 -O0 -std=c++14"
for c in $SOURCE ;
do
echo -e "\e[1;34mCompiling $c\e[0m"
$CPP $HEADER $CPPFLAGS -c -o "${c%.*}.o" $c
done
OBJECTS=$(find . -type f -name "*.o")
$CPP -o model $OBJECTS $LIBS
rm $OBJECTS
# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
#include <bus.hpp>
#include <iostream>
Bus& Bus::operator<< (Tile& tile)
{
tile.initiator_socket(this->target_socket);
return *this;
}
Bus& Bus::operator<< (SharedMemory& sharedmemory)
{
this->initiator_socket(sharedmemory.target_socket);
sc_dt::uint64 address = sharedmemory.GetAddress();
unsigned int size = sharedmemory.GetSize();
this->starts.push_back(address);
this->ends.push_back(address + size);
return *this;
}
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
#ifndef BUS_HPP
#define BUS_HPP
#include <core/bus.hpp>
#include <tile.hpp>
#include <sharedmemory.hpp>
class Bus
: public core::Bus
{
public:
Bus(const char* name)
: core::Bus(name) {};
Bus& operator<< (Tile& tile);
Bus& operator<< (SharedMemory& sharedmemory);
};
#endif
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
#ifndef CHANNEL_HPP
#define CHANNEL_HPP
#include <sdf.h>
#define BYTES_PER_TOKEN 4
struct Channel
{
Channel(const char* name, unsigned int prate, unsigned int crate, unsigned int size)
: name(name)
, usageaddress(0)
, indexaddress(0)
, fifoaddress(0)
, producerate(prate)
, consumerate(crate)
, fifosize(size)
{
};
const char* name;
unsigned long long usageaddress; // Virtual address
unsigned long long indexaddress; // Virtual address - index of the first token in the FIFO
unsigned long long fifoaddress; // Virtual address
unsigned int producerate;
unsigned int consumerate;
unsigned int fifosize; // in tokens
};
#endif
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
#include <core/bus.hpp>
#include <iostream>
namespace core
{
Bus::Bus(sc_core::sc_module_name name)
: sc_core::sc_module(name)
, target_socket("target_bus_socket")
, initiator_socket("initiator_bus_socket")
{
this->target_socket.register_b_transport(this, &Bus::b_transport);
}
// generates slave address spaces - 0x10 per slave
void Bus::end_of_elaboration()
{
size_t slaves = this->initiator_socket.size();
for(unsigned int i = 0; i < slaves; i++)
{
std::cerr << "Slave connected to Bus: " << i << ": " << this->starts[i] << " - " << this->ends[i] << std::endl;
}
size_t masters = this->target_socket.size();
}
void Bus::b_transport(int id, tlm::tlm_generic_payload& trans, sc_core::sc_time& delay)
{
sc_dt::uint64 global_addr = trans.get_address();
int slaveid = this->AddressToSlaveID(global_addr);
if(slaveid < 0)
{
trans.set_response_status(tlm::TLM_ADDRESS_ERROR_RESPONSE);
std::cerr << "\e[1;31m" << this->name() << ": " << "\e[1;31mInvalid address " << global_addr << std::endl;
return;
}
sc_dt::uint64 slave_addr = global_addr - this->starts[slaveid];
trans.set_address(slave_addr);
this->initiator_socket[slaveid]->b_transport(trans, delay);
trans.set_address(global_addr);
}
int Bus::AddressToSlaveID(unsigned int addr)
{
for(unsigned int i = 0; i < this->starts.size(); i++)
{
if( (addr >= this->starts[i]) && (addr <= this->ends[i]))
return i;
}
return -1;
}
} // namespace core
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
#ifndef CORE_BUS_HPP
#define CORE_BUS_HPP
#include <vector>
#define SC_INCLUDE_DYNAMIC_PROCESS
#include <systemc>
#include <tlm_utils/multi_passthrough_target_socket.h>
#include <tlm_utils/multi_passthrough_initiator_socket.h>
#include <tlm.h>
namespace core
{
class Bus
: public sc_core::sc_module
{
public:
tlm_utils::multi_passthrough_initiator_socket<Bus> initiator_socket;
tlm_utils::multi_passthrough_target_socket<Bus> target_socket;
Bus(sc_core::sc_module_name name);
~Bus(){};
protected:
std::vector<sc_dt::uint64> starts;
std::vector<sc_dt::uint64> ends;
private:
virtual void b_transport(int id, tlm::tlm_generic_payload& trans, sc_core::sc_time& delay);
virtual void end_of_elaboration();
// Address mapping
int AddressToSlaveID(unsigned int addr);
};
} // namespace core
#endif
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
#include <core/master.hpp>
#include <iostream>
namespace core
{
Master::Master(sc_core::sc_module_name name)
: sc_core::sc_module(name)
, initiator_socket("socket")
{
std::cerr << "\e[1;30mMaster constructor called for \033[0m" << this->name() << std::endl;
this->initiator_socket.bind(*this);
SC_THREAD(Execute);
}
const int BYTES_PER_WORD = 4;
int Master::WriteWord(sc_dt::uint64 addr, unsigned int* word)
{
tlm::tlm_generic_payload pl;
pl.set_byte_enable_ptr(NULL);
pl.set_byte_enable_length(0);
pl.set_dmi_allowed(false);
pl.set_data_length(BYTES_PER_WORD);
pl.set_streaming_width(BYTES_PER_WORD);
pl.set_data_ptr(reinterpret_cast< unsigned char* >(word));
pl.set_address(addr);
pl.set_command(tlm::TLM_WRITE_COMMAND);
pl.set_response_status(tlm::TLM_INCOMPLETE_RESPONSE);
sc_core::sc_time nodelay = sc_core::SC_ZERO_TIME;
initiator_socket->b_transport(pl, nodelay);
if(pl.get_response_status() != tlm::TLM_OK_RESPONSE)
{
std::cerr << "\e[1;37m" << this->name() << " \033[1;36mwrite"
<< "\033[1;31m failed"
<< "\033[1;37m at " << sc_core::sc_time_stamp()
<< std::endl;
}
return 0;
}
int Master::ReadWord(sc_dt::uint64 addr, unsigned int* word)
{
tlm::tlm_generic_payload pl;
pl.set_byte_enable_ptr(NULL);
pl.set_byte_enable_length(0);
pl.set_dmi_allowed(false);
pl.set_data_length(BYTES_PER_WORD);
pl.set_streaming_width(BYTES_PER_WORD);
pl.set_data_ptr(reinterpret_cast< unsigned char* >(word));
pl.set_address(addr);
pl.set_command(tlm::TLM_READ_COMMAND);
pl.set_response_status(tlm::TLM_INCOMPLETE_RESPONSE);
sc_core::sc_time nodelay = sc_core::SC_ZERO_TIME;
initiator_socket->b_transport(pl, nodelay);
if(pl.get_response_status() != tlm::TLM_OK_RESPONSE)
{
std::cerr << "\e[1;37m" << this->name() << " \033[1;36mread"
<< "\033[1;31m failed"
<< "\033[1;37m at " << sc_core::sc_time_stamp()
<< std::endl;
}
return 0;
}
tlm::tlm_sync_enum Master::nb_transport_bw(tlm::tlm_generic_payload&, tlm::tlm_phase&, sc_core::sc_time& )
{
std::cerr << "\e[0;33minvalidate_direct_mem_ptr called" << std::endl;
return tlm::TLM_COMPLETED;
}
void Master::invalidate_direct_mem_ptr(sc_dt::uint64, sc_dt::uint64 )
{
std::cerr << "\e[0;33minvalidate_direct_mem_ptr called" << std::endl;
}
} // namespace core
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
#ifndef MASTER_HPP
#define MASTER_HPP
#include <systemc>
#include <tlm.h>
namespace core
{
class Master
: public sc_core::sc_module
, protected tlm::tlm_bw_transport_if<>
{
public:
SC_HAS_PROCESS(Master);
Master(sc_core::sc_module_name);
~Master(){};
tlm::tlm_initiator_socket<> initiator_socket;
protected:
virtual void Execute() = 0;
int WriteWord(sc_dt::uint64 addr, unsigned int* word);
int ReadWord( sc_dt::uint64 addr, unsigned int* word);
private:
virtual tlm::tlm_sync_enum nb_transport_bw(tlm::tlm_generic_payload&, tlm::tlm_phase&, sc_core::sc_time&);
virtual void invalidate_direct_mem_ptr(sc_dt::uint64, sc_dt::uint64);
};
}
#endif
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
#include <core/slave.hpp>
#include <iostream>
namespace core
{
Memory::Memory(sc_core::sc_module_name name, size_t size, sc_core::sc_time& readdelay, sc_core::sc_time& writedelay)
: sc_core::sc_module(name)
, target_socket("target_socket")
, memory(size, 0)
, readdelay(readdelay)
, writedelay(writedelay)
{
std::cerr << "\e[1;30mMemory constructor called for \033[0m" << this->name() << std::endl;
this->target_socket.bind(*this);
}
int Memory::CheckIndex(int index)
{
if(index >= this->memory.size() or index < 0)
return -1;
return 0;
}
void Memory::b_transport(tlm::tlm_generic_payload& trans, sc_core::sc_time& delay)
{
sc_dt::uint64 index = trans.get_address();
unsigned int data_length = trans.get_data_length();
unsigned int width = trans.get_streaming_width();
unsigned int* data = reinterpret_cast< unsigned int* >(trans.get_data_ptr());
// check for valid payload attributes
if(this->CheckIndex(index) != 0)
{
std::cerr << "\e[1;31m" << this->name() << ": " << "\e[1;31mInvalid address "
<< index << std::endl;
trans.set_response_status(tlm::TLM_ADDRESS_ERROR_RESPONSE);
return;
}
else if(trans.get_byte_enable_ptr() != NULL)
{
std::cerr << "\e[1;31m" << this->name() << ": " << "\e[1;31mInvalid trans.get_byte_enable_ptr value!" << std::endl;
trans.set_response_status(tlm::TLM_BYTE_ENABLE_ERROR_RESPONSE);
return;
}
else if(width != 4)
{
std::cerr << "\e[1;31m" << this->name() << ": " << "\e[1;31mInvalid streaming_width! Must always be 4" << std::endl;
trans.set_response_status(tlm::TLM_BURST_ERROR_RESPONSE);
return;
}
else if(data_length != 4)
{
std::cerr << "\e[1;31m" << this->name() << ": " << "\e[1;31mInvalid data_length! Must always be 4" << std::endl;
trans.set_response_status(tlm::TLM_BURST_ERROR_RESPONSE);
return;
}
switch(trans.get_command())
{
case tlm::TLM_WRITE_COMMAND:
this->memory[index] = *data;
sc_core::wait(this->writedelay);
break;
case tlm::TLM_READ_COMMAND:
*data = this->memory[index];
sc_core::wait(this->readdelay);
break;
case tlm::TLM_IGNORE_COMMAND:
default:
std::cerr << "\e[1;31m" << this->name() << ": " << "\e[1;31mInvalid command!" << std::endl;
break;
}
trans.set_response_status(tlm::TLM_OK_RESPONSE);
}
tlm::tlm_sync_enum Memory::nb_transport_fw(tlm::tlm_generic_payload&, tlm::tlm_phase&, sc_core::sc_time&)
{
std::cerr << "\e[0;33mnb_transport_fw called" << std::endl;
return tlm::TLM_COMPLETED;
}
bool Memory::get_direct_mem_ptr(tlm::tlm_generic_payload&, tlm::tlm_dmi&)
{
std::cerr << "\e[0;33mget_direct_mem_ptr called" << std::endl;
return false;
}
unsigned int Memory::transport_dbg(tlm::tlm_generic_payload&)
{
std::cerr << "\e[0;33mtransport_dbg called" << std::endl;
return 0;
}
} // namespace core
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
#ifndef SLAVE_HPP
#define SLAVE_HPP
#define SC_INCLUDE_DYNAMIC_PROCESSES
#include <systemc>
#include <tlm.h>
#include <vector>
namespace core
{
class Memory
: public sc_core::sc_module
, protected tlm::tlm_fw_transport_if<>
{
public:
tlm::tlm_target_socket<> target_socket;
Memory(sc_core::sc_module_name name, size_t size, sc_core::sc_time& readdelay, sc_core::sc_time& writedelay);
~Memory(){};
private:
int CheckIndex(int index);
virtual void b_transport(tlm::tlm_generic_payload& trans, sc_core::sc_time& delay);
std::vector<unsigned long> memory;
sc_core::sc_time readdelay;
sc_core::sc_time writedelay;
virtual tlm::tlm_sync_enum nb_transport_fw(tlm::tlm_generic_payload&, tlm::tlm_phase&, sc_core::sc_time&);
virtual bool get_direct_mem_ptr(tlm::tlm_generic_payload&, tlm::tlm_dmi&);
virtual unsigned int transport_dbg(tlm::tlm_generic_payload&);
};
} // namespace core
#endif
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
#include <delayvector.hpp>
#include <cstdlib>
#include <iostream>
#include <gsl/gsl_randist.h>
#include <gsl/gsl_statistics_double.h>
DelayVector::DelayVector(const char *path, DISTRIBUTION distribution)
: delayindex(0)
, rng(NULL)
, distribution(distribution)
{
this->ReadDelayVector(path);
this->rng = gsl_rng_alloc(gsl_rng_default);
// By default, the random number generator gets seeded with 0
// This shall not be changed to get reproducible results
}
DelayVector::DelayVector(std::string path, DISTRIBUTION distribution)
: delayindex(0)
, rng(NULL)
, distribution(distribution)
{
this->ReadDelayVector(path.c_str());
this->rng = gsl_rng_alloc(gsl_rng_default);
// By default, the random number generator gets seeded with 0
// This shall not be changed to get reproducible results