Commit c5ab05ac authored by phlo's avatar phlo

added MMap prototype

parent 4e7fd88b
......@@ -37,6 +37,7 @@ SRC = boolector.cc \
encoder_smtlib_functional.cc \
encoder_smtlib_relational.cc \
instruction.cc \
mmap.cc \
program.cc \
trace.cc \
shell.cc \
......
......@@ -40,6 +40,10 @@ constexpr char eol = '\n';
//
extern bool verbose;
// seed used by random number generators
//
extern uint64_t seed;
} // namespace ConcuBinE
#endif
......@@ -13,10 +13,11 @@
namespace ConcuBinE {
//==============================================================================
// global flags
// global variables
//==============================================================================
bool verbose = false;
uint64_t seed = static_cast<uint64_t>(time(NULL));
//==============================================================================
// usage
......@@ -132,7 +133,6 @@ int help (const char * name, const int argc, const char **argv)
int simulate (const char * name, const int argc, const char ** argv)
{
size_t bound = 0;
uint64_t seed = static_cast<uint64_t>(time(NULL));
Program::List::ptr programs = std::make_shared<Program::List>();
for (int i = 0; i < argc; i++)
......@@ -201,7 +201,7 @@ int simulate (const char * name, const int argc, const char ** argv)
}
// run program with given seed
Trace::ptr trace = Simulator::simulate(programs, bound, seed);
Trace::ptr trace = Simulator::simulate(programs, bound);
// print the result
std::cout << trace->print();
......
#include "mmap.hh"
#include <sstream>
#include <iostream>
#include "parser.hh"
namespace ConcuBinE {
//==============================================================================
// MMap
//==============================================================================
//------------------------------------------------------------------------------
// constructors
//------------------------------------------------------------------------------
MMap::MMap(std::istream & f, const std::string & p) : path(p)
{
size_t line_num = 1;
for (std::string line_buf; std::getline(f, line_buf); line_num++)
{
// skip empty lines
if (line_buf.empty())
continue;
std::istringstream line(line_buf);
// skip comments
if (line_buf[line_buf.find_first_not_of(" \t")] == '#')
continue;
word_t address;
if (!(line >> address))
{
line.clear();
std::string token;
if (!(line >> token))
parser_error(path, line_num, "missing address");
parser_error(path, line_num, "illegal address [" + token + "]");
}
word_t value;
if (!(line >> value))
{
line.clear();
std::string token;
if (!(line >> token))
parser_error(path, line_num, "missing value");
parser_error(path, line_num, "illegal value [" + token + "]");
}
emplace(address, value);
}
}
//------------------------------------------------------------------------------
// member functions
//------------------------------------------------------------------------------
// MMap::print -----------------------------------------------------------------
std::string MMap::print () const
{
std::ostringstream ss;
for (const auto & [adr, val] : *this)
ss << adr << " " << val << eol;
return ss.str();
}
} // namespace ConcuBinE
#ifndef MMAP_HH_
#define MMAP_HH_
#include <map>
#include "common.hh"
namespace ConcuBinE {
//==============================================================================
// MMap class
//==============================================================================
struct MMap : std::map<word_t, word_t>
{
//----------------------------------------------------------------------------
// member types
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// members
//----------------------------------------------------------------------------
// path to memory map file
//
std::string path;
//----------------------------------------------------------------------------
// constructors
//----------------------------------------------------------------------------
// inherit base constructors
//
using std::map<word_t, word_t>::map;
// construct from file
//
MMap (std::istream & file, const std::string & path);
//----------------------------------------------------------------------------
// member functions
//----------------------------------------------------------------------------
// print memory map
//
std::string print () const;
};
//==============================================================================
// non-member operators
//==============================================================================
} // namespace ConcuBinE
#endif
......@@ -35,7 +35,7 @@ Program::Program(std::istream & f, const std::string & p) : path(p)
std::vector<
std::tuple<std::string, word_t, const std::string *>> labelled_jumps;
for (std::string line_buf; getline(f, line_buf); line_num++)
for (std::string line_buf; std::getline(f, line_buf); line_num++)
{
// skip empty lines
if (line_buf.empty())
......
......@@ -27,13 +27,11 @@ inline void erase (C & container, T & val)
//------------------------------------------------------------------------------
Simulator::Simulator (const Program::List::ptr & p,
const size_t b,
const uint64_t s) :
const size_t b) :
programs(p),
trace(std::make_unique<Trace>(p)),
step(0),
bound(b ? b : static_cast<size_t>(-1)),
seed(s),
state(p->size(), State::running),
active(p->size())
{
......@@ -459,10 +457,9 @@ Trace::ptr Simulator::run (std::function<word_t()> scheduler)
// Simulator::simulate ---------------------------------------------------------
Trace::ptr Simulator::simulate (const Program::List::ptr & programs,
const size_t bound,
const size_t seed)
const size_t bound)
{
Simulator simulator {programs, bound, seed};
Simulator simulator {programs, bound};
// Mersenne Twister pseudo-random number generator
std::mt19937_64 random(seed);
......
......@@ -58,10 +58,6 @@ struct Simulator
//
size_t bound;
// seed used for random thread scheduling
//
uint64_t seed;
// current thread
//
word_t thread;
......@@ -92,9 +88,7 @@ struct Simulator
// constructors
//----------------------------------------------------------------------------
Simulator (const Program::List::ptr & programs,
size_t bound = 0,
uint64_t seed = 0);
Simulator (const Program::List::ptr & programs, size_t bound = 0);
//----------------------------------------------------------------------------
// private functions
......@@ -195,8 +189,7 @@ struct Simulator
// runs the simulator using a random trace
//
static Trace::ptr simulate (const Program::List::ptr & programs,
size_t bound = 0,
uint64_t seed = 0);
size_t bound = 0);
// replay the given trace (trace must match simulator configuration)
//
......
......@@ -45,19 +45,20 @@ TEST_RUN := run_all_tests
GTEST_FILTER = --gtest_filter=
# GTEST_FILTER += "*"
GTEST_FILTER += Encoder.*
GTEST_FILTER += smtlib.*
GTEST_FILTER += smtlib_Encoder.*
GTEST_FILTER += smtlib_Functional.*
GTEST_FILTER += smtlib_Relational.*
GTEST_FILTER += btor2.*
GTEST_FILTER += btor2_Encoder.*
GTEST_FILTER += Simulator.*
# GTEST_FILTER += Encoder.*
# GTEST_FILTER += smtlib.*
# GTEST_FILTER += smtlib_Encoder.*
# GTEST_FILTER += smtlib_Functional.*
# GTEST_FILTER += smtlib_Relational.*
# GTEST_FILTER += btor2.*
# GTEST_FILTER += btor2_Encoder.*
# GTEST_FILTER += Simulator.*
# GTEST_FILTER += Main.*
# GTEST_FILTER += Experimental.*
GTEST_FILTER += Instruction.*
GTEST_FILTER += Program.*
GTEST_FILTER += Trace.*
# GTEST_FILTER += Instruction.*
# GTEST_FILTER += Program.*
# GTEST_FILTER += Trace.*
GTEST_FILTER += MMap.*
# GTEST_FILTER += Shell.*
# GTEST_FILTER += Boolector.*
# GTEST_FILTER += BtorMC.*
......@@ -100,8 +101,8 @@ experimental: $(EXPERIMENTS) $(GTEST_LIB)
$(CXX) $(CXXFLAGS) $^ $(TEST_MAIN) -o $@
# build executable containing all test cases
$(TEST_RUN): $(GTEST_LIB) $(OBJ) $(TEST_OBJ)
$(CXX) $(CXXFLAGS) $^ $(TEST_MAIN) $(LDFLAGS) -o $@
$(TEST_RUN): $(GTEST_LIB) $(OBJ) $(TEST_OBJ) $(TEST_MAIN)
$(CXX) $(CXXFLAGS) $^ $(LDFLAGS) -o $@
# build googletest library
$(GTEST_DIR):
......
......@@ -7,6 +7,7 @@
namespace ConcuBinE {
bool verbose = true;
uint64_t seed = 0;
} // namespace ConcuBinE
......
#include <gtest/gtest.h>
#include "mmap.hh"
#include "parser.hh"
namespace ConcuBinE::test {
//==============================================================================
// MMap tests
//==============================================================================
struct MMap : public ::testing::Test
{
std::string path = "dummy.mmap";
ConcuBinE::MMap mmap;
void create_mmap (std::string code)
{
std::istringstream inbuf {code};
mmap = ConcuBinE::MMap(inbuf, path);
}
};
// construction ================================================================
TEST_F(MMap, construction)
{
create_mmap("0 0\n");
ConcuBinE::MMap & m1 = mmap;
ASSERT_FALSE(m1.empty());
// copy construction
ConcuBinE::MMap m2 (m1);
ASSERT_NE(&m1[0], &m2[0]);
ASSERT_EQ(m1, m2);
const auto * ptr = &m1[0];
// std::move construction
ConcuBinE::MMap m3 (std::move(m1));
ASSERT_TRUE(m1.empty());
ASSERT_EQ(m2, m3);
ASSERT_EQ(ptr, &m3[0]);
// copy assignment
m1 = m2;
ASSERT_EQ(m1, m3);
ASSERT_NE(&m1[0], &m2[0]);
ASSERT_NE(&m1[0], &m3[0]);
// std::move assignment
m2 = std::move(m3);
ASSERT_TRUE(m3.empty());
ASSERT_EQ(m1, m2);
ASSERT_EQ(ptr, &m2[0]);
}
// parser ======================================================================
TEST_F(MMap, parse)
{
create_mmap(
"0 0\n"
"1 1\n"
"2 2\n"
);
ASSERT_EQ(path, mmap.path);
ASSERT_EQ(3, mmap.size());
for (word_t i = 0; i < mmap.size(); i++)
ASSERT_EQ(i, mmap.at(i));
}
TEST_F(MMap, parse_comment)
{
create_mmap(
"# a comment\n"
"0 0\n"
"# another comment\n"
"1 1\n"
);
ASSERT_EQ(path, mmap.path);
ASSERT_EQ(2, mmap.size());
for (word_t i = 0; i < mmap.size(); i++)
ASSERT_EQ(i, mmap.at(i));
}
TEST_F(MMap, parse_empty_line)
{
create_mmap(
"0 0\n"
"\n"
"1 1\n"
);
ASSERT_EQ(path, mmap.path);
ASSERT_EQ(2, mmap.size());
for (word_t i = 0; i < mmap.size(); i++)
ASSERT_EQ(i, mmap.at(i));
}
TEST_F(MMap, parse_file_not_found)
{
try
{
mmap = create_from_file<ConcuBinE::MMap>("file");
FAIL() << "should throw an exception";
}
catch (const std::exception & e)
{
ASSERT_STREQ("file not found", e.what());
}
}
TEST_F(MMap, parse_illegal_address)
{
try
{
create_mmap("ILLEGAL 0\n");
FAIL() << "should throw an exception";
}
catch (const std::exception & e)
{
ASSERT_EQ(path + ":1: illegal address [ILLEGAL]", e.what());
}
}
TEST_F(MMap, parse_illegal_value)
{
try
{
create_mmap("0 ILLEGAL\n");
FAIL() << "should throw an exception";
}
catch (const std::exception & e)
{
ASSERT_EQ(path + ":1: illegal value [ILLEGAL]", e.what());
}
}
// MMap::print =================================================================
TEST_F(MMap, print)
{
std::string expected =
"0 0\n"
"1 1\n"
"2 2\n";
create_mmap(expected);
ASSERT_EQ(expected, mmap.print());
}
} // namespace ConcuBinE::test
......@@ -138,16 +138,14 @@ TEST_F(Program, parse_empty_line)
TEST_F(Program, parse_file_not_found)
{
std::string file = "file_not_found";
try
{
program = create_from_file<ConcuBinE::Program>(file);
program = create_from_file<ConcuBinE::Program>("file");
ASSERT_TRUE(false);
}
catch (const std::exception & e)
{
ASSERT_STREQ("file_not_found not found", e.what());
ASSERT_STREQ("file not found", e.what());
}
}
......
......@@ -251,12 +251,12 @@ TEST_F(Trace, parse_file_not_found)
{
trace =
std::make_unique<ConcuBinE::Trace>(
create_from_file<ConcuBinE::Trace>("file_not_found"));
create_from_file<ConcuBinE::Trace>("file"));
FAIL() << "should throw an std::exception";
}
catch (const std::exception & e)
{
ASSERT_STREQ("file_not_found not found", e.what());
ASSERT_STREQ("file not found", e.what());
}
}
......
......@@ -34,7 +34,7 @@ Trace::Trace(std::istream & file, const std::string & path) :
size_t line_num = 1;
// parse programs
for (std::string line_buf; getline(file, line_buf); ++line_num)
for (std::string line_buf; std::getline(file, line_buf); ++line_num)
{
// skip empty lines
if (line_buf.empty())
......@@ -72,7 +72,7 @@ Trace::Trace(std::istream & file, const std::string & path) :
// parse body
line_num++;
for (std::string line_buf; getline(file, line_buf); line_num++)
for (std::string line_buf; std::getline(file, line_buf); line_num++)
{
// skip empty lines
if (line_buf.empty())
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment