Adding gem5 source to svn.

git-svn-id: https://www4.informatik.uni-erlangen.de/i4svn/danceos/trunk/devel/fail@1819 8c4709b5-6ec9-48aa-a5cd-a96041d1645a
This commit is contained in:
friemel
2012-10-24 19:18:57 +00:00
parent f7ff71bd46
commit b41eec3f65
3222 changed files with 658579 additions and 1 deletions

View File

@ -0,0 +1,8 @@
from m5.SimObject import SimObject
from m5.params import *
class CPA(SimObject):
type = 'CPA'
enabled = Param.Bool(False, "Is Annotation enabled?")
user_apps = VectorParam.String([], "List of apps to get symbols for")

View File

@ -0,0 +1,94 @@
# -*- mode:python -*-
# Copyright (c) 2006 The Regents of The University of Michigan
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met: redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer;
# redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution;
# neither the name of the copyright holders nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Authors: Nathan Binkert
Import('*')
if env['CP_ANNOTATE']:
SimObject('CPA.py')
Source('cp_annotate.cc')
Source('atomicio.cc')
Source('bigint.cc')
Source('bitmap.cc')
Source('callback.cc')
Source('circlebuf.cc')
Source('cprintf.cc')
Source('debug.cc')
if env['USE_FENV']:
Source('fenv.c')
Source('hostinfo.cc')
Source('inet.cc')
Source('inifile.cc')
Source('intmath.cc')
Source('match.cc')
Source('misc.cc')
Source('output.cc')
Source('pollevent.cc')
Source('random.cc')
Source('random_mt.cc')
Source('range.cc')
if env['TARGET_ISA'] != 'no':
Source('remote_gdb.cc')
Source('socket.cc')
Source('statistics.cc')
Source('str.cc')
Source('time.cc')
Source('trace.cc')
Source('userinfo.cc')
Source('loader/aout_object.cc')
Source('loader/ecoff_object.cc')
Source('loader/elf_object.cc')
Source('loader/hex_file.cc')
Source('loader/object_file.cc')
Source('loader/raw_object.cc')
Source('loader/symtab.cc')
Source('stats/text.cc')
DebugFlag('Annotate', "State machine annotation debugging")
DebugFlag('AnnotateQ', "State machine annotation queue debugging")
DebugFlag('AnnotateVerbose', "Dump all state machine annotation details")
DebugFlag('GDBAcc', "Remote debugger accesses")
DebugFlag('GDBExtra', "Dump extra information on reads and writes")
DebugFlag('GDBMisc', "Breakpoints, traps, watchpoints, etc.")
DebugFlag('GDBRead', "Reads to the remote address space")
DebugFlag('GDBRecv', "Messages received from the remote application")
DebugFlag('GDBSend', "Messages sent to the remote application")
DebugFlag('GDBWrite', "Writes to the remote address space")
DebugFlag('SQL', "SQL queries sent to the server")
DebugFlag('StatEvents', "Statistics event tracking")
CompoundFlag('GDBAll',
[ 'GDBMisc', 'GDBAcc', 'GDBRead', 'GDBWrite', 'GDBSend', 'GDBRecv',
'GDBExtra' ],
desc="All Remote debugging flags")
CompoundFlag('AnnotateAll', ['Annotate', 'AnnotateQ', 'AnnotateVerbose'],
desc="All Annotation flags")

View File

@ -0,0 +1,92 @@
/*
* Copyright (c) 2008 The Hewlett-Packard Development Company
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#include <cerrno>
#include <cstdio>
#include "base/atomicio.hh"
ssize_t
atomic_read(int fd, void *s, size_t n)
{
char *p = reinterpret_cast<char *>(s);
size_t pos = 0;
// Keep reading until we've gotten all of the data.
while (n > pos) {
ssize_t result = read(fd, p + pos, n - pos);
// We didn't get any more data, so we should probably punt,
// otherwise we'd just keep spinning
if (result == 0)
break;
// If there was an error, try again on EINTR/EAGAIN, pass the
// error up otherwise.
if (result == -1) {
if (errno == EINTR || errno == EAGAIN)
continue;
return result;
}
pos += result;
}
return pos;
}
ssize_t
atomic_write(int fd, const void *s, size_t n)
{
const char *p = reinterpret_cast<const char *>(s);
size_t pos = 0;
// Keep writing until we've written all of the data
while (n > pos) {
ssize_t result = write(fd, p + pos, n - pos);
// We didn't manage to write anything this time, so we should
// probably punt, otherwise we'd just keep spinning
if (result == 0)
break;
// If there was an error, try again on EINTR/EAGAIN, pass the
// error up otherwise.
if (result == -1) {
if (errno == EINTR || errno == EAGAIN)
continue;
return result;
}
pos += result;
}
return pos;
}

View File

@ -0,0 +1,44 @@
/*
* Copyright (c) 2008 The Hewlett-Packard Development Company
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#ifndef __BASE_ATOMICIO_HH__
#define __BASE_ATOMICIO_HH__
#include <unistd.h>
// These functions keep reading/writing, if possible, until all data
// has been transferred. Basically, try again when there's no error,
// but there is data left also retry on EINTR.
// This function blocks until it is done.
ssize_t atomic_read(int fd, void *s, size_t n);
ssize_t atomic_write(int fd, const void *s, size_t n);
#endif // __BASE_ATOMICIO_HH__

View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Gabe Black
*/
#include <iostream>
#include "base/bigint.hh"
using namespace std;
ostream & operator << (ostream & os, const Twin64_t & t)
{
os << t.a << ", " << t.b;
return os;
}
ostream & operator << (ostream & os, const Twin32_t & t)
{
os << t.a << ", " << t.b;
return os;
}

View File

@ -0,0 +1,98 @@
/*
* Copyright (c) 2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Ali Saidi
*/
#include <iostream>
#include "base/misc.hh"
#include "base/types.hh"
#ifndef __BASE_BIGINT_HH__
#define __BASE_BIGINT_HH__
// Create a couple of large int types for atomic reads
struct m5_twin64_t {
uint64_t a;
uint64_t b;
m5_twin64_t()
{}
m5_twin64_t(const uint64_t x)
{
a = x;
b = x;
}
inline m5_twin64_t& operator=(const uint64_t x)
{
a = x;
b = x;
return *this;
}
operator uint64_t()
{
panic("Tried to cram a twin64_t into an integer!\n");
return a;
}
};
struct m5_twin32_t {
uint32_t a;
uint32_t b;
m5_twin32_t()
{}
m5_twin32_t(const uint32_t x)
{
a = x;
b = x;
}
inline m5_twin32_t& operator=(const uint32_t x)
{
a = x;
b = x;
return *this;
}
operator uint32_t()
{
panic("Tried to cram a twin32_t into an integer!\n");
return a;
}
};
// This is for twin loads (two 64 bit values), not 1 128 bit value (as far as
// endian conversion is concerned!
typedef m5_twin64_t Twin64_t;
typedef m5_twin32_t Twin32_t;
// Output operator overloads
std::ostream & operator << (std::ostream & os, const Twin64_t & t);
std::ostream & operator << (std::ostream & os, const Twin32_t & t);
#endif // __BASE_BIGINT_HH__

View File

@ -0,0 +1,181 @@
/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Steve Reinhardt
* Nathan Binkert
*/
#ifndef __BASE_BITFIELD_HH__
#define __BASE_BITFIELD_HH__
#include "base/types.hh"
/**
* Generate a 64-bit mask of 'nbits' 1s, right justified.
*/
inline uint64_t
mask(int nbits)
{
return (nbits == 64) ? (uint64_t)-1LL : (1ULL << nbits) - 1;
}
/**
* Extract the bitfield from position 'first' to 'last' (inclusive)
* from 'val' and right justify it. MSB is numbered 63, LSB is 0.
*/
template <class T>
inline
T
bits(T val, int first, int last)
{
int nbits = first - last + 1;
return (val >> last) & mask(nbits);
}
/**
* Extract the bit from this position from 'val' and right justify it.
*/
template <class T>
inline
T
bits(T val, int bit)
{
return bits(val, bit, bit);
}
/**
* Mask off the given bits in place like bits() but without shifting.
* msb = 63, lsb = 0
*/
template <class T>
inline
T
mbits(T val, int first, int last)
{
return val & (mask(first+1) & ~mask(last));
}
inline uint64_t
mask(int first, int last)
{
return mbits((uint64_t)-1LL, first, last);
}
/**
* Sign-extend an N-bit value to 64 bits.
*/
template <int N>
inline
int64_t
sext(uint64_t val)
{
int sign_bit = bits(val, N-1, N-1);
return sign_bit ? (val | ~mask(N)) : val;
}
/**
* Return val with bits first to last set to bit_val
*/
template <class T, class B>
inline
T
insertBits(T val, int first, int last, B bit_val)
{
T t_bit_val = bit_val;
T bmask = mask(first - last + 1) << last;
return ((t_bit_val << last) & bmask) | (val & ~bmask);
}
/**
* Overloaded for access to only one bit in value
*/
template <class T, class B>
inline
T
insertBits(T val, int bit, B bit_val)
{
return insertBits(val, bit, bit, bit_val);
}
/**
* A convenience function to replace bits first to last of val with bit_val
* in place.
*/
template <class T, class B>
inline
void
replaceBits(T& val, int first, int last, B bit_val)
{
val = insertBits(val, first, last, bit_val);
}
/** Overloaded function to allow to access only 1 bit*/
template <class T, class B>
inline
void
replaceBits(T& val, int bit, B bit_val)
{
val = insertBits(val, bit, bit, bit_val);
}
/**
* Returns the bit position of the MSB that is set in the input
*/
inline
int
findMsbSet(uint64_t val) {
int msb = 0;
if (!val)
return 0;
if (bits(val, 63,32)) { msb += 32; val >>= 32; }
if (bits(val, 31,16)) { msb += 16; val >>= 16; }
if (bits(val, 15,8)) { msb += 8; val >>= 8; }
if (bits(val, 7,4)) { msb += 4; val >>= 4; }
if (bits(val, 3,2)) { msb += 2; val >>= 2; }
if (bits(val, 1,1)) { msb += 1; }
return msb;
}
/**
* Returns the bit position of the LSB that is set in the input
*/
inline int
findLsbSet(uint64_t val) {
int lsb = 0;
if (!val)
return sizeof(val) * 8;
if (!bits(val, 31,0)) { lsb += 32; val >>= 32; }
if (!bits(val, 15,0)) { lsb += 16; val >>= 16; }
if (!bits(val, 7,0)) { lsb += 8; val >>= 8; }
if (!bits(val, 3,0)) { lsb += 4; val >>= 4; }
if (!bits(val, 1,0)) { lsb += 2; val >>= 2; }
if (!bits(val, 0,0)) { lsb += 1; }
return lsb;
}
#endif // __BASE_BITFIELD_HH__

View File

@ -0,0 +1,106 @@
/*
* Copyright (c) 2010 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
* not be construed as granting a license to any other intellectual
* property including but not limited to intellectual property relating
* to a hardware implementation of the functionality of the software
* licensed hereunder. You may use the software subject to the license
* terms below provided that you ensure that this notice is replicated
* unmodified and in its entirety in all distributions of the software,
* modified or unmodified, in source code or in binary form.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: William Wang
* Ali Saidi
* Chris Emmons
*/
#include <cassert>
#include "base/bitmap.hh"
#include "base/misc.hh"
const size_t Bitmap::sizeofHeaderBuffer = sizeof(Magic) + sizeof(Header) +
sizeof(Info);
// bitmap class ctor
Bitmap::Bitmap(VideoConvert::Mode _mode, uint16_t w, uint16_t h, uint8_t *d)
: mode(_mode), height(h), width(w), data(d),
vc(mode, VideoConvert::rgb8888, width, height), headerBuffer(0)
{
}
Bitmap::~Bitmap() {
if (headerBuffer)
delete [] headerBuffer;
}
void
Bitmap::write(std::ostream *bmp) const
{
assert(data);
// header is always the same for a bitmap object; compute the info once per
// bitmap object
if (!headerBuffer) {
// For further information see:
// http://en.wikipedia.org/wiki/BMP_file_format
Magic magic = {{'B','M'}};
Header header = {
static_cast<uint32_t>(sizeof(VideoConvert::Rgb8888)) *
width * height, 0, 0, 54};
Info info = {static_cast<uint32_t>(sizeof(Info)), width, height, 1,
static_cast<uint32_t>(sizeof(VideoConvert::Rgb8888)) * 8,
0, static_cast<uint32_t>(sizeof(VideoConvert::Rgb8888)) *
width * height, 1, 1, 0, 0};
char *p = headerBuffer = new char[sizeofHeaderBuffer];
memcpy(p, &magic, sizeof(Magic));
p += sizeof(Magic);
memcpy(p, &header, sizeof(Header));
p += sizeof(Header);
memcpy(p, &info, sizeof(Info));
}
// 1. write the header
bmp->write(headerBuffer, sizeofHeaderBuffer);
// 2. write the bitmap data
uint8_t *tmp = vc.convert(data);
uint32_t *tmp32 = (uint32_t*)tmp;
// BMP start store data left to right starting with the bottom row
// so we need to do some creative flipping
for (int i = height - 1; i >= 0; i--)
for (int j = 0; j < width; j++)
bmp->write((char*)&tmp32[i * width + j], sizeof(uint32_t));
bmp->flush();
delete [] tmp;
}

View File

@ -0,0 +1,127 @@
/*
* Copyright (c) 2010 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
* not be construed as granting a license to any other intellectual
* property including but not limited to intellectual property relating
* to a hardware implementation of the functionality of the software
* licensed hereunder. You may use the software subject to the license
* terms below provided that you ensure that this notice is replicated
* unmodified and in its entirety in all distributions of the software,
* modified or unmodified, in source code or in binary form.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: William Wang
* Ali Saidi
* Chris Emmons
*/
#ifndef __BASE_BITMAP_HH__
#define __BASE_BITMAP_HH__
#include <fstream>
#include "base/vnc/convert.hh"
/**
* @file Declaration of a class that writes a frame buffer to a bitmap
*/
// write frame buffer into a bitmap picture
class Bitmap
{
public:
/** Create a Bitmap creator that takes data in the given mode & size
* and outputs to an fstream
* @param mode the type of data that is being provided
* @param h the hight of the image
* @param w the width of the image
* @param d the data for the image in mode
*/
Bitmap(VideoConvert::Mode mode, uint16_t w, uint16_t h, uint8_t *d);
/** Destructor */
~Bitmap();
/** Provide the converter with the data that should be output. It will be
* converted into rgb8888 and write out when write() is called.
* @param d the data
*/
void rawData(uint8_t* d) { data = d; }
/** Write the provided data into the fstream provided
* @param bmp stream to write to
*/
void write(std::ostream *bmp) const;
/** Gets a hash over the bitmap for quick comparisons to other bitmaps.
* @return hash of the bitmap
*/
uint64_t getHash() const { return vc.getHash(data); }
private:
VideoConvert::Mode mode;
uint16_t height;
uint16_t width;
uint8_t *data;
VideoConvert vc;
mutable char *headerBuffer;
static const size_t sizeofHeaderBuffer;
struct Magic
{
unsigned char magic_number[2];
};
struct Header
{
uint32_t size;
uint16_t reserved1;
uint16_t reserved2;
uint32_t offset;
};
struct Info
{
uint32_t Size;
uint32_t Width;
uint32_t Height;
uint16_t Planes;
uint16_t BitCount;
uint32_t Compression;
uint32_t SizeImage;
uint32_t XPelsPerMeter;
uint32_t YPelsPerMeter;
uint32_t ClrUsed;
uint32_t ClrImportant;
};
};
#endif // __BASE_BITMAP_HH__

View File

@ -0,0 +1,309 @@
/*
* Copyright (c) 2007-2008 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Gabe Black
*/
#ifndef __BASE_BITUNION_HH__
#define __BASE_BITUNION_HH__
#include "base/bitfield.hh"
#include "base/types.hh"
// The following implements the BitUnion system of defining bitfields
//on top of an underlying class. This is done through the pervasive use of
//both named and unnamed unions which all contain the same actual storage.
//Since they're unioned with each other, all of these storage locations
//overlap. This allows all of the bitfields to manipulate the same data
//without having to have access to each other. More details are provided with
//the individual components.
//This namespace is for classes which implement the backend of the BitUnion
//stuff. Don't use any of these directly, except for the Bitfield classes in
//the *BitfieldTypes class(es).
namespace BitfieldBackend
{
//A base class for all bitfields. It instantiates the actual storage,
//and provides getBits and setBits functions for manipulating it. The
//Data template parameter is type of the underlying storage.
template<class Data>
class BitfieldBase
{
protected:
Data __data;
//This function returns a range of bits from the underlying storage.
//It relies on the "bits" function above. It's the user's
//responsibility to make sure that there is a properly overloaded
//version of this function for whatever type they want to overlay.
inline uint64_t
getBits(int first, int last) const
{
return bits(__data, first, last);
}
//Similar to the above, but for settings bits with replaceBits.
inline void
setBits(int first, int last, uint64_t val)
{
replaceBits(__data, first, last, val);
}
};
//This class contains all the "regular" bitfield classes. It is inherited
//by all BitUnions which give them access to those types.
template<class Type>
class RegularBitfieldTypes
{
protected:
//This class implements ordinary bitfields, that is a span of bits
//who's msb is "first", and who's lsb is "last".
template<int first, int last=first>
class Bitfield : public BitfieldBase<Type>
{
public:
operator const uint64_t () const
{
return this->getBits(first, last);
}
uint64_t
operator=(const uint64_t _data)
{
this->setBits(first, last, _data);
return _data;
}
};
//A class which specializes the above so that it can only be read
//from. This is accomplished explicitly making sure the assignment
//operator is blocked. The conversion operator is carried through
//inheritance. This will unfortunately need to be copied into each
//bitfield type due to limitations with how templates work
template<int first, int last=first>
class BitfieldRO : public Bitfield<first, last>
{
private:
uint64_t
operator=(const uint64_t _data);
};
//Similar to the above, but only allows writing.
template<int first, int last=first>
class BitfieldWO : public Bitfield<first, last>
{
private:
operator const uint64_t () const;
public:
using Bitfield<first, last>::operator=;
};
};
//This class contains all the "regular" bitfield classes. It is inherited
//by all BitUnions which give them access to those types.
template<class Type>
class SignedBitfieldTypes
{
protected:
//This class implements ordinary bitfields, that is a span of bits
//who's msb is "first", and who's lsb is "last".
template<int first, int last=first>
class SignedBitfield : public BitfieldBase<Type>
{
public:
operator const int64_t () const
{
return sext<first - last + 1>(this->getBits(first, last));
}
int64_t
operator=(const int64_t _data)
{
this->setBits(first, last, _data);
return _data;
}
};
//A class which specializes the above so that it can only be read
//from. This is accomplished explicitly making sure the assignment
//operator is blocked. The conversion operator is carried through
//inheritance. This will unfortunately need to be copied into each
//bitfield type due to limitations with how templates work
template<int first, int last=first>
class SignedBitfieldRO : public SignedBitfield<first, last>
{
private:
int64_t
operator=(const int64_t _data);
};
//Similar to the above, but only allows writing.
template<int first, int last=first>
class SignedBitfieldWO : public SignedBitfield<first, last>
{
private:
operator const int64_t () const;
public:
int64_t operator=(const int64_t _data)
{
*((SignedBitfield<first, last> *)this) = _data;
return _data;
}
};
};
template<class Type>
class BitfieldTypes : public RegularBitfieldTypes<Type>,
public SignedBitfieldTypes<Type>
{};
//When a BitUnion is set up, an underlying class is created which holds
//the actual union. This class then inherits from it, and provids the
//implementations for various operators. Setting things up this way
//prevents having to redefine these functions in every different BitUnion
//type. More operators could be implemented in the future, as the need
//arises.
template <class Type, class Base>
class BitUnionOperators : public Base
{
public:
BitUnionOperators(Type const & _data)
{
Base::__data = _data;
}
BitUnionOperators() {}
operator const Type () const
{
return Base::__data;
}
Type
operator=(Type const & _data)
{
Base::__data = _data;
return _data;
}
bool
operator<(Base const & base) const
{
return Base::__data < base.__data;
}
bool
operator==(Base const & base) const
{
return Base::__data == base.__data;
}
};
}
//This macro is a backend for other macros that specialize it slightly.
//First, it creates/extends a namespace "BitfieldUnderlyingClasses" and
//sticks the class which has the actual union in it, which
//BitfieldOperators above inherits from. Putting these classes in a special
//namespace ensures that there will be no collisions with other names as long
//as the BitUnion names themselves are all distinct and nothing else uses
//the BitfieldUnderlyingClasses namespace, which is unlikely. The class itself
//creates a typedef of the "type" parameter called __DataType. This allows
//the type to propagate outside of the macro itself in a controlled way.
//Finally, the base storage is defined which BitfieldOperators will refer to
//in the operators it defines. This macro is intended to be followed by
//bitfield definitions which will end up inside it's union. As explained
//above, these is overlayed the __data member in its entirety by each of the
//bitfields which are defined in the union, creating shared storage with no
//overhead.
#define __BitUnion(type, name) \
class BitfieldUnderlyingClasses##name : \
public BitfieldBackend::BitfieldTypes<type> \
{ \
public: \
typedef type __DataType; \
union { \
type __data;\
//This closes off the class and union started by the above macro. It is
//followed by a typedef which makes "name" refer to a BitfieldOperator
//class inheriting from the class and union just defined, which completes
//building up the type for the user.
#define EndBitUnion(name) \
}; \
}; \
typedef BitfieldBackend::BitUnionOperators< \
BitfieldUnderlyingClasses##name::__DataType, \
BitfieldUnderlyingClasses##name> name;
//This sets up a bitfield which has other bitfields nested inside of it. The
//__data member functions like the "underlying storage" of the top level
//BitUnion. Like everything else, it overlays with the top level storage, so
//making it a regular bitfield type makes the entire thing function as a
//regular bitfield when referred to by itself.
#define __SubBitUnion(fieldType, first, last, name) \
class : public BitfieldBackend::BitfieldTypes<__DataType> \
{ \
public: \
union { \
fieldType<first, last> __data;
//This closes off the union created above and gives it a name. Unlike the top
//level BitUnion, we're interested in creating an object instead of a type.
//The operators are defined in the macro itself instead of a class for
//technical reasons. If someone determines a way to move them to one, please
//do so.
#define EndSubBitUnion(name) \
}; \
inline operator const __DataType () const \
{ return __data; } \
\
inline const __DataType operator = (const __DataType & _data) \
{ return __data = _data;} \
} name;
//Regular bitfields
//These define macros for read/write regular bitfield based subbitfields.
#define SubBitUnion(name, first, last) \
__SubBitUnion(Bitfield, first, last, name)
//Regular bitfields
//These define macros for read/write regular bitfield based subbitfields.
#define SignedSubBitUnion(name, first, last) \
__SubBitUnion(SignedBitfield, first, last, name)
//Use this to define an arbitrary type overlayed with bitfields.
#define BitUnion(type, name) __BitUnion(type, name)
//Use this to define conveniently sized values overlayed with bitfields.
#define BitUnion64(name) __BitUnion(uint64_t, name)
#define BitUnion32(name) __BitUnion(uint32_t, name)
#define BitUnion16(name) __BitUnion(uint16_t, name)
#define BitUnion8(name) __BitUnion(uint8_t, name)
#endif // __BASE_BITUNION_HH__

View File

@ -0,0 +1,39 @@
/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#include "base/callback.hh"
CallbackQueue::~CallbackQueue()
{
queue::iterator i = callbacks.begin();
queue::iterator end = callbacks.end();
for (; i != end; ++i)
(*i)->autoDestruct();
}

View File

@ -0,0 +1,156 @@
/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#ifndef __BASE_CALLBACK_HH__
#define __BASE_CALLBACK_HH__
#include <list>
#include <string>
/**
* Generic callback class. This base class provides a virtual process
* function that gets called when the callback queue is processed.
*/
class Callback
{
protected:
friend class CallbackQueue;
virtual void autoDestruct() {}
public:
/**
* virtualize the destructor to make sure that the correct one
* gets called.
*/
virtual ~Callback() {}
/**
* virtual process function that is invoked when the callback
* queue is executed.
*/
virtual void process() = 0;
};
/// Helper template class to turn a simple class member function into
/// a callback.
template <class T, void (T::* F)()>
class MakeCallback : public Callback
{
protected:
T *object;
const bool autoDestroy;
void autoDestruct() { if (autoDestroy) delete this; }
public:
MakeCallback(T *o, bool auto_destroy = false)
: object(o), autoDestroy(auto_destroy)
{ }
MakeCallback(T &o, bool auto_destroy = false)
: object(&o), autoDestroy(auto_destroy)
{ }
void process() { (object->*F)(); }
};
class CallbackQueue
{
protected:
/**
* Simple typedef for the data structure that stores all of the
* callbacks.
*/
typedef std::list<Callback *> queue;
/**
* List of all callbacks. To be called in fifo order.
*/
queue callbacks;
public:
~CallbackQueue();
std::string name() const { return "CallbackQueue"; }
/**
* Add a callback to the end of the queue
* @param callback the callback to be added to the queue
*/
void
add(Callback *callback)
{
callbacks.push_back(callback);
}
template <class T, void (T::* F)()>
void
add(T *obj)
{
add(new MakeCallback<T, F>(obj, true));
}
template <class T, void (T::* F)()>
void
add(T &obj)
{
add(new MakeCallback<T, F>(&obj, true));
}
/**
* Find out if there are any callbacks in the queue
*/
bool empty() const { return callbacks.empty(); }
/**
* process all callbacks
*/
void
process()
{
queue::iterator i = callbacks.begin();
queue::iterator end = callbacks.end();
while (i != end) {
(*i)->process();
++i;
}
}
/**
* clear the callback queue
*/
void
clear()
{
callbacks.clear();
}
};
#endif // __BASE_CALLBACK_HH__

View File

@ -0,0 +1,68 @@
/*
* Copyright (c) 2008 The Hewlett-Packard Development Company
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#ifndef __BASE_CAST_HH__
#define __BASE_CAST_HH__
#include <cassert>
// This is designed for situations where we have a pointer to a base
// type, but in all cases when we cast it to a derived type, we know
// by construction that it should work correctly.
#if defined(DEBUG)
// In debug builds, do the dynamic cast and assert the result is good
template <class T, class U>
inline T
safe_cast(U ptr)
{
T ret = dynamic_cast<T>(ptr);
assert(ret);
return ret;
}
#else
// In non debug builds statically cast the result to the pointer we
// want to use. This is technically unsafe, but this is only for
// cases where we know that this should work by construction.
template <class T, class U>
inline T
safe_cast(U ptr)
{
return static_cast<T>(ptr);
}
#endif
#endif // __BASE_CAST_HH__

View File

@ -0,0 +1,147 @@
/*
* Copyright (c) 2001-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Steve Reinhardt
*/
#ifndef __BASE__CHUNK_GENERATOR_HH__
#define __BASE__CHUNK_GENERATOR_HH__
/**
* @file
* Declaration and inline definition of ChunkGenerator object.
*/
#include <algorithm>
#include "base/intmath.hh"
#include "base/types.hh"
/**
* This class takes an arbitrary memory region (address/length pair)
* and generates a series of appropriately (e.g. block- or page-)
* aligned chunks covering the same region.
*
* Example usage:
\code
for (ChunkGenerator gen(addr, size, chunkSize); !gen.done(); gen.next()) {
doSomethingChunky(gen.addr(), gen.size());
}
\endcode
*/
class ChunkGenerator
{
private:
/** The starting address of the current chunk. */
Addr curAddr;
/** The starting address of the next chunk (after the current one). */
Addr nextAddr;
/** The size of the current chunk (in bytes). */
unsigned curSize;
/** The number of bytes remaining in the region after the current chunk. */
unsigned sizeLeft;
/** The start address so we can calculate offset in writing block. */
const Addr startAddr;
/** The maximum chunk size, e.g., the cache block size or page size. */
const unsigned chunkSize;
public:
/**
* Constructor.
* @param _startAddr The starting address of the region.
* @param totalSize The total size of the region.
* @param _chunkSize The size/alignment of chunks into which
* the region should be decomposed.
*/
ChunkGenerator(Addr _startAddr, unsigned totalSize, unsigned _chunkSize)
: startAddr(_startAddr), chunkSize(_chunkSize)
{
// chunkSize must be a power of two
assert(chunkSize == 0 || isPowerOf2(chunkSize));
assert(totalSize >= 0);
// set up initial chunk.
curAddr = startAddr;
if (chunkSize == 0) //Special Case, if we see 0, assume no chuncking
{
nextAddr = startAddr + totalSize;
}
else
{
// nextAddr should be *next* chunk start
nextAddr = roundUp(startAddr, chunkSize);
if (curAddr == nextAddr) {
// ... even if startAddr is already chunk-aligned
nextAddr += chunkSize;
}
}
// how many bytes are left between curAddr and the end of this chunk?
unsigned left_in_chunk = nextAddr - curAddr;
curSize = std::min(totalSize, left_in_chunk);
sizeLeft = totalSize - curSize;
}
/** Return starting address of current chunk. */
Addr addr() const { return curAddr; }
/** Return size in bytes of current chunk. */
unsigned size() const { return curSize; }
/** Number of bytes we have already chunked up. */
unsigned complete() const { return curAddr - startAddr; }
/**
* Are we done? That is, did the last call to next() advance
* past the end of the region?
* @return True if yes, false if more to go.
*/
bool done() const { return (curSize == 0); }
/**
* Advance generator to next chunk.
* @return True if successful, false if unsuccessful
* (because we were at the last chunk).
*/
bool
next()
{
if (sizeLeft == 0) {
curSize = 0;
return false;
}
curAddr = nextAddr;
curSize = std::min(sizeLeft, chunkSize);
sizeLeft -= curSize;
nextAddr += curSize;
return true;
}
};
#endif // __BASE__CHUNK_GENERATOR_HH__

View File

@ -0,0 +1,214 @@
/*
* Copyright (c) 2002-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
#include "base/atomicio.hh"
#include "base/circlebuf.hh"
#include "base/cprintf.hh"
#include "base/intmath.hh"
using namespace std;
CircleBuf::CircleBuf(int l)
: _rollover(false), _buflen(l), _size(0), _start(0), _stop(0)
{
_buf = new char[_buflen];
}
CircleBuf::~CircleBuf()
{
if (_buf)
delete [] _buf;
}
void
CircleBuf::dump()
{
cprintf("start = %10d, stop = %10d, buflen = %10d\n",
_start, _stop, _buflen);
fflush(stdout);
atomic_write(STDOUT_FILENO, _buf, _buflen);
atomic_write(STDOUT_FILENO, "<\n", 2);
}
void
CircleBuf::flush()
{
_start = 0;
_stop = 0;
_rollover = false;
}
void
CircleBuf::read(char *b, int len)
{
_size -= len;
if (_size < 0)
_size = 0;
if (_stop > _start) {
len = min(len, _stop - _start);
memcpy(b, _buf + _start, len);
_start += len;
}
else {
int endlen = _buflen - _start;
if (endlen > len) {
memcpy(b, _buf + _start, len);
_start += len;
}
else {
memcpy(b, _buf + _start, endlen);
_start = min(len - endlen, _stop);
memcpy(b + endlen, _buf, _start);
}
}
}
void
CircleBuf::read(int fd, int len)
{
_size -= len;
if (_size < 0)
_size = 0;
if (_stop > _start) {
len = min(len, _stop - _start);
atomic_write(fd, _buf + _start, len);
_start += len;
}
else {
int endlen = _buflen - _start;
if (endlen > len) {
atomic_write(fd, _buf + _start, len);
_start += len;
}
else {
atomic_write(fd, _buf + _start, endlen);
_start = min(len - endlen, _stop);
atomic_write(fd, _buf, _start);
}
}
}
void
CircleBuf::read(int fd)
{
_size = 0;
if (_stop > _start) {
atomic_write(fd, _buf + _start, _stop - _start);
}
else {
atomic_write(fd, _buf + _start, _buflen - _start);
atomic_write(fd, _buf, _stop);
}
_start = _stop;
}
void
CircleBuf::read(ostream &out)
{
_size = 0;
if (_stop > _start) {
out.write(_buf + _start, _stop - _start);
}
else {
out.write(_buf + _start, _buflen - _start);
out.write(_buf, _stop);
}
_start = _stop;
}
void
CircleBuf::readall(int fd)
{
if (_rollover)
atomic_write(fd, _buf + _stop, _buflen - _stop);
atomic_write(fd, _buf, _stop);
_start = _stop;
}
void
CircleBuf::write(char b)
{
write(&b, 1);
}
void
CircleBuf::write(const char *b)
{
write(b, strlen(b));
}
void
CircleBuf::write(const char *b, int len)
{
if (len <= 0)
return;
_size += len;
if (_size > _buflen)
_size = _buflen;
int old_start = _start;
int old_stop = _stop;
if (len >= _buflen) {
_start = 0;
_stop = _buflen;
_rollover = true;
memcpy(_buf, b + (len - _buflen), _buflen);
return;
}
if (_stop + len <= _buflen) {
memcpy(_buf + _stop, b, len);
_stop += len;
} else {
int end_len = _buflen - old_stop;
_stop = len - end_len;
memcpy(_buf + old_stop, b, end_len);
memcpy(_buf, b + end_len, _stop);
_rollover = true;
}
if ((old_start > old_stop && old_start < _stop) ||
(old_start < old_stop && _stop < old_stop))
_start = _stop + 1;
}

View File

@ -0,0 +1,64 @@
/*
* Copyright (c) 2002-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#ifndef __CIRCLEBUF_HH__
#define __CIRCLEBUF_HH__
#include <iosfwd>
class CircleBuf
{
protected:
char *_buf;
bool _rollover;
int _buflen;
int _size;
int _start;
int _stop;
public:
explicit CircleBuf(int l);
~CircleBuf();
bool empty() const { return _size == 0; }
int size() const { return _size; }
void dump();
void flush();
void read(char *b, int len);
void read(int fd, int len);
void read(int fd);
void read(std::ostream &out);
void readall(int fd);
void write(char b);
void write(const char *b);
void write(const char *b, int len);
};
#endif // __CIRCLEBUF_HH__

View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Ali Saidi
*/
#ifndef __BASE_COMPILER_HH__
#define __BASE_COMPILER_HH__
//http://msdn2.microsoft.com/en-us/library/ms937669.aspx
//http://msdn2.microsoft.com/en-us/library/aa448724.aspx
//http://docs.sun.com/source/819-3688/sun.specific.html#marker-998278
//http://gcc.gnu.org/onlinedocs/gcc-3.3.1/gcc/Function-Attributes.html#Function%20Attributes
#if defined(__GNUC__)
#define M5_ATTR_NORETURN __attribute__((noreturn))
#define M5_PRAGMA_NORETURN(x)
#define M5_DUMMY_RETURN
#define M5_VAR_USED __attribute__((unused))
#define M5_ATTR_PACKED __attribute__ ((__packed__))
#define M5_NO_INLINE __attribute__ ((__noinline__))
#elif defined(__SUNPRO_CC)
// this doesn't do anything with sun cc, but why not
#define M5_ATTR_NORETURN __sun_attr__((__noreturn__))
#define M5_DUMMY_RETURN return (0);
#define DO_PRAGMA(x) _Pragma(#x)
#define M5_VAR_USED
#define M5_PRAGMA_NORETURN(x) DO_PRAGMA(does_not_return(x))
#define M5_ATTR_PACKED __attribute__ ((__packed__))
#define M5_NO_INLINE __attribute__ ((__noinline__))
#else
#error "Need to define compiler options in base/compiler.hh"
#endif
#endif // __BASE_COMPILER_HH__

View File

@ -0,0 +1,94 @@
/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Gabe Black
*/
#ifndef __BASE_CONDCODE_HH__
#define __BASE_CONDCODE_HH__
#include "base/bitfield.hh"
#include "base/trace.hh"
/**
* Calculate the carry flag from an addition. This should work even when
* a carry value is also added in.
*/
inline
bool
findCarry(int width, uint64_t dest, uint64_t src1, uint64_t src2) {
int shift = width - 1;
return ((~(dest >> shift) & 1) +
((src1 >> shift) & 1) +
((src2 >> shift) & 1)) & 0x2;
}
/**
* Calculate the overflow flag from an addition.
*/
inline
bool
findOverflow(int width, uint64_t dest, uint64_t src1, uint64_t src2) {
int shift = width - 1;
return ((src1 ^ ~src2) & (src1 ^ dest)) & (1ULL << shift);
}
/**
* Calculate the parity of a value. 1 is for odd parity and 0 is for even.
*/
inline
bool
findParity(int width, uint64_t dest) {
dest &= mask(width);
dest ^= (dest >> 32);
dest ^= (dest >> 16);
dest ^= (dest >> 8);
dest ^= (dest >> 4);
dest ^= (dest >> 2);
dest ^= (dest >> 1);
return dest & 1;
}
/**
* Calculate the negative flag.
*/
inline
bool
findNegative(int width, uint64_t dest) {
return bits(dest, width - 1, width - 1);
}
/**
* Calculate the zero flag.
*/
inline
bool
findZero(int width, uint64_t dest) {
return !(dest & mask(width));
}
#endif // __BASE_CONDCODE_HH__

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,523 @@
/*
* Copyright (c) 2006-2009 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Ali Saidi
*/
#ifndef __BASE__CP_ANNOTATE_HH__
#define __BASE__CP_ANNOTATE_HH__
#include <list>
#include <map>
#include <string>
#include <vector>
#include "base/loader/symtab.hh"
#include "base/hashmap.hh"
#include "base/trace.hh"
#include "base/types.hh"
#include "config/cp_annotate.hh"
#include "config/the_isa.hh"
#include "sim/serialize.hh"
#include "sim/system.hh"
#if CP_ANNOTATE
#include "params/CPA.hh"
#endif
class System;
class ThreadContext;
#if !CP_ANNOTATE
class CPA
{
public:
enum flags {
FL_NONE = 0x00,
FL_HW = 0x01,
FL_BAD = 0x02,
FL_QOPP = 0x04,
FL_WAIT = 0x08,
FL_LINK = 0x10,
FL_RESET = 0x20
};
static CPA *cpa() { return NULL; }
static bool available() { return false; }
bool enabled() { return false; }
void swSmBegin(ThreadContext *tc) { return; }
void swSmEnd(ThreadContext *tc) { return; }
void swExplictBegin(ThreadContext *tc) { return; }
void swAutoBegin(ThreadContext *tc, Addr next_pc) { return; }
void swEnd(ThreadContext *tc) { return; }
void swQ(ThreadContext *tc) { return; }
void swDq(ThreadContext *tc) { return; }
void swPq(ThreadContext *tc) { return; }
void swRq(ThreadContext *tc) { return; }
void swWf(ThreadContext *tc) { return; }
void swWe(ThreadContext *tc) { return; }
void swSq(ThreadContext *tc) { return; }
void swAq(ThreadContext *tc) { return; }
void swLink(ThreadContext *tc) { return; }
void swIdentify(ThreadContext *tc) { return; }
uint64_t swGetId(ThreadContext *tc) { return 0; }
void swSyscallLink(ThreadContext *tc) { return; }
void hwBegin(flags f, System *sys, uint64_t frame, std::string sm,
std::string st) { return; }
void hwQ(flags f, System *sys, uint64_t frame, std::string sm,
std::string q, uint64_t qid, System *q_sys = NULL,
int32_t count = 1) { return; }
void hwDq(flags f, System *sys, uint64_t frame, std::string sm,
std::string q, uint64_t qid, System *q_sys = NULL,
int32_t count = 1) { return; }
void hwPq(flags f, System *sys, uint64_t frame, std::string sm,
std::string q, uint64_t qid, System *q_sys = NULL,
int32_t count = 1) { return; }
void hwRq(flags f, System *sys, uint64_t frame, std::string sm,
std::string q, uint64_t qid, System *q_sys = NULL,
int32_t count = 1) { return; }
void hwWf(flags f, System *sys, uint64_t frame, std::string sm,
std::string q, uint64_t qid, System *q_sys = NULL,
int32_t count = 1) { return; }
void hwWe(flags f, System *sys, uint64_t frame, std::string sm,
std::string q, uint64_t qid, System *q_sys = NULL,
int32_t count = 1) { return; }
};
#else
class CPA : SimObject
{
public:
typedef CPAParams Params;
/** The known operations that are written to the annotation output file. */
enum ops {
OP_BEGIN = 0x01,
OP_WAIT_EMPTY = 0x02,
OP_WAIT_FULL = 0x03,
OP_QUEUE = 0x04,
OP_DEQUEUE = 0x05,
OP_SIZE_QUEUE = 0x08,
OP_PEEK = 0x09,
OP_LINK = 0x0A,
OP_IDENT = 0x0B,
OP_RESERVE = 0x0C
};
/** Flags for the various options.*/
enum flags {
/* no flags */
FL_NONE = 0x00,
/* operation was done on hardware */
FL_HW = 0x01,
/* operation should cause a warning when encountered */
FL_BAD = 0x02,
/* Queue like a stack, not a queue */
FL_QOPP = 0x04,
/* Mark HW state as waiting for some non-resource constraint
* (e.g. wait because SM only starts after 10 items are queued) */
FL_WAIT = 0x08,
/* operation is linking to another state machine */
FL_LINK = 0x10,
/* queue should be completely cleared/reset before executing this
* operation */
FL_RESET = 0x20
};
protected:
const Params *
params() const
{
return dynamic_cast<const Params *>(_params);
}
/* struct that is written to the annotation output file */
struct AnnotateData : public RefCounted {
Tick time;
uint32_t data;
uint32_t orig_data;
uint16_t sm;
uint16_t stq;
uint8_t op;
uint8_t flag;
uint8_t cpu;
bool dump;
void serialize(std::ostream &os);
void unserialize(Checkpoint *cp, const std::string &section);
};
typedef RefCountingPtr<AnnotateData> AnnDataPtr;
/* header for the annotation file */
struct AnnotateHeader {
uint64_t version;
uint64_t num_recs;
uint64_t key_off;
uint64_t idx_off;
uint32_t key_len;
uint32_t idx_len;
};
AnnotateHeader ah;
std::vector<uint64_t> annotateIdx;
// number of state machines encountered in the simulation
int numSm;
// number of states encountered in the simulation
int numSmt;
// number of states/queues for a given state machine/system respectively
std::vector<int> numSt, numQ;
// number of systems in the simulation
int numSys;
// number of queues in the state machine
int numQs;
// maximum connection id assigned so far
uint64_t conId;
// Convert state strings into state ids
typedef m5::hash_map<std::string, int> SCache;
typedef std::vector<SCache> StCache;
// Convert sm and queue name,id into queue id
typedef std::pair<std::string, uint64_t> Id;
typedef m5::hash_map<Id, int> IdHCache;
typedef std::vector<IdHCache> IdCache;
// Hold mapping of sm and queues to output python
typedef std::vector<std::pair<int, Id> > IdMap;
// System pointer to name,id
typedef std::map<System*, std::pair<std::string, int> > NameCache;
// array of systems each of which is a stack of running sm
typedef std::pair<int, uint64_t> StackId;
typedef std::map<StackId, std::vector<int> > SmStack;
// map of each context and if it's currently in explict state mode
// states are not automatically updated until it leaves
typedef std::map<StackId, bool> SwExpl;
typedef std::map<int,int> IMap;
// List of annotate records have not been written/completed yet
typedef std::list<AnnDataPtr> AnnotateList;
// Maintain link state information
typedef std::map<int, int> LinkMap;
// SC Links
typedef m5::hash_map<Id, AnnDataPtr> ScHCache;
typedef std::vector<ScHCache> ScCache;
AnnotateList data;
// vector indexed by queueid to find current number of elements and bytes
std::vector<int> qSize;
std::vector<int32_t> qBytes;
// Turn state machine string into state machine id (small int)
// Used for outputting key to convert id back into string
SCache smtCache;
// Turn state machine id, state name into state id (small int)
StCache stCache;
// turn system, queue, and queue identify into qid (small int)
// turn system, state, and context into state machine id (small int)
IdCache qCache, smCache;
//Link state machines accross system calls
ScCache scLinks;
// System pointer to name,id
NameCache nameCache;
// Stack of state machines currently nested (should unwind correctly)
SmStack smStack;
// Map of currently outstanding links
LinkMap lnMap;
// If the state machine is currently exculding automatic changes
SwExpl swExpl;
// Last state that a given state machine was in
IMap lastState;
// Hold mapping of sm and queues to output python
IdMap smMap, qMap;
// Items still in queue, used for sanity checking
std::vector<AnnotateList> qData;
void doDq(System *sys, int flags, int cpu, int sm, std::string q, int qi,
int count);
void doQ(System *sys, int flags, int cpu, int sm, std::string q, int qi,
int count);
void doSwSmEnd(System *sys, int cpuid, std::string sm, uint64_t frame);
// Turn a system id, state machine string, state machine id into a small int
// for annotation output
int
getSm(int sysi, std::string si, uint64_t id)
{
int smi;
Id smid = Id(si, id);
smi = smCache[sysi-1][smid];
if (smi == 0) {
smCache[sysi-1][smid] = smi = ++numSm;
assert(smi < 65535);
smMap.push_back(std::make_pair<int, Id>(sysi, smid));
}
return smi;
}
// Turn a state machine string, state string into a small int
// for annotation output
int
getSt(std::string sm, std::string s)
{
int sti, smi;
smi = smtCache[sm];
if (smi == 0)
smi = smtCache[sm] = ++numSmt;
while (stCache.size() < smi) {
//stCache.resize(sm);
stCache.push_back(SCache());
numSt.push_back(0);
}
//assert(stCache.size() == sm);
//assert(numSt.size() == sm);
sti = stCache[smi-1][s];
if (sti == 0)
stCache[smi-1][s] = sti = ++numSt[smi-1];
return sti;
}
// Turn state machine pointer into a smal int for annotation output
int
getSys(System *s)
{
NameCache::iterator i = nameCache.find(s);
if (i == nameCache.end()) {
nameCache[s] = std::make_pair<std::string,int>(s->name(), ++numSys);
i = nameCache.find(s);
// might need to put smstackid into map here, but perhaps not
//smStack.push_back(std::vector<int>());
//swExpl.push_back(false);
numQ.push_back(0);
qCache.push_back(IdHCache());
smCache.push_back(IdHCache());
scLinks.push_back(ScHCache());
}
return i->second.second;
}
// Turn queue name, and queue context into small int for
// annotation output
int
getQ(int sys, std::string q, uint64_t id)
{
int qi;
Id qid = Id(q, id);
qi = qCache[sys-1][qid];
if (qi == 0) {
qi = qCache[sys-1][qid] = ++numQs;
assert(qi < 65535);
qSize.push_back(0);
qBytes.push_back(0);
qData.push_back(AnnotateList());
numQ[sys-1]++;
qMap.push_back(std::make_pair<int, Id>(sys, qid));
}
return qi;
}
void swBegin(System *sys, int cpuid, std::string st, uint64_t frame,
bool expl = false, int flags = FL_NONE);
AnnDataPtr add(int t, int f, int c, int sm, int stq, int32_t data=0);
std::ostream *osbin;
bool _enabled;
/** Only allow one CPA object in a system. It doesn't make sense to have
* more that one per simulation because if a part of the system was
* important it would have annotations and queues, and with more than one
* object none of the sanity checking for queues will work. */
static bool exists;
static CPA *_cpa;
std::map<std::string, SymbolTable*> userApp;
public:
static CPA *cpa() { return _cpa; }
void swSmBegin(ThreadContext *tc);
void swSmEnd(ThreadContext *tc);
void swExplictBegin(ThreadContext *tc);
void swAutoBegin(ThreadContext *tc, Addr next_pc);
void swEnd(ThreadContext *tc);
void swQ(ThreadContext *tc);
void swDq(ThreadContext *tc);
void swPq(ThreadContext *tc);
void swRq(ThreadContext *tc);
void swWf(ThreadContext *tc);
void swWe(ThreadContext *tc);
void swSq(ThreadContext *tc);
void swAq(ThreadContext *tc);
void swLink(ThreadContext *tc);
void swIdentify(ThreadContext *tc);
uint64_t swGetId(ThreadContext *tc);
void swSyscallLink(ThreadContext *tc);
inline void hwBegin(flags f, System *sys, uint64_t frame, std::string sm,
std::string st)
{
if (!enabled())
return;
int sysi = getSys(sys);
int smi = getSm(sysi, sm, frame);
add(OP_BEGIN, FL_HW | f, 0, smi, getSt(sm, st));
if (f & FL_BAD)
warn("BAD state encountered: at cycle %d: %s\n", curTick(), st);
}
inline void hwQ(flags f, System *sys, uint64_t frame, std::string sm,
std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1)
{
if (!enabled())
return;
int sysi = getSys(sys);
int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid);
DPRINTFS(AnnotateQ, sys,
"hwQ: %s[%#x] cur size %d %d bytes: %d adding: %d\n",
q, qid, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
doQ(sys, FL_HW | f, 0, getSm(sysi, sm, frame), q, qi, count);
}
inline void hwDq(flags f, System *sys, uint64_t frame, std::string sm,
std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1)
{
if (!enabled())
return;
int sysi = getSys(sys);
int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid);
DPRINTFS(AnnotateQ, sys,
"hwDQ: %s[%#x] cur size %d %d bytes: %d removing: %d\n",
q, qid, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
doDq(sys, FL_HW | f, 0, getSm(sysi,sm, frame), q, qi, count);
}
inline void hwPq(flags f, System *sys, uint64_t frame, std::string sm,
std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1)
{
if (!enabled())
return;
int sysi = getSys(sys);
int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid);
DPRINTFS(AnnotateQ, sys,
"hwPQ: %s[%#x] cur size %d %d bytes: %d peeking: %d\n",
q, qid, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
add(OP_PEEK, FL_HW | f, 0, getSm(sysi, sm, frame), qi, count);
}
inline void hwRq(flags f, System *sys, uint64_t frame, std::string sm,
std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1)
{
if (!enabled())
return;
int sysi = getSys(sys);
int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid);
DPRINTFS(AnnotateQ, sys,
"hwRQ: %s[%#x] cur size %d %d bytes: %d reserving: %d\n",
q, qid, qSize[qi-1], qData[qi-1].size(), qBytes[qi-1], count);
add(OP_RESERVE, FL_HW | f, 0, getSm(sysi, sm, frame), qi, count);
}
inline void hwWf(flags f, System *sys, uint64_t frame, std::string sm,
std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1)
{
if (!enabled())
return;
int sysi = getSys(sys);
int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid);
add(OP_WAIT_FULL, FL_HW | f, 0, getSm(sysi, sm, frame), qi, count);
}
inline void hwWe(flags f, System *sys, uint64_t frame, std::string sm,
std::string q, uint64_t qid, System *q_sys = NULL, int32_t count = 1)
{
if (!enabled())
return;
int sysi = getSys(sys);
int qi = getQ(q_sys ? getSys(q_sys) : sysi, q, qid);
add(OP_WAIT_EMPTY, FL_HW | f, 0, getSm(sysi, sm, frame), qi, count);
}
public:
CPA(Params *p);
void startup();
// This code is ISA specific and will need to be changed
// if the annotation code is used for something other than Alpha
inline uint64_t getFrame(ThreadContext *tc)
{ return (tc->readMiscRegNoEffect(TheISA::IPR_PALtemp23) &
~ULL(0x3FFF)); }
static bool available() { return true; }
bool
enabled()
{
if (!this)
return false;
return _enabled;
}
void dump(bool all);
void dumpKey();
void serialize(std::ostream &os);
void unserialize(Checkpoint *cp, const std::string &section);
};
#endif // !CP_ANNOTATE
#endif //__BASE__CP_ANNOTATE_HH__

View File

@ -0,0 +1,294 @@
/*
* Copyright (c) 2002-2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#include <cassert>
#include <iomanip>
#include <iostream>
#include <sstream>
#include "base/cprintf.hh"
using namespace std;
namespace cp {
Print::Print(std::ostream &stream, const std::string &format)
: stream(stream), format(format.c_str()), ptr(format.c_str()), cont(false)
{
saved_flags = stream.flags();
saved_fill = stream.fill();
saved_precision = stream.precision();
}
Print::Print(std::ostream &stream, const char *format)
: stream(stream), format(format), ptr(format), cont(false)
{
saved_flags = stream.flags();
saved_fill = stream.fill();
saved_precision = stream.precision();
}
Print::~Print()
{
}
void
Print::process()
{
fmt.clear();
size_t len;
while (*ptr) {
switch (*ptr) {
case '%':
if (ptr[1] != '%')
goto processing;
stream.put('%');
ptr += 2;
break;
case '\n':
stream << endl;
++ptr;
break;
case '\r':
++ptr;
if (*ptr != '\n')
stream << endl;
break;
default:
len = strcspn(ptr, "%\n\r\0");
stream.write(ptr, len);
ptr += len;
break;
}
}
return;
processing:
bool done = false;
bool end_number = false;
bool have_precision = false;
int number = 0;
stream.fill(' ');
stream.flags((ios::fmtflags)0);
while (!done) {
++ptr;
if (*ptr >= '0' && *ptr <= '9') {
if (end_number)
continue;
} else if (number > 0)
end_number = true;
switch (*ptr) {
case 's':
fmt.format = Format::string;
done = true;
break;
case 'c':
fmt.format = Format::character;
done = true;
break;
case 'l':
continue;
case 'p':
fmt.format = Format::integer;
fmt.base = Format::hex;
fmt.alternate_form = true;
done = true;
break;
case 'X':
fmt.uppercase = true;
case 'x':
fmt.base = Format::hex;
fmt.format = Format::integer;
done = true;
break;
case 'o':
fmt.base = Format::oct;
fmt.format = Format::integer;
done = true;
break;
case 'd':
case 'i':
case 'u':
fmt.format = Format::integer;
done = true;
break;
case 'G':
fmt.uppercase = true;
case 'g':
fmt.format = Format::floating;
fmt.float_format = Format::best;
done = true;
break;
case 'E':
fmt.uppercase = true;
case 'e':
fmt.format = Format::floating;
fmt.float_format = Format::scientific;
done = true;
break;
case 'f':
fmt.format = Format::floating;
fmt.float_format = Format::fixed;
done = true;
break;
case 'n':
stream << "we don't do %n!!!\n";
done = true;
break;
case '#':
fmt.alternate_form = true;
break;
case '-':
fmt.flush_left = true;
break;
case '+':
fmt.print_sign = true;
break;
case ' ':
fmt.blank_space = true;
break;
case '.':
fmt.width = number;
fmt.precision = 0;
have_precision = true;
number = 0;
end_number = false;
break;
case '0':
if (number == 0) {
fmt.fill_zero = true;
break;
}
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
number = number * 10 + (*ptr - '0');
break;
case '*':
if (have_precision)
fmt.get_precision = true;
else
fmt.get_width = true;
break;
case '%':
assert(false && "we shouldn't get here");
break;
default:
done = true;
break;
}
if (end_number) {
if (have_precision)
fmt.precision = number;
else
fmt.width = number;
end_number = false;
number = 0;
}
}
++ptr;
}
void
Print::end_args()
{
size_t len;
while (*ptr) {
switch (*ptr) {
case '%':
if (ptr[1] != '%')
stream << "<extra arg>";
stream.put('%');
ptr += 2;
break;
case '\n':
stream << endl;
++ptr;
break;
case '\r':
++ptr;
if (*ptr != '\n')
stream << endl;
break;
default:
len = strcspn(ptr, "%\n\r\0");
stream.write(ptr, len);
ptr += len;
break;
}
}
stream.flags(saved_flags);
stream.fill(saved_fill);
stream.precision(saved_precision);
}
} // namespace cp

View File

@ -0,0 +1,192 @@
/*
* Copyright (c) 2002-2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
* Steve Reinhardt
*/
#ifndef __BASE_CPRINTF_HH__
#define __BASE_CPRINTF_HH__
#include <ios>
#include <iostream>
#include <list>
#include <string>
#include "base/cprintf_formats.hh"
#include "base/varargs.hh"
namespace cp {
#define CPRINTF_DECLARATION VARARGS_DECLARATION(cp::Print)
#define CPRINTF_DEFINITION VARARGS_DEFINITION(cp::Print)
struct Print
{
protected:
std::ostream &stream;
const char *format;
const char *ptr;
bool cont;
std::ios::fmtflags saved_flags;
char saved_fill;
int saved_precision;
Format fmt;
void process();
public:
Print(std::ostream &stream, const std::string &format);
Print(std::ostream &stream, const char *format);
~Print();
int
get_number(int data)
{
return data;
}
template <typename T>
int
get_number(const T& data)
{
return 0;
}
template <typename T>
void
add_arg(const T &data)
{
if (!cont)
process();
if (fmt.get_width) {
fmt.get_width = false;
cont = true;
fmt.width = get_number(data);
return;
}
if (fmt.get_precision) {
fmt.get_precision = false;
cont = true;
fmt.precision = get_number(data);
return;
}
switch (fmt.format) {
case Format::character:
format_char(stream, data, fmt);
break;
case Format::integer:
format_integer(stream, data, fmt);
break;
case Format::floating:
format_float(stream, data, fmt);
break;
case Format::string:
format_string(stream, data, fmt);
break;
default:
stream << "<bad format>";
break;
}
}
void end_args();
};
} // namespace cp
typedef VarArgs::List<cp::Print> CPrintfArgsList;
inline void
ccprintf(std::ostream &stream, const char *format, const CPrintfArgsList &args)
{
cp::Print print(stream, format);
args.add_args(print);
}
inline void
ccprintf(std::ostream &stream, const char *format, CPRINTF_DECLARATION)
{
cp::Print print(stream, format);
VARARGS_ADDARGS(print);
}
inline void
cprintf(const char *format, CPRINTF_DECLARATION)
{
ccprintf(std::cout, format, VARARGS_ALLARGS);
}
inline std::string
csprintf(const char *format, CPRINTF_DECLARATION)
{
std::stringstream stream;
ccprintf(stream, format, VARARGS_ALLARGS);
return stream.str();
}
/*
* functions again with std::string. We have both so we don't waste
* time converting const char * to std::string since we don't take
* advantage of it.
*/
inline void
ccprintf(std::ostream &stream, const std::string &format,
const CPrintfArgsList &args)
{
ccprintf(stream, format.c_str(), args);
}
inline void
ccprintf(std::ostream &stream, const std::string &format, CPRINTF_DECLARATION)
{
ccprintf(stream, format.c_str(), VARARGS_ALLARGS);
}
inline void
cprintf(const std::string &format, CPRINTF_DECLARATION)
{
ccprintf(std::cout, format.c_str(), VARARGS_ALLARGS);
}
inline std::string
csprintf(const std::string &format, CPRINTF_DECLARATION)
{
std::stringstream stream;
ccprintf(stream, format.c_str(), VARARGS_ALLARGS);
return stream.str();
}
#endif // __CPRINTF_HH__

View File

@ -0,0 +1,360 @@
/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#ifndef __BASE_CPRINTF_FORMATS_HH__
#define __BASE_CPRINTF_FORMATS_HH__
#include <cstring>
#include <ostream>
#include <sstream>
namespace cp {
struct Format
{
bool alternate_form;
bool flush_left;
bool print_sign;
bool blank_space;
bool fill_zero;
bool uppercase;
enum { dec, hex, oct } base;
enum { none, string, integer, character, floating } format;
enum { best, fixed, scientific } float_format;
int precision;
int width;
bool get_precision;
bool get_width;
Format() { clear(); }
void clear()
{
alternate_form = false;
flush_left = false;
print_sign = false;
blank_space = false;
fill_zero = false;
uppercase = false;
base = dec;
format = none;
precision = -1;
width = 0;
get_precision = false;
get_width = false;
}
};
template <typename T>
inline void
_format_char(std::ostream &out, const T &data, Format &fmt)
{
using namespace std;
out << data;
}
template <typename T>
inline void
_format_integer(std::ostream &out, const T &data, Format &fmt)
{
using namespace std;
switch (fmt.base) {
case Format::hex:
out.setf(std::ios::hex, std::ios::basefield);
break;
case Format::oct:
out.setf(std::ios::oct, std::ios::basefield);
break;
case Format::dec:
out.setf(std::ios::dec, std::ios::basefield);
break;
}
if (fmt.alternate_form) {
if (!fmt.fill_zero)
out.setf(std::ios::showbase);
else {
switch (fmt.base) {
case Format::hex:
out << "0x";
fmt.width -= 2;
break;
case Format::oct:
out << "0";
fmt.width -= 1;
break;
case Format::dec:
break;
}
}
}
if (fmt.fill_zero)
out.fill('0');
if (fmt.width > 0)
out.width(fmt.width);
if (fmt.flush_left && !fmt.fill_zero)
out.setf(std::ios::left);
if (fmt.print_sign)
out.setf(std::ios::showpos);
if (fmt.uppercase)
out.setf(std::ios::uppercase);
out << data;
}
template <typename T>
inline void
_format_float(std::ostream &out, const T &data, Format &fmt)
{
using namespace std;
switch (fmt.float_format) {
case Format::scientific:
if (fmt.precision != -1) {
if (fmt.width > 0)
out.width(fmt.width);
if (fmt.precision == 0)
fmt.precision = 1;
else
out.setf(std::ios::scientific);
out.precision(fmt.precision);
} else
if (fmt.width > 0)
out.width(fmt.width);
if (fmt.uppercase)
out.setf(std::ios::uppercase);
break;
case Format::fixed:
if (fmt.precision != -1) {
if (fmt.width > 0)
out.width(fmt.width);
out.setf(std::ios::fixed);
out.precision(fmt.precision);
} else
if (fmt.width > 0)
out.width(fmt.width);
break;
default:
if (fmt.precision != -1)
out.precision(fmt.precision);
if (fmt.width > 0)
out.width(fmt.width);
break;
}
out << data;
}
template <typename T>
inline void
_format_string(std::ostream &out, const T &data, Format &fmt)
{
using namespace std;
#if defined(__GNUC__) && (__GNUC__ < 3) || 1
if (fmt.width > 0) {
std::stringstream foo;
foo << data;
int flen = foo.str().size();
if (fmt.width > flen) {
char *spaces = new char[fmt.width - flen + 1];
memset(spaces, ' ', fmt.width - flen);
spaces[fmt.width - flen] = 0;
if (fmt.flush_left)
out << foo.str() << spaces;
else
out << spaces << foo.str();
delete [] spaces;
} else
out << data;
} else
out << data;
#else
if (fmt.width > 0)
out.width(fmt.width);
if (fmt.flush_left)
out.setf(std::ios::left);
out << data;
#endif
}
/////////////////////////////////////////////////////////////////////////////
//
// The code below controls the actual usage of formats for various types
//
//
// character formats
//
template <typename T>
inline void
format_char(std::ostream &out, const T &data, Format &fmt)
{ out << "<bad arg type for char format>"; }
inline void
format_char(std::ostream &out, char data, Format &fmt)
{ _format_char(out, data, fmt); }
inline void
format_char(std::ostream &out, unsigned char data, Format &fmt)
{ _format_char(out, data, fmt); }
inline void
format_char(std::ostream &out, signed char data, Format &fmt)
{ _format_char(out, data, fmt); }
inline void
format_char(std::ostream &out, short data, Format &fmt)
{ _format_char(out, (char)data, fmt); }
inline void
format_char(std::ostream &out, unsigned short data, Format &fmt)
{ _format_char(out, (char)data, fmt); }
inline void
format_char(std::ostream &out, int data, Format &fmt)
{ _format_char(out, (char)data, fmt); }
inline void
format_char(std::ostream &out, unsigned int data, Format &fmt)
{ _format_char(out, (char)data, fmt); }
inline void
format_char(std::ostream &out, long data, Format &fmt)
{ _format_char(out, (char)data, fmt); }
inline void
format_char(std::ostream &out, unsigned long data, Format &fmt)
{ _format_char(out, (char)data, fmt); }
inline void
format_char(std::ostream &out, long long data, Format &fmt)
{ _format_char(out, (char)data, fmt); }
inline void
format_char(std::ostream &out, unsigned long long data, Format &fmt)
{ _format_char(out, (char)data, fmt); }
//
// integer formats
//
template <typename T>
inline void
format_integer(std::ostream &out, const T &data, Format &fmt)
{ _format_integer(out, data, fmt); }
inline void
format_integer(std::ostream &out, char data, Format &fmt)
{ _format_integer(out, (int)data, fmt); }
inline void
format_integer(std::ostream &out, unsigned char data, Format &fmt)
{ _format_integer(out, (int)data, fmt); }
inline void
format_integer(std::ostream &out, signed char data, Format &fmt)
{ _format_integer(out, (int)data, fmt); }
#if 0
inline void
format_integer(std::ostream &out, short data, Format &fmt)
{ _format_integer(out, data, fmt); }
inline void
format_integer(std::ostream &out, unsigned short data, Format &fmt)
{ _format_integer(out, data, fmt); }
inline void
format_integer(std::ostream &out, int data, Format &fmt)
{ _format_integer(out, data, fmt); }
inline void
format_integer(std::ostream &out, unsigned int data, Format &fmt)
{ _format_integer(out, data, fmt); }
inline void
format_integer(std::ostream &out, long data, Format &fmt)
{ _format_integer(out, data, fmt); }
inline void
format_integer(std::ostream &out, unsigned long data, Format &fmt)
{ _format_integer(out, data, fmt); }
inline void
format_integer(std::ostream &out, long long data, Format &fmt)
{ _format_integer(out, data, fmt); }
inline void
format_integer(std::ostream &out, unsigned long long data, Format &fmt)
{ _format_integer(out, data, fmt); }
#endif
//
// floating point formats
//
template <typename T>
inline void
format_float(std::ostream &out, const T &data, Format &fmt)
{ out << "<bad arg type for float format>"; }
inline void
format_float(std::ostream &out, float data, Format &fmt)
{ _format_float(out, data, fmt); }
inline void
format_float(std::ostream &out, double data, Format &fmt)
{ _format_float(out, data, fmt); }
//
// string formats
//
template <typename T>
inline void
format_string(std::ostream &out, const T &data, Format &fmt)
{ _format_string(out, data, fmt); }
inline void
format_string(std::ostream &out, const std::stringstream &data, Format &fmt)
{ _format_string(out, data.str(), fmt); }
} // namespace cp
#endif // __CPRINTF_FORMATS_HH__

View File

@ -0,0 +1,31 @@
/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
const char *compileDate = __DATE__ " " __TIME__;

View File

@ -0,0 +1,185 @@
/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#include <sys/types.h>
#include <unistd.h>
#include <algorithm>
#include <csignal>
#include <map>
#include <vector>
#include "base/cprintf.hh"
#include "base/debug.hh"
#include "base/misc.hh"
using namespace std;
namespace Debug {
//
// This function will cause the process to signal itself with a
// SIGTRAP which is ignored if not in gdb, but will cause the debugger
// to break if in gdb.
//
void
breakpoint()
{
#ifndef NDEBUG
kill(getpid(), SIGTRAP);
#else
cprintf("Debug::breakpoint suppressed, compiled with NDEBUG\n");
#endif
}
//
// Flags for debugging purposes. Primarily for trace.hh
//
typedef std::map<string, Flag *> FlagsMap;
int allFlagsVersion = 0;
FlagsMap &
allFlags()
{
static FlagsMap flags;
return flags;
}
Flag *
findFlag(const std::string &name)
{
FlagsMap::iterator i = allFlags().find(name);
if (i == allFlags().end())
return NULL;
return i->second;
}
Flag::Flag(const char *name, const char *desc)
: _name(name), _desc(desc)
{
pair<FlagsMap::iterator, bool> result =
allFlags().insert(make_pair(name, this));
if (!result.second)
panic("Flag %s already defined!", name);
++allFlagsVersion;
}
Flag::~Flag()
{
// should find and remove flag.
}
void
CompoundFlag::enable()
{
SimpleFlag::enable();
for_each(_kids.begin(), _kids.end(), mem_fun(&Flag::enable));
}
void
CompoundFlag::disable()
{
SimpleFlag::disable();
for_each(_kids.begin(), _kids.end(), mem_fun(&Flag::disable));
}
struct AllFlags : public Flag
{
AllFlags()
: Flag("All", "All Flags")
{}
void
enable()
{
FlagsMap::iterator i = allFlags().begin();
FlagsMap::iterator end = allFlags().end();
for (; i != end; ++i)
if (i->second != this)
i->second->enable();
}
void
disable()
{
FlagsMap::iterator i = allFlags().begin();
FlagsMap::iterator end = allFlags().end();
for (; i != end; ++i)
if (i->second != this)
i->second->disable();
}
};
AllFlags theAllFlags;
Flag *const All = &theAllFlags;
bool
changeFlag(const char *s, bool value)
{
Flag *f = findFlag(s);
if (!f)
return false;
if (value)
f->enable();
else
f->disable();
return true;
}
} // namespace Debug
// add a set of functions that can easily be invoked from gdb
void
setDebugFlag(const char *string)
{
Debug::changeFlag(string, true);
}
void
clearDebugFlag(const char *string)
{
Debug::changeFlag(string, false);
}
void
dumpDebugFlags()
{
using namespace Debug;
FlagsMap::iterator i = allFlags().begin();
FlagsMap::iterator end = allFlags().end();
for (; i != end; ++i) {
SimpleFlag *f = dynamic_cast<SimpleFlag *>(i->second);
if (f && f->status())
cprintf("%s\n", f->name());
}
}

View File

@ -0,0 +1,115 @@
/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* Copyright (c) 2010 The Hewlett-Packard Development Company
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#ifndef __BASE_DEBUG_HH__
#define __BASE_DEBUG_HH__
#include <string>
#include <vector>
namespace Debug {
void breakpoint();
class Flag
{
protected:
const char *_name;
const char *_desc;
std::vector<Flag *> _kids;
public:
Flag(const char *name, const char *desc);
virtual ~Flag();
std::string name() const { return _name; }
std::string desc() const { return _desc; }
std::vector<Flag *> kids() { return _kids; }
virtual void enable() = 0;
virtual void disable() = 0;
};
class SimpleFlag : public Flag
{
protected:
bool _status;
public:
SimpleFlag(const char *name, const char *desc)
: Flag(name, desc)
{ }
bool status() const { return _status; }
operator bool() const { return _status; }
bool operator!() const { return !_status; }
void enable() { _status = true; }
void disable() { _status = false; }
};
class CompoundFlag : public SimpleFlag
{
protected:
void
addFlag(Flag &f)
{
if (&f != NULL)
_kids.push_back(&f);
}
public:
CompoundFlag(const char *name, const char *desc,
Flag &f00 = *(Flag *)0, Flag &f01 = *(Flag *)0,
Flag &f02 = *(Flag *)0, Flag &f03 = *(Flag *)0,
Flag &f04 = *(Flag *)0, Flag &f05 = *(Flag *)0,
Flag &f06 = *(Flag *)0, Flag &f07 = *(Flag *)0,
Flag &f08 = *(Flag *)0, Flag &f09 = *(Flag *)0,
Flag &f10 = *(Flag *)0, Flag &f11 = *(Flag *)0,
Flag &f12 = *(Flag *)0, Flag &f13 = *(Flag *)0,
Flag &f14 = *(Flag *)0, Flag &f15 = *(Flag *)0,
Flag &f16 = *(Flag *)0, Flag &f17 = *(Flag *)0,
Flag &f18 = *(Flag *)0, Flag &f19 = *(Flag *)0)
: SimpleFlag(name, desc)
{
addFlag(f00); addFlag(f01); addFlag(f02); addFlag(f03); addFlag(f04);
addFlag(f05); addFlag(f06); addFlag(f07); addFlag(f08); addFlag(f09);
addFlag(f10); addFlag(f11); addFlag(f12); addFlag(f13); addFlag(f14);
addFlag(f15); addFlag(f16); addFlag(f17); addFlag(f18); addFlag(f19);
}
void enable();
void disable();
};
} // namespace Debug
#endif // __BASE_DEBUG_HH__

View File

@ -0,0 +1,56 @@
/*
* Copyright (c) 2007 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Ali Saidi
*/
#include <assert.h>
#include <fenv.h>
#include <stdlib.h>
void m5_fesetround(int rm);
int m5_fegetround();
static const int m5_round_ops[] = {FE_DOWNWARD, FE_TONEAREST, FE_TOWARDZERO, FE_UPWARD};
void m5_fesetround(int rm)
{
assert(rm >= 0 && rm < 4);
fesetround(m5_round_ops[rm]);
}
int m5_fegetround()
{
int x;
int rm = fegetround();
for(x = 0; x < 4; x++)
if (m5_round_ops[x] == rm)
return x;
abort();
return 0;
}

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2004-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Steve Reinhardt
*/
#ifndef __BASE_FENV_HH__
#define __BASE_FENV_HH__
#include "config/use_fenv.hh"
#define M5_FE_DOWNWARD 0
#define M5_FE_TONEAREST 1
#define M5_FE_TOWARDZERO 2
#define M5_FE_UPWARD 3
#if USE_FENV
extern "C" {
void m5_fesetround(int rm);
int m5_fegetround();
}
#else
// Dummy definitions to allow code to compile w/o a real <fenv.h>.
inline void m5_fesetround(int rm) { ; }
inline int m5_fegetround() {return 0; }
#endif // USE_FENV
#endif // __BASE_FENV_HH__

View File

@ -0,0 +1,79 @@
/*
* Copyright (c) 2008 The Hewlett-Packard Development Company
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#ifndef __BASE_FLAGS_HH__
#define __BASE_FLAGS_HH__
template <typename T>
class Flags
{
private:
T _flags;
public:
typedef T Type;
Flags() : _flags(0) {}
Flags(Type flags) : _flags(flags) {}
operator const Type() const { return _flags; }
template <typename U>
const Flags<T> &
operator=(const Flags<U> &flags)
{
_flags = flags._flags;
return *this;
}
const Flags<T> &
operator=(T flags)
{
_flags = flags;
return *this;
}
bool isSet() const { return _flags; }
bool isSet(Type flags) const { return (_flags & flags); }
bool allSet() const { return !(~_flags); }
bool allSet(Type flags) const { return (_flags & flags) == flags; }
bool noneSet() const { return _flags == 0; }
bool noneSet(Type flags) const { return (_flags & flags) == 0; }
void clear() { _flags = 0; }
void clear(Type flags) { _flags &= ~flags; }
void set(Type flags) { _flags |= flags; }
void set(Type f, bool val) { _flags = (_flags & ~f) | (val ? f : 0); }
void
update(Type flags, Type mask)
{
_flags = (_flags & ~mask) | (flags & mask);
}
};
#endif // __BASE_FLAGS_HH__

View File

@ -0,0 +1,193 @@
/*
* Copyright (c) 2012 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
* not be construed as granting a license to any other intellectual
* property including but not limited to intellectual property relating
* to a hardware implementation of the functionality of the software
* licensed hereunder. You may use the software subject to the license
* terms below provided that you ensure that this notice is replicated
* unmodified and in its entirety in all distributions of the software,
* modified or unmodified, in source code or in binary form.
*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
* Andreas Hansson
*/
#ifndef __HASHMAP_HH__
#define __HASHMAP_HH__
#if defined(__GNUC__)
// for compilers that deprecate ext/hash_map, i.e. gcc >= 4.3 and
// clang, use unordered_map
// we need to determine what is available, as in the non-c++0x case,
// e.g. gcc >= 4.3 and <= 4.5, the containers are in the std::tr1
// namespace, and only gcc >= 4.6 (with -std=c++0x) adds the final
// container implementation in the std namespace
#if defined(__clang__)
// align with -std=c++0x only for clang >= 3.0 in CCFLAGS and also
// check if the header is present as this depends on what clang was
// built against, using XCode clang 3.1, for example, the header is
// not present without adding -stdlib=libc++
#if (__clang_major__ >= 3 && __has_include(<unordered_map>))
#define HAVE_STD_UNORDERED_MAP 1
#else
// we only support clang versions above 2.9 and these all have the tr1
// unordered_map
#define HAVE_STD_TR1_UNORDERED_MAP 1
#endif
#else
// align with -std=c++0x only for gcc >= 4.6 in CCFLAGS, contrary to
// clang we can rely entirely on the compiler version
#if ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4)
#define HAVE_STD_UNORDERED_MAP 1
#else
#define HAVE_STD_TR1_UNORDERED_MAP 1
#endif
#endif
// set a default value of 0
#ifndef HAVE_STD_UNORDERED_MAP
#define HAVE_STD_UNORDERED_MAP 0
#endif
// set a default value of 0
#ifndef HAVE_STD_TR1_UNORDERED_MAP
#define HAVE_STD_TR1_UNORDERED_MAP 0
#endif
// now we are ready to deal with the actual includes based on what is
// available
#if (HAVE_STD_UNORDERED_MAP || HAVE_STD_TR1_UNORDERED_MAP)
#define hash_map unordered_map
#define hash_multimap unordered_multimap
#define hash_set unordered_set
#define hash_multiset unordered_multiset
// these versions also have an existing hash function for strings and
// 64-bit integer types
#define HAVE_HASH_FUNCTIONS 1
#if HAVE_STD_UNORDERED_MAP
// clang or gcc >= 4.6
#include <unordered_map>
#include <unordered_set>
// note that this assumes that -std=c++0x is added to the command line
// which is done in the SConstruct CXXFLAGS for gcc >= 4.6 and clang
// >= 3.0
#define __hash_namespace std
#define __hash_namespace_begin namespace std {
#define __hash_namespace_end }
#else
// clang <= 3.0, gcc >= 4.3 and < 4.6
#include <tr1/unordered_map>
#include <tr1/unordered_set>
#define __hash_namespace std::tr1
#define __hash_namespace_begin namespace std { namespace tr1 {
#define __hash_namespace_end } }
#endif
#else
// gcc < 4.3
#include <ext/hash_map>
#include <ext/hash_set>
#define __hash_namespace __gnu_cxx
#define __hash_namespace_begin namespace __gnu_cxx {
#define __hash_namespace_end }
#endif
#else
// non GNU compiler
#include <hash_map>
#include <hash_set>
#define __hash_namsepace std
#define __hash_namespace_begin namespace std {
#define __hash_namespace_end }
#endif
#include <string>
#include "base/types.hh"
namespace m5 {
using ::__hash_namespace::hash_multimap;
using ::__hash_namespace::hash_multiset;
using ::__hash_namespace::hash_map;
using ::__hash_namespace::hash_set;
using ::__hash_namespace::hash;
}
///////////////////////////////////
// Some default Hashing Functions
//
__hash_namespace_begin
// if the hash functions for 64-bit integer types and strings are not
// already available, then declare them here
#if !defined(HAVE_HASH_FUNCTIONS)
#if !defined(__LP64__) && !defined(__alpha__) && !defined(__SUNPRO_CC)
template<>
struct hash<uint64_t> {
size_t operator()(uint64_t r) const {
return r;
}
};
template<>
struct hash<int64_t> {
size_t operator()(int64_t r) const {
return r;
};
};
#endif
template<>
struct hash<std::string> {
size_t operator()(const std::string &s) const {
return(__stl_hash_string(s.c_str()));
}
};
template <>
struct hash<std::pair<std::string, uint64_t> > {
size_t operator() (std::pair<std::string, uint64_t> r) const {
return (__stl_hash_string(r.first.c_str())) ^ r.second;
}
};
#endif
__hash_namespace_end
#endif // __HASHMAP_HH__

View File

@ -0,0 +1,118 @@
/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#include <unistd.h>
#ifdef __APPLE__
#include <mach/mach_init.h>
#include <mach/shared_region.h>
#include <mach/task.h>
#endif
#include <cctype>
#include <cerrno>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include "base/misc.hh"
#include "base/types.hh"
using namespace std;
string
__get_hostname()
{
char host[256];
if (gethostname(host, sizeof host) == -1)
warn("could not get host name!");
return host;
}
string &
hostname()
{
static string hostname = __get_hostname();
return hostname;
}
uint64_t
procInfo(const char *filename, const char *target)
{
int done = 0;
char line[80];
char format[80];
long usage;
FILE *fp = fopen(filename, "r");
while (fp && !feof(fp) && !done) {
if (fgets(line, 80, fp)) {
if (strncmp(line, target, strlen(target)) == 0) {
snprintf(format, sizeof(format), "%s %%ld", target);
sscanf(line, format, &usage);
fclose(fp);
return usage ;
}
}
}
if (fp)
fclose(fp);
return 0;
}
uint64_t
memUsage()
{
// For the Mach-based Darwin kernel, use the task_info of the self task
#ifdef __APPLE__
struct task_basic_info t_info;
mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT;
if (KERN_SUCCESS != task_info(mach_task_self(),
TASK_BASIC_INFO, (task_info_t)&t_info,
&t_info_count)) {
return 0;
}
// Mimic Darwin's implementation of top and subtract
// SHARED_REGION_SIZE from the tasks virtual size to account for the
// shared memory submap that is incorporated into every process.
return (t_info.virtual_size - SHARED_REGION_SIZE) / 1024;
#else
// Linux implementation
return procInfo("/proc/self/status", "VmSize:");
#endif
}

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#ifndef __HOSTINFO_HH__
#define __HOSTINFO_HH__
#include <string>
#include "base/types.hh"
std::string &hostname();
uint64_t procInfo(const char *filename, const char *target);
/**
* Determine the simulator process' total virtual memory usage.
*
* @return virtual memory usage in kilobytes
*/
uint64_t memUsage();
#endif // __HOSTINFO_HH__

View File

@ -0,0 +1,301 @@
/*
* Copyright (c) 2002-2005 The Regents of The University of Michigan
* Copyright (c) 2010 Advanced Micro Devices, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
* Gabe Black
*/
#include <cstddef>
#include <cstdio>
#include <sstream>
#include <string>
#include "base/cprintf.hh"
#include "base/inet.hh"
#include "base/types.hh"
using namespace std;
namespace Net {
EthAddr::EthAddr()
{
memset(data, 0, ETH_ADDR_LEN);
}
EthAddr::EthAddr(const uint8_t ea[ETH_ADDR_LEN])
{
*data = *ea;
}
EthAddr::EthAddr(const eth_addr &ea)
{
*data = *ea.data;
}
EthAddr::EthAddr(const std::string &addr)
{
parse(addr);
}
const EthAddr &
EthAddr::operator=(const eth_addr &ea)
{
*data = *ea.data;
return *this;
}
const EthAddr &
EthAddr::operator=(const std::string &addr)
{
parse(addr);
return *this;
}
void
EthAddr::parse(const std::string &addr)
{
// the hack below is to make sure that ETH_ADDR_LEN is 6 otherwise
// the sscanf function won't work.
int bytes[ETH_ADDR_LEN == 6 ? ETH_ADDR_LEN : -1];
if (sscanf(addr.c_str(), "%x:%x:%x:%x:%x:%x", &bytes[0], &bytes[1],
&bytes[2], &bytes[3], &bytes[4], &bytes[5]) != ETH_ADDR_LEN) {
memset(data, 0xff, ETH_ADDR_LEN);
return;
}
for (int i = 0; i < ETH_ADDR_LEN; ++i) {
if (bytes[i] & ~0xff) {
memset(data, 0xff, ETH_ADDR_LEN);
return;
}
data[i] = bytes[i];
}
}
string
EthAddr::string() const
{
stringstream stream;
stream << *this;
return stream.str();
}
bool
operator==(const EthAddr &left, const EthAddr &right)
{
return memcmp(left.bytes(), right.bytes(), ETH_ADDR_LEN);
}
ostream &
operator<<(ostream &stream, const EthAddr &ea)
{
const uint8_t *a = ea.addr();
ccprintf(stream, "%x:%x:%x:%x:%x:%x", a[0], a[1], a[2], a[3], a[4], a[5]);
return stream;
}
string
IpAddress::string() const
{
stringstream stream;
stream << *this;
return stream.str();
}
bool
operator==(const IpAddress &left, const IpAddress &right)
{
return left.ip() == right.ip();
}
ostream &
operator<<(ostream &stream, const IpAddress &ia)
{
uint32_t ip = ia.ip();
ccprintf(stream, "%x.%x.%x.%x",
(uint8_t)(ip >> 24), (uint8_t)(ip >> 16),
(uint8_t)(ip >> 8), (uint8_t)(ip >> 0));
return stream;
}
string
IpNetmask::string() const
{
stringstream stream;
stream << *this;
return stream.str();
}
bool
operator==(const IpNetmask &left, const IpNetmask &right)
{
return (left.ip() == right.ip()) &&
(left.netmask() == right.netmask());
}
ostream &
operator<<(ostream &stream, const IpNetmask &in)
{
ccprintf(stream, "%s/%d", (const IpAddress &)in, in.netmask());
return stream;
}
string
IpWithPort::string() const
{
stringstream stream;
stream << *this;
return stream.str();
}
bool
operator==(const IpWithPort &left, const IpWithPort &right)
{
return (left.ip() == right.ip()) && (left.port() == right.port());
}
ostream &
operator<<(ostream &stream, const IpWithPort &iwp)
{
ccprintf(stream, "%s:%d", (const IpAddress &)iwp, iwp.port());
return stream;
}
uint16_t
cksum(const IpPtr &ptr)
{
int sum = ip_cksum_add(ptr->bytes(), ptr->hlen(), 0);
return ip_cksum_carry(sum);
}
uint16_t
__tu_cksum(const IpPtr &ip)
{
int tcplen = ip->len() - ip->hlen();
int sum = ip_cksum_add(ip->payload(), tcplen, 0);
sum = ip_cksum_add(&ip->ip_src, 8, sum); // source and destination
sum += htons(ip->ip_p + tcplen);
return ip_cksum_carry(sum);
}
uint16_t
cksum(const TcpPtr &tcp)
{ return __tu_cksum(IpPtr(tcp.packet())); }
uint16_t
cksum(const UdpPtr &udp)
{ return __tu_cksum(IpPtr(udp.packet())); }
bool
IpHdr::options(vector<const IpOpt *> &vec) const
{
vec.clear();
const uint8_t *data = bytes() + sizeof(struct ip_hdr);
int all = hlen() - sizeof(struct ip_hdr);
while (all > 0) {
const IpOpt *opt = (const IpOpt *)data;
int len = opt->len();
if (all < len)
return false;
vec.push_back(opt);
all -= len;
data += len;
}
return true;
}
bool
TcpHdr::options(vector<const TcpOpt *> &vec) const
{
vec.clear();
const uint8_t *data = bytes() + sizeof(struct tcp_hdr);
int all = off() - sizeof(struct tcp_hdr);
while (all > 0) {
const TcpOpt *opt = (const TcpOpt *)data;
int len = opt->len();
if (all < len)
return false;
vec.push_back(opt);
all -= len;
data += len;
}
return true;
}
bool
TcpOpt::sack(vector<SackRange> &vec) const
{
vec.clear();
const uint8_t *data = bytes() + sizeof(struct tcp_hdr);
int all = len() - offsetof(tcp_opt, opt_data.sack);
while (all > 0) {
const uint16_t *sack = (const uint16_t *)data;
int len = sizeof(uint16_t) * 2;
if (all < len) {
vec.clear();
return false;
}
vec.push_back(RangeIn(ntohs(sack[0]), ntohs(sack[1])));
all -= len;
data += len;
}
return false;
}
int
hsplit(const EthPacketPtr &ptr)
{
int split_point = 0;
IpPtr ip(ptr);
if (ip) {
split_point = ip.pstart();
TcpPtr tcp(ip);
if (tcp)
split_point = tcp.pstart();
UdpPtr udp(ip);
if (udp)
split_point = udp.pstart();
}
return split_point;
}
} // namespace Net

View File

@ -0,0 +1,476 @@
/*
* Copyright (c) 2002-2005 The Regents of The University of Michigan
* Copyright (c) 2010 Advanced Micro Devices, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
* Steve Reinhardt
* Gabe Black
*/
#ifndef __BASE_INET_HH__
#define __BASE_INET_HH__
#include <iosfwd>
#include <string>
#include <utility>
#include <vector>
#include "base/range.hh"
#include "base/types.hh"
#include "dev/etherpkt.hh"
#include "dnet/os.h"
#include "dnet/eth.h"
#include "dnet/ip.h"
#include "dnet/ip6.h"
#include "dnet/addr.h"
#include "dnet/arp.h"
#include "dnet/icmp.h"
#include "dnet/tcp.h"
#include "dnet/udp.h"
#include "dnet/intf.h"
#include "dnet/route.h"
#include "dnet/fw.h"
#include "dnet/blob.h"
#include "dnet/rand.h"
namespace Net {
/*
* Ethernet Stuff
*/
struct EthAddr : protected eth_addr
{
protected:
void parse(const std::string &addr);
public:
EthAddr();
EthAddr(const uint8_t ea[ETH_ADDR_LEN]);
EthAddr(const eth_addr &ea);
EthAddr(const std::string &addr);
const EthAddr &operator=(const eth_addr &ea);
const EthAddr &operator=(const std::string &addr);
int size() const { return sizeof(eth_addr); }
const uint8_t *bytes() const { return &data[0]; }
uint8_t *bytes() { return &data[0]; }
const uint8_t *addr() const { return &data[0]; }
bool unicast() const { return data[0] == 0x00; }
bool multicast() const { return data[0] == 0x01; }
bool broadcast() const { return data[0] == 0xff; }
std::string string() const;
operator uint64_t() const
{
uint64_t reg = 0;
reg |= ((uint64_t)data[0]) << 40;
reg |= ((uint64_t)data[1]) << 32;
reg |= ((uint64_t)data[2]) << 24;
reg |= ((uint64_t)data[3]) << 16;
reg |= ((uint64_t)data[4]) << 8;
reg |= ((uint64_t)data[5]) << 0;
return reg;
}
};
std::ostream &operator<<(std::ostream &stream, const EthAddr &ea);
bool operator==(const EthAddr &left, const EthAddr &right);
struct EthHdr : public eth_hdr
{
uint16_t type() const { return ntohs(eth_type); }
const EthAddr &src() const { return *(EthAddr *)&eth_src; }
const EthAddr &dst() const { return *(EthAddr *)&eth_dst; }
int size() const { return sizeof(eth_hdr); }
const uint8_t *bytes() const { return (const uint8_t *)this; }
const uint8_t *payload() const { return bytes() + size(); }
uint8_t *bytes() { return (uint8_t *)this; }
uint8_t *payload() { return bytes() + size(); }
};
class EthPtr
{
protected:
friend class IpPtr;
EthPacketPtr p;
public:
EthPtr() {}
EthPtr(const EthPacketPtr &ptr) : p(ptr) { }
EthHdr *operator->() { return (EthHdr *)p->data; }
EthHdr &operator*() { return *(EthHdr *)p->data; }
operator EthHdr *() { return (EthHdr *)p->data; }
const EthHdr *operator->() const { return (const EthHdr *)p->data; }
const EthHdr &operator*() const { return *(const EthHdr *)p->data; }
operator const EthHdr *() const { return (const EthHdr *)p->data; }
const EthPtr &operator=(const EthPacketPtr &ptr) { p = ptr; return *this; }
const EthPacketPtr packet() const { return p; }
EthPacketPtr packet() { return p; }
bool operator!() const { return !p; }
operator bool() const { return p; }
int off() const { return 0; }
int pstart() const { return off() + ((const EthHdr*)p->data)->size(); }
};
/*
* IP Stuff
*/
struct IpAddress
{
protected:
uint32_t _ip;
public:
IpAddress() : _ip(0)
{}
IpAddress(const uint32_t __ip) : _ip(__ip)
{}
uint32_t ip() const { return _ip; }
std::string string() const;
};
std::ostream &operator<<(std::ostream &stream, const IpAddress &ia);
bool operator==(const IpAddress &left, const IpAddress &right);
struct IpNetmask : public IpAddress
{
protected:
uint8_t _netmask;
public:
IpNetmask() : IpAddress(), _netmask(0)
{}
IpNetmask(const uint32_t __ip, const uint8_t __netmask) :
IpAddress(__ip), _netmask(__netmask)
{}
uint8_t netmask() const { return _netmask; }
std::string string() const;
};
std::ostream &operator<<(std::ostream &stream, const IpNetmask &in);
bool operator==(const IpNetmask &left, const IpNetmask &right);
struct IpWithPort : public IpAddress
{
protected:
uint16_t _port;
public:
IpWithPort() : IpAddress(), _port(0)
{}
IpWithPort(const uint32_t __ip, const uint16_t __port) :
IpAddress(__ip), _port(__port)
{}
uint8_t port() const { return _port; }
std::string string() const;
};
std::ostream &operator<<(std::ostream &stream, const IpWithPort &iwp);
bool operator==(const IpWithPort &left, const IpWithPort &right);
struct IpOpt;
struct IpHdr : public ip_hdr
{
uint8_t version() const { return ip_v; }
uint8_t hlen() const { return ip_hl * 4; }
uint8_t tos() const { return ip_tos; }
uint16_t len() const { return ntohs(ip_len); }
uint16_t id() const { return ntohs(ip_id); }
uint16_t frag_flags() const { return ntohs(ip_off) >> 13; }
uint16_t frag_off() const { return ntohs(ip_off) & 0x1fff; }
uint8_t ttl() const { return ip_ttl; }
uint8_t proto() const { return ip_p; }
uint16_t sum() const { return ip_sum; }
uint32_t src() const { return ntohl(ip_src); }
uint32_t dst() const { return ntohl(ip_dst); }
void sum(uint16_t sum) { ip_sum = sum; }
void id(uint16_t _id) { ip_id = htons(_id); }
void len(uint16_t _len) { ip_len = htons(_len); }
bool options(std::vector<const IpOpt *> &vec) const;
int size() const { return hlen(); }
const uint8_t *bytes() const { return (const uint8_t *)this; }
const uint8_t *payload() const { return bytes() + size(); }
uint8_t *bytes() { return (uint8_t *)this; }
uint8_t *payload() { return bytes() + size(); }
};
class IpPtr
{
protected:
friend class TcpPtr;
friend class UdpPtr;
EthPacketPtr p;
void set(const EthPacketPtr &ptr)
{
p = 0;
if (ptr) {
EthHdr *eth = (EthHdr *)ptr->data;
if (eth->type() == ETH_TYPE_IP)
p = ptr;
}
}
public:
IpPtr() : p(0) {}
IpPtr(const EthPacketPtr &ptr) : p(0) { set(ptr); }
IpPtr(const EthPtr &ptr) : p(0) { set(ptr.p); }
IpPtr(const IpPtr &ptr) : p(ptr.p) { }
IpHdr *get() { return (IpHdr *)(p->data + sizeof(eth_hdr)); }
IpHdr *operator->() { return get(); }
IpHdr &operator*() { return *get(); }
const IpHdr *get() const
{ return (const IpHdr *)(p->data + sizeof(eth_hdr)); }
const IpHdr *operator->() const { return get(); }
const IpHdr &operator*() const { return *get(); }
const IpPtr &operator=(const EthPacketPtr &ptr) { set(ptr); return *this; }
const IpPtr &operator=(const EthPtr &ptr) { set(ptr.p); return *this; }
const IpPtr &operator=(const IpPtr &ptr) { p = ptr.p; return *this; }
const EthPacketPtr packet() const { return p; }
EthPacketPtr packet() { return p; }
bool operator!() const { return !p; }
operator bool() const { return p; }
int off() const { return sizeof(eth_hdr); }
int pstart() const { return off() + get()->size(); }
};
uint16_t cksum(const IpPtr &ptr);
struct IpOpt : public ip_opt
{
uint8_t type() const { return opt_type; }
uint8_t typeNumber() const { return IP_OPT_NUMBER(opt_type); }
uint8_t typeClass() const { return IP_OPT_CLASS(opt_type); }
uint8_t typeCopied() const { return IP_OPT_COPIED(opt_type); }
uint8_t len() const { return IP_OPT_TYPEONLY(type()) ? 1 : opt_len; }
bool isNumber(int num) const { return typeNumber() == IP_OPT_NUMBER(num); }
bool isClass(int cls) const { return typeClass() == IP_OPT_CLASS(cls); }
bool isCopied(int cpy) const { return typeCopied() == IP_OPT_COPIED(cpy); }
const uint8_t *data() const { return opt_data.data8; }
void sec(ip_opt_data_sec &sec) const;
void lsrr(ip_opt_data_rr &rr) const;
void ssrr(ip_opt_data_rr &rr) const;
void ts(ip_opt_data_ts &ts) const;
uint16_t satid() const { return ntohs(opt_data.satid); }
uint16_t mtup() const { return ntohs(opt_data.mtu); }
uint16_t mtur() const { return ntohs(opt_data.mtu); }
void tr(ip_opt_data_tr &tr) const;
const uint32_t *addext() const { return &opt_data.addext[0]; }
uint16_t rtralt() const { return ntohs(opt_data.rtralt); }
void sdb(std::vector<uint32_t> &vec) const;
};
/*
* TCP Stuff
*/
struct TcpOpt;
struct TcpHdr : public tcp_hdr
{
uint16_t sport() const { return ntohs(th_sport); }
uint16_t dport() const { return ntohs(th_dport); }
uint32_t seq() const { return ntohl(th_seq); }
uint32_t ack() const { return ntohl(th_ack); }
uint8_t off() const { return th_off; }
uint8_t flags() const { return th_flags & 0x3f; }
uint16_t win() const { return ntohs(th_win); }
uint16_t sum() const { return th_sum; }
uint16_t urp() const { return ntohs(th_urp); }
void sum(uint16_t sum) { th_sum = sum; }
void seq(uint32_t _seq) { th_seq = htonl(_seq); }
void flags(uint8_t _flags) { th_flags = _flags; }
bool options(std::vector<const TcpOpt *> &vec) const;
int size() const { return off(); }
const uint8_t *bytes() const { return (const uint8_t *)this; }
const uint8_t *payload() const { return bytes() + size(); }
uint8_t *bytes() { return (uint8_t *)this; }
uint8_t *payload() { return bytes() + size(); }
};
class TcpPtr
{
protected:
EthPacketPtr p;
int _off;
void set(const EthPacketPtr &ptr, int offset) { p = ptr; _off = offset; }
void set(const IpPtr &ptr)
{
if (ptr && ptr->proto() == IP_PROTO_TCP)
set(ptr.p, sizeof(eth_hdr) + ptr->hlen());
else
set(0, 0);
}
public:
TcpPtr() : p(0), _off(0) {}
TcpPtr(const IpPtr &ptr) : p(0), _off(0) { set(ptr); }
TcpPtr(const TcpPtr &ptr) : p(ptr.p), _off(ptr._off) {}
TcpHdr *get() { return (TcpHdr *)(p->data + _off); }
TcpHdr *operator->() { return get(); }
TcpHdr &operator*() { return *get(); }
const TcpHdr *get() const { return (const TcpHdr *)(p->data + _off); }
const TcpHdr *operator->() const { return get(); }
const TcpHdr &operator*() const { return *get(); }
const TcpPtr &operator=(const IpPtr &i) { set(i); return *this; }
const TcpPtr &operator=(const TcpPtr &t) { set(t.p, t._off); return *this; }
const EthPacketPtr packet() const { return p; }
EthPacketPtr packet() { return p; }
bool operator!() const { return !p; }
operator bool() const { return p; }
int off() const { return _off; }
int pstart() const { return off() + get()->size(); }
};
uint16_t cksum(const TcpPtr &ptr);
typedef Range<uint16_t> SackRange;
struct TcpOpt : public tcp_opt
{
uint8_t type() const { return opt_type; }
uint8_t len() const { return TCP_OPT_TYPEONLY(type()) ? 1 : opt_len; }
bool isopt(int opt) const { return type() == opt; }
const uint8_t *data() const { return opt_data.data8; }
uint16_t mss() const { return ntohs(opt_data.mss); }
uint8_t wscale() const { return opt_data.wscale; }
bool sack(std::vector<SackRange> &vec) const;
uint32_t echo() const { return ntohl(opt_data.echo); }
uint32_t tsval() const { return ntohl(opt_data.timestamp[0]); }
uint32_t tsecr() const { return ntohl(opt_data.timestamp[1]); }
uint32_t cc() const { return ntohl(opt_data.cc); }
uint8_t cksum() const{ return opt_data.cksum; }
const uint8_t *md5() const { return opt_data.md5; }
int size() const { return len(); }
const uint8_t *bytes() const { return (const uint8_t *)this; }
const uint8_t *payload() const { return bytes() + size(); }
uint8_t *bytes() { return (uint8_t *)this; }
uint8_t *payload() { return bytes() + size(); }
};
/*
* UDP Stuff
*/
struct UdpHdr : public udp_hdr
{
uint16_t sport() const { return ntohs(uh_sport); }
uint16_t dport() const { return ntohs(uh_dport); }
uint16_t len() const { return ntohs(uh_ulen); }
uint16_t sum() const { return uh_sum; }
void sum(uint16_t sum) { uh_sum = sum; }
void len(uint16_t _len) { uh_ulen = htons(_len); }
int size() const { return sizeof(udp_hdr); }
const uint8_t *bytes() const { return (const uint8_t *)this; }
const uint8_t *payload() const { return bytes() + size(); }
uint8_t *bytes() { return (uint8_t *)this; }
uint8_t *payload() { return bytes() + size(); }
};
class UdpPtr
{
protected:
EthPacketPtr p;
int _off;
void set(const EthPacketPtr &ptr, int offset) { p = ptr; _off = offset; }
void set(const IpPtr &ptr)
{
if (ptr && ptr->proto() == IP_PROTO_UDP)
set(ptr.p, sizeof(eth_hdr) + ptr->hlen());
else
set(0, 0);
}
public:
UdpPtr() : p(0), _off(0) {}
UdpPtr(const IpPtr &ptr) : p(0), _off(0) { set(ptr); }
UdpPtr(const UdpPtr &ptr) : p(ptr.p), _off(ptr._off) {}
UdpHdr *get() { return (UdpHdr *)(p->data + _off); }
UdpHdr *operator->() { return get(); }
UdpHdr &operator*() { return *get(); }
const UdpHdr *get() const { return (const UdpHdr *)(p->data + _off); }
const UdpHdr *operator->() const { return get(); }
const UdpHdr &operator*() const { return *get(); }
const UdpPtr &operator=(const IpPtr &i) { set(i); return *this; }
const UdpPtr &operator=(const UdpPtr &t) { set(t.p, t._off); return *this; }
const EthPacketPtr packet() const { return p; }
EthPacketPtr packet() { return p; }
bool operator!() const { return !p; }
operator bool() const { return p; }
int off() const { return _off; }
int pstart() const { return off() + get()->size(); }
};
uint16_t cksum(const UdpPtr &ptr);
int hsplit(const EthPacketPtr &ptr);
} // namespace Net
#endif // __BASE_INET_HH__

View File

@ -0,0 +1,328 @@
/*
* Copyright (c) 2001-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
* Steve Reinhardt
*/
#include <algorithm>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include "base/inifile.hh"
#include "base/str.hh"
using namespace std;
IniFile::IniFile()
{}
IniFile::~IniFile()
{
SectionTable::iterator i = table.begin();
SectionTable::iterator end = table.end();
while (i != end) {
delete (*i).second;
++i;
}
}
bool
IniFile::load(const string &file)
{
ifstream f(file.c_str());
if (!f.is_open())
return false;
return load(f);
}
const string &
IniFile::Entry::getValue() const
{
referenced = true;
return value;
}
void
IniFile::Section::addEntry(const std::string &entryName,
const std::string &value,
bool append)
{
EntryTable::iterator ei = table.find(entryName);
if (ei == table.end()) {
// new entry
table[entryName] = new Entry(value);
}
else if (append) {
// append new reult to old entry
ei->second->appendValue(value);
}
else {
// override old entry
ei->second->setValue(value);
}
}
bool
IniFile::Section::add(const std::string &assignment)
{
string::size_type offset = assignment.find('=');
if (offset == string::npos) {
// no '=' found
cerr << "Can't parse .ini line " << assignment << endl;
return false;
}
// if "+=" rather than just "=" then append value
bool append = (assignment[offset-1] == '+');
string entryName = assignment.substr(0, append ? offset-1 : offset);
string value = assignment.substr(offset + 1);
eat_white(entryName);
eat_white(value);
addEntry(entryName, value, append);
return true;
}
IniFile::Entry *
IniFile::Section::findEntry(const std::string &entryName) const
{
referenced = true;
EntryTable::const_iterator ei = table.find(entryName);
return (ei == table.end()) ? NULL : ei->second;
}
IniFile::Section *
IniFile::addSection(const string &sectionName)
{
SectionTable::iterator i = table.find(sectionName);
if (i != table.end()) {
return i->second;
}
else {
// new entry
Section *sec = new Section();
table[sectionName] = sec;
return sec;
}
}
IniFile::Section *
IniFile::findSection(const string &sectionName) const
{
SectionTable::const_iterator i = table.find(sectionName);
return (i == table.end()) ? NULL : i->second;
}
// Take string of the form "<section>:<parameter>=<value>" and add to
// database. Return true if successful, false if parse error.
bool
IniFile::add(const string &str)
{
// find ':'
string::size_type offset = str.find(':');
if (offset == string::npos) // no ':' found
return false;
string sectionName = str.substr(0, offset);
string rest = str.substr(offset + 1);
eat_white(sectionName);
Section *s = addSection(sectionName);
return s->add(rest);
}
bool
IniFile::load(istream &f)
{
Section *section = NULL;
while (!f.eof()) {
f >> ws; // Eat whitespace
if (f.eof()) {
break;
}
string line;
getline(f, line);
if (line.size() == 0)
continue;
eat_end_white(line);
int last = line.size() - 1;
if (line[0] == '[' && line[last] == ']') {
string sectionName = line.substr(1, last - 1);
eat_white(sectionName);
section = addSection(sectionName);
continue;
}
if (section == NULL)
continue;
if (!section->add(line))
return false;
}
return true;
}
bool
IniFile::find(const string &sectionName, const string &entryName,
string &value) const
{
Section *section = findSection(sectionName);
if (section == NULL)
return false;
Entry *entry = section->findEntry(entryName);
if (entry == NULL)
return false;
value = entry->getValue();
return true;
}
bool
IniFile::sectionExists(const string &sectionName) const
{
return findSection(sectionName) != NULL;
}
bool
IniFile::Section::printUnreferenced(const string &sectionName)
{
bool unref = false;
bool search_unref_entries = false;
vector<string> unref_ok_entries;
Entry *entry = findEntry("unref_entries_ok");
if (entry != NULL) {
tokenize(unref_ok_entries, entry->getValue(), ' ');
if (unref_ok_entries.size()) {
search_unref_entries = true;
}
}
for (EntryTable::iterator ei = table.begin();
ei != table.end(); ++ei) {
const string &entryName = ei->first;
Entry *entry = ei->second;
if (entryName == "unref_section_ok" ||
entryName == "unref_entries_ok")
{
continue;
}
if (!entry->isReferenced()) {
if (search_unref_entries &&
(std::find(unref_ok_entries.begin(), unref_ok_entries.end(),
entryName) != unref_ok_entries.end()))
{
continue;
}
cerr << "Parameter " << sectionName << ":" << entryName
<< " not referenced." << endl;
unref = true;
}
}
return unref;
}
bool
IniFile::printUnreferenced()
{
bool unref = false;
for (SectionTable::iterator i = table.begin();
i != table.end(); ++i) {
const string &sectionName = i->first;
Section *section = i->second;
if (!section->isReferenced()) {
if (section->findEntry("unref_section_ok") == NULL) {
cerr << "Section " << sectionName << " not referenced."
<< endl;
unref = true;
}
}
else {
if (section->printUnreferenced(sectionName)) {
unref = true;
}
}
}
return unref;
}
void
IniFile::Section::dump(const string &sectionName)
{
for (EntryTable::iterator ei = table.begin();
ei != table.end(); ++ei) {
cout << sectionName << ": " << (*ei).first << " => "
<< (*ei).second->getValue() << "\n";
}
}
void
IniFile::dump()
{
for (SectionTable::iterator i = table.begin();
i != table.end(); ++i) {
i->second->dump(i->first);
}
}

View File

@ -0,0 +1,203 @@
/*
* Copyright (c) 2001-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
* Steve Reinhardt
*/
#ifndef __INIFILE_HH__
#define __INIFILE_HH__
#include <fstream>
#include <list>
#include <string>
#include <vector>
#include "base/hashmap.hh"
/**
* @file
* Declaration of IniFile object.
* @todo Change comments to match documentation style.
*/
///
/// This class represents the contents of a ".ini" file.
///
/// It's basically a two level lookup table: a set of named sections,
/// where each section is a set of key/value pairs. Section names,
/// keys, and values are all uninterpreted strings.
///
class IniFile
{
protected:
///
/// A single key/value pair.
///
class Entry
{
std::string value; ///< The entry value.
mutable bool referenced; ///< Has this entry been used?
public:
/// Constructor.
Entry(const std::string &v)
: value(v), referenced(false)
{
}
/// Has this entry been used?
bool isReferenced() { return referenced; }
/// Fetch the value.
const std::string &getValue() const;
/// Set the value.
void setValue(const std::string &v) { value = v; }
/// Append the given string to the value. A space is inserted
/// between the existing value and the new value. Since this
/// operation is typically used with values that are
/// space-separated lists of tokens, this keeps the tokens
/// separate.
void appendValue(const std::string &v) { value += " "; value += v; }
};
///
/// A section.
///
class Section
{
/// EntryTable type. Map of strings to Entry object pointers.
typedef m5::hash_map<std::string, Entry *> EntryTable;
EntryTable table; ///< Table of entries.
mutable bool referenced; ///< Has this section been used?
public:
/// Constructor.
Section()
: table(), referenced(false)
{
}
/// Has this section been used?
bool isReferenced() { return referenced; }
/// Add an entry to the table. If an entry with the same name
/// already exists, the 'append' parameter is checked If true,
/// the new value will be appended to the existing entry. If
/// false, the new value will replace the existing entry.
void addEntry(const std::string &entryName, const std::string &value,
bool append);
/// Add an entry to the table given a string assigment.
/// Assignment should be of the form "param=value" or
/// "param+=value" (for append). This funciton parses the
/// assignment statment and calls addEntry().
/// @retval True for success, false if parse error.
bool add(const std::string &assignment);
/// Find the entry with the given name.
/// @retval Pointer to the entry object, or NULL if none.
Entry *findEntry(const std::string &entryName) const;
/// Print the unreferenced entries in this section to cerr.
/// Messages can be suppressed using "unref_section_ok" and
/// "unref_entries_ok".
/// @param sectionName Name of this section, for use in output message.
/// @retval True if any entries were printed.
bool printUnreferenced(const std::string &sectionName);
/// Print the contents of this section to cout (for debugging).
void dump(const std::string &sectionName);
};
/// SectionTable type. Map of strings to Section object pointers.
typedef m5::hash_map<std::string, Section *> SectionTable;
protected:
/// Hash of section names to Section object pointers.
SectionTable table;
/// Look up section with the given name, creating a new section if
/// not found.
/// @retval Pointer to section object.
Section *addSection(const std::string &sectionName);
/// Look up section with the given name.
/// @retval Pointer to section object, or NULL if not found.
Section *findSection(const std::string &sectionName) const;
public:
/// Constructor.
IniFile();
/// Destructor.
~IniFile();
/// Load parameter settings from given istream. This is a helper
/// function for load(string) and loadCPP(), which open a file
/// and then pass it here.
/// @retval True if successful, false if errors were encountered.
bool load(std::istream &f);
/// Load the specified file.
/// Parameter settings found in the file will be merged with any
/// already defined in this object.
/// @param file The path of the file to load.
/// @retval True if successful, false if errors were encountered.
bool load(const std::string &file);
/// Take string of the form "<section>:<parameter>=<value>" or
/// "<section>:<parameter>+=<value>" and add to database.
/// @retval True if successful, false if parse error.
bool add(const std::string &s);
/// Find value corresponding to given section and entry names.
/// Value is returned by reference in 'value' param.
/// @retval True if found, false if not.
bool find(const std::string &section, const std::string &entry,
std::string &value) const;
/// Determine whether the named section exists in the .ini file.
/// Note that the 'Section' class is (intentionally) not public,
/// so all clients can do is get a bool that says whether there
/// are any values in that section or not.
/// @return True if the section exists.
bool sectionExists(const std::string &section) const;
/// Print unreferenced entries in object. Iteratively calls
/// printUnreferend() on all the constituent sections.
bool printUnreferenced();
/// Dump contents to cout. For debugging.
void dump();
};
#endif // __INIFILE_HH__

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2001, 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
* Steve Reinhardt
*/
#include "base/intmath.hh"
int
prevPrime(int n)
{
int decr;
// If the number is even, let's start with the previous odd number.
if (!(n & 1))
--n;
// Lets test for divisibility by 3. Then we will be able to easily
// avoid numbers that are divisible by 3 in the future.
decr = n % 3;
if (decr == 0) {
n -= 2;
decr = 2;
}
else if (decr == 1)
decr = 4;
for (;;) {
if (isPrime(n))
return n;
n -= decr;
// Toggle between 2 and 4 to prevent trying numbers that are known
// to be divisible by 3.
decr = 6 - decr;
}
}

View File

@ -0,0 +1,254 @@
/*
* Copyright (c) 2001, 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#ifndef __BASE_INTMATH_HH__
#define __BASE_INTMATH_HH__
#include <cassert>
#include "base/misc.hh"
#include "base/types.hh"
// Returns the prime number one less than n.
int prevPrime(int n);
// Determine if a number is prime
template <class T>
inline bool
isPrime(T n)
{
T i;
if (n == 2 || n == 3)
return true;
// Don't try every odd number to prove if it is a prime.
// Toggle between every 2nd and 4th number.
// (This is because every 6th odd number is divisible by 3.)
for (i = 5; i*i <= n; i += 6) {
if (((n % i) == 0 ) || ((n % (i + 2)) == 0) ) {
return false;
}
}
return true;
}
template <class T>
inline T
leastSigBit(T n)
{
return n & ~(n - 1);
}
template <class T>
inline bool
isPowerOf2(T n)
{
return n != 0 && leastSigBit(n) == n;
}
inline uint64_t
power(uint32_t n, uint32_t e)
{
if (e > 20)
warn("Warning, power() function is quite slow for large exponents\n");
if (e == 0)
return 1;
uint64_t result = n;
uint64_t old_result = 0;
for (int x = 1; x < e; x++) {
old_result = result;
result *= n;
if (old_result > result)
warn("power() overflowed!\n");
}
return result;
}
inline int
floorLog2(unsigned x)
{
assert(x > 0);
int y = 0;
if (x & 0xffff0000) { y += 16; x >>= 16; }
if (x & 0x0000ff00) { y += 8; x >>= 8; }
if (x & 0x000000f0) { y += 4; x >>= 4; }
if (x & 0x0000000c) { y += 2; x >>= 2; }
if (x & 0x00000002) { y += 1; }
return y;
}
inline int
floorLog2(unsigned long x)
{
assert(x > 0);
int y = 0;
#if defined(__LP64__)
if (x & ULL(0xffffffff00000000)) { y += 32; x >>= 32; }
#endif
if (x & 0xffff0000) { y += 16; x >>= 16; }
if (x & 0x0000ff00) { y += 8; x >>= 8; }
if (x & 0x000000f0) { y += 4; x >>= 4; }
if (x & 0x0000000c) { y += 2; x >>= 2; }
if (x & 0x00000002) { y += 1; }
return y;
}
inline int
floorLog2(unsigned long long x)
{
assert(x > 0);
int y = 0;
if (x & ULL(0xffffffff00000000)) { y += 32; x >>= 32; }
if (x & ULL(0x00000000ffff0000)) { y += 16; x >>= 16; }
if (x & ULL(0x000000000000ff00)) { y += 8; x >>= 8; }
if (x & ULL(0x00000000000000f0)) { y += 4; x >>= 4; }
if (x & ULL(0x000000000000000c)) { y += 2; x >>= 2; }
if (x & ULL(0x0000000000000002)) { y += 1; }
return y;
}
inline int
floorLog2(int x)
{
assert(x > 0);
return floorLog2((unsigned)x);
}
inline int
floorLog2(long x)
{
assert(x > 0);
return floorLog2((unsigned long)x);
}
inline int
floorLog2(long long x)
{
assert(x > 0);
return floorLog2((unsigned long long)x);
}
template <class T>
inline int
ceilLog2(T n)
{
if (n == 1)
return 0;
return floorLog2(n - (T)1) + 1;
}
template <class T>
inline T
floorPow2(T n)
{
return (T)1 << floorLog2(n);
}
template <class T>
inline T
ceilPow2(T n)
{
return (T)1 << ceilLog2(n);
}
template <class T>
inline T
divCeil(T a, T b)
{
return (a + b - 1) / b;
}
template <class T>
inline T
roundUp(T val, int align)
{
T mask = (T)align - 1;
return (val + mask) & ~mask;
}
template <class T>
inline T
roundDown(T val, int align)
{
T mask = (T)align - 1;
return val & ~mask;
}
inline bool
isHex(char c)
{
return (c >= '0' && c <= '9') ||
(c >= 'A' && c <= 'F') ||
(c >= 'a' && c <= 'f');
}
inline bool
isOct(char c)
{
return c >= '0' && c <= '7';
}
inline bool
isDec(char c)
{
return c >= '0' && c <= '9';
}
inline int
hex2Int(char c)
{
if (c >= '0' && c <= '9')
return (c - '0');
if (c >= 'A' && c <= 'F')
return (c - 'A') + 10;
if (c >= 'a' && c <= 'f')
return (c - 'a') + 10;
return 0;
}
#endif // __BASE_INTMATH_HH__

View File

@ -0,0 +1,94 @@
/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Steve Reinhardt
*/
#include <string>
#include "base/loader/aout_object.hh"
#include "base/loader/exec_aout.h"
#include "base/loader/symtab.hh"
#include "base/trace.hh"
#include "debug/Loader.hh"
using namespace std;
ObjectFile *
AoutObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data)
{
if (!N_BADMAG(*(aout_exechdr *)data)) {
// right now this is only used for Alpha PAL code
return new AoutObject(fname, fd, len, data,
ObjectFile::Alpha, ObjectFile::UnknownOpSys);
}
else {
return NULL;
}
}
AoutObject::AoutObject(const string &_filename, int _fd,
size_t _len, uint8_t *_data,
Arch _arch, OpSys _opSys)
: ObjectFile(_filename, _fd, _len, _data, _arch, _opSys)
{
execHdr = (aout_exechdr *)fileData;
entry = execHdr->entry;
text.baseAddr = N_TXTADDR(*execHdr);
text.size = execHdr->tsize;
text.fileImage = fileData + N_TXTOFF(*execHdr);
data.baseAddr = N_DATADDR(*execHdr);
data.size = execHdr->dsize;
data.fileImage = fileData + N_DATOFF(*execHdr);
bss.baseAddr = N_BSSADDR(*execHdr);
bss.size = execHdr->bsize;
bss.fileImage = NULL;
DPRINTFR(Loader, "text: 0x%x %d\ndata: 0x%x %d\nbss: 0x%x %d\n",
text.baseAddr, text.size, data.baseAddr, data.size,
bss.baseAddr, bss.size);
}
bool
AoutObject::loadGlobalSymbols(SymbolTable *symtab, Addr addrMask)
{
// a.out symbols not supported yet
return false;
}
bool
AoutObject::loadLocalSymbols(SymbolTable *symtab, Addr addrMask)
{
// a.out symbols not supported yet
return false;
}

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Steve Reinhardt
*/
#ifndef __AOUT_OBJECT_HH__
#define __AOUT_OBJECT_HH__
#include "base/loader/object_file.hh"
// forward decls: avoid including exec_aout.h here
struct aout_exechdr;
class AoutObject : public ObjectFile
{
protected:
aout_exechdr *execHdr;
AoutObject(const std::string &_filename, int _fd,
size_t _len, uint8_t *_data,
Arch _arch, OpSys _opSys);
public:
virtual ~AoutObject() {}
virtual bool loadGlobalSymbols(SymbolTable *symtab, Addr addrMask =
std::numeric_limits<Addr>::max());
virtual bool loadLocalSymbols(SymbolTable *symtab, Addr addrMask =
std::numeric_limits<Addr>::max());
static ObjectFile *tryFile(const std::string &fname, int fd,
size_t len, uint8_t *data);
};
#endif // __AOUT_OBJECT_HH__

View File

@ -0,0 +1,519 @@
/*
* Copyright (c) 2003, 2005-2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Steve Reinhardt
*/
/*
* Taken from binutils-2.14.90.0.5 include/coff/sym.h
*/
/* Declarations of internal format of MIPS ECOFF symbols.
Originally contributed by MIPS Computer Systems and Third Eye Software.
Changes contributed by Cygnus Support are in the public domain.
This file is just aggregated with the files that make up the GNU
release; it is not considered part of GAS, GDB, or other GNU
programs. */
/*
* |-----------------------------------------------------------|
* | Copyright (c) 1992, 1991, 1990 MIPS Computer Systems, Inc.|
* | MIPS Computer Systems, Inc. grants reproduction and use |
* | rights to all parties, PROVIDED that this comment is |
* | maintained in the copy. |
* |-----------------------------------------------------------|
*/
#ifndef _SYM_H
#define _SYM_H
/* (C) Copyright 1984 by Third Eye Software, Inc.
*
* Third Eye Software, Inc. grants reproduction and use rights to
* all parties, PROVIDED that this comment is maintained in the copy.
*
* Third Eye makes no claims about the applicability of this
* symbol table to a particular use.
*/
/*
* This file contains the definition of the Third Eye Symbol Table.
*
* Symbols are assumed to be in 'encounter order' - i.e. the order that
* the things they represent were encountered by the compiler/assembler/loader.
* EXCEPT for globals! These are assumed to be bunched together,
* probably right after the last 'normal' symbol. Globals ARE sorted
* in ascending order.
*
* -----------------------------------------------------------------------
* A brief word about Third Eye naming/use conventions:
*
* All arrays and index's are 0 based.
* All "ifooMax" values are the highest legal value PLUS ONE. This makes
* them good for allocating arrays, etc. All checks are "ifoo < ifooMax".
*
* "isym" Index into the SYMbol table.
* "ipd" Index into the Procedure Descriptor array.
* "ifd" Index into the File Descriptor array.
* "iss" Index into String Space.
* "cb" Count of Bytes.
* "rgPd" array whose domain is "0..ipdMax-1" and RanGe is PDR.
* "rgFd" array whose domain is "0..ifdMax-1" and RanGe is FDR.
*/
/*
* Symbolic Header (HDR) structure.
* As long as all the pointers are set correctly,
* we don't care WHAT order the various sections come out in!
*
* A file produced solely for the use of CDB will probably NOT have
* any instructions or data areas in it, as these are available
* in the original.
*/
typedef struct ecoff_symhdr {
coff_short magic; /* to verify validity of the table */
coff_short vstamp; /* version stamp */
coff_int ilineMax; /* number of line number entries */
coff_int idnMax; /* max index into dense number table */
coff_int ipdMax; /* number of procedures */
coff_int isymMax; /* number of local symbols */
coff_int ioptMax; /* max index into optimization symbol entries */
coff_int iauxMax; /* number of auxillary symbol entries */
coff_int issMax; /* max index into local strings */
coff_int issExtMax; /* max index into external strings */
coff_int ifdMax; /* number of file descriptor entries */
coff_int crfd; /* number of relative file descriptor entries */
coff_int iextMax; /* max index into external symbols */
coff_addr cbLine; /* number of bytes for line number entries */
coff_addr cbLineOffset; /* offset to start of line number entries*/
coff_addr cbDnOffset; /* offset to start dense number table */
coff_addr cbPdOffset; /* offset to procedure descriptor table */
coff_addr cbSymOffset; /* offset to start of local symbols*/
coff_addr cbOptOffset; /* offset to optimization symbol entries */
coff_addr cbAuxOffset; /* offset to start of auxillary symbol entries*/
coff_addr cbSsOffset; /* offset to start of local strings */
coff_addr cbSsExtOffset; /* offset to start of external strings */
coff_addr cbFdOffset; /* offset to file descriptor table */
coff_addr cbRfdOffset; /* offset to relative file descriptor table */
coff_addr cbExtOffset; /* offset to start of external symbol entries*/
/* If you add machine dependent fields, add them here */
} HDRR, *pHDRR;
#define cbHDRR sizeof(HDRR)
#define hdrNil ((pHDRR)0)
/*
* The FDR and PDR structures speed mapping of address <-> name.
* They are sorted in ascending memory order and are kept in
* memory by CDB at runtime.
*/
/*
* File Descriptor
*
* There is one of these for EVERY FILE, whether compiled with
* full debugging symbols or not. The name of a file should be
* the path name given to the compiler. This allows the user
* to simply specify the names of the directories where the COMPILES
* were done, and we will be able to find their files.
* A field whose comment starts with "R - " indicates that it will be
* setup at runtime.
*/
typedef struct ecoff_fdr {
coff_addr adr; /* memory address of beginning of file */
coff_addr cbLineOffset; /* byte offset from header for this file ln's */
coff_addr cbLine; /* size of lines for this file */
coff_addr cbSs; /* number of bytes in the ss */
coff_int rss; /* file name (of source, if known) */
coff_int issBase; /* file's string space */
coff_int isymBase; /* beginning of symbols */
coff_int csym; /* count file's of symbols */
coff_int ilineBase; /* file's line symbols */
coff_int cline; /* count of file's line symbols */
coff_int ioptBase; /* file's optimization entries */
coff_int copt; /* count of file's optimization entries */
coff_int ipdFirst; /* start of procedures for this file */
coff_int cpd; /* count of procedures for this file */
coff_int iauxBase; /* file's auxiliary entries */
coff_int caux; /* count of file's auxiliary entries */
coff_int rfdBase; /* index into the file indirect table */
coff_int crfd; /* count file indirect entries */
unsigned lang: 5; /* language for this file */
unsigned fMerge : 1; /* whether this file can be merged */
unsigned fReadin : 1; /* true if it was read in (not just created) */
unsigned fBigendian : 1;/* if set, was compiled on big endian machine */
/* aux's will be in compile host's sex */
unsigned glevel : 2; /* level this file was compiled with */
unsigned reserved : 22; /* reserved for future use */
coff_uint reserved2;
} FDR, *pFDR;
#define cbFDR sizeof(FDR)
#define fdNil ((pFDR)0)
#define ifdNil -1
#define ifdTemp 0
#define ilnNil -1
/*
* Procedure Descriptor
*
* There is one of these for EVERY TEXT LABEL.
* If a procedure is in a file with full symbols, then isym
* will point to the PROC symbols, else it will point to the
* global symbol for the label.
*/
typedef struct pdr {
coff_addr adr; /* memory address of start of procedure */
coff_addr cbLineOffset; /* byte offset for this procedure from the fd base */
coff_int isym; /* start of local symbol entries */
coff_int iline; /* start of line number entries*/
coff_uint regmask; /* save register mask */
coff_int regoffset; /* save register offset */
coff_int iopt; /* start of optimization symbol entries*/
coff_uint fregmask; /* save floating point register mask */
coff_int fregoffset; /* save floating point register offset */
coff_int frameoffset; /* frame size */
coff_int lnLow; /* lowest line in the procedure */
coff_int lnHigh; /* highest line in the procedure */
/* These fields are new for 64 bit ECOFF. */
unsigned gp_prologue : 8; /* byte size of GP prologue */
unsigned gp_used : 1; /* true if the procedure uses GP */
unsigned reg_frame : 1; /* true if register frame procedure */
unsigned prof : 1; /* true if compiled with -pg */
unsigned reserved : 13; /* reserved: must be zero */
unsigned localoff : 8; /* offset of local variables from vfp */
coff_short framereg; /* frame pointer register */
coff_short pcreg; /* offset or reg of return pc */
} PDR, *pPDR;
#define cbPDR sizeof(PDR)
#define pdNil ((pPDR) 0)
#define ipdNil -1
/*
* The structure of the runtime procedure descriptor created by the loader
* for use by the static exception system.
*/
/*
* If 0'd out because exception_info chokes Visual C++ and because there
* don't seem to be any references to this structure elsewhere in gdb.
*/
#if 0
typedef struct runtime_pdr {
coff_addr adr; /* memory address of start of procedure */
coff_uint regmask; /* save register mask */
coff_int regoffset; /* save register offset */
coff_uint fregmask; /* save floating point register mask */
coff_int fregoffset; /* save floating point register offset */
coff_int frameoffset; /* frame size */
coff_ushort framereg; /* frame pointer register */
coff_ushort pcreg; /* offset or reg of return pc */
coff_int irpss; /* index into the runtime string table */
coff_uint reserved;
struct exception_info *exception_info;/* pointer to exception array */
} RPDR, *pRPDR;
#define cbRPDR sizeof(RPDR)
#define rpdNil ((pRPDR) 0)
#endif
/*
* Line Numbers
*
* Line Numbers are segregated from the normal symbols because they
* are [1] smaller , [2] are of no interest to your
* average loader, and [3] are never needed in the middle of normal
* scanning and therefore slow things down.
*
* By definition, the first LINER for any given procedure will have
* the first line of a procedure and represent the first address.
*/
typedef coff_int LINER, *pLINER;
#define lineNil ((pLINER)0)
#define cbLINER sizeof(LINER)
#define ilineNil -1
/*
* The Symbol Structure (GFW, to those who Know!)
*/
typedef struct ecoff_sym {
coff_long value; /* value of symbol */
coff_int iss; /* index into String Space of name */
unsigned st : 6; /* symbol type */
unsigned sc : 5; /* storage class - text, data, etc */
unsigned reserved : 1; /* reserved */
unsigned index : 20; /* index into sym/aux table */
} SYMR, *pSYMR;
#define symNil ((pSYMR)0)
#define cbSYMR sizeof(SYMR)
#define isymNil -1
#define indexNil 0xfffff
#define issNil -1
#define issNull 0
/* The following converts a memory resident string to an iss.
* This hack is recognized in SbFIss, in sym.c of the debugger.
*/
#define IssFSb(sb) (0x80000000 | ((coff_ulong)(sb)))
/* E X T E R N A L S Y M B O L R E C O R D
*
* Same as the SYMR except it contains file context to determine where
* the index is.
*/
typedef struct ecoff_extsym {
SYMR asym; /* symbol for the external */
unsigned jmptbl:1; /* symbol is a jump table entry for shlibs */
unsigned cobol_main:1; /* symbol is a cobol main procedure */
unsigned weakext:1; /* symbol is weak external */
unsigned reserved:29; /* reserved for future use */
coff_int ifd; /* where the iss and index fields point into */
} EXTR, *pEXTR;
#define extNil ((pEXTR)0)
#define cbEXTR sizeof(EXTR)
/* A U X I L L A R Y T Y P E I N F O R M A T I O N */
/*
* Type Information Record
*/
typedef struct {
unsigned fBitfield : 1; /* set if bit width is specified */
unsigned continued : 1; /* indicates additional TQ info in next AUX */
unsigned bt : 6; /* basic type */
unsigned tq4 : 4;
unsigned tq5 : 4;
/* ---- 16 bit boundary ---- */
unsigned tq0 : 4;
unsigned tq1 : 4; /* 6 type qualifiers - tqPtr, etc. */
unsigned tq2 : 4;
unsigned tq3 : 4;
} TIR, *pTIR;
#define cbTIR sizeof(TIR)
#define tiNil ((pTIR)0)
#define itqMax 6
/*
* Relative symbol record
*
* If the rfd field is 4095, the index field indexes into the global symbol
* table.
*/
typedef struct {
unsigned rfd : 12; /* index into the file indirect table */
unsigned index : 20; /* index int sym/aux/iss tables */
} RNDXR, *pRNDXR;
#define cbRNDXR sizeof(RNDXR)
#define rndxNil ((pRNDXR)0)
/* dense numbers or sometimes called block numbers are stored in this type,
* a rfd of 0xffffffff is an index into the global table.
*/
typedef struct {
coff_uint rfd; /* index into the file table */
coff_uint index; /* index int sym/aux/iss tables */
} DNR, *pDNR;
#define cbDNR sizeof(DNR)
#define dnNil ((pDNR)0)
/*
* Auxillary information occurs only if needed.
* It ALWAYS occurs in this order when present.
isymMac used by stProc only
TIR type info
TIR additional TQ info (if first TIR was not enough)
rndx if (bt == btStruct,btUnion,btEnum,btSet,btRange,
btTypedef):
rsym.index == iaux for btSet or btRange
else rsym.index == isym
dimLow btRange, btSet
dimMac btRange, btSet
rndx0 As many as there are tq arrays
dimLow0
dimHigh0
...
rndxMax-1
dimLowMax-1
dimHighMax-1
width in bits if (bit field), width in bits.
*/
#define cAuxMax (6 + (idimMax*3))
/* a union of all possible info in the AUX universe */
typedef union {
TIR ti; /* type information record */
RNDXR rndx; /* relative index into symbol table */
coff_int dnLow; /* low dimension */
coff_int dnHigh; /* high dimension */
coff_int isym; /* symbol table index (end of proc) */
coff_int iss; /* index into string space (not used) */
coff_int width; /* width for non-default sized struc fields */
coff_int count; /* count of ranges for variant arm */
} AUXU, *pAUXU;
#define cbAUXU sizeof(AUXU)
#define auxNil ((pAUXU)0)
#define iauxNil -1
/*
* Optimization symbols
*
* Optimization symbols contain some overlap information with the normal
* symbol table. In particular, the proc information
* is somewhat redundant but necessary to easily find the other information
* present.
*
* All of the offsets are relative to the beginning of the last otProc
*/
typedef struct {
unsigned ot: 8; /* optimization type */
unsigned value: 24; /* address where we are moving it to */
RNDXR rndx; /* points to a symbol or opt entry */
coff_ulong offset; /* relative offset this occured */
} OPTR, *pOPTR;
#define optNil ((pOPTR) 0)
#define cbOPTR sizeof(OPTR)
#define ioptNil -1
/*
* File Indirect
*
* When a symbol is referenced across files the following procedure is used:
* 1) use the file index to get the File indirect entry.
* 2) use the file indirect entry to get the File descriptor.
* 3) add the sym index to the base of that file's sym table
*
*/
typedef coff_long RFDT, *pRFDT;
#define cbRFDT sizeof(RFDT)
#define rfdNil -1
/*
* The file indirect table in the mips loader is known as an array of FITs.
* This is done to keep the code in the loader readable in the area where
* these tables are merged. Note this is only a name change.
*/
typedef coff_int FIT, *pFIT;
#define cbFIT sizeof(FIT)
#define ifiNil -1
#define fiNil ((pFIT) 0)
#ifdef _LANGUAGE_PASCAL
#define ifdNil -1
#define ilnNil -1
#define ipdNil -1
#define ilineNil -1
#define isymNil -1
#define indexNil 16#fffff
#define issNil -1
#define issNull 0
#define itqMax 6
#define iauxNil -1
#define ioptNil -1
#define rfdNil -1
#define ifiNil -1
#endif /* _LANGUAGE_PASCAL */
/* Dense numbers
*
* Rather than use file index, symbol index pairs to represent symbols
* and globals, we use dense number so that they can be easily embeded
* in intermediate code and the programs that process them can
* use direct access tabls instead of hash table (which would be
* necesary otherwise because of the sparse name space caused by
* file index, symbol index pairs. Dense number are represented
* by RNDXRs.
*/
/*
* The following table defines the meaning of each SYM field as
* a function of the "st". (scD/B == scData OR scBss)
*
* Note: the value "isymMac" is used by symbols that have the concept
* of enclosing a block of related information. This value is the
* isym of the first symbol AFTER the end associated with the primary
* symbol. For example if a procedure was at isym==90 and had an
* isymMac==155, the associated end would be at isym==154, and the
* symbol at 155 would probably (although not necessarily) be the
* symbol for the next procedure. This allows rapid skipping over
* internal information of various sorts. "stEnd"s ALWAYS have the
* isym of the primary symbol that started the block.
*
ST SC VALUE INDEX
-------- ------ -------- ------
stFile scText address isymMac
stLabel scText address ---
stGlobal scD/B address iaux
stStatic scD/B address iaux
stParam scAbs offset iaux
stLocal scAbs offset iaux
stProc scText address iaux (isymMac is first AUX)
stStaticProc scText address iaux (isymMac is first AUX)
stMember scNil ordinal --- (if member of enum)
(mipsread thinks the case below has a bit, not byte, offset.)
stMember scNil byte offset iaux (if member of struct/union)
stMember scBits bit offset iaux (bit field spec)
stBlock scText address isymMac (text block)
(the code seems to think that rather than scNil, we see scInfo for
the two cases below.)
stBlock scNil cb isymMac (struct/union member define)
stBlock scNil cMembers isymMac (enum member define)
(New types added by SGI to simplify things:)
stStruct scInfo cb isymMac (struct type define)
stUnion scInfo cb isymMac (union type define)
stEnum scInfo cMembers isymMac (enum type define)
stEnd scText address isymStart
stEnd scNil ------- isymStart (struct/union/enum)
stTypedef scNil ------- iaux
stRegReloc sc??? value old register number
stForward sc??? new address isym to original symbol
stConstant scInfo value --- (scalar)
stConstant scInfo iss --- (complex, e.g. string)
*
*/
#endif

View File

@ -0,0 +1,200 @@
/*
* Copyright (c) 2003, 2005-2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Steve Reinhardt
*/
/*
* Taken from binutils-2.14.90.0.5 include/coff/symconst.h
*/
/* Declarations of constants for internal format of MIPS ECOFF symbols.
Originally contributed by MIPS Computer Systems and Third Eye Software.
Changes contributed by Cygnus Support are in the public domain.
This file is just aggregated with the files that make up the GNU
release; it is not considered part of GAS, GDB, or other GNU
programs. */
/*
* |-----------------------------------------------------------|
* | Copyright (c) 1992, 1991, 1990 MIPS Computer Systems, Inc.|
* | MIPS Computer Systems, Inc. grants reproduction and use |
* | rights to all parties, PROVIDED that this comment is |
* | maintained in the copy. |
* |-----------------------------------------------------------|
*/
/* (C) Copyright 1984 by Third Eye Software, Inc.
*
* Third Eye Software, Inc. grants reproduction and use rights to
* all parties, PROVIDED that this comment is maintained in the copy.
*
* Third Eye makes no claims about the applicability of this
* symbol table to a particular use.
*/
/* glevels for field in FDR */
#define GLEVEL_0 2
#define GLEVEL_1 1
#define GLEVEL_2 0 /* for upward compat reasons. */
#define GLEVEL_3 3
/* magic number fo symheader */
#define magicSym 0x7009
/* The Alpha uses this value instead, for some reason. */
#define magicSym2 0x1992
/* Language codes */
#define langC 0
#define langPascal 1
#define langFortran 2
#define langAssembler 3 /* one Assembley inst might map to many mach */
#define langMachine 4
#define langNil 5
#define langAda 6
#define langPl1 7
#define langCobol 8
#define langStdc 9 /* FIXME: Collides with SGI langCplusplus */
#define langCplusplus 9 /* FIXME: Collides with langStdc */
#define langCplusplusV2 10 /* SGI addition */
#define langMax 11 /* maximun allowed 32 -- 5 bits */
/* The following are value definitions for the fields in the SYMR */
/*
* Storage Classes
*/
#define scNil 0
#define scText 1 /* text symbol */
#define scData 2 /* initialized data symbol */
#define scBss 3 /* un-initialized data symbol */
#define scRegister 4 /* value of symbol is register number */
#define scAbs 5 /* value of symbol is absolute */
#define scUndefined 6 /* who knows? */
#define scCdbLocal 7 /* variable's value is IN se->va.?? */
#define scBits 8 /* this is a bit field */
#define scCdbSystem 9 /* variable's value is IN CDB's address space */
#define scDbx 9 /* overlap dbx internal use */
#define scRegImage 10 /* register value saved on stack */
#define scInfo 11 /* symbol contains debugger information */
#define scUserStruct 12 /* address in struct user for current process */
#define scSData 13 /* load time only small data */
#define scSBss 14 /* load time only small common */
#define scRData 15 /* load time only read only data */
#define scVar 16 /* Var parameter (fortran,pascal) */
#define scCommon 17 /* common variable */
#define scSCommon 18 /* small common */
#define scVarRegister 19 /* Var parameter in a register */
#define scVariant 20 /* Variant record */
#define scSUndefined 21 /* small undefined(external) data */
#define scInit 22 /* .init section symbol */
#define scBasedVar 23 /* Fortran or PL/1 ptr based var */
#define scXData 24 /* exception handling data */
#define scPData 25 /* Procedure section */
#define scFini 26 /* .fini section */
#define scRConst 27 /* .rconst section */
#define scMax 32
/*
* Symbol Types
*/
#define stNil 0 /* Nuthin' special */
#define stGlobal 1 /* external symbol */
#define stStatic 2 /* static */
#define stParam 3 /* procedure argument */
#define stLocal 4 /* local variable */
#define stLabel 5 /* label */
#define stProc 6 /* " " Procedure */
#define stBlock 7 /* beginnning of block */
#define stEnd 8 /* end (of anything) */
#define stMember 9 /* member (of anything - struct/union/enum */
#define stTypedef 10 /* type definition */
#define stFile 11 /* file name */
#define stRegReloc 12 /* register relocation */
#define stForward 13 /* forwarding address */
#define stStaticProc 14 /* load time only static procs */
#define stConstant 15 /* const */
#define stStaParam 16 /* Fortran static parameters */
/* These new symbol types have been recently added to SGI machines. */
#define stStruct 26 /* Beginning of block defining a struct type */
#define stUnion 27 /* Beginning of block defining a union type */
#define stEnum 28 /* Beginning of block defining an enum type */
#define stIndirect 34 /* Indirect type specification */
/* Pseudo-symbols - internal to debugger */
#define stStr 60 /* string */
#define stNumber 61 /* pure number (ie. 4 NOR 2+2) */
#define stExpr 62 /* 2+2 vs. 4 */
#define stType 63 /* post-coersion SER */
#define stMax 64
/* definitions for fields in TIR */
/* type qualifiers for ti.tq0 -> ti.(itqMax-1) */
#define tqNil 0 /* bt is what you see */
#define tqPtr 1 /* pointer */
#define tqProc 2 /* procedure */
#define tqArray 3 /* duh */
#define tqFar 4 /* longer addressing - 8086/8 land */
#define tqVol 5 /* volatile */
#define tqConst 6 /* const */
#define tqMax 8
/* basic types as seen in ti.bt */
#define btNil 0 /* undefined (also, enum members) */
#define btAdr 1 /* address - integer same size as pointer */
#define btChar 2 /* character */
#define btUChar 3 /* unsigned character */
#define btShort 4 /* short */
#define btUShort 5 /* unsigned short */
#define btInt 6 /* int */
#define btUInt 7 /* unsigned int */
#define btLong 8 /* long */
#define btULong 9 /* unsigned long */
#define btFloat 10 /* float (real) */
#define btDouble 11 /* Double (real) */
#define btStruct 12 /* Structure (Record) */
#define btUnion 13 /* Union (variant) */
#define btEnum 14 /* Enumerated */
#define btTypedef 15 /* defined via a typedef, isymRef points */
#define btRange 16 /* subrange of int */
#define btSet 17 /* pascal sets */
#define btComplex 18 /* fortran complex */
#define btDComplex 19 /* fortran double complex */
#define btIndirect 20 /* forward or unnamed typedef */
#define btFixedDec 21 /* Fixed Decimal */
#define btFloatDec 22 /* Float Decimal */
#define btString 23 /* Varying Length Character String */
#define btBit 24 /* Aligned Bit String */
#define btPicture 25 /* Picture */
#define btVoid 26 /* void */
#define btLongLong 27 /* long long */
#define btULongLong 28 /* unsigned long long */
#define btMax 64

View File

@ -0,0 +1,161 @@
/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Steve Reinhardt
*/
#include <string>
#include "base/loader/ecoff_object.hh"
#include "base/loader/symtab.hh"
#include "base/misc.hh"
#include "base/trace.hh"
#include "base/types.hh"
#include "debug/Loader.hh"
// Only alpha will be able to load ecoff files for now.
// base/types.hh and ecoff_machdep.h must be before the other .h files
// because they are are gathered from other code bases and require some
// typedefs from those files.
#include "arch/alpha/ecoff_machdep.h"
#include "base/loader/coff_sym.h"
#include "base/loader/coff_symconst.h"
#include "base/loader/exec_ecoff.h"
using namespace std;
ObjectFile *
EcoffObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data)
{
if (((ecoff_filehdr *)data)->f_magic == ECOFF_MAGIC_ALPHA) {
// it's Alpha ECOFF
return new EcoffObject(fname, fd, len, data,
ObjectFile::Alpha, ObjectFile::Tru64);
}
else {
return NULL;
}
}
EcoffObject::EcoffObject(const string &_filename, int _fd,
size_t _len, uint8_t *_data,
Arch _arch, OpSys _opSys)
: ObjectFile(_filename, _fd, _len, _data, _arch, _opSys)
{
execHdr = (ecoff_exechdr *)fileData;
fileHdr = &(execHdr->f);
aoutHdr = &(execHdr->a);
entry = aoutHdr->entry;
text.baseAddr = aoutHdr->text_start;
text.size = aoutHdr->tsize;
text.fileImage = fileData + ECOFF_TXTOFF(execHdr);
data.baseAddr = aoutHdr->data_start;
data.size = aoutHdr->dsize;
data.fileImage = fileData + ECOFF_DATOFF(execHdr);
bss.baseAddr = aoutHdr->bss_start;
bss.size = aoutHdr->bsize;
bss.fileImage = NULL;
DPRINTFR(Loader, "text: 0x%x %d\ndata: 0x%x %d\nbss: 0x%x %d\n",
text.baseAddr, text.size, data.baseAddr, data.size,
bss.baseAddr, bss.size);
}
bool
EcoffObject::loadGlobalSymbols(SymbolTable *symtab, Addr addrMask)
{
if (!symtab)
return false;
if (fileHdr->f_magic != ECOFF_MAGIC_ALPHA) {
warn("loadGlobalSymbols: wrong magic on %s\n", filename);
return false;
}
ecoff_symhdr *syms = (ecoff_symhdr *)(fileData + fileHdr->f_symptr);
if (syms->magic != magicSym2) {
warn("loadGlobalSymbols: bad symbol header magic on %s\n", filename);
return false;
}
ecoff_extsym *ext_syms = (ecoff_extsym *)(fileData + syms->cbExtOffset);
char *ext_strings = (char *)(fileData + syms->cbSsExtOffset);
for (int i = 0; i < syms->iextMax; i++) {
ecoff_sym *entry = &(ext_syms[i].asym);
if (entry->iss != -1)
symtab->insert(entry->value, ext_strings + entry->iss);
}
return true;
}
bool
EcoffObject::loadLocalSymbols(SymbolTable *symtab, Addr addrMask)
{
if (!symtab)
return false;
if (fileHdr->f_magic != ECOFF_MAGIC_ALPHA) {
warn("loadGlobalSymbols: wrong magic on %s\n", filename);
return false;
}
ecoff_symhdr *syms = (ecoff_symhdr *)(fileData + fileHdr->f_symptr);
if (syms->magic != magicSym2) {
warn("loadGlobalSymbols: bad symbol header magic on %s\n", filename);
return false;
}
ecoff_sym *local_syms = (ecoff_sym *)(fileData + syms->cbSymOffset);
char *local_strings = (char *)(fileData + syms->cbSsOffset);
ecoff_fdr *fdesc = (ecoff_fdr *)(fileData + syms->cbFdOffset);
for (int i = 0; i < syms->ifdMax; i++) {
ecoff_sym *entry = (ecoff_sym *)(local_syms + fdesc[i].isymBase);
char *strings = (char *)(local_strings + fdesc[i].issBase);
for (int j = 0; j < fdesc[i].csym; j++) {
if (entry[j].st == stGlobal || entry[j].st == stProc)
if (entry[j].iss != -1)
symtab->insert(entry[j].value, strings + entry[j].iss);
}
}
for (int i = 0; i < syms->isymMax; i++) {
ecoff_sym *entry = &(local_syms[i]);
if (entry->st == stProc)
symtab->insert(entry->value, local_strings + entry->iss);
}
return true;
}

View File

@ -0,0 +1,64 @@
/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Steve Reinhardt
*/
#ifndef __ECOFF_OBJECT_HH__
#define __ECOFF_OBJECT_HH__
#include "base/loader/object_file.hh"
// forward decls: avoid including exec_ecoff.h here
struct ecoff_exechdr;
struct ecoff_filehdr;
struct ecoff_aouthdr;
class EcoffObject : public ObjectFile
{
protected:
ecoff_exechdr *execHdr;
ecoff_filehdr *fileHdr;
ecoff_aouthdr *aoutHdr;
EcoffObject(const std::string &_filename, int _fd,
size_t _len, uint8_t *_data,
Arch _arch, OpSys _opSys);
public:
virtual ~EcoffObject() {}
virtual bool loadGlobalSymbols(SymbolTable *symtab, Addr addrMask =
std::numeric_limits<Addr>::max());
virtual bool loadLocalSymbols(SymbolTable *symtab, Addr addrMask =
std::numeric_limits<Addr>::max());
static ObjectFile *tryFile(const std::string &fname, int fd,
size_t len, uint8_t *data);
};
#endif // __ECOFF_OBJECT_HH__

View File

@ -0,0 +1,476 @@
/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Steve Reinhardt
* Ali Saidi
*/
#include <cassert>
#include <string>
#include "base/loader/elf_object.hh"
#include "base/loader/symtab.hh"
#include "base/bitfield.hh"
#include "base/misc.hh"
#include "base/trace.hh"
#include "debug/Loader.hh"
#include "sim/byteswap.hh"
#include "gelf.h"
using namespace std;
ObjectFile *
ElfObject::tryFile(const string &fname, int fd, size_t len, uint8_t *data)
{
Elf *elf;
GElf_Ehdr ehdr;
Arch arch = UnknownArch;
OpSys opSys = UnknownOpSys;
// check that header matches library version
if (elf_version(EV_CURRENT) == EV_NONE)
panic("wrong elf version number!");
// get a pointer to elf structure
elf = elf_memory((char*)data,len);
// will only fail if fd is invalid
assert(elf != NULL);
// Check that we actually have a elf file
if (gelf_getehdr(elf, &ehdr) ==0) {
DPRINTFR(Loader, "Not ELF\n");
elf_end(elf);
return NULL;
} else {
//Detect the architecture
//Since we don't know how to check for alpha right now, we'll
//just assume if it wasn't something else and it's 64 bit, that's
//what it must be.
if (ehdr.e_machine == EM_SPARC64 ||
(ehdr.e_machine == EM_SPARC &&
ehdr.e_ident[EI_CLASS] == ELFCLASS64)||
ehdr.e_machine == EM_SPARCV9) {
arch = ObjectFile::SPARC64;
} else if (ehdr.e_machine == EM_SPARC32PLUS ||
(ehdr.e_machine == EM_SPARC &&
ehdr.e_ident[EI_CLASS] == ELFCLASS32)) {
arch = ObjectFile::SPARC32;
} else if (ehdr.e_machine == EM_MIPS
&& ehdr.e_ident[EI_CLASS] == ELFCLASS32) {
if (ehdr.e_ident[EI_DATA] == ELFDATA2LSB) {
arch = ObjectFile::Mips;
} else {
fatal("The binary you're trying to load is compiled for big "
"endian MIPS. M5\nonly supports little endian MIPS. "
"Please recompile your binary.\n");
}
} else if (ehdr.e_machine == EM_X86_64 &&
ehdr.e_ident[EI_CLASS] == ELFCLASS64) {
arch = ObjectFile::X86_64;
} else if (ehdr.e_machine == EM_386 &&
ehdr.e_ident[EI_CLASS] == ELFCLASS32) {
arch = ObjectFile::I386;
} else if (ehdr.e_ident[EI_CLASS] == ELFCLASS64) {
arch = ObjectFile::Alpha;
} else if (ehdr.e_machine == EM_ARM) {
if (bits(ehdr.e_entry, 0)) {
arch = ObjectFile::Thumb;
} else {
arch = ObjectFile::Arm;
}
} else if (ehdr.e_machine == EM_PPC &&
ehdr.e_ident[EI_CLASS] == ELFCLASS32) {
if (ehdr.e_ident[EI_DATA] == ELFDATA2MSB) {
arch = ObjectFile::Power;
} else {
fatal("The binary you're trying to load is compiled for "
"little endian Power.\nM5 only supports big "
"endian Power. Please recompile your binary.\n");
}
} else if (ehdr.e_machine == EM_PPC64) {
fatal("The binary you're trying to load is compiled for 64-bit "
"Power. M5\n only supports 32-bit Power. Please "
"recompile your binary.\n");
} else {
warn("Unknown architecture: %d\n", ehdr.e_machine);
arch = ObjectFile::UnknownArch;
}
//Detect the operating system
switch (ehdr.e_ident[EI_OSABI])
{
case ELFOSABI_LINUX:
opSys = ObjectFile::Linux;
break;
case ELFOSABI_SOLARIS:
opSys = ObjectFile::Solaris;
break;
case ELFOSABI_TRU64:
opSys = ObjectFile::Tru64;
break;
case ELFOSABI_ARM:
opSys = ObjectFile::LinuxArmOABI;
break;
default:
opSys = ObjectFile::UnknownOpSys;
}
//take a look at the .note.ABI section
//It can let us know what's what.
if (opSys == ObjectFile::UnknownOpSys) {
Elf_Scn *section;
GElf_Shdr shdr;
Elf_Data *data;
uint32_t osAbi;;
int secIdx = 1;
// Get the first section
section = elf_getscn(elf, secIdx);
// While there are no more sections
while (section != NULL && opSys == ObjectFile::UnknownOpSys) {
gelf_getshdr(section, &shdr);
if (shdr.sh_type == SHT_NOTE && !strcmp(".note.ABI-tag",
elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name))) {
// we have found a ABI note section
// Check the 5th 32bit word for OS 0 == linux, 1 == hurd,
// 2 == solaris, 3 == freebsd
data = elf_rawdata(section, NULL);
assert(data->d_buf);
if(ehdr.e_ident[EI_DATA] == ELFDATA2LSB)
osAbi = htole(((uint32_t*)data->d_buf)[4]);
else
osAbi = htobe(((uint32_t*)data->d_buf)[4]);
switch(osAbi) {
case 0:
opSys = ObjectFile::Linux;
break;
case 2:
opSys = ObjectFile::Solaris;
break;
}
} // if section found
if (!strcmp(".SUNW_version", elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name)))
opSys = ObjectFile::Solaris;
if (!strcmp(".stab.index", elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name)))
opSys = ObjectFile::Solaris;
section = elf_getscn(elf, ++secIdx);
} // while sections
}
ElfObject * result = new ElfObject(fname, fd, len, data, arch, opSys);
//The number of headers in the file
result->_programHeaderCount = ehdr.e_phnum;
//Record the size of each entry
result->_programHeaderSize = ehdr.e_phentsize;
if(result->_programHeaderCount) //If there is a program header table
{
//Figure out the virtual address of the header table in the
//final memory image. We use the program headers themselves
//to translate from a file offset to the address in the image.
GElf_Phdr phdr;
uint64_t e_phoff = ehdr.e_phoff;
result->_programHeaderTable = 0;
for(int hdrnum = 0; hdrnum < result->_programHeaderCount; hdrnum++)
{
gelf_getphdr(elf, hdrnum, &phdr);
//Check if we've found the segment with the headers in it
if(phdr.p_offset <= e_phoff &&
phdr.p_offset + phdr.p_filesz > e_phoff)
{
result->_programHeaderTable = phdr.p_paddr + e_phoff;
break;
}
}
}
else
result->_programHeaderTable = 0;
elf_end(elf);
return result;
}
}
ElfObject::ElfObject(const string &_filename, int _fd,
size_t _len, uint8_t *_data,
Arch _arch, OpSys _opSys)
: ObjectFile(_filename, _fd, _len, _data, _arch, _opSys)
{
Elf *elf;
GElf_Ehdr ehdr;
// check that header matches library version
if (elf_version(EV_CURRENT) == EV_NONE)
panic("wrong elf version number!");
// get a pointer to elf structure
elf = elf_memory((char*)fileData,len);
// will only fail if fd is invalid
assert(elf != NULL);
// Check that we actually have a elf file
if (gelf_getehdr(elf, &ehdr) ==0) {
panic("Not ELF, shouldn't be here");
}
entry = ehdr.e_entry;
// initialize segment sizes to 0 in case they're not present
text.size = data.size = bss.size = 0;
int secIdx = 1;
Elf_Scn *section;
GElf_Shdr shdr;
// The first address of some important sections.
Addr textSecStart = 0;
Addr dataSecStart = 0;
Addr bssSecStart = 0;
// Get the first section
section = elf_getscn(elf, secIdx);
// Find the beginning of the most interesting sections.
while (section != NULL) {
gelf_getshdr(section, &shdr);
char * secName = elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name);
if (secName) {
if (!strcmp(".text", secName)) {
textSecStart = shdr.sh_addr;
} else if (!strcmp(".data", secName)) {
dataSecStart = shdr.sh_addr;
} else if (!strcmp(".bss", secName)) {
bssSecStart = shdr.sh_addr;
}
} else {
Elf_Error errorNum = (Elf_Error)elf_errno();
if (errorNum != ELF_E_NONE) {
const char *errorMessage = elf_errmsg(errorNum);
fatal("Error from libelf: %s.\n", errorMessage);
}
}
section = elf_getscn(elf, ++secIdx);
}
// Go through all the segments in the program, record them, and scrape
// out information about the text, data, and bss areas needed by other
// code.
for (int i = 0; i < ehdr.e_phnum; ++i) {
GElf_Phdr phdr;
if (gelf_getphdr(elf, i, &phdr) == 0) {
panic("gelf_getphdr failed for segment %d.", i);
}
// for now we don't care about non-loadable segments
if (!(phdr.p_type & PT_LOAD))
continue;
// Check to see if this segment contains the bss section.
if (phdr.p_paddr <= bssSecStart &&
phdr.p_paddr + phdr.p_memsz > bssSecStart &&
phdr.p_memsz - phdr.p_filesz > 0) {
bss.baseAddr = phdr.p_paddr + phdr.p_filesz;
bss.size = phdr.p_memsz - phdr.p_filesz;
bss.fileImage = NULL;
}
// Check to see if this is the text or data segment
if (phdr.p_vaddr <= textSecStart &&
phdr.p_vaddr + phdr.p_filesz > textSecStart) {
text.baseAddr = phdr.p_paddr;
text.size = phdr.p_filesz;
text.fileImage = fileData + phdr.p_offset;
} else if (phdr.p_vaddr <= dataSecStart &&
phdr.p_vaddr + phdr.p_filesz > dataSecStart) {
data.baseAddr = phdr.p_paddr;
data.size = phdr.p_filesz;
data.fileImage = fileData + phdr.p_offset;
} else {
// If it's none of the above but is loadable,
// load the filesize worth of data
Segment extra;
extra.baseAddr = phdr.p_paddr;
extra.size = phdr.p_filesz;
extra.fileImage = fileData + phdr.p_offset;
extraSegments.push_back(extra);
}
}
// should have found at least one loadable segment
assert(text.size != 0);
DPRINTFR(Loader, "text: 0x%x %d\ndata: 0x%x %d\nbss: 0x%x %d\n",
text.baseAddr, text.size, data.baseAddr, data.size,
bss.baseAddr, bss.size);
elf_end(elf);
// We will actually read the sections when we need to load them
}
bool
ElfObject::loadSomeSymbols(SymbolTable *symtab, int binding, Addr mask)
{
Elf *elf;
int sec_idx = 1; // there is a 0 but it is nothing, go figure
Elf_Scn *section;
GElf_Shdr shdr;
Elf_Data *data;
int count, ii;
bool found = false;
GElf_Sym sym;
if (!symtab)
return false;
// check that header matches library version
if (elf_version(EV_CURRENT) == EV_NONE)
panic("wrong elf version number!");
// get a pointer to elf structure
elf = elf_memory((char*)fileData,len);
assert(elf != NULL);
// Get the first section
section = elf_getscn(elf, sec_idx);
// While there are no more sections
while (section != NULL) {
gelf_getshdr(section, &shdr);
if (shdr.sh_type == SHT_SYMTAB) {
found = true;
data = elf_getdata(section, NULL);
count = shdr.sh_size / shdr.sh_entsize;
DPRINTF(Loader, "Found Symbol Table, %d symbols present\n", count);
// loop through all the symbols, only loading global ones
for (ii = 0; ii < count; ++ii) {
gelf_getsym(data, ii, &sym);
if (GELF_ST_BIND(sym.st_info) == binding) {
char *sym_name = elf_strptr(elf, shdr.sh_link, sym.st_name);
if (sym_name && sym_name[0] != '$') {
DPRINTF(Loader, "Symbol: %-40s value %#x\n",
sym_name, sym.st_value);
symtab->insert(sym.st_value & mask, sym_name);
}
}
}
}
++sec_idx;
section = elf_getscn(elf, sec_idx);
}
elf_end(elf);
return found;
}
bool
ElfObject::loadGlobalSymbols(SymbolTable *symtab, Addr addrMask)
{
return loadSomeSymbols(symtab, STB_GLOBAL, addrMask);
}
bool
ElfObject::loadLocalSymbols(SymbolTable *symtab, Addr addrMask)
{
return loadSomeSymbols(symtab, STB_LOCAL, addrMask);
}
bool
ElfObject::loadSections(PortProxy& memProxy, Addr addrMask)
{
if (!ObjectFile::loadSections(memProxy, addrMask))
return false;
vector<Segment>::iterator extraIt;
for (extraIt = extraSegments.begin();
extraIt != extraSegments.end(); extraIt++) {
if (!loadSection(&(*extraIt), memProxy, addrMask)) {
return false;
}
}
return true;
}
void
ElfObject::getSections()
{
Elf *elf;
int sec_idx = 1; // there is a 0 but it is nothing, go figure
Elf_Scn *section;
GElf_Shdr shdr;
GElf_Ehdr ehdr;
assert(!sectionNames.size());
// check that header matches library version
if (elf_version(EV_CURRENT) == EV_NONE)
panic("wrong elf version number!");
// get a pointer to elf structure
elf = elf_memory((char*)fileData,len);
assert(elf != NULL);
// Check that we actually have a elf file
if (gelf_getehdr(elf, &ehdr) ==0) {
panic("Not ELF, shouldn't be here");
}
// Get the first section
section = elf_getscn(elf, sec_idx);
// While there are no more sections
while (section != NULL) {
gelf_getshdr(section, &shdr);
sectionNames.insert(elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name));
section = elf_getscn(elf, ++sec_idx);
} // while sections
}
bool
ElfObject::sectionExists(string sec)
{
if (!sectionNames.size())
getSections();
return sectionNames.find(sec) != sectionNames.end();
}

View File

@ -0,0 +1,85 @@
/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Steve Reinhardt
*/
#ifndef __ELF_OBJECT_HH__
#define __ELF_OBJECT_HH__
#include <set>
#include <vector>
#include "base/loader/object_file.hh"
class ElfObject : public ObjectFile
{
protected:
//The global definition of a "Section" is closest to elf's segments.
typedef ObjectFile::Section Segment;
//These values are provided to a linux process by the kernel, so we
//need to keep them around.
Addr _programHeaderTable;
uint16_t _programHeaderSize;
uint16_t _programHeaderCount;
std::set<std::string> sectionNames;
/// Helper functions for loadGlobalSymbols() and loadLocalSymbols().
bool loadSomeSymbols(SymbolTable *symtab, int binding, Addr mask);
ElfObject(const std::string &_filename, int _fd,
size_t _len, uint8_t *_data,
Arch _arch, OpSys _opSys);
void getSections();
bool sectionExists(std::string sec);
std::vector<Segment> extraSegments;
public:
virtual ~ElfObject() {}
bool loadSections(PortProxy& memProxy,
Addr addrMask = std::numeric_limits<Addr>::max());
virtual bool loadGlobalSymbols(SymbolTable *symtab, Addr addrMask =
std::numeric_limits<Addr>::max());
virtual bool loadLocalSymbols(SymbolTable *symtab, Addr addrMask =
std::numeric_limits<Addr>::max());
virtual bool isDynamic() { return sectionExists(".interp"); }
virtual bool hasTLS() { return sectionExists(".tbss"); }
static ObjectFile *tryFile(const std::string &fname, int fd,
size_t len, uint8_t *data);
Addr programHeaderTable() {return _programHeaderTable;}
uint16_t programHeaderSize() {return _programHeaderSize;}
uint16_t programHeaderCount() {return _programHeaderCount;}
};
#endif // __ELF_OBJECT_HH__

View File

@ -0,0 +1,61 @@
/*
* Taken from NetBSD sys/exec_aout.h
*/
/* $NetBSD: exec_aout.h,v 1.29 2002/12/10 17:14:31 thorpej Exp $ */
/*
* Copyright (c) 1993, 1994 Christopher G. Demetriou
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Christopher G. Demetriou.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SYS_EXEC_AOUT_H_
#define _SYS_EXEC_AOUT_H_
#ifndef N_PAGSIZ
#define N_PAGSIZ(ex) (AOUT_LDPGSZ)
#endif
/* a_magic */
#define OMAGIC 0407 /* old impure format */
#define NMAGIC 0410 /* read-only text */
#define ZMAGIC 0413 /* demand load format */
#define N_ALIGN(ex,x) \
(N_GETMAGIC(ex) == ZMAGIC ? \
((x) + AOUT_LDPGSZ - 1) & ~(AOUT_LDPGSZ - 1) : (x))
/* Valid magic number check. */
#define N_BADMAG(ex) \
(N_GETMAGIC(ex) != NMAGIC && N_GETMAGIC(ex) != OMAGIC && \
N_GETMAGIC(ex) != ZMAGIC)
//Only alpha will be able to load aout for now
#include "arch/alpha/aout_machdep.h"
#endif /* !_SYS_EXEC_AOUT_H_ */

View File

@ -0,0 +1,107 @@
/*
* Taken from NetBSD sys/exec_ecoff.h
*/
/* $NetBSD: exec_ecoff.h,v 1.13 2003/01/18 09:53:18 thorpej Exp $ */
/*
* Copyright (c) 1994 Adam Glass
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Adam Glass.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SYS_EXEC_ECOFF_H_
#define _SYS_EXEC_ECOFF_H_
struct ecoff_filehdr {
coff_ushort f_magic; /* magic number */
coff_ushort f_nscns; /* # of sections */
coff_uint f_timdat; /* time and date stamp */
coff_ulong f_symptr; /* file offset of symbol table */
coff_uint f_nsyms; /* # of symbol table entries */
coff_ushort f_opthdr; /* sizeof the optional header */
coff_ushort f_flags; /* flags??? */
};
struct ecoff_aouthdr {
coff_ushort magic;
coff_ushort vstamp;
ECOFF_PAD
coff_ulong tsize;
coff_ulong dsize;
coff_ulong bsize;
coff_ulong entry;
coff_ulong text_start;
coff_ulong data_start;
coff_ulong bss_start;
ECOFF_MACHDEP;
};
struct ecoff_scnhdr { /* needed for size info */
char s_name[8]; /* name */
coff_ulong s_paddr; /* physical addr? for ROMing?*/
coff_ulong s_vaddr; /* virtual addr? */
coff_ulong s_size; /* size */
coff_ulong s_scnptr; /* file offset of raw data */
coff_ulong s_relptr; /* file offset of reloc data */
coff_ulong s_lnnoptr; /* file offset of line data */
coff_ushort s_nreloc; /* # of relocation entries */
coff_ushort s_nlnno; /* # of line entries */
coff_uint s_flags; /* flags */
};
struct ecoff_exechdr {
struct ecoff_filehdr f;
struct ecoff_aouthdr a;
};
#define ECOFF_HDR_SIZE (sizeof(struct ecoff_exechdr))
#define ECOFF_OMAGIC 0407
#define ECOFF_NMAGIC 0410
#define ECOFF_ZMAGIC 0413
#define ECOFF_ROUND(value, by) \
(((value) + (by) - 1) & ~((by) - 1))
#define ECOFF_BLOCK_ALIGN(ep, value) \
((ep)->a.magic == ECOFF_ZMAGIC ? ECOFF_ROUND((value), ECOFF_LDPGSZ) : \
(value))
#define ECOFF_TXTOFF(ep) \
((ep)->a.magic == ECOFF_ZMAGIC ? 0 : \
ECOFF_ROUND(ECOFF_HDR_SIZE + (ep)->f.f_nscns * \
sizeof(struct ecoff_scnhdr), ECOFF_SEGMENT_ALIGNMENT(ep)))
#define ECOFF_DATOFF(ep) \
(ECOFF_BLOCK_ALIGN((ep), ECOFF_TXTOFF(ep) + (ep)->a.tsize))
#define ECOFF_SEGMENT_ALIGN(ep, value) \
(ECOFF_ROUND((value), ((ep)->a.magic == ECOFF_ZMAGIC ? ECOFF_LDPGSZ : \
ECOFF_SEGMENT_ALIGNMENT(ep))))
#endif /* !_SYS_EXEC_ECOFF_H_ */

View File

@ -0,0 +1,138 @@
/*
* Copyright (c) 2007 MIPS Technologies, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Jaidev Patwardhan
*/
#include <cctype>
#include <cstdio>
#include <list>
#include <string>
#include "base/loader/hex_file.hh"
#include "base/loader/symtab.hh"
#include "base/cprintf.hh"
#include "mem/port_proxy.hh"
using namespace std;
/*
* Load a Hex File into memory. Currently only used with MIPS
* BARE_IRON mode. A hex file consists of [Address Data] tuples that
* get directly loaded into physical memory. The address specified is
* a word address (i.e., to get the byte address, shift left by 2) The
* data is a full 32-bit hex value.
*/
HexFile::HexFile(const string _filename)
: filename(_filename)
{
fp = fopen(filename.c_str(), "r");
if (fp == NULL)
panic("Unable to open %s\n", filename.c_str());
}
HexFile::~HexFile()
{
}
bool
HexFile::loadSections(PortProxy& memProxy)
{
char Line[64];
Addr MemAddr;
uint32_t Data;
while (!feof(fp)) {
char *ret = fgets(Line, sizeof(Line), fp);
if (!ret)
panic("malformed file");
parseLine(Line, &MemAddr, &Data);
if (MemAddr != 0) {
// Now, write to memory
memProxy.writeBlob(MemAddr << 2, (uint8_t *)&Data, sizeof(Data));
}
}
return true;
}
void
HexFile::parseLine(char *Str, Addr *A, uint32_t *D)
{
int i = 0;
bool Flag = false;
*A = 0;
*D = 0;
int Digit = 0;
unsigned Number = 0;
/* Skip white spaces */
while (Str[i] != '\0' && Str[i]==' ')
i++;
/* Ok, we're at some character...process things */
while (Str[i] != '\0') {
if (Str[i] >= '0' && Str[i] <= '9') {
Digit = Str[i] - '0';
} else if (Str[i] >= 'a' && Str[i] <= 'f') {
Digit = Str[i] - 'a' + 10;
} else if (Str[i] >= 'A' && Str[i] <= 'F') {
Digit=Str[i]-'A'+10;
} else if (Str[i] == ' ' || Str[i] == '\n') {
if (Number == 0)
return;
if (Flag == false) {
*A = Number;
Number = 0;
Flag = true;
} else {
*D = Number;
return;
}
} else {
// Ok, we've encountered a non-hex character, cannot be a
// valid line, skip and return 0's
*A = 0;
*D = 0;
return;
}
Number <<= 4;
Number += Digit;
i++;
}
if (Flag != true) {
*A = 0;
*D = 0;
} else {
*D = Number;
}
}
void
HexFile::close()
{
fclose(fp);
}

View File

@ -0,0 +1,58 @@
/*
* Copyright (c) 2002-2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Jaidev Patwardhan
*/
#ifndef __BASE_LOADER_HEX_FILE_HH__
#define __BASE_LOADER_HEX_FILE_HH__
#include <cstdio>
#include <limits>
#include <string>
#include "base/types.hh"
class PortProxy;
class HexFile
{
protected:
const std::string filename;
FILE *fp;
void parseLine(char *, Addr *, uint32_t *);
public:
HexFile(const std::string _filename);
virtual ~HexFile();
void close();
bool loadSections(PortProxy& memProxy);
};
#endif // __BASE_LOADER_HEX_FILE_HH__

View File

@ -0,0 +1,150 @@
/*
* Copyright (c) 2002-2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
* Steve Reinhardt
*/
#include <sys/mman.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <cstdio>
#include <list>
#include <string>
#include "base/loader/aout_object.hh"
#include "base/loader/ecoff_object.hh"
#include "base/loader/elf_object.hh"
#include "base/loader/object_file.hh"
#include "base/loader/raw_object.hh"
#include "base/loader/symtab.hh"
#include "base/cprintf.hh"
#include "mem/port_proxy.hh"
using namespace std;
ObjectFile::ObjectFile(const string &_filename, int _fd,
size_t _len, uint8_t *_data,
Arch _arch, OpSys _opSys)
: filename(_filename), descriptor(_fd), fileData(_data), len(_len),
arch(_arch), opSys(_opSys)
{
}
ObjectFile::~ObjectFile()
{
close();
}
bool
ObjectFile::loadSection(Section *sec, PortProxy& memProxy, Addr addrMask)
{
if (sec->size != 0) {
Addr addr = sec->baseAddr & addrMask;
if (sec->fileImage) {
memProxy.writeBlob(addr, sec->fileImage, sec->size);
}
else {
// no image: must be bss
memProxy.memsetBlob(addr, 0, sec->size);
}
}
return true;
}
bool
ObjectFile::loadSections(PortProxy& memProxy, Addr addrMask)
{
return (loadSection(&text, memProxy, addrMask)
&& loadSection(&data, memProxy, addrMask)
&& loadSection(&bss, memProxy, addrMask));
}
void
ObjectFile::close()
{
if (descriptor >= 0) {
::close(descriptor);
descriptor = -1;
}
if (fileData) {
::munmap((char*)fileData, len);
fileData = NULL;
}
}
ObjectFile *
createObjectFile(const string &fname, bool raw)
{
// open the file
int fd = open(fname.c_str(), O_RDONLY);
if (fd < 0) {
return NULL;
}
// find the length of the file by seeking to the end
size_t len = (size_t)lseek(fd, 0, SEEK_END);
// mmap the whole shebang
uint8_t *fileData =
(uint8_t *)mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0);
if (fileData == MAP_FAILED) {
close(fd);
return NULL;
}
ObjectFile *fileObj = NULL;
// figure out what we have here
if ((fileObj = EcoffObject::tryFile(fname, fd, len, fileData)) != NULL) {
return fileObj;
}
if ((fileObj = AoutObject::tryFile(fname, fd, len, fileData)) != NULL) {
return fileObj;
}
if ((fileObj = ElfObject::tryFile(fname, fd, len, fileData)) != NULL) {
return fileObj;
}
if (raw)
return RawObject::tryFile(fname, fd, len, fileData);
// don't know what it is
close(fd);
munmap((char*)fileData, len);
return NULL;
}

View File

@ -0,0 +1,136 @@
/*
* Copyright (c) 2002-2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
* Steve Reinhardt
*/
#ifndef __OBJECT_FILE_HH__
#define __OBJECT_FILE_HH__
#include <limits>
#include <string>
#include "base/types.hh"
class PortProxy;
class SymbolTable;
class ObjectFile
{
public:
enum Arch {
UnknownArch,
Alpha,
SPARC64,
SPARC32,
Mips,
X86_64,
I386,
Arm,
Thumb,
Power
};
enum OpSys {
UnknownOpSys,
Tru64,
Linux,
Solaris,
LinuxArmOABI
};
protected:
const std::string filename;
int descriptor;
uint8_t *fileData;
size_t len;
Arch arch;
OpSys opSys;
ObjectFile(const std::string &_filename, int _fd,
size_t _len, uint8_t *_data,
Arch _arch, OpSys _opSys);
public:
virtual ~ObjectFile();
void close();
virtual bool loadSections(PortProxy& memProxy, Addr addrMask =
std::numeric_limits<Addr>::max());
virtual bool loadGlobalSymbols(SymbolTable *symtab, Addr addrMask =
std::numeric_limits<Addr>::max()) = 0;
virtual bool loadLocalSymbols(SymbolTable *symtab, Addr addrMask =
std::numeric_limits<Addr>::max()) = 0;
virtual bool isDynamic() { return false; }
virtual bool hasTLS() { return false; }
Arch getArch() const { return arch; }
OpSys getOpSys() const { return opSys; }
protected:
struct Section {
Addr baseAddr;
uint8_t *fileImage;
size_t size;
};
Addr entry;
Addr globalPtr;
Section text;
Section data;
Section bss;
bool loadSection(Section *sec, PortProxy& memProxy, Addr addrMask);
void setGlobalPointer(Addr global_ptr) { globalPtr = global_ptr; }
public:
Addr entryPoint() const { return entry; }
Addr globalPointer() const { return globalPtr; }
Addr textBase() const { return text.baseAddr; }
Addr dataBase() const { return data.baseAddr; }
Addr bssBase() const { return bss.baseAddr; }
size_t textSize() const { return text.size; }
size_t dataSize() const { return data.size; }
size_t bssSize() const { return bss.size; }
void setTextBase(Addr a) { text.baseAddr = a; }
};
ObjectFile *createObjectFile(const std::string &fname, bool raw = false);
#endif // __OBJECT_FILE_HH__

View File

@ -0,0 +1,82 @@
/*
* Copyright (c) 2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Steve Reinhardt
*/
#include "base/loader/raw_object.hh"
#include "base/loader/symtab.hh"
#include "base/trace.hh"
#include "debug/Loader.hh"
ObjectFile *
RawObject::tryFile(const std::string &fname, int fd, size_t len, uint8_t *data)
{
return new RawObject(fname, fd, len, data, ObjectFile::UnknownArch,
ObjectFile::UnknownOpSys);
}
RawObject::RawObject(const std::string &_filename, int _fd, size_t _len,
uint8_t *_data, Arch _arch, OpSys _opSys)
: ObjectFile(_filename, _fd, _len, _data, _arch, _opSys)
{
text.baseAddr = 0;
text.size = len;
text.fileImage = fileData;
data.baseAddr = 0;
data.size = 0;
data.fileImage = NULL;
bss.baseAddr = 0;
bss.size = 0;
bss.fileImage = NULL;
DPRINTFR(Loader, "text: 0x%x %d\ndata: 0x%x %d\nbss: 0x%x %d\n",
text.baseAddr, text.size, data.baseAddr, data.size,
bss.baseAddr, bss.size);
}
bool
RawObject::loadGlobalSymbols(SymbolTable *symtab, Addr addrMask)
{
/* int fnameStart = filename.rfind('/',filename.size()) + 1;
int extStart = filename.rfind('.',filename.size());
symtab->insert(text.baseAddr & addrMask, filename.substr(fnameStart,
extStart-fnameStart) + "_start");*/
return true;
}
bool
RawObject::loadLocalSymbols(SymbolTable *symtab, Addr addrMask)
{
/* int fnameStart = filename.rfind('/',filename.size()) + 1;
int extStart = filename.rfind('.',filename.size());
symtab->insert(text.baseAddr & addrMask, filename.substr(fnameStart,
extStart-fnameStart) + "_start");*/
return true;
}

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Ali Saidi
*/
#ifndef __BASE_LOADER_RAW_OBJECT_HH__
#define __BASE_LOADER_RAW_OBJECT_HH__
#include "base/loader/object_file.hh"
class RawObject: public ObjectFile
{
protected:
RawObject(const std::string &_filename, int _fd, size_t _len,
uint8_t *_data, Arch _arch, OpSys _opSys);
public:
virtual ~RawObject() {}
virtual bool loadGlobalSymbols(SymbolTable *symtab, Addr addrMask =
std::numeric_limits<Addr>::max());
virtual bool loadLocalSymbols(SymbolTable *symtab, Addr addrMask =
std::numeric_limits<Addr>::max());
static ObjectFile *tryFile(const std::string &fname, int fd, size_t len,
uint8_t *data);
};
#endif // __BASE_LOADER_RAW_OBJECT_HH__

View File

@ -0,0 +1,139 @@
/*
* Copyright (c) 2002-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include "base/loader/symtab.hh"
#include "base/misc.hh"
#include "base/str.hh"
#include "base/types.hh"
#include "sim/serialize.hh"
using namespace std;
SymbolTable *debugSymbolTable = NULL;
void
SymbolTable::clear()
{
addrTable.clear();
symbolTable.clear();
}
bool
SymbolTable::insert(Addr address, string symbol)
{
if (symbol.empty())
return false;
if (!addrTable.insert(make_pair(address, symbol)).second)
return false;
if (!symbolTable.insert(make_pair(symbol, address)).second)
return false;
return true;
}
bool
SymbolTable::load(const string &filename)
{
string buffer;
ifstream file(filename.c_str());
if (!file)
fatal("file error: Can't open symbol table file %s\n", filename);
while (!file.eof()) {
getline(file, buffer);
if (buffer.empty())
continue;
string::size_type idx = buffer.find(',');
if (idx == string::npos)
return false;
string address = buffer.substr(0, idx);
eat_white(address);
if (address.empty())
return false;
string symbol = buffer.substr(idx + 1);
eat_white(symbol);
if (symbol.empty())
return false;
Addr addr;
if (!to_number(address, addr))
return false;
if (!insert(addr, symbol))
return false;
}
file.close();
return true;
}
void
SymbolTable::serialize(const string &base, ostream &os)
{
paramOut(os, base + ".size", addrTable.size());
int i = 0;
ATable::const_iterator p, end = addrTable.end();
for (p = addrTable.begin(); p != end; ++p) {
paramOut(os, csprintf("%s.addr_%d", base, i), p->first);
paramOut(os, csprintf("%s.symbol_%d", base, i), p->second);
++i;
}
}
void
SymbolTable::unserialize(const string &base, Checkpoint *cp,
const string &section)
{
clear();
int size;
paramIn(cp, section, base + ".size", size);
for (int i = 0; i < size; ++i) {
Addr addr;
std::string symbol;
paramIn(cp, section, csprintf("%s.addr_%d", base, i), addr);
paramIn(cp, section, csprintf("%s.symbol_%d", base, i), symbol);
insert(addr, symbol);
}
}

View File

@ -0,0 +1,177 @@
/*
* Copyright (c) 2002-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
* Steve Reinhardt
*/
#ifndef __SYMTAB_HH__
#define __SYMTAB_HH__
#include <iosfwd>
#include <map>
#include <string>
#include "base/types.hh"
class Checkpoint;
class SymbolTable
{
public:
typedef std::map<Addr, std::string> ATable;
typedef std::map<std::string, Addr> STable;
private:
ATable addrTable;
STable symbolTable;
private:
bool
upperBound(Addr addr, ATable::const_iterator &iter) const
{
// find first key *larger* than desired address
iter = addrTable.upper_bound(addr);
// if very first key is larger, we're out of luck
if (iter == addrTable.begin())
return false;
return true;
}
public:
SymbolTable() {}
SymbolTable(const std::string &file) { load(file); }
~SymbolTable() {}
void clear();
bool insert(Addr address, std::string symbol);
bool load(const std::string &file);
const ATable &getAddrTable() const { return addrTable; }
const STable &getSymbolTable() const { return symbolTable; }
public:
void serialize(const std::string &base, std::ostream &os);
void unserialize(const std::string &base, Checkpoint *cp,
const std::string &section);
public:
bool
findSymbol(Addr address, std::string &symbol) const
{
ATable::const_iterator i = addrTable.find(address);
if (i == addrTable.end())
return false;
symbol = (*i).second;
return true;
}
bool
findAddress(const std::string &symbol, Addr &address) const
{
STable::const_iterator i = symbolTable.find(symbol);
if (i == symbolTable.end())
return false;
address = (*i).second;
return true;
}
/// Find the nearest symbol equal to or less than the supplied
/// address (e.g., the label for the enclosing function).
/// @param addr The address to look up.
/// @param symbol Return reference for symbol string.
/// @param symaddr Return reference for symbol address.
/// @param nextaddr Address of following symbol (for
/// determining valid range of symbol).
/// @retval True if a symbol was found.
bool
findNearestSymbol(Addr addr, std::string &symbol, Addr &symaddr,
Addr &nextaddr) const
{
ATable::const_iterator i;
if (!upperBound(addr, i))
return false;
nextaddr = i->first;
--i;
symaddr = i->first;
symbol = i->second;
return true;
}
/// Overload for findNearestSymbol() for callers who don't care
/// about nextaddr.
bool
findNearestSymbol(Addr addr, std::string &symbol, Addr &symaddr) const
{
ATable::const_iterator i;
if (!upperBound(addr, i))
return false;
--i;
symaddr = i->first;
symbol = i->second;
return true;
}
bool
findNearestAddr(Addr addr, Addr &symaddr, Addr &nextaddr) const
{
ATable::const_iterator i;
if (!upperBound(addr, i))
return false;
nextaddr = i->first;
--i;
symaddr = i->first;
return true;
}
bool
findNearestAddr(Addr addr, Addr &symaddr) const
{
ATable::const_iterator i;
if (!upperBound(addr, i))
return false;
--i;
symaddr = i->first;
return true;
}
};
/// Global unified debugging symbol table (for target). Conceptually
/// there should be one of these per System object for full system,
/// and per Process object for non-full-system, but so far one big
/// global one has worked well enough.
extern SymbolTable *debugSymbolTable;
#endif // __SYMTAB_HH__

View File

@ -0,0 +1,98 @@
/*
* Copyright (c) 2004-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#include "base/match.hh"
#include "base/str.hh"
using namespace std;
ObjectMatch::ObjectMatch()
{
}
ObjectMatch::ObjectMatch(const string &expr)
{
setExpression(expr);
}
void
ObjectMatch::setExpression(const string &expr)
{
tokens.resize(1);
tokenize(tokens[0], expr, '.');
}
void
ObjectMatch::setExpression(const vector<string> &expr)
{
if (expr.empty()) {
tokens.resize(0);
} else {
tokens.resize(expr.size());
for (vector<string>::size_type i = 0; i < expr.size(); ++i)
tokenize(tokens[i], expr[i], '.');
}
}
/**
* @todo this should probably be changed to just use regular
* expression code
*/
bool
ObjectMatch::domatch(const string &name) const
{
vector<string> name_tokens;
tokenize(name_tokens, name, '.');
int ntsize = name_tokens.size();
int num_expr = tokens.size();
for (int i = 0; i < num_expr; ++i) {
const vector<string> &token = tokens[i];
int jstop = token.size();
bool match = true;
for (int j = 0; j < jstop; ++j) {
if (j >= ntsize)
break;
const string &var = token[j];
if (var != "*" && var != name_tokens[j]) {
match = false;
break;
}
}
if (match == true)
return true;
}
return false;
}

View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2004-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
/* @file
* User Console Definitions
*/
#ifndef __BASE_MATCH_HH__
#define __BASE_MATCH_HH__
#include <string>
#include <vector>
class ObjectMatch
{
protected:
std::vector<std::vector<std::string> > tokens;
bool domatch(const std::string &name) const;
public:
ObjectMatch();
ObjectMatch(const std::string &expression);
void setExpression(const std::string &expression);
void setExpression(const std::vector<std::string> &expression);
bool match(const std::string &name) const
{
return tokens.empty() ? false : domatch(name);
}
};
#endif // __BASE_MATCH_HH__

View File

@ -0,0 +1,116 @@
/*
* Copyright (c) 2002-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#include <cstdlib>
#include <iostream>
#include <string>
#include "base/cprintf.hh"
#include "base/hostinfo.hh"
#include "base/misc.hh"
#include "base/output.hh"
#include "base/trace.hh"
#include "base/types.hh"
#include "base/varargs.hh"
#include "sim/core.hh"
using namespace std;
bool want_warn = true;
bool want_info = true;
bool want_hack = true;
bool warn_verbose = false;
bool info_verbose = false;
bool hack_verbose = false;
void
__exit_message(const char *prefix, int code,
const char *func, const char *file, int line,
const char *fmt, CPRINTF_DEFINITION)
{
CPrintfArgsList args(VARARGS_ALLARGS);
string format = prefix;
format += ": ";
format += fmt;
switch (format[format.size() - 1]) {
case '\n':
case '\r':
break;
default:
format += "\n";
}
format += " @ cycle %d\n[%s:%s, line %d]\n";
format += "Memory Usage: %ld KBytes\n";
args.push_back(curTick());
args.push_back(func);
args.push_back(file);
args.push_back(line);
args.push_back(memUsage());
ccprintf(cerr, format.c_str(), args);
if (code < 0)
abort();
else
exit(code);
}
void
__base_message(std::ostream &stream, const char *prefix, bool verbose,
const char *func, const char *file, int line,
const char *fmt, CPRINTF_DEFINITION)
{
CPrintfArgsList args(VARARGS_ALLARGS);
string format = prefix;
format += ": ";
format += fmt;
switch (format[format.size() - 1]) {
case '\n':
case '\r':
break;
default:
format += "\n";
}
if (verbose) {
format += " @ cycle %d\n[%s:%s, line %d]\n";
args.push_back(curTick());
args.push_back(func);
args.push_back(file);
args.push_back(line);
}
ccprintf(stream, format.c_str(), args);
}

View File

@ -0,0 +1,150 @@
/*
* Copyright (c) 2002-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
* Dave Greene
*/
#ifndef __BASE_MISC_HH__
#define __BASE_MISC_HH__
#include "base/compiler.hh"
#include "base/cprintf.hh"
#include "base/varargs.hh"
#if defined(__SUNPRO_CC)
#define __FUNCTION__ "how to fix me?"
#endif
// General exit message, these functions will never return and will
// either abort() if code is < 0 or exit with the code if >= 0
void __exit_message(const char *prefix, int code,
const char *func, const char *file, int line,
const char *format, CPRINTF_DECLARATION) M5_ATTR_NORETURN;
void __exit_message(const char *prefix, int code,
const char *func, const char *file, int line,
const std::string &format, CPRINTF_DECLARATION) M5_ATTR_NORETURN;
inline void
__exit_message(const char *prefix, int code,
const char *func, const char *file, int line,
const std::string& format, CPRINTF_DEFINITION)
{
__exit_message(prefix, code, func, file, line, format.c_str(),
VARARGS_ALLARGS);
}
M5_PRAGMA_NORETURN(__exit_message)
#define exit_message(prefix, code, ...) \
__exit_message(prefix, code, __FUNCTION__, __FILE__, __LINE__, \
__VA_ARGS__)
//
// This implements a cprintf based panic() function. panic() should
// be called when something happens that should never ever happen
// regardless of what the user does (i.e., an acutal m5 bug). panic()
// calls abort which can dump core or enter the debugger.
//
//
#define panic(...) exit_message("panic", -1, __VA_ARGS__)
//
// This implements a cprintf based fatal() function. fatal() should
// be called when the simulation cannot continue due to some condition
// that is the user's fault (bad configuration, invalid arguments,
// etc.) and not a simulator bug. fatal() calls exit(1), i.e., a
// "normal" exit with an error code, as opposed to abort() like
// panic() does.
//
#define fatal(...) exit_message("fatal", 1, __VA_ARGS__)
void
__base_message(std::ostream &stream, const char *prefix, bool verbose,
const char *func, const char *file, int line,
const char *format, CPRINTF_DECLARATION);
inline void
__base_message(std::ostream &stream, const char *prefix, bool verbose,
const char *func, const char *file, int line,
const std::string &format, CPRINTF_DECLARATION)
{
__base_message(stream, prefix, verbose, func, file, line, format.c_str(),
VARARGS_ALLARGS);
}
#define base_message(stream, prefix, verbose, ...) \
__base_message(stream, prefix, verbose, __FUNCTION__, __FILE__, __LINE__, \
__VA_ARGS__)
// Only print the message the first time this expression is
// encountered. i.e. This doesn't check the string itself and
// prevent duplicate strings, this prevents the statement from
// happening more than once. So, even if the arguments change and that
// would have resulted in a different message thoes messages would be
// supressed.
#define base_message_once(...) do { \
static bool once = false; \
if (!once) { \
base_message(__VA_ARGS__); \
once = true; \
} \
} while (0)
#define cond_message(cond, ...) do { \
if (cond) \
base_message(__VA_ARGS__); \
} while (0)
#define cond_message_once(cond, ...) do { \
static bool once = false; \
if (!once && cond) { \
base_message(__VA_ARGS__); \
once = true; \
} \
} while (0)
extern bool want_warn, warn_verbose;
extern bool want_info, info_verbose;
extern bool want_hack, hack_verbose;
#define warn(...) \
cond_message(want_warn, std::cerr, "warn", warn_verbose, __VA_ARGS__)
#define inform(...) \
cond_message(want_info, std::cout, "info", info_verbose, __VA_ARGS__)
#define hack(...) \
cond_message(want_hack, std::cerr, "hack", hack_verbose, __VA_ARGS__)
#define warn_once(...) \
cond_message_once(want_warn, std::cerr, "warn", warn_verbose, __VA_ARGS__)
#define inform_once(...) \
cond_message_once(want_info, std::cout, "info", info_verbose, __VA_ARGS__)
#define hack_once(...) \
cond_message_once(want_hack, std::cerr, "hack", hack_verbose, __VA_ARGS__)
#endif // __BASE_MISC_HH__

View File

@ -0,0 +1,203 @@
/*
* Copyright (c) 2002-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Steve Raasch
*/
template<class T, T MV>
class ModNum {
private:
T value;
// Compiler should optimize this
void setValue(T n) { value = n % MV; }
public:
ModNum() {}
ModNum(T n) { setValue(n); }
ModNum(const ModNum<T, MV> &n) : value(n.value) {}
ModNum operator=(T n) {
setValue(n);
return *this;
}
const ModNum operator=(ModNum n) {
value = n.value;
return *this;
}
// Return the value if object used as RHS
operator T() const { return value; }
//
// Operator "+="
//
const ModNum<T, MV> operator+=(ModNum<T, MV> r) {
setValue(value + r.value);
return *this;
}
const ModNum<T, MV> operator+=(T r) {
setValue(value + r);
return *this;
}
//
// Operator "-="
//
const ModNum<T, MV> operator-=(ModNum<T, MV> r) {
setValue(value - r.value);
return *this;
}
const ModNum<T, MV> operator-=(T r) {
setValue(value - r);
return *this;
}
//
// Operator "++"
//
// PREFIX (like ++a)
const ModNum<T, MV> operator++() {
*this += 1;
return *this;
}
// POSTFIX (like a++)
const ModNum<T, MV> operator++(int) {
ModNum<T, MV> rv = *this;
*this += 1;
return rv;
}
//
// Operator "--"
//
// PREFIX (like --a)
const ModNum<T, MV> operator--() {
*this -= 1;
return *this;
}
// POSTFIX (like a--)
const ModNum<T, MV> operator--(int) {
ModNum<T, MV> rv = *this;
*this -= 1;
return rv;
}
};
//
// Define operator "+" like this to avoid creating a temporary
//
template<class T, T MV>
inline ModNum<T, MV>
operator+(ModNum<T, MV> l, ModNum<T, MV> r) {
l += r;
return l;
}
template<class T, T MV>
inline ModNum<T, MV>
operator+(ModNum<T, MV> l, T r) {
l += r;
return l;
}
template<class T, T MV>
inline ModNum<T, MV>
operator+(T l, ModNum<T, MV> r) {
r += l;
return r;
}
//
// Define operator "-" like this to avoid creating a temporary
//
template<class T, T MV>
inline ModNum<T, MV>
operator-(ModNum<T, MV> l, ModNum<T, MV> r) {
l -= r;
return l;
}
template<class T, T MV>
inline ModNum<T, MV>
operator-(ModNum<T, MV> l, T r) {
l -= r;
return l;
}
template<class T, T MV>
inline ModNum<T, MV>
operator-(T l, ModNum<T, MV> r) {
r -= l;
return r;
}
//
// Comparison operators
// (all other cases are handled with conversons)
//
template<class T, T MV>
inline bool
operator<(ModNum<T, MV> l, ModNum<T, MV> r) {
return l.value < r.value;
}
template<class T, T MV>
inline bool
operator>(ModNum<T, MV> l, ModNum<T, MV> r) {
return l.value > r.value;
}
template<class T, T MV>
inline bool
operator==(ModNum<T, MV> l, ModNum<T, MV> r) {
return l.value == r.value;
}
template<class T, T MV>
inline bool
operator<=(ModNum<T, MV> l, ModNum<T, MV> r) {
return l.value <= r.value;
}
template<class T, T MV>
inline bool
operator>=(ModNum<T, MV> l, ModNum<T, MV> r) {
return l.value >= r.value;
}

View File

@ -0,0 +1,267 @@
/*
* Copyright (c) 2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
* Chris Emmons
*/
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <cassert>
#include <cerrno>
#include <climits>
#include <cstdlib>
#include <fstream>
#include <gzstream.hh>
#include "base/misc.hh"
#include "base/output.hh"
using namespace std;
OutputDirectory simout;
/**
* @file This file manages creating / deleting output files for the simulator.
*/
OutputDirectory::OutputDirectory()
{}
OutputDirectory::~OutputDirectory()
{
for (map_t::iterator i = files.begin(); i != files.end(); i++) {
if (i->second)
delete i->second;
}
}
std::ostream *
OutputDirectory::checkForStdio(const string &name) const
{
if (name == "cerr" || name == "stderr")
return &cerr;
if (name == "cout" || name == "stdout")
return &cout;
return NULL;
}
ostream *
OutputDirectory::openFile(const string &filename,
ios_base::openmode mode)
{
if (filename.find(".gz", filename.length()-3) < filename.length()) {
ogzstream *file = new ogzstream(filename.c_str(), mode);
if (!file->is_open())
fatal("Cannot open file %s", filename);
assert(files.find(filename) == files.end());
files[filename] = file;
return file;
} else {
ofstream *file = new ofstream(filename.c_str(), mode);
if (!file->is_open())
fatal("Cannot open file %s", filename);
assert(files.find(filename) == files.end());
files[filename] = file;
return file;
}
}
void
OutputDirectory::close(ostream *openStream) {
map_t::iterator i;
for (i = files.begin(); i != files.end(); i++) {
if (i->second != openStream)
continue;
ofstream *fs = dynamic_cast<ofstream*>(i->second);
if (fs) {
fs->close();
delete i->second;
break;
} else {
ogzstream *gfs = dynamic_cast<ogzstream*>(i->second);
if (gfs) {
gfs->close();
delete i->second;
break;
}
}
}
if (i == files.end())
fatal("Attempted to close an unregistred file stream");
files.erase(i);
}
void
OutputDirectory::setDirectory(const string &d)
{
if (!dir.empty())
panic("Output directory already set!\n");
dir = d;
// guarantee that directory ends with a path separator
if (dir[dir.size() - 1] != PATH_SEPARATOR)
dir += PATH_SEPARATOR;
}
const string &
OutputDirectory::directory() const
{
if (dir.empty())
panic("Output directory not set!");
return dir;
}
inline string
OutputDirectory::resolve(const string &name) const
{
return (name[0] != PATH_SEPARATOR) ? dir + name : name;
}
ostream *
OutputDirectory::create(const string &name, bool binary)
{
ostream *file = checkForStdio(name);
if (file)
return file;
string filename = resolve(name);
ios_base::openmode mode =
ios::trunc | (binary ? ios::binary : (ios::openmode)0);
file = openFile(filename, mode);
return file;
}
ostream *
OutputDirectory::find(const string &name) const
{
ostream *file = checkForStdio(name);
if (file)
return file;
const string filename = resolve(name);
map_t::const_iterator i = files.find(filename);
if (i != files.end())
return (*i).second;
return NULL;
}
bool
OutputDirectory::isFile(const std::ostream *os)
{
return os && os != &cerr && os != &cout;
}
bool
OutputDirectory::isFile(const string &name) const
{
// definitely a file if in our data structure
if (find(name) != NULL) return true;
struct stat st_buf;
int st = stat(name.c_str(), &st_buf);
return (st == 0) && S_ISREG(st_buf.st_mode);
}
string
OutputDirectory::createSubdirectory(const string &name) const
{
const string new_dir = resolve(name);
if (new_dir.find(directory()) == string::npos)
fatal("Attempting to create subdirectory not in m5 output dir\n");
// if it already exists, that's ok; otherwise, fail if we couldn't create
if ((mkdir(new_dir.c_str(), 0755) != 0) && (errno != EEXIST))
fatal("Failed to create new output subdirectory '%s'\n", new_dir);
return name + PATH_SEPARATOR;
}
void
OutputDirectory::remove(const string &name, bool recursive)
{
const string fname = resolve(name);
if (fname.find(directory()) == string::npos)
fatal("Attempting to remove file/dir not in output dir\n");
if (isFile(fname)) {
// close and release file if we have it open
map_t::iterator itr = files.find(fname);
if (itr != files.end()) {
delete itr->second;
files.erase(itr);
}
if (::remove(fname.c_str()) != 0)
fatal("Could not erase file '%s'\n", fname);
} else {
// assume 'name' is a directory
if (recursive) {
DIR *dir = opendir(fname.c_str());
// silently ignore removal request for non-existent directory
if ((!dir) && (errno == ENOENT))
return;
// fail on other errors
if (!dir) {
perror("opendir");
fatal("Error opening directory for recursive removal '%s'\n",
fname);
}
struct dirent *de = readdir(dir);
while (de != NULL) {
// ignore files starting with a '.'; user must delete those
// manually if they really want to
if (de->d_name[0] != '.')
remove(name + PATH_SEPARATOR + de->d_name, recursive);
de = readdir(dir);
}
}
// try to force recognition that we deleted the files in the directory
sync();
if (::remove(fname.c_str()) != 0) {
perror("Warning! 'remove' failed. Could not erase directory.");
}
}
}

View File

@ -0,0 +1,184 @@
/*
* Copyright (c) 2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
* Chris Emmons
*/
#ifndef __BASE_OUTPUT_HH__
#define __BASE_OUTPUT_HH__
#include <ios>
#include <map>
#include <string>
/** Interface for creating files in a gem5 output directory. */
class OutputDirectory
{
private:
/** File names and associated stream handles */
typedef std::map<std::string, std::ostream *> map_t;
/** Open file streams within this directory */
map_t files;
/** Name of this directory */
std::string dir;
/** System-specific path separator character */
static const char PATH_SEPARATOR = '/';
/**
* Returns relative file names prepended with name of this directory.
* Returns absolute file names unaltered.
*
* @param name file name to prepend with directory name
* @return file name prepended with base directory name or unaltered
* absolute file name
*/
std::string resolve(const std::string &name) const;
protected:
/**
* Determines whether given file name corresponds to standard output
* streams.
*
* @param name name of file to check
* @return output stream for standard output or error stream if name
* corresponds to one or the other; NULL otherwise
*/
std::ostream *checkForStdio(const std::string &name) const;
public:
/** Constructor. */
OutputDirectory();
/** Destructor. */
~OutputDirectory();
/** Opens a file (optionally compressed).
*
* Will open a file as a compressed stream if filename ends in .gz.
*
* @param filename file to open
* @param mode attributes to open file with
* @return stream pointer to opened file; will cause sim fail on error
*/
std::ostream *openFile(const std::string &filename,
std::ios_base::openmode mode = std::ios::trunc);
/**
* Sets name of this directory.
* @param dir name of this directory
*/
void setDirectory(const std::string &dir);
/**
* Gets name of this directory.
* @return name of this directory
*/
const std::string &directory() const;
/**
* Creates a file in this directory (optionally compressed).
*
* Will open a file as a compressed stream if filename ends in .gz.
*
* @param name name of file to create (without this directory's name
* leading it)
* @param binary true to create a binary file; false otherwise
* @return stream to the opened file
*/
std::ostream *create(const std::string &name, bool binary = false);
/**
* Closes a file stream.
*
* Stream must have been opened through this interface, or sim will fail.
*
* @param openStream open stream to close
*/
void close(std::ostream *openStream);
/**
* Finds stream associated with a file.
* @param name of file
* @return stream to specified file or NULL if file does not exist
*/
std::ostream *find(const std::string &name) const;
/**
* Returns true if stream is open and not standard output or error.
* @param os output stream to evaluate
* @return true if os is non-NULL and not cout or cerr
*/
static bool isFile(const std::ostream *os);
/**
* Determines whether a file name corresponds to a file in this directory.
* @param name name of file to evaluate
* @return true iff file has been opened in this directory or exists on the
* file system within this directory
*/
bool isFile(const std::string &name) const;
/**
* Returns true if stream is open and not standard output or error.
* @param os output stream to evaluate
* @return true if os is non-NULL and not cout or cerr
*/
static inline bool isFile(const std::ostream &os) {
return isFile(&os);
}
/**
* Creates a subdirectory within this directory.
* @param name name of subdirectory
* @return the new subdirectory's name suffixed with a path separator
*/
std::string createSubdirectory(const std::string &name) const;
/**
* Removes a specified file or subdirectory.
*
* Will cause sim to fail for most errors. However, it will only warn the
* user if a directory could not be removed. This is in place to
* accommodate slow file systems where file deletions within a subdirectory
* may not be recognized quickly enough thereby causing the subsequent call
* to remove the directory to fail (seemingly unempty directory).
*
* @param name name of file or subdirectory to remove; name should not
* be prepended with the name of this directory object
* @param recursive set to true to attempt to recursively delete a
* subdirectory and its contents
*/
void remove(const std::string &name, bool recursive=false);
};
extern OutputDirectory simout;
#endif // __BASE_OUTPUT_HH__

View File

@ -0,0 +1,279 @@
/*
* Copyright (c) 2002-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#include <sys/ioctl.h>
#include <sys/types.h>
#if defined(__sun__) || defined(__SUNPRO_CC)
#include <sys/file.h>
#endif
#include <fcntl.h>
#include <unistd.h>
#include <csignal>
#include "base/misc.hh"
#include "base/pollevent.hh"
#include "base/types.hh"
#include "sim/async.hh"
#include "sim/core.hh"
#include "sim/serialize.hh"
using namespace std;
PollQueue pollQueue;
/////////////////////////////////////////////////////
//
PollEvent::PollEvent(int _fd, int _events)
: queue(NULL), enabled(true)
{
pfd.fd = _fd;
pfd.events = _events;
}
PollEvent::~PollEvent()
{
if (queue)
queue->remove(this);
}
void
PollEvent::disable()
{
if (!enabled) return;
enabled = false;
if (queue)
queue->copy();
}
void
PollEvent::enable()
{
if (enabled) return;
enabled = true;
if (queue)
queue->copy();
}
void
PollEvent::serialize(ostream &os)
{
SERIALIZE_SCALAR(pfd.fd);
SERIALIZE_SCALAR(pfd.events);
SERIALIZE_SCALAR(enabled);
}
void
PollEvent::unserialize(Checkpoint *cp, const std::string &section)
{
UNSERIALIZE_SCALAR(pfd.fd);
UNSERIALIZE_SCALAR(pfd.events);
UNSERIALIZE_SCALAR(enabled);
}
/////////////////////////////////////////////////////
//
PollQueue::PollQueue()
: poll_fds(NULL), max_size(0), num_fds(0)
{ }
PollQueue::~PollQueue()
{
removeHandler();
for (int i = 0; i < num_fds; i++)
setupAsyncIO(poll_fds[0].fd, false);
delete [] poll_fds;
}
void
PollQueue::copy()
{
eventvec_t::iterator i = events.begin();
eventvec_t::iterator end = events.end();
num_fds = 0;
while (i < end) {
if ((*i)->enabled)
poll_fds[num_fds++] = (*i)->pfd;
++i;
}
}
void
PollQueue::remove(PollEvent *event)
{
eventvec_t::iterator i = events.begin();
eventvec_t::iterator end = events.end();
while (i < end) {
if (*i == event) {
events.erase(i);
copy();
event->queue = NULL;
return;
}
++i;
}
panic("Event does not exist. Cannot remove.");
}
void
PollQueue::schedule(PollEvent *event)
{
if (event->queue)
panic("Event already scheduled!");
event->queue = this;
events.push_back(event);
setupAsyncIO(event->pfd.fd, true);
// if we ran out of space in the fd array, double the capacity
// if this is the first time that we've scheduled an event, create
// the array with an initial size of 16
if (++num_fds > max_size) {
if (max_size > 0) {
delete [] poll_fds;
max_size *= 2;
} else {
max_size = 16;
setupHandler();
}
poll_fds = new pollfd[max_size];
}
copy();
}
void
PollQueue::service()
{
int ret = poll(poll_fds, num_fds, 0);
if (ret <= 0)
return;
for (int i = 0; i < num_fds; i++) {
int revents = poll_fds[i].revents;
if (revents) {
events[i]->process(revents);
if (--ret <= 0)
break;
}
}
}
struct sigaction PollQueue::oldio;
struct sigaction PollQueue::oldalrm;
bool PollQueue::handler = false;
void
PollQueue::setupAsyncIO(int fd, bool set)
{
int flags = fcntl(fd, F_GETFL);
if (flags == -1)
panic("Could not set up async IO");
if (set)
flags |= FASYNC;
else
flags &= ~(FASYNC);
if (fcntl(fd, F_SETFL, flags) == -1)
panic("Could not set up async IO");
if (set) {
if (fcntl(fd, F_SETOWN, getpid()) == -1)
panic("Could not set up async IO");
}
}
void
PollQueue::setupHandler()
{
struct sigaction act;
act.sa_handler = handleIO;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_RESTART;
if (sigaction(SIGIO, &act, &oldio) == -1)
panic("could not do sigaction");
act.sa_handler = handleALRM;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_RESTART;
if (sigaction(SIGALRM, &act, &oldalrm) == -1)
panic("could not do sigaction");
alarm(1);
handler = true;
}
void
PollQueue::removeHandler()
{
if (sigaction(SIGIO, &oldio, NULL) == -1)
panic("could not remove handler");
if (sigaction(SIGIO, &oldalrm, NULL) == -1)
panic("could not remove handler");
}
void
PollQueue::handleIO(int sig)
{
if (sig != SIGIO)
panic("Wrong Handler");
async_event = true;
async_io = true;
}
void
PollQueue::handleALRM(int sig)
{
if (sig != SIGALRM)
panic("Wrong Handler");
async_event = true;
async_alarm = true;
alarm(1);
}

View File

@ -0,0 +1,101 @@
/*
* Copyright (c) 2002-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#ifndef __POLLEVENT_H__
#define __POLLEVENT_H__
#include <poll.h>
#include <vector>
#include "sim/core.hh"
class Checkpoint;
class PollQueue;
class PollEvent
{
private:
friend class PollQueue;
protected:
pollfd pfd;
PollQueue *queue;
bool enabled;
public:
PollEvent(int fd, int event);
virtual ~PollEvent();
void disable();
void enable();
virtual void process(int revent) = 0;
bool queued() { return queue != 0; }
virtual void serialize(std::ostream &os);
virtual void unserialize(Checkpoint *cp, const std::string &section);
};
class PollQueue
{
private:
typedef std::vector<PollEvent *> eventvec_t;
eventvec_t events;
pollfd *poll_fds;
int max_size;
int num_fds;
public:
PollQueue();
~PollQueue();
void copy();
void remove(PollEvent *event);
void schedule(PollEvent *event);
void service();
protected:
static bool handler;
static struct sigaction oldio;
static struct sigaction oldalrm;
public:
static void setupAsyncIO(int fd, bool set);
static void handleIO(int);
static void handleALRM(int);
static void removeHandler();
static void setupHandler();
};
extern PollQueue pollQueue;
#endif // __POLLEVENT_H__

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2007 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* @file
* Printable Object Base Class Declaration
*/
#ifndef __PRINTABLE_HH__
#define __PRINTABLE_HH__
#include <ostream>
#include <string>
/**
* Abstract base class for objects which support being printed
* to a stream for debugging. Primarily used to support PrintReq
* in memory system.
*/
class Printable
{
public:
Printable() {}
virtual ~Printable() {}
virtual void print(std::ostream &os,
int verbosity = 0,
const std::string &prefix = "") const = 0;
};
#endif // __PRINTABLE_HH__

View File

@ -0,0 +1,127 @@
/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
* Ali Saidi
*/
#include <limits>
#include "base/fenv.hh"
#include "base/intmath.hh"
#include "base/misc.hh"
#include "base/random.hh"
#include "sim/serialize.hh"
using namespace std;
Random::Random()
{
// default random seed taken from original source
init(5489);
}
Random::Random(uint32_t s)
{
init(s);
}
Random::Random(uint32_t init_key[], int key_length)
{
init(init_key, key_length);
}
Random::~Random()
{
}
// To preserve the uniform random distribution between min and max,
// and allow all numbers to be represented, we generate a uniform
// random number to the nearest power of two greater than max. If
// this number doesn't fall between 0 and max, we try again. Anything
// else would skew the distribution.
uint32_t
Random::genrand(uint32_t max)
{
if (max == 0)
return 0;
if (max == std::numeric_limits<uint32_t>::max())
return genrand();
int log = ceilLog2(max + 1);
int shift = (sizeof(uint32_t) * 8 - log);
uint32_t random;
do {
random = genrand() >> shift;
} while (random > max);
return random;
}
uint64_t
Random::genrand(uint64_t max)
{
if (max == 0)
return 0;
if (max == std::numeric_limits<uint64_t>::max())
return genrand();
int log = ceilLog2(max + 1);
int shift = (sizeof(uint64_t) * 8 - log);
uint64_t random;
do {
random = (uint64_t)genrand() << 32 | (uint64_t)genrand();
random = random >> shift;
} while (random > max);
return random;
}
void
Random::serialize(const string &base, ostream &os)
{
int length = N;
paramOut(os, base + ".mti", mti);
paramOut(os, base + ".length", length);
arrayParamOut(os, base + ".data", mt, length);
}
void
Random::unserialize(const string &base, Checkpoint *cp, const string &section)
{
int length;
paramIn(cp, section, base + ".mti", mti);
paramIn(cp, section, base + ".length", length);
if (length != N)
panic("cant unserialize random number data. length != %d\n", length);
arrayParamIn(cp, section, base + ".data", mt, length);
}
Random random_mt;

View File

@ -0,0 +1,249 @@
/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
* Ali Saidi
*/
/*
* Mersenne Twister random number generator has a period of
* 2^19937-1.
*
* The actual math is in its own file to keep the license clear.
*/
#ifndef __BASE_RANDOM_HH__
#define __BASE_RANDOM_HH__
#include <ios>
#include <string>
#include "base/range.hh"
#include "base/types.hh"
class Checkpoint;
class Random
{
protected:
static const int N = 624;
static const int M = 397;
static const uint32_t MATRIX_A = (uint32_t)0x9908b0df;
static const uint32_t UPPER_MASK = (uint32_t)0x80000000;
static const uint32_t LOWER_MASK = (uint32_t)0x7fffffff;
uint32_t mt[N];
int mti;
uint32_t genrand();
uint32_t genrand(uint32_t max);
uint64_t genrand(uint64_t max);
void
_random(int8_t &value)
{
value = genrand() & (int8_t)-1;
}
void
_random(int16_t &value)
{
value = genrand() & (int16_t)-1;
}
void
_random(int32_t &value)
{
value = (int32_t)genrand();
}
void
_random(int64_t &value)
{
value = (int64_t)genrand() << 32 | (int64_t)genrand();
}
void
_random(uint8_t &value)
{
value = genrand() & (uint8_t)-1;
}
void
_random(uint16_t &value)
{
value = genrand() & (uint16_t)-1;
}
void
_random(uint32_t &value)
{
value = genrand();
}
void
_random(uint64_t &value)
{
value = (uint64_t)genrand() << 32 | (uint64_t)genrand();
}
// [0,1]
void
_random(float &value)
{
// ieee floats have 23 bits of mantissa
value = (genrand() >> 9) / 8388608.0;
}
// [0,1]
void
_random(double &value)
{
double number = genrand() * 2097152.0 + (genrand() >> 11);
value = number / 9007199254740992.0;
}
// Range based versions of the random number generator
int8_t
_random(int8_t min, int8_t max)
{
uint32_t diff = max - min;
return static_cast<int8_t>(min + genrand(diff));
}
int16_t
_random(int16_t min, int16_t max)
{
uint32_t diff = max - min;
return static_cast<int16_t>(min + genrand(diff));
}
int32_t
_random(int32_t min, int32_t max)
{
uint32_t diff = max - min;
return static_cast<int32_t>(min + genrand(diff));
}
int64_t
_random(int64_t min, int64_t max)
{
uint64_t diff = max - min;
return static_cast<int64_t>(min + genrand(diff));
}
uint8_t
_random(uint8_t min, uint8_t max)
{
uint32_t diff = max - min;
return static_cast<uint8_t>(min + genrand(diff));
}
uint16_t
_random(uint16_t min, uint16_t max)
{
uint32_t diff = max - min;
return static_cast<uint16_t>(min + genrand(diff));
}
uint32_t
_random(uint32_t min, uint32_t max)
{
uint32_t diff = max - min;
return static_cast<uint32_t>(min + genrand(diff));
}
uint64_t
_random(uint64_t min, uint64_t max)
{
uint64_t diff = max - min;
return static_cast<uint64_t>(min + genrand(diff));
}
public:
Random();
Random(uint32_t s);
Random(uint32_t init_key[], int key_length);
~Random();
void init(uint32_t s);
void init(uint32_t init_key[], int key_length);
template <typename T>
T
random()
{
T value;
_random(value);
return value;
}
template <typename T>
T
random(T min, T max)
{
return _random(min, max);
}
template <typename T>
T
random(const Range<T> &range)
{
return _random(range.start, range.end);
}
// [0,1]
double
gen_real1()
{
return genrand() / 4294967296.0;
}
// [0,1)
double
gen_real2()
{
return genrand() / 4294967295.0;
}
// (0,1)
double
gen_real3()
{
return ((double)genrand() + 0.5) / 4294967296.0;
}
public:
void serialize(const std::string &base, std::ostream &os);
void unserialize(const std::string &base, Checkpoint *cp,
const std::string &section);
};
extern Random random_mt;
#endif // __BASE_RANDOM_HH__

View File

@ -0,0 +1,149 @@
/*
* A C-program for MT19937, with initialization improved 2002/1/26.
* Coded by Takuji Nishimura and Makoto Matsumoto.
*
* Before using, initialize the state by using init_genrand(seed)
* or init_by_array(init_key, key_length).
*
* Copyright (C) 1997-2002 Makoto Matsumoto and Takuji Nishimura
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* 3. The names of its contributors may not be used to endorse or
* promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
* Any feedback is very welcome.
* http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
* email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
*/
#include "base/random.hh"
/* initializes mt[N] with a seed */
void
Random::init(uint32_t s)
{
mti = N + 1;
mt[0] = s & (uint32_t)0xffffffff;
for (mti = 1; mti < N; mti++) {
mt[mti] = 1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti;
/* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
/* In the previous versions, MSBs of the seed affect */
/* only MSBs of the array mt[]. */
/* 2002/01/09 modified by Makoto Matsumoto */
mt[mti] &= (uint32_t)0xffffffff;
/* for >32 bit machines */
}
}
/* initialize by an array with array-length */
/* init_key is the array for initializing keys */
/* key_length is its length */
/* slight change for C++, 2004/2/26 */
void
Random::init(uint32_t init_key[], int key_length)
{
int i = 1;
int j = 0;
int k = (N > key_length) ? N : key_length;
init(19650218);
for (; k; k--) {
mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * (uint32_t)1664525))
+ init_key[j] + j; /* non linear */
mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
i++;
j++;
if (i >= N) {
mt[0] = mt[N - 1];
i = 1;
}
if (j >= key_length)
j = 0;
}
for (k = N - 1; k; k--) {
/* non linear */
mt[i] = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >> 30)) * 1566083941UL)) - i;
/* for WORDSIZE > 32 machines */
mt[i] &= (uint32_t)0xffffffff;
i++;
if (i >= N) {
mt[0] = mt[N - 1];
i = 1;
}
}
/* MSB is 1; assuring non-zero initial array */
mt[0] = (uint32_t)0x80000000;
}
/* generates a random number on [0,0xffffffff]-interval */
uint32_t
Random::genrand()
{
uint32_t y;
static uint32_t mag01[2] = { 0, MATRIX_A};
if (mti >= N) { /* generate N words at one time */
int kk;
for (kk = 0; kk < N - M; kk++) {
y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
mt[kk] = mt[kk + M] ^ (y >> 1) ^ mag01[y & 0x1UL];
}
for (; kk < N - 1; kk++) {
y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
mt[kk] = mt[kk + (M - N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
}
y = (mt[N - 1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
mt[N - 1] = mt[M - 1] ^ (y >> 1) ^ mag01[y & 0x1UL];
mti = 0;
}
y = mt[mti++];
/* Tempering */
y ^= (y >> 11);
y ^= (y << 7) & (uint32_t)0x9d2c5680;
y ^= (y << 15) & (uint32_t)0xefc60000;
y ^= (y >> 18);
return y;
}

View File

@ -0,0 +1,85 @@
/*
* Copyright (c) 2004-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#include "base/intmath.hh"
#include "base/range.hh"
#include "base/str.hh"
using namespace std;
template <class T>
bool
__x_parse_range(const std::string &str, T &first, T &last)
{
std::vector<std::string> values;
tokenize(values, str, ':');
T thefirst, thelast;
if (values.size() != 2)
return false;
std::string s = values[0];
std::string e = values[1];
if (!to_number(s, thefirst))
return false;
bool increment = (e[0] == '+');
if (increment)
e = e.substr(1);
if (!to_number(e, thelast))
return false;
if (increment)
thelast += thefirst - 1;
first = thefirst;
last = thelast;
return true;
}
#define RANGE_PARSE(type) \
template<> bool \
__parse_range(const std::string &s, type &first, type &last) \
{ return __x_parse_range(s, first, last); }
RANGE_PARSE(unsigned long long)
RANGE_PARSE(signed long long)
RANGE_PARSE(unsigned long)
RANGE_PARSE(signed long)
RANGE_PARSE(unsigned int)
RANGE_PARSE(signed int)
RANGE_PARSE(unsigned short)
RANGE_PARSE(signed short)
RANGE_PARSE(unsigned char)
RANGE_PARSE(signed char)

View File

@ -0,0 +1,364 @@
/*
* Copyright (c) 2002-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
* Steve Reinhardt
*/
#ifndef __BASE_RANGE_HH__
#define __BASE_RANGE_HH__
#include <cassert>
#include <iostream>
#include <string>
/**
* @param s range string
* EndExclusive Ranges are in the following format:
* @verbatim
* <range> := {<start_val>}:{<end>}
* <start> := <end_val> | +<delta>
* @endverbatim
*/
template <class T>
bool __parse_range(const std::string &s, T &start, T &end);
template <class T>
struct Range
{
T start;
T end;
Range() { invalidate(); }
template <class U>
Range(const std::pair<U, U> &r)
: start(r.first), end(r.second)
{}
template <class U>
Range(const Range<U> &r)
: start(r.start), end(r.end)
{}
Range(const std::string &s)
{
if (!__parse_range(s, start, end))
invalidate();
}
template <class U>
const Range<T> &operator=(const Range<U> &r)
{
start = r.start;
end = r.end;
return *this;
}
template <class U>
const Range<T> &operator=(const std::pair<U, U> &r)
{
start = r.first;
end = r.second;
return *this;
}
const Range &operator=(const std::string &s)
{
if (!__parse_range(s, start, end))
invalidate();
return *this;
}
void invalidate() { start = 1; end = 0; }
T size() const { return end - start + 1; }
bool valid() const { return start < end; }
};
template <class T>
inline std::ostream &
operator<<(std::ostream &o, const Range<T> &r)
{
o << '[' << r.start << "," << r.end << ']';
return o;
}
template <class T>
inline Range<T>
RangeEx(T start, T end)
{ return std::make_pair(start, end - 1); }
template <class T>
inline Range<T>
RangeIn(T start, T end)
{ return std::make_pair(start, end); }
template <class T, class U>
inline Range<T>
RangeSize(T start, U size)
{ return std::make_pair(start, start + size - 1); }
////////////////////////////////////////////////////////////////////////
//
// Range to Range Comparisons
//
/**
* @param range1 is a range.
* @param range2 is a range.
* @return if range1 and range2 are identical.
*/
template <class T, class U>
inline bool
operator==(const Range<T> &range1, const Range<U> &range2)
{
return range1.start == range2.start && range1.end == range2.end;
}
/**
* @param range1 is a range.
* @param range2 is a range.
* @return if range1 and range2 are not identical.
*/
template <class T, class U>
inline bool
operator!=(const Range<T> &range1, const Range<U> &range2)
{
return range1.start != range2.start || range1.end != range2.end;
}
/**
* @param range1 is a range.
* @param range2 is a range.
* @return if range1 is less than range2 and does not overlap range1.
*/
template <class T, class U>
inline bool
operator<(const Range<T> &range1, const Range<U> &range2)
{
return range1.start < range2.start;
}
/**
* @param range1 is a range.
* @param range2 is a range.
* @return if range1 is less than range2. range1 may overlap range2,
* but not extend beyond the end of range2.
*/
template <class T, class U>
inline bool
operator<=(const Range<T> &range1, const Range<U> &range2)
{
return range1.start <= range2.start;
}
/**
* @param range1 is a range.
* @param range2 is a range.
* @return if range1 is greater than range2 and does not overlap range2.
*/
template <class T, class U>
inline bool
operator>(const Range<T> &range1, const Range<U> &range2)
{
return range1.start > range2.start;
}
/**
* @param range1 is a range.
* @param range2 is a range.
* @return if range1 is greater than range2. range1 may overlap range2,
* but not extend beyond the beginning of range2.
*/
template <class T, class U>
inline bool
operator>=(const Range<T> &range1, const Range<U> &range2)
{
return range1.start >= range2.start;
}
////////////////////////////////////////////////////////////////////////
//
// Position to Range Comparisons
//
/**
* @param pos position compared to the range.
* @param range range compared against.
* @return indicates that position pos is within the range.
*/
template <class T, class U>
inline bool
operator==(const T &pos, const Range<U> &range)
{
return pos >= range.start && pos <= range.end;
}
/**
* @param pos position compared to the range.
* @param range range compared against.
* @return indicates that position pos is not within the range.
*/
template <class T, class U>
inline bool
operator!=(const T &pos, const Range<U> &range)
{
return pos < range.start || pos > range.end;
}
/**
* @param pos position compared to the range.
* @param range range compared against.
* @return indicates that position pos is below the range.
*/
template <class T, class U>
inline bool
operator<(const T &pos, const Range<U> &range)
{
return pos < range.start;
}
/**
* @param pos position compared to the range.
* @param range range compared against.
* @return indicates that position pos is below or in the range.
*/
template <class T, class U>
inline bool
operator<=(const T &pos, const Range<U> &range)
{
return pos <= range.end;
}
/**
* @param pos position compared to the range.
* @param range range compared against.
* @return indicates that position pos is above the range.
*/
template <class T, class U>
inline bool
operator>(const T &pos, const Range<U> &range)
{
return pos > range.end;
}
/**
* @param pos position compared to the range.
* @param range range compared against.
* @return indicates that position pos is above or in the range.
*/
template <class T, class U>
inline bool
operator>=(const T &pos, const Range<U> &range)
{
return pos >= range.start;
}
////////////////////////////////////////////////////////////////////////
//
// Range to Position Comparisons (for symmetry)
//
/**
* @param range range compared against.
* @param pos position compared to the range.
* @return indicates that position pos is within the range.
*/
template <class T, class U>
inline bool
operator==(const Range<T> &range, const U &pos)
{
return pos >= range.start && pos <= range.end;
}
/**
* @param range range compared against.
* @param pos position compared to the range.
* @return indicates that position pos is not within the range.
*/
template <class T, class U>
inline bool
operator!=(const Range<T> &range, const U &pos)
{
return pos < range.start || pos > range.end;
}
/**
* @param range range compared against.
* @param pos position compared to the range.
* @return indicates that position pos is above the range.
*/
template <class T, class U>
inline bool
operator<(const Range<T> &range, const U &pos)
{
// with -std=gnu++0x, gcc and clang get confused when range.end is
// compared to pos using the operator "<", and the parser expects it
// to be the opening bracket for a template parameter,
// i.e. range.end<pos>(...);, the reason seems to be the range-type
// iteration introduced in c++11 where begin and end are members
// that return iterators
return operator<(range.end, pos);
}
/**
* @param range range compared against.
* @param pos position compared to the range.
* @return indicates that position pos is above or in the range.
*/
template <class T, class U>
inline bool
operator<=(const Range<T> &range, const U &pos)
{
return range.start <= pos;
}
/**
* @param range range compared against.
* @param pos position compared to the range.
* 'range > pos' indicates that position pos is below the range.
*/
template <class T, class U>
inline bool
operator>(const Range<T> &range, const U &pos)
{
return range.start > pos;
}
/**
* @param range range compared against.
* @param pos position compared to the range.
* 'range >= pos' indicates that position pos is below or in the range.
*/
template <class T, class U>
inline bool
operator>=(const Range<T> &range, const U &pos)
{
return range.end >= pos;
}
#endif // __BASE_RANGE_HH__

View File

@ -0,0 +1,324 @@
/*
* Copyright (c) 2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Ali Saidi
*/
#ifndef __BASE_RANGE_MAP_HH__
#define __BASE_RANGE_MAP_HH__
#include <map>
#include <utility>
#include "base/range.hh"
/**
* The range_map uses an STL map to implement an interval tree. The
* type of both the key (range) and the value are template
* parameters. It can, for example, be used for address decoding,
* using a range of addresses to map to ports.
*/
template <class T,class V>
class range_map
{
private:
typedef std::map<Range<T>,V> RangeMap;
RangeMap tree;
public:
typedef typename RangeMap::iterator iterator;
typedef typename RangeMap::const_iterator const_iterator;
template <class U>
const_iterator
find(const Range<U> &r) const
{
const_iterator i;
i = tree.upper_bound(r);
if (i == tree.begin()) {
if (i->first.start <= r.end && i->first.end >= r.start)
return i;
else
// Nothing could match, so return end()
return tree.end();
}
--i;
if (i->first.start <= r.end && i->first.end >= r.start)
return i;
return tree.end();
}
template <class U>
iterator
find(const Range<U> &r)
{
iterator i;
i = tree.upper_bound(r);
if (i == tree.begin()) {
if (i->first.start <= r.end && i->first.end >= r.start)
return i;
else
// Nothing could match, so return end()
return tree.end();
}
--i;
if (i->first.start <= r.end && i->first.end >= r.start)
return i;
return tree.end();
}
template <class U>
const_iterator
find(const U &r) const
{
return find(RangeSize(r, 1));
}
template <class U>
iterator
find(const U &r)
{
return find(RangeSize(r, 1));
}
template <class U>
bool
intersect(const Range<U> &r)
{
iterator i;
i = find(r);
if (i != tree.end())
return true;
return false;
}
template <class U,class W>
iterator
insert(const Range<U> &r, const W d)
{
if (intersect(r))
return tree.end();
return tree.insert(std::make_pair(r, d)).first;
}
size_t
erase(T k)
{
return tree.erase(k);
}
void
erase(iterator p)
{
tree.erase(p);
}
void
erase(iterator p, iterator q)
{
tree.erase(p,q);
}
void
clear()
{
tree.erase(tree.begin(), tree.end());
}
const_iterator
begin() const
{
return tree.begin();
}
iterator
begin()
{
return tree.begin();
}
const_iterator
end() const
{
return tree.end();
}
iterator
end()
{
return tree.end();
}
size_t
size() const
{
return tree.size();
}
bool
empty() const
{
return tree.empty();
}
};
template <class T,class V>
class range_multimap
{
private:
typedef std::multimap<Range<T>,V> RangeMap;
RangeMap tree;
public:
typedef typename RangeMap::iterator iterator;
template <class U>
std::pair<iterator,iterator> find(const Range<U> &r)
{
iterator i;
iterator j;
i = tree.lower_bound(r);
if (i == tree.begin()) {
if (i->first.start <= r.end && i->first.end >= r.start)
return std::make_pair<iterator, iterator>(i,i);
else
// Nothing could match, so return end()
return std::make_pair<iterator, iterator>(tree.end(), tree.end());
}
i--;
if (i->first.start <= r.end && i->first.end >= r.start) {
// we have at least one match
j = i;
i--;
while (i->first.start <= r.end && i->first.end >=
r.start) {
if (i == tree.begin())
break;
i--;
}
if (i == tree.begin() && i->first.start <= r.end && i->first.end >=
r.start)
return std::make_pair<iterator, iterator>(i,j);
i++;
return std::make_pair<iterator, iterator>(i,j);
}
return std::make_pair<iterator, iterator>(tree.end(), tree.end());
}
template <class U>
bool
intersect(const Range<U> &r)
{
std::pair<iterator,iterator> p;
p = find(r);
if (p.first != tree.end())
return true;
return false;
}
template <class U,class W>
iterator
insert(const Range<U> &r, const W d)
{
std::pair<iterator,iterator> p;
p = find(r);
if ((p.first->first.start == r.start && p.first->first.end == r.end) ||
p.first == tree.end())
return tree.insert(std::make_pair<Range<T>,V>(r, d));
else
return tree.end();
}
size_t
erase(T k)
{
return tree.erase(k);
}
void
erase(iterator p)
{
tree.erase(p);
}
void
erase(iterator p, iterator q)
{
tree.erase(p,q);
}
void
clear()
{
tree.erase(tree.begin(), tree.end());
}
iterator
begin()
{
return tree.begin();
}
iterator
end()
{
return tree.end();
}
size_t
size()
{
return tree.size();
}
bool
empty()
{
return tree.empty();
}
};
#endif //__BASE_RANGE_MAP_HH__

View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2007 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Ali Saidi
*/
#ifndef __BASE_RANGE_OPS_HH__
#define __BASE_RANGE_OPS_HH__
#include <list>
#include <vector>
#include "base/range.hh"
template <class T>
inline void
FilterRangeList(std::vector<Range<T> > filter_list,
std::list<Range<T> > &range_list)
{
typedef typename std::list<Range<T> > RangeList;
for (typename RangeList::size_type x = 0; x < filter_list.size(); x++) {
typename RangeList::iterator i = range_list.begin();
while (i != range_list.end()) {
// Is the range within one of our filter ranges?
if (filter_list[x] == i->start || filter_list[x] == i->end)
i = range_list.erase(i);
else
++i;
}
}
}
#endif //__BASE_RANGE_OPS_HH__

View File

@ -0,0 +1,230 @@
/*
* Copyright (c) 2002-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#ifndef __BASE_REFCNT_HH__
#define __BASE_REFCNT_HH__
/**
* @file base/refcnt.hh
*
* Classes for managing reference counted objects.
*/
/**
* Derive from RefCounted if you want to enable reference counting of
* this class. If you want to use automatic reference counting, you
* should use RefCountingPtr<T> instead of regular pointers.
*/
class RefCounted
{
private:
// The reference count is mutable because one may want to
// reference count a const pointer. This really is OK because
// const is about logical constness of the object not really about
// strictly disallowing an object to change.
mutable int count;
private:
// Don't allow a default copy constructor or copy operator on
// these objects because the default operation will copy the
// reference count as well and we certainly don't want that.
RefCounted(const RefCounted &);
RefCounted &operator=(const RefCounted &);
public:
/**
* We initialize the reference count to zero and the first object
* to take ownership of it must increment it to one.
*
* @attention A memory leak will occur if you never assign a newly
* constructed object to a reference counting pointer.
*/
RefCounted() : count(0) {}
/**
* We make the destructor virtual because we're likely to have
* virtual functions on reference counted objects.
*
* @todo Even if this were true, does it matter? Shouldn't the
* derived class indicate this? This only matters if we would
* ever choose to delete a "RefCounted *" which I doubt we'd ever
* do. We don't ever delete a "void *".
*/
virtual ~RefCounted() {}
/// Increment the reference count
void incref() { ++count; }
/// Decrement the reference count and destroy the object if all
/// references are gone.
void decref() { if (--count <= 0) delete this; }
};
/**
* If you want a reference counting pointer to a mutable object,
* create it like this:
* @code
* typedef RefCountingPtr<Foo> FooPtr;
* @endcode
*
* @attention Do not use "const FooPtr"
* To create a reference counting pointer to a const object, use this:
* @code
* typedef RefCountingPtr<const Foo> ConstFooPtr;
* @endcode
*
* These two usages are analogous to iterator and const_iterator in the stl.
*/
template <class T>
class RefCountingPtr
{
protected:
/// The stored pointer.
/// Arguably this should be private.
T *data;
/**
* Copy a new pointer value and increment the reference count if
* it is a valid pointer. Note, this does not delete the
* reference any existing object.
* @param d Pointer to store.
*/
void
copy(T *d)
{
data = d;
if (data)
data->incref();
}
/**
* Delete the reference to any existing object if it is non NULL.
* @attention this doesn't clear the pointer value, so a double
* decref could happen if not careful.
*/
void
del()
{
if (data)
data->decref();
}
/**
* Drop the old reference and change it to something new.
*/
void
set(T *d)
{
// Need to check if we're actually changing because otherwise
// we could delete the last reference before adding the new
// reference.
if (data != d) {
del();
copy(d);
}
}
public:
/// Create an empty reference counting pointer.
RefCountingPtr() : data(0) {}
/// Create a new reference counting pointer to some object
/// (probably something newly created). Adds a reference.
RefCountingPtr(T *data) { copy(data); }
/// Create a new reference counting pointer by copying another
/// one. Adds a reference.
RefCountingPtr(const RefCountingPtr &r) { copy(r.data); }
/// Destroy the pointer and any reference it may hold.
~RefCountingPtr() { del(); }
// The following pointer access functions are const because they
// don't actually change the pointer, though the user could change
// what is pointed to. This is analagous to a "Foo * const".
/// Access a member variable.
T *operator->() const { return data; }
/// Dereference the pointer.
T &operator*() const { return *data; }
/// Directly access the pointer itself without taking a reference.
T *get() const { return data; }
/// Assign a new value to the pointer
const RefCountingPtr &operator=(T *p) { set(p); return *this; }
/// Copy the pointer from another RefCountingPtr
const RefCountingPtr &operator=(const RefCountingPtr &r)
{ return operator=(r.data); }
/// Check if the pointer is empty
bool operator!() const { return data == 0; }
/// Check if the pointer is non-empty
operator bool() const { return data != 0; }
};
/// Check for equality of two reference counting pointers.
template<class T>
inline bool operator==(const RefCountingPtr<T> &l, const RefCountingPtr<T> &r)
{ return l.get() == r.get(); }
/// Check for equality of of a reference counting pointers and a
/// regular pointer
template<class T>
inline bool operator==(const RefCountingPtr<T> &l, const T *r)
{ return l.get() == r; }
/// Check for equality of of a reference counting pointers and a
/// regular pointer
template<class T>
inline bool operator==(const T *l, const RefCountingPtr<T> &r)
{ return l == r.get(); }
/// Check for inequality of two reference counting pointers.
template<class T>
inline bool operator!=(const RefCountingPtr<T> &l, const RefCountingPtr<T> &r)
{ return l.get() != r.get(); }
/// Check for inequality of of a reference counting pointers and a
/// regular pointer
template<class T>
inline bool operator!=(const RefCountingPtr<T> &l, const T *r)
{ return l.get() != r; }
/// Check for inequality of of a reference counting pointers and a
/// regular pointer
template<class T>
inline bool operator!=(const T *l, const RefCountingPtr<T> &r)
{ return l != r.get(); }
#endif // __BASE_REFCNT_HH__

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,272 @@
/*
* Copyright (c) 2002-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#ifndef __REMOTE_GDB_HH__
#define __REMOTE_GDB_HH__
#include <sys/signal.h>
#include <map>
#include "arch/types.hh"
#include "base/pollevent.hh"
#include "base/socket.hh"
#include "cpu/pc_event.hh"
class System;
class ThreadContext;
class GDBListener;
enum GDBCommands
{
GDBSignal = '?', // last signal
GDBSetBaud = 'b', // set baud (depracated)
GDBSetBreak = 'B', // set breakpoint (depracated)
GDBCont = 'c', // resume
GDBAsyncCont = 'C', // continue with signal
GDBDebug = 'd', // toggle debug flags (deprecated)
GDBDetach = 'D', // detach remote gdb
GDBRegR = 'g', // read general registers
GDBRegW = 'G', // write general registers
GDBSetThread = 'H', // set thread
GDBCycleStep = 'i', // step a single cycle
GDBSigCycleStep = 'I', // signal then cycle step
GDBKill = 'k', // kill program
GDBMemR = 'm', // read memory
GDBMemW = 'M', // write memory
GDBReadReg = 'p', // read register
GDBSetReg = 'P', // write register
GDBQueryVar = 'q', // query variable
GDBSetVar = 'Q', // set variable
GDBReset = 'r', // reset system. (Deprecated)
GDBStep = 's', // step
GDBAsyncStep = 'S', // signal and step
GDBThreadAlive = 'T', // find out if the thread is alive
GDBTargetExit = 'W', // target exited
GDBBinaryDload = 'X', // write memory
GDBClrHwBkpt = 'z', // remove breakpoint or watchpoint
GDBSetHwBkpt = 'Z' // insert breakpoint or watchpoint
};
const char GDBStart = '$';
const char GDBEnd = '#';
const char GDBGoodP = '+';
const char GDBBadP = '-';
const int GDBPacketBufLen = 1024;
class BaseRemoteGDB
{
private:
friend void debugger();
friend class GDBListener;
//Helper functions
protected:
int digit2i(char);
char i2digit(int);
Addr hex2i(const char **);
//Address formats, break types, and gdb commands may change
//between architectures, so they're defined as virtual
//functions.
virtual void mem2hex(void *, const void *, int);
virtual const char * hex2mem(void *, const char *, int);
virtual const char * break_type(char c);
virtual const char * gdb_command(char cmd);
protected:
class Event : public PollEvent
{
protected:
BaseRemoteGDB *gdb;
public:
Event(BaseRemoteGDB *g, int fd, int e);
void process(int revent);
};
friend class Event;
Event *event;
GDBListener *listener;
int number;
protected:
//The socket commands come in through
int fd;
protected:
#ifdef notyet
label_t recover;
#endif
bool active;
bool attached;
System *system;
ThreadContext *context;
protected:
class GdbRegCache
{
public:
GdbRegCache(size_t newSize) : regs(new uint64_t[newSize]), size(newSize)
{}
~GdbRegCache()
{
delete [] regs;
}
uint64_t * regs;
size_t size;
size_t bytes() { return size * sizeof(uint64_t); }
};
GdbRegCache gdbregs;
protected:
uint8_t getbyte();
void putbyte(uint8_t b);
int recv(char *data, int len);
void send(const char *data);
protected:
// Machine memory
virtual bool read(Addr addr, size_t size, char *data);
virtual bool write(Addr addr, size_t size, const char *data);
template <class T> T read(Addr addr);
template <class T> void write(Addr addr, T data);
public:
BaseRemoteGDB(System *system, ThreadContext *context, size_t cacheSize);
virtual ~BaseRemoteGDB();
void replaceThreadContext(ThreadContext *tc) { context = tc; }
void attach(int fd);
void detach();
bool isattached();
virtual bool acc(Addr addr, size_t len) = 0;
bool trap(int type);
virtual bool breakpoint()
{
return trap(SIGTRAP);
}
protected:
virtual void getregs() = 0;
virtual void setregs() = 0;
virtual void clearSingleStep() = 0;
virtual void setSingleStep() = 0;
PCEventQueue *getPcEventQueue();
protected:
class HardBreakpoint : public PCEvent
{
private:
BaseRemoteGDB *gdb;
public:
int refcount;
public:
HardBreakpoint(BaseRemoteGDB *_gdb, Addr addr);
const std::string name() const { return gdb->name() + ".hwbkpt"; }
virtual void process(ThreadContext *tc);
};
friend class HardBreakpoint;
typedef std::map<Addr, HardBreakpoint *> break_map_t;
typedef break_map_t::iterator break_iter_t;
break_map_t hardBreakMap;
bool insertSoftBreak(Addr addr, size_t len);
bool removeSoftBreak(Addr addr, size_t len);
virtual bool insertHardBreak(Addr addr, size_t len);
bool removeHardBreak(Addr addr, size_t len);
protected:
void clearTempBreakpoint(Addr &bkpt);
void setTempBreakpoint(Addr bkpt);
public:
std::string name();
};
template <class T>
inline T
BaseRemoteGDB::read(Addr addr)
{
T temp;
read(addr, sizeof(T), (char *)&temp);
return temp;
}
template <class T>
inline void
BaseRemoteGDB::write(Addr addr, T data)
{ write(addr, sizeof(T), (const char *)&data); }
class GDBListener
{
protected:
class Event : public PollEvent
{
protected:
GDBListener *listener;
public:
Event(GDBListener *l, int fd, int e);
void process(int revent);
};
friend class Event;
Event *event;
protected:
ListenSocket listener;
BaseRemoteGDB *gdb;
int port;
public:
GDBListener(BaseRemoteGDB *g, int p);
~GDBListener();
void accept();
void listen();
std::string name();
};
#endif /* __REMOTE_GDB_H__ */

View File

@ -0,0 +1,130 @@
/*
* Copyright (c) 2002-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <cerrno>
#include "base/misc.hh"
#include "base/socket.hh"
#include "base/types.hh"
using namespace std;
bool ListenSocket::listeningDisabled = false;
bool ListenSocket::anyListening = false;
void
ListenSocket::disableAll()
{
if (anyListening)
panic("Too late to disable all listeners, already have a listener");
listeningDisabled = true;
}
bool
ListenSocket::allDisabled()
{
return listeningDisabled;
}
////////////////////////////////////////////////////////////////////////
//
//
ListenSocket::ListenSocket()
: listening(false), fd(-1)
{}
ListenSocket::~ListenSocket()
{
if (fd != -1)
close(fd);
}
// Create a socket and configure it for listening
bool
ListenSocket::listen(int port, bool reuse)
{
if (listening)
panic("Socket already listening!");
fd = ::socket(PF_INET, SOCK_STREAM, 0);
if (fd < 0)
panic("Can't create socket:%s !", strerror(errno));
if (reuse) {
int i = 1;
if (::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&i,
sizeof(i)) < 0)
panic("ListenSocket(listen): setsockopt() SO_REUSEADDR failed!");
}
struct sockaddr_in sockaddr;
sockaddr.sin_family = PF_INET;
sockaddr.sin_addr.s_addr = INADDR_ANY;
sockaddr.sin_port = htons(port);
int ret = ::bind(fd, (struct sockaddr *)&sockaddr, sizeof (sockaddr));
if (ret != 0) {
if (ret == -1 && errno != EADDRINUSE)
panic("ListenSocket(listen): bind() failed!");
return false;
}
if (::listen(fd, 1) == -1)
panic("ListenSocket(listen): listen() failed!");
listening = true;
anyListening = true;
return true;
}
// Open a connection. Accept will block, so if you don't want it to,
// make sure a connection is ready before you call accept.
int
ListenSocket::accept(bool nodelay)
{
struct sockaddr_in sockaddr;
socklen_t slen = sizeof (sockaddr);
int sfd = ::accept(fd, (struct sockaddr *)&sockaddr, &slen);
if (sfd != -1 && nodelay) {
int i = 1;
::setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, (char *)&i, sizeof(i));
}
return sfd;
}

View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2002-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#ifndef __SOCKET_HH__
#define __SOCKET_HH__
class ListenSocket
{
protected:
static bool listeningDisabled;
static bool anyListening;
public:
static void disableAll();
static bool allDisabled();
protected:
bool listening;
int fd;
public:
ListenSocket();
virtual ~ListenSocket();
virtual int accept(bool nodelay = false);
virtual bool listen(int port, bool reuse = true);
int getfd() const { return fd; }
bool islistening() const { return listening; }
};
#endif //__SOCKET_HH__

View File

@ -0,0 +1,474 @@
/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#include <fstream>
#include <iomanip>
#include <list>
#include <map>
#include <string>
#include "base/callback.hh"
#include "base/cprintf.hh"
#include "base/debug.hh"
#include "base/hostinfo.hh"
#include "base/misc.hh"
#include "base/statistics.hh"
#include "base/str.hh"
#include "base/time.hh"
#include "base/trace.hh"
using namespace std;
namespace Stats {
std::string Info::separatorString = "::";
typedef map<const void *, Info *> MapType;
// We wrap these in a function to make sure they're built in time.
list<Info *> &
statsList()
{
static list<Info *> the_list;
return the_list;
}
MapType &
statsMap()
{
static MapType the_map;
return the_map;
}
void
InfoAccess::setInfo(Info *info)
{
if (statsMap().find(this) != statsMap().end())
panic("shouldn't register stat twice!");
statsList().push_back(info);
#ifndef NDEBUG
pair<MapType::iterator, bool> result =
#endif
statsMap().insert(make_pair(this, info));
assert(result.second && "this should never fail");
assert(statsMap().find(this) != statsMap().end());
}
void
InfoAccess::setParams(const StorageParams *params)
{
info()->storageParams = params;
}
void
InfoAccess::setInit()
{
info()->flags.set(init);
}
Info *
InfoAccess::info()
{
MapType::const_iterator i = statsMap().find(this);
assert(i != statsMap().end());
return (*i).second;
}
const Info *
InfoAccess::info() const
{
MapType::const_iterator i = statsMap().find(this);
assert(i != statsMap().end());
return (*i).second;
}
StorageParams::~StorageParams()
{
}
typedef map<std::string, Info *> NameMapType;
NameMapType &
nameMap()
{
static NameMapType the_map;
return the_map;
}
int Info::id_count = 0;
int debug_break_id = -1;
Info::Info()
: flags(none), precision(-1), prereq(0), storageParams(NULL)
{
id = id_count++;
if (debug_break_id >= 0 and debug_break_id == id)
Debug::breakpoint();
}
Info::~Info()
{
}
bool
validateStatName(const string &name)
{
if (name.empty())
return false;
vector<string> vec;
tokenize(vec, name, '.');
vector<string>::const_iterator item = vec.begin();
while (item != vec.end()) {
if (item->empty())
return false;
string::const_iterator c = item->begin();
// The first character is different
if (!isalpha(*c) && *c != '_')
return false;
// The rest of the characters have different rules.
while (++c != item->end()) {
if (!isalnum(*c) && *c != '_')
return false;
}
++item;
}
return true;
}
void
Info::setName(const string &name)
{
if (!validateStatName(name))
panic("invalid stat name '%s'", name);
pair<NameMapType::iterator, bool> p =
nameMap().insert(make_pair(name, this));
Info *other = p.first->second;
bool result = p.second;
if (!result) {
// using other->name instead of just name to avoid a compiler
// warning. They should be the same.
panic("same statistic name used twice! name=%s\n", other->name);
}
this->name = name;
}
bool
Info::less(Info *stat1, Info *stat2)
{
const string &name1 = stat1->name;
const string &name2 = stat2->name;
vector<string> v1;
vector<string> v2;
tokenize(v1, name1, '.');
tokenize(v2, name2, '.');
size_type last = min(v1.size(), v2.size()) - 1;
for (off_type i = 0; i < last; ++i)
if (v1[i] != v2[i])
return v1[i] < v2[i];
// Special compare for last element.
if (v1[last] == v2[last])
return v1.size() < v2.size();
else
return v1[last] < v2[last];
return false;
}
bool
Info::baseCheck() const
{
if (!(flags & Stats::init)) {
#ifdef DEBUG
cprintf("this is stat number %d\n", id);
#endif
panic("Not all stats have been initialized");
return false;
}
if ((flags & display) && name.empty()) {
panic("all printable stats must be named");
return false;
}
return true;
}
void
Info::enable()
{
}
void
VectorInfo::enable()
{
size_type s = size();
if (subnames.size() < s)
subnames.resize(s);
if (subdescs.size() < s)
subdescs.resize(s);
}
void
VectorDistInfo::enable()
{
size_type s = size();
if (subnames.size() < s)
subnames.resize(s);
if (subdescs.size() < s)
subdescs.resize(s);
}
void
Vector2dInfo::enable()
{
if (subnames.size() < x)
subnames.resize(x);
if (subdescs.size() < x)
subdescs.resize(x);
if (y_subnames.size() < y)
y_subnames.resize(y);
}
void
HistStor::grow_out()
{
int size = cvec.size();
int zero = size / 2; // round down!
int top_half = zero + (size - zero + 1) / 2; // round up!
int bottom_half = (size - zero) / 2; // round down!
// grow down
int low_pair = zero - 1;
for (int i = zero - 1; i >= bottom_half; i--) {
cvec[i] = cvec[low_pair];
if (low_pair - 1 >= 0)
cvec[i] += cvec[low_pair - 1];
low_pair -= 2;
}
assert(low_pair == 0 || low_pair == -1 || low_pair == -2);
for (int i = bottom_half - 1; i >= 0; i--)
cvec[i] = Counter();
// grow up
int high_pair = zero;
for (int i = zero; i < top_half; i++) {
cvec[i] = cvec[high_pair];
if (high_pair + 1 < size)
cvec[i] += cvec[high_pair + 1];
high_pair += 2;
}
assert(high_pair == size || high_pair == size + 1);
for (int i = top_half; i < size; i++)
cvec[i] = Counter();
max_bucket *= 2;
min_bucket *= 2;
bucket_size *= 2;
}
void
HistStor::grow_convert()
{
int size = cvec.size();
int half = (size + 1) / 2; // round up!
//bool even = (size & 1) == 0;
int pair = size - 1;
for (int i = size - 1; i >= half; --i) {
cvec[i] = cvec[pair];
if (pair - 1 >= 0)
cvec[i] += cvec[pair - 1];
pair -= 2;
}
for (int i = half - 1; i >= 0; i--)
cvec[i] = Counter();
min_bucket = -max_bucket;// - (even ? bucket_size : 0);
bucket_size *= 2;
}
void
HistStor::grow_up()
{
int size = cvec.size();
int half = (size + 1) / 2; // round up!
int pair = 0;
for (int i = 0; i < half; i++) {
cvec[i] = cvec[pair];
if (pair + 1 < size)
cvec[i] += cvec[pair + 1];
pair += 2;
}
assert(pair == size || pair == size + 1);
for (int i = half; i < size; i++)
cvec[i] = Counter();
max_bucket *= 2;
bucket_size *= 2;
}
Formula::Formula()
{
}
Formula::Formula(Temp r)
{
root = r;
setInit();
assert(size());
}
const Formula &
Formula::operator=(Temp r)
{
assert(!root && "Can't change formulas");
root = r;
setInit();
assert(size());
return *this;
}
const Formula &
Formula::operator+=(Temp r)
{
if (root)
root = NodePtr(new BinaryNode<std::plus<Result> >(root, r));
else {
root = r;
setInit();
}
assert(size());
return *this;
}
void
Formula::result(VResult &vec) const
{
if (root)
vec = root->result();
}
Result
Formula::total() const
{
return root ? root->total() : 0.0;
}
size_type
Formula::size() const
{
if (!root)
return 0;
else
return root->size();
}
void
Formula::reset()
{
}
bool
Formula::zero() const
{
VResult vec;
result(vec);
for (VResult::size_type i = 0; i < vec.size(); ++i)
if (vec[i] != 0.0)
return false;
return true;
}
string
Formula::str() const
{
return root ? root->str() : "";
}
CallbackQueue dumpQueue;
CallbackQueue resetQueue;
void
registerResetCallback(Callback *cb)
{
resetQueue.add(cb);
}
bool _enabled = false;
bool
enabled()
{
return _enabled;
}
void
enable()
{
if (_enabled)
fatal("Stats are already enabled");
_enabled = true;
}
void
registerDumpCallback(Callback *cb)
{
dumpQueue.add(cb);
}
} // namespace Stats
void
debugDumpStats()
{
Stats::dump();
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,255 @@
/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#ifndef __BASE_STATS_INFO_HH__
#define __BASE_STATS_INFO_HH__
#include "base/stats/types.hh"
#include "base/flags.hh"
namespace Stats {
typedef uint16_t FlagsType;
typedef ::Flags<FlagsType> Flags;
/** Nothing extra to print. */
const FlagsType none = 0x0000;
/** This Stat is Initialized */
const FlagsType init = 0x0001;
/** Print this stat. */
const FlagsType display = 0x0002;
/** Print the total. */
const FlagsType total = 0x0010;
/** Print the percent of the total that this entry represents. */
const FlagsType pdf = 0x0020;
/** Print the cumulative percentage of total upto this entry. */
const FlagsType cdf = 0x0040;
/** Print the distribution. */
const FlagsType dist = 0x0080;
/** Don't print if this is zero. */
const FlagsType nozero = 0x0100;
/** Don't print if this is NAN */
const FlagsType nonan = 0x0200;
/** Mask of flags that can't be set directly */
const FlagsType __reserved = init | display;
struct StorageParams;
struct Output;
class Info
{
public:
/** The name of the stat. */
std::string name;
/** The separator string used for vectors, dist, etc. */
static std::string separatorString;
/** The description of the stat. */
std::string desc;
/** The formatting flags. */
Flags flags;
/** The display precision. */
int precision;
/** A pointer to a prerequisite Stat. */
const Info *prereq;
/**
* A unique stat ID for each stat in the simulator.
* Can be used externally for lookups as well as for debugging.
*/
static int id_count;
int id;
public:
const StorageParams *storageParams;
public:
Info();
virtual ~Info();
/** Set the name of this statistic */
void setName(const std::string &name);
void setSeparator(std::string _sep) { separatorString = _sep;}
/**
* Check that this stat has been set up properly and is ready for
* use
* @return true for success
*/
virtual bool check() const = 0;
bool baseCheck() const;
/**
* Enable the stat for use
*/
virtual void enable();
/**
* Prepare the stat for dumping.
*/
virtual void prepare() = 0;
/**
* Reset the stat to the default state.
*/
virtual void reset() = 0;
/**
* @return true if this stat has a value and satisfies its
* requirement as a prereq
*/
virtual bool zero() const = 0;
/**
* Visitor entry for outputing statistics data
*/
virtual void visit(Output &visitor) = 0;
/**
* Checks if the first stat's name is alphabetically less than the second.
* This function breaks names up at periods and considers each subname
* separately.
* @param stat1 The first stat.
* @param stat2 The second stat.
* @return stat1's name is alphabetically before stat2's
*/
static bool less(Info *stat1, Info *stat2);
};
class ScalarInfo : public Info
{
public:
virtual Counter value() const = 0;
virtual Result result() const = 0;
virtual Result total() const = 0;
};
class VectorInfo : public Info
{
public:
/** Names and descriptions of subfields. */
std::vector<std::string> subnames;
std::vector<std::string> subdescs;
public:
void enable();
public:
virtual size_type size() const = 0;
virtual const VCounter &value() const = 0;
virtual const VResult &result() const = 0;
virtual Result total() const = 0;
};
enum DistType { Deviation, Dist, Hist };
struct DistData
{
DistType type;
Counter min;
Counter max;
Counter bucket_size;
Counter min_val;
Counter max_val;
Counter underflow;
Counter overflow;
VCounter cvec;
Counter sum;
Counter squares;
Counter logs;
Counter samples;
};
class DistInfo : public Info
{
public:
/** Local storage for the entry values, used for printing. */
DistData data;
};
class VectorDistInfo : public Info
{
public:
std::vector<DistData> data;
/** Names and descriptions of subfields. */
std::vector<std::string> subnames;
std::vector<std::string> subdescs;
void enable();
protected:
/** Local storage for the entry values, used for printing. */
mutable VResult rvec;
public:
virtual size_type size() const = 0;
};
class Vector2dInfo : public Info
{
public:
/** Names and descriptions of subfields. */
std::vector<std::string> subnames;
std::vector<std::string> subdescs;
std::vector<std::string> y_subnames;
size_type x;
size_type y;
/** Local storage for the entry values, used for printing. */
mutable VCounter cvec;
void enable();
};
class FormulaInfo : public VectorInfo
{
public:
virtual std::string str() const = 0;
};
/** Data structure of sparse histogram */
struct SparseHistData
{
MCounter cmap;
Counter samples;
};
class SparseHistInfo : public Info
{
public:
/** Local storage for the entry values, used for printing. */
SparseHistData data;
};
} // namespace Stats
#endif // __BASE_STATS_INFO_HH__

View File

@ -0,0 +1,66 @@
/*
* Copyright (c) 2004-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#ifndef __BASE_STATS_OUTPUT_HH__
#define __BASE_STATS_OUTPUT_HH__
#include <list>
#include <string>
namespace Stats {
class Info;
class ScalarInfo;
class VectorInfo;
class DistInfo;
class VectorDistInfo;
class Vector2dInfo;
class FormulaInfo;
class SparseHistInfo; // Sparse histogram
struct Output
{
virtual ~Output() {}
virtual void begin() = 0;
virtual void end() = 0;
virtual bool valid() const = 0;
virtual void visit(const ScalarInfo &info) = 0;
virtual void visit(const VectorInfo &info) = 0;
virtual void visit(const DistInfo &info) = 0;
virtual void visit(const VectorDistInfo &info) = 0;
virtual void visit(const Vector2dInfo &info) = 0;
virtual void visit(const FormulaInfo &info) = 0;
virtual void visit(const SparseHistInfo &info) = 0; // Sparse histogram
};
} // namespace Stats
#endif // __BASE_STATS_OUTPUT_HH__

View File

@ -0,0 +1,702 @@
/*
* Copyright (c) 2004-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#if defined(__APPLE__)
#define _GLIBCPP_USE_C99 1
#endif
#if defined(__sun)
#include <math.h>
#endif
#include <cassert>
#ifdef __SUNPRO_CC
#include <math.h>
#endif
#include <cmath>
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include "base/stats/info.hh"
#include "base/stats/text.hh"
#include "base/cast.hh"
#include "base/misc.hh"
#include "base/str.hh"
using namespace std;
#ifndef NAN
float __nan();
/** Define Not a number. */
#define NAN (__nan())
/** Need to define __nan() */
#define __M5_NAN
#endif
#ifdef __M5_NAN
float
__nan()
{
union {
uint32_t ui;
float f;
} nan;
nan.ui = 0x7fc00000;
return nan.f;
}
#endif
namespace Stats {
std::list<Info *> &statsList();
Text::Text()
: mystream(false), stream(NULL), descriptions(false)
{
}
Text::Text(std::ostream &stream)
: mystream(false), stream(NULL), descriptions(false)
{
open(stream);
}
Text::Text(const std::string &file)
: mystream(false), stream(NULL), descriptions(false)
{
open(file);
}
Text::~Text()
{
if (mystream) {
assert(stream);
delete stream;
}
}
void
Text::open(std::ostream &_stream)
{
if (stream)
panic("stream already set!");
mystream = false;
stream = &_stream;
if (!valid())
fatal("Unable to open output stream for writing\n");
}
void
Text::open(const std::string &file)
{
if (stream)
panic("stream already set!");
mystream = true;
stream = new ofstream(file.c_str(), ios::trunc);
if (!valid())
fatal("Unable to open statistics file for writing\n");
}
bool
Text::valid() const
{
return stream != NULL && stream->good();
}
void
Text::begin()
{
ccprintf(*stream, "\n---------- Begin Simulation Statistics ----------\n");
}
void
Text::end()
{
ccprintf(*stream, "\n---------- End Simulation Statistics ----------\n");
stream->flush();
}
bool
Text::noOutput(const Info &info)
{
if (!info.flags.isSet(display))
return true;
if (info.prereq && info.prereq->zero())
return true;
return false;
}
string
ValueToString(Result value, int precision)
{
stringstream val;
if (!std::isnan(value)) {
if (precision != -1)
val.precision(precision);
else if (value == rint(value))
val.precision(0);
val.unsetf(ios::showpoint);
val.setf(ios::fixed);
val << value;
} else {
val << "nan";
}
return val.str();
}
struct ScalarPrint
{
Result value;
string name;
string desc;
Flags flags;
bool descriptions;
int precision;
Result pdf;
Result cdf;
void update(Result val, Result total);
void operator()(ostream &stream) const;
};
void
ScalarPrint::update(Result val, Result total)
{
value = val;
if (total) {
pdf = val / total;
cdf += pdf;
}
}
void
ScalarPrint::operator()(ostream &stream) const
{
if ((flags.isSet(nozero) && value == 0.0) ||
(flags.isSet(nonan) && std::isnan(value)))
return;
stringstream pdfstr, cdfstr;
if (!std::isnan(pdf))
ccprintf(pdfstr, "%.2f%%", pdf * 100.0);
if (!std::isnan(cdf))
ccprintf(cdfstr, "%.2f%%", cdf * 100.0);
ccprintf(stream, "%-40s %12s %10s %10s", name,
ValueToString(value, precision), pdfstr, cdfstr);
if (descriptions) {
if (!desc.empty())
ccprintf(stream, " # %s", desc);
}
stream << endl;
}
struct VectorPrint
{
string name;
string separatorString;
string desc;
vector<string> subnames;
vector<string> subdescs;
Flags flags;
bool descriptions;
int precision;
VResult vec;
Result total;
void operator()(ostream &stream) const;
};
void
VectorPrint::operator()(std::ostream &stream) const
{
size_type _size = vec.size();
Result _total = 0.0;
if (flags.isSet(pdf | cdf)) {
for (off_type i = 0; i < _size; ++i) {
_total += vec[i];
}
}
string base = name + separatorString;
ScalarPrint print;
print.name = name;
print.desc = desc;
print.precision = precision;
print.descriptions = descriptions;
print.flags = flags;
print.pdf = _total ? 0.0 : NAN;
print.cdf = _total ? 0.0 : NAN;
bool havesub = !subnames.empty();
if (_size == 1) {
print.value = vec[0];
print(stream);
return;
}
for (off_type i = 0; i < _size; ++i) {
if (havesub && (i >= subnames.size() || subnames[i].empty()))
continue;
print.name = base + (havesub ? subnames[i] : to_string(i));
print.desc = subdescs.empty() ? desc : subdescs[i];
print.update(vec[i], _total);
print(stream);
}
if (flags.isSet(::Stats::total)) {
print.pdf = NAN;
print.cdf = NAN;
print.name = base + "total";
print.desc = desc;
print.value = total;
print(stream);
}
}
struct DistPrint
{
string name;
string separatorString;
string desc;
Flags flags;
bool descriptions;
int precision;
const DistData &data;
DistPrint(const Text *text, const DistInfo &info);
DistPrint(const Text *text, const VectorDistInfo &info, int i);
void init(const Text *text, const Info &info);
void operator()(ostream &stream) const;
};
DistPrint::DistPrint(const Text *text, const DistInfo &info)
: data(info.data)
{
init(text, info);
}
DistPrint::DistPrint(const Text *text, const VectorDistInfo &info, int i)
: data(info.data[i])
{
init(text, info);
name = info.name + "_" +
(info.subnames[i].empty() ? (to_string(i)) : info.subnames[i]);
if (!info.subdescs[i].empty())
desc = info.subdescs[i];
}
void
DistPrint::init(const Text *text, const Info &info)
{
name = info.name;
separatorString = info.separatorString;
desc = info.desc;
flags = info.flags;
precision = info.precision;
descriptions = text->descriptions;
}
void
DistPrint::operator()(ostream &stream) const
{
string base = name + separatorString;
ScalarPrint print;
print.precision = precision;
print.flags = flags;
print.descriptions = descriptions;
print.desc = desc;
print.pdf = NAN;
print.cdf = NAN;
print.name = base + "samples";
print.value = data.samples;
print(stream);
print.name = base + "mean";
print.value = data.samples ? data.sum / data.samples : NAN;
print(stream);
if (data.type == Hist) {
print.name = base + "gmean";
print.value = data.samples ? exp(data.logs / data.samples) : NAN;
print(stream);
}
Result stdev = NAN;
if (data.samples)
stdev = sqrt((data.samples * data.squares - data.sum * data.sum) /
(data.samples * (data.samples - 1.0)));
print.name = base + "stdev";
print.value = stdev;
print(stream);
if (data.type == Deviation)
return;
size_t size = data.cvec.size();
Result total = 0.0;
if (data.type == Dist && data.underflow != NAN)
total += data.underflow;
for (off_type i = 0; i < size; ++i)
total += data.cvec[i];
if (data.type == Dist && data.overflow != NAN)
total += data.overflow;
if (total) {
print.pdf = 0.0;
print.cdf = 0.0;
}
if (data.type == Dist && data.underflow != NAN) {
print.name = base + "underflows";
print.update(data.underflow, total);
print(stream);
}
for (off_type i = 0; i < size; ++i) {
stringstream namestr;
namestr << base;
Counter low = i * data.bucket_size + data.min;
Counter high = ::min(low + data.bucket_size - 1.0, data.max);
namestr << low;
if (low < high)
namestr << "-" << high;
print.name = namestr.str();
print.update(data.cvec[i], total);
print(stream);
}
if (data.type == Dist && data.overflow != NAN) {
print.name = base + "overflows";
print.update(data.overflow, total);
print(stream);
}
print.pdf = NAN;
print.cdf = NAN;
if (data.type == Dist && data.min_val != NAN) {
print.name = base + "min_value";
print.value = data.min_val;
print(stream);
}
if (data.type == Dist && data.max_val != NAN) {
print.name = base + "max_value";
print.value = data.max_val;
print(stream);
}
print.name = base + "total";
print.value = total;
print(stream);
}
void
Text::visit(const ScalarInfo &info)
{
if (noOutput(info))
return;
ScalarPrint print;
print.value = info.result();
print.name = info.name;
print.desc = info.desc;
print.flags = info.flags;
print.descriptions = descriptions;
print.precision = info.precision;
print.pdf = NAN;
print.cdf = NAN;
print(*stream);
}
void
Text::visit(const VectorInfo &info)
{
if (noOutput(info))
return;
size_type size = info.size();
VectorPrint print;
print.name = info.name;
print.separatorString = info.separatorString;
print.desc = info.desc;
print.flags = info.flags;
print.descriptions = descriptions;
print.precision = info.precision;
print.vec = info.result();
print.total = info.total();
if (!info.subnames.empty()) {
for (off_type i = 0; i < size; ++i) {
if (!info.subnames[i].empty()) {
print.subnames = info.subnames;
print.subnames.resize(size);
for (off_type i = 0; i < size; ++i) {
if (!info.subnames[i].empty() &&
!info.subdescs[i].empty()) {
print.subdescs = info.subdescs;
print.subdescs.resize(size);
break;
}
}
break;
}
}
}
print(*stream);
}
void
Text::visit(const Vector2dInfo &info)
{
if (noOutput(info))
return;
bool havesub = false;
VectorPrint print;
if (!info.y_subnames.empty()) {
for (off_type i = 0; i < info.y; ++i) {
if (!info.y_subnames[i].empty()) {
print.subnames = info.y_subnames;
}
break;
}
}
print.flags = info.flags;
print.separatorString = info.separatorString;
print.descriptions = descriptions;
print.precision = info.precision;
if (!info.subnames.empty()) {
for (off_type i = 0; i < info.x; ++i)
if (!info.subnames[i].empty())
havesub = true;
}
VResult tot_vec(info.y);
Result super_total = 0.0;
for (off_type i = 0; i < info.x; ++i) {
if (havesub && (i >= info.subnames.size() || info.subnames[i].empty()))
continue;
off_type iy = i * info.y;
VResult yvec(info.y);
Result total = 0.0;
for (off_type j = 0; j < info.y; ++j) {
yvec[j] = info.cvec[iy + j];
tot_vec[j] += yvec[j];
total += yvec[j];
super_total += yvec[j];
}
print.name = info.name + "_" +
(havesub ? info.subnames[i] : to_string(i));
print.desc = info.desc;
print.vec = yvec;
print.total = total;
print(*stream);
}
if (info.flags.isSet(::Stats::total) && (info.x > 1)) {
print.name = info.name;
print.desc = info.desc;
print.vec = tot_vec;
print.total = super_total;
print(*stream);
}
}
void
Text::visit(const DistInfo &info)
{
if (noOutput(info))
return;
DistPrint print(this, info);
print(*stream);
}
void
Text::visit(const VectorDistInfo &info)
{
if (noOutput(info))
return;
for (off_type i = 0; i < info.size(); ++i) {
DistPrint print(this, info, i);
print(*stream);
}
}
void
Text::visit(const FormulaInfo &info)
{
visit((const VectorInfo &)info);
}
/*
This struct implements the output methods for the sparse
histogram stat
*/
struct SparseHistPrint
{
string name;
string separatorString;
string desc;
Flags flags;
bool descriptions;
int precision;
const SparseHistData &data;
SparseHistPrint(const Text *text, const SparseHistInfo &info);
void init(const Text *text, const Info &info);
void operator()(ostream &stream) const;
};
/* Call initialization function */
SparseHistPrint::SparseHistPrint(const Text *text, const SparseHistInfo &info)
: data(info.data)
{
init(text, info);
}
/* Initialization function */
void
SparseHistPrint::init(const Text *text, const Info &info)
{
name = info.name;
separatorString = info.separatorString;
desc = info.desc;
flags = info.flags;
precision = info.precision;
descriptions = text->descriptions;
}
/* Grab data from map and write to output stream */
void
SparseHistPrint::operator()(ostream &stream) const
{
string base = name + separatorString;
ScalarPrint print;
print.precision = precision;
print.flags = flags;
print.descriptions = descriptions;
print.desc = desc;
print.pdf = NAN;
print.cdf = NAN;
print.name = base + "samples";
print.value = data.samples;
print(stream);
MCounter::const_iterator it;
for (it = data.cmap.begin(); it != data.cmap.end(); it++) {
stringstream namestr;
namestr << base;
namestr <<(*it).first;
print.name = namestr.str();
print.value = (*it).second;
print(stream);
}
print.pdf = NAN;
print.cdf = NAN;
print.name = base + "total";
print.value = total;
print(stream);
}
void
Text::visit(const SparseHistInfo &info)
{
if (noOutput(info))
return;
SparseHistPrint print(this, info);
print(*stream);
}
Output *
initText(const string &filename, bool desc)
{
static Text text;
static bool connected = false;
if (!connected) {
ostream *os = simout.find(filename);
if (!os)
os = simout.create(filename);
text.open(*os);
text.descriptions = desc;
connected = true;
}
return &text;
}
} // namespace Stats

View File

@ -0,0 +1,82 @@
/*
* Copyright (c) 2004-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#ifndef __BASE_STATS_TEXT_HH__
#define __BASE_STATS_TEXT_HH__
#include <iosfwd>
#include <string>
#include "base/stats/output.hh"
#include "base/output.hh"
namespace Stats {
class Text : public Output
{
protected:
bool mystream;
std::ostream *stream;
protected:
bool noOutput(const Info &info);
public:
bool descriptions;
public:
Text();
Text(std::ostream &stream);
Text(const std::string &file);
~Text();
void open(std::ostream &stream);
void open(const std::string &file);
// Implement Visit
virtual void visit(const ScalarInfo &info);
virtual void visit(const VectorInfo &info);
virtual void visit(const DistInfo &info);
virtual void visit(const VectorDistInfo &info);
virtual void visit(const Vector2dInfo &info);
virtual void visit(const FormulaInfo &info);
virtual void visit(const SparseHistInfo &info);
// Implement Output
virtual bool valid() const;
virtual void begin();
virtual void end();
};
Output *initText(const std::string &filename, bool desc);
} // namespace Stats
#endif // __BASE_STATS_TEXT_HH__

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2004-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#ifndef __BASE_STATS_TYPES_HH__
#define __BASE_STATS_TYPES_HH__
#include <limits>
#include <map>
#include <vector>
#include "base/types.hh"
namespace Stats {
/** All counters are of 64-bit values. */
typedef double Counter;
/** vector of counters. */
typedef std::vector<Counter> VCounter;
/** map of counters */
typedef std::map<Counter, int> MCounter;
typedef std::numeric_limits<Counter> CounterLimits;
/** All results are doubles. */
typedef double Result;
/** vector of results. */
typedef std::vector<Result> VResult;
typedef unsigned int size_type;
typedef unsigned int off_type;
} // namespace Stats
#endif // __BASE_STATS_TYPES_HH__

View File

@ -0,0 +1,98 @@
/*
* Copyright (c) 2010 The Hewlett-Packard Development Company
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#ifndef __BASE_STL_HELPERS_HH__
#define __BASE_STL_HELPERS_HH__
#include <algorithm>
#include <iostream>
namespace m5 {
namespace stl_helpers {
template <typename T>
void
deletePointer(T &ptr)
{
delete ptr;
ptr = NULL;
}
template <class T>
class ContainerPrint
{
private:
std::ostream &out;
bool first;
public:
ContainerPrint(std::ostream &out)
: out(out), first(true)
{}
void
operator()(const T &elem)
{
// First one doesn't get a space before it. The rest do.
if (first)
first = false;
else
out << " ";
out << elem;
}
};
// Treat all objects in an stl container as pointers to heap objects,
// calling delete on each one and zeroing the pointers along the way
template <template <typename T, typename A> class C, typename T, typename A>
void
deletePointers(C<T,A> &container)
{
std::for_each(container.begin(), container.end(), deletePointer<T>);
}
// Write out all elements in an stl container as a space separated
// list enclosed in square brackets
template <template <typename T, typename A> class C, typename T, typename A>
std::ostream &
operator<<(std::ostream& out, const C<T,A> &vec)
{
out << "[ ";
std::for_each(vec.begin(), vec.end(), ContainerPrint<T>(out));
out << " ]";
out << std::flush;
return out;
}
} // namespace stl_helpers
} // namespace m5
#endif // __BASE_STL_HELPERS_HH__

View File

@ -0,0 +1,375 @@
/*
* Copyright (c) 2001-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#include <cctype>
#include <cstring>
#include <iostream>
#include <limits>
#include <string>
#include <vector>
#include "base/intmath.hh"
#include "base/str.hh"
using namespace std;
bool
split_first(const string &s, string &lhs, string &rhs, char c)
{
string::size_type offset = s.find(c);
if (offset == string::npos) {
lhs = s;
rhs = "";
return false;
}
lhs = s.substr(0, offset);
rhs = s.substr(offset + 1);
return true;
}
bool
split_last(const string &s, string &lhs, string &rhs, char c)
{
string::size_type offset = s.rfind(c);
if (offset == string::npos) {
lhs = s;
rhs = "";
return false;
}
lhs = s.substr(0, offset);
rhs = s.substr(offset + 1);
return true;
}
void
tokenize(vector<string>& v, const string &s, char token, bool ignore)
{
string::size_type first = 0;
string::size_type last = s.find_first_of(token);
if (s.empty())
return;
if (ignore && last == first) {
while (last == first)
last = s.find_first_of(token, ++first);
if (last == string::npos) {
if (first != s.size())
v.push_back(s.substr(first));
return;
}
}
while (last != string::npos) {
v.push_back(s.substr(first, last - first));
if (ignore) {
first = s.find_first_not_of(token, last + 1);
if (first == string::npos)
return;
} else
first = last + 1;
last = s.find_first_of(token, first);
}
v.push_back(s.substr(first));
}
/**
* @todo This function will not handle the smallest negative decimal
* value for a signed type
*/
template <class T>
inline bool
__to_number(string value, T &retval)
{
static const T maxnum = ((T)-1);
static const bool sign = numeric_limits<T>::is_signed;
static const int bits = numeric_limits<T>::digits;
static const T hexmax = maxnum & (((T)1 << (bits - 4)) - 1);
static const T octmax = maxnum & (((T)1 << (bits - 3)) - 1);
static const T signmax = numeric_limits<T>::max();
static const T decmax = signmax / 10;
#if 0
cout << "maxnum = 0x" << hex << (unsigned long long)maxnum << "\n"
<< "sign = 0x" << hex << (unsigned long long)sign << "\n"
<< "hexmax = 0x" << hex << (unsigned long long)hexmax << "\n"
<< "octmax = 0x" << hex << (unsigned long long)octmax << "\n"
<< "signmax = 0x" << hex << (unsigned long long)signmax << "\n"
<< "decmax = 0x" << hex << (unsigned long long)decmax << "\n";
#endif
eat_white(value);
bool negative = false;
bool hex = false;
bool oct = false;
int last = value.size() - 1;
retval = 0;
int i = 0;
char c = value[i];
if (!isDec(c)) {
if (c == '-' && sign)
negative = true;
else
return false;
}
else {
retval += c - '0';
if (last == 0) return true;
}
if (c == '0')
oct = true;
c = value[++i];
if (oct) {
if (sign && negative)
return false;
if (!isOct(c)) {
if (c == 'X' || c == 'x') {
hex = true;
oct = false;
} else
return false;
}
else
retval += c - '0';
} else if (!isDec(c))
goto multiply;
else {
if (sign && negative && c == '0')
return false;
retval *= 10;
retval += c - '0';
if (last == 1) {
if (sign && negative) retval = -retval;
return true;
}
}
if (hex) {
if (last == 1)
return false;
for (i = 2; i <= last ; i++) {
c = value[i];
if (!isHex(c))
return false;
if (retval > hexmax) return false;
retval *= 16;
retval += hex2Int(c);
}
return true;
} else if (oct) {
for (i = 2; i <= last ; i++) {
c = value[i];
if (!isOct(c))
return false;
if (retval > octmax) return false;
retval *= 8;
retval += (c - '0');
}
return true;
}
for (i = 2; i < last ; i++) {
c = value[i];
if (!isDec(c))
goto multiply;
if (retval > decmax) return false;
bool atmax = retval == decmax;
retval *= 10;
retval += c - '0';
if (atmax && retval < decmax) return false;
if (sign && (retval & ((T)1 << (sizeof(T) * 8 - 1))))
return false;
}
c = value[last];
if (isDec(c)) {
if (retval > decmax) return false;
bool atmax = retval == decmax;
retval *= 10;
retval += c - '0';
if (atmax && retval < decmax) return false;
if (sign && negative) {
if ((retval & ((T)1 << (sizeof(T) * 8 - 1))) &&
retval >= (T)-signmax)
return false;
retval = -retval;
}
else
if (sign && (retval & ((T)1 << ((sizeof(T) * 8) - 1))))
return false;
return true;
}
multiply:
signed long long mult = 1;
T val;
switch (c) {
case 'k':
case 'K':
if (i != last) return false;
mult = 1024;
val = signmax / mult;
break;
case 'm':
case 'M':
if (i != last) return false;
mult = 1024 * 1024;
val = signmax / mult;
break;
case 'g':
case 'G':
if (i != last) return false;
mult = 1024 * 1024 * 1024;
val = signmax / mult;
break;
case 'e':
case 'E':
if (i >= last) return false;
mult = 0;
for (i++; i <= last; i++) {
c = value[i];
if (!isDec(c))
return false;
mult *= 10;
mult += c - '0';
}
for (i = 0; i < mult; i++) {
if (retval > signmax / 10)
return false;
retval *= 10;
if (sign && (retval & ((T)1 << (sizeof(T) * 8 - 1))))
return false;
}
if (sign && negative) {
if ((retval & ((T)1 << (sizeof(T) * 8 - 1))) &&
retval >= (T)-signmax)
return false;
retval = -retval;
}
else
if (sign && (retval & ((T)1 << ((sizeof(T) * 8) - 1))))
return false;
return true;
default:
return false;
}
if (sign && negative)
return false;
if (mult > (unsigned long long)signmax)
return false;
if (retval > val)
return false;
retval *= mult;
return true;
}
#define STN(type) \
template<> \
bool to_number<type>(const string &value, type &retval) \
{ return __to_number(value, retval); }
STN(unsigned long long)
STN(signed long long)
STN(unsigned long)
STN(signed long)
STN(unsigned int)
STN(signed int)
STN(unsigned short)
STN(signed short)
STN(unsigned char)
STN(signed char)
STN(char)
template<>
bool to_number<bool>(const string &value, bool &retval)
{
string lowered = to_lower(value);
if (value == "0") {
retval = false;
return true;
}
if (value == "1"){
retval = true;
return true;
}
if (lowered == "false") {
retval = false;
return true;
}
if (lowered == "true"){
retval = true;
return true;
}
if (lowered == "no") {
retval = false;
return true;
}
if (lowered == "yes"){
retval = true;
return true;
}
return false;
}

View File

@ -0,0 +1,143 @@
/*
* Copyright (c) 2001-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
* Steve Reinhardt
*/
#ifndef __STR_HH__
#define __STR_HH__
#include <cctype>
#include <sstream>
#include <string>
#include <vector>
template<class> class Hash;
template<>
class Hash<std::string> {
public:
unsigned operator()(const std::string &s) {
std::string::const_iterator i = s.begin();
std::string::const_iterator end = s.end();
unsigned hash = 5381;
while (i < end)
hash = ((hash << 5) + hash) + *i++;
return hash;
}
};
inline void
eat_lead_white(std::string &s)
{
std::string::size_type off = s.find_first_not_of(' ');
if (off != std::string::npos) {
std::string::iterator begin = s.begin();
s.erase(begin, begin + off);
}
}
inline void
eat_end_white(std::string &s)
{
std::string::size_type off = s.find_last_not_of(' ');
if (off != std::string::npos)
s.erase(s.begin() + off + 1, s.end());
}
inline void
eat_white(std::string &s)
{
eat_lead_white(s);
eat_end_white(s);
}
inline std::string
to_lower(const std::string &s)
{
std::string lower;
int len = s.size();
lower.reserve(len);
for (int i = 0; i < len; ++i)
lower.push_back(tolower(s[i]));
return lower;
}
// Split the string s into lhs and rhs on the first occurence of the
// character c.
bool
split_first(const std::string &s, std::string &lhs, std::string &rhs, char c);
// Split the string s into lhs and rhs on the last occurence of the
// character c.
bool
split_last(const std::string &s, std::string &lhs, std::string &rhs, char c);
// Tokenize the string <s> splitting on the character <token>, and
// place the result in the string vector <vector>. If <ign> is true,
// then empty result strings (due to trailing tokens, or consecutive
// tokens) are skipped.
void
tokenize(std::vector<std::string> &vector, const std::string &s,
char token, bool ign = true);
template <class T> bool
to_number(const std::string &value, T &retval);
template <class T>
inline std::string
to_string(const T &value)
{
std::stringstream str;
str << value;
return str.str();
}
// Put quotes around string arg if it contains spaces.
inline std::string
quote(const std::string &s)
{
std::string ret;
bool quote = s.find(' ') != std::string::npos;
if (quote)
ret = '"';
ret += s;
if (quote)
ret += '"';
return ret;
}
#endif //__STR_HH__

View File

@ -0,0 +1,167 @@
/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <sstream>
#include "base/time.hh"
#include "config/use_posix_clock.hh"
#include "sim/core.hh"
#include "sim/serialize.hh"
using namespace std;
void
Time::_set(bool monotonic)
{
#if USE_POSIX_CLOCK
::clock_gettime(monotonic ? CLOCK_MONOTONIC : CLOCK_REALTIME, &_time);
#else
timeval tv;
::gettimeofday(&tv, NULL);
operator=(tv);
#endif
}
void
Time::setTick(Tick ticks)
{
uint64_t nsecs = ticks / SimClock::Int::ns;
set(nsecs / NSEC_PER_SEC, nsecs % NSEC_PER_SEC);
}
Tick
Time::getTick() const
{
return (nsec() + sec() * NSEC_PER_SEC) * SimClock::Int::ns;
}
string
Time::date(const string &format) const
{
time_t sec = this->sec();
char buf[256];
if (format.empty()) {
#ifdef __SUNPRO_CC
ctime_r(&sec, buf, sizeof(buf));
#else
ctime_r(&sec, buf);
#endif
buf[24] = '\0';
return buf;
}
struct tm *tm = localtime(&sec);
strftime(buf, sizeof(buf), format.c_str(), tm);
return buf;
}
string
Time::time() const
{
double time = double(*this);
double secs = fmod(time, 60.0);
double all_mins = floor(time / 60.0);
double mins = fmod(all_mins, 60.0);
double hours = floor(all_mins / 60.0);
stringstream str;
if (hours > 0.0) {
if (hours < 10.0)
str << '0';
str << hours << ':';
}
if (mins > 0.0) {
if (mins < 10.0)
str << '0';
str << mins << ':';
}
if (secs < 10.0 && !str.str().empty())
str << '0';
str << secs;
return str.str();
}
void
Time::serialize(const std::string &base, ostream &os)
{
paramOut(os, base + ".sec", sec());
paramOut(os, base + ".nsec", nsec());
}
void
Time::unserialize(const std::string &base, Checkpoint *cp,
const string &section)
{
time_t secs;
time_t nsecs;
paramIn(cp, section, base + ".sec", secs);
paramIn(cp, section, base + ".nsec", nsecs);
sec(secs);
nsec(nsecs);
}
void
sleep(const Time &time)
{
timespec ts = time;
#if USE_POSIX_CLOCK
clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);
#else
nanosleep(&ts, NULL);
#endif
}
time_t
mkutctime(struct tm *time)
{
time_t ret;
char *tz;
tz = getenv("TZ");
setenv("TZ", "", 1);
tzset();
ret = mktime(time);
if (tz)
setenv("TZ", tz, 1);
else
unsetenv("TZ");
tzset();
return ret;
}

View File

@ -0,0 +1,273 @@
/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Steve Reinhardt
* Nathan Binkert
*/
#ifndef __BASE_TIME_HH__
#define __BASE_TIME_HH__
#include <sys/time.h>
#include <inttypes.h>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iosfwd>
#include <iostream>
#include <string>
#include "base/types.hh"
class Checkpoint;
class Time
{
protected:
timespec _time;
/**
* Internal time set function
*/
void _set(bool monotonic);
public:
static const long NSEC_PER_SEC = 1000 * 1000 * 1000;
static const long NSEC_PER_MSEC = 1000 * 1000;
static const long NSEC_PER_USEC = 1000;
public:
explicit Time() { clear(); }
explicit Time(double sec) { operator=(sec); }
Time(const Time &val) : _time(val._time) { }
Time(uint64_t sec, uint64_t nsec) { set(sec, nsec); }
Time(const timeval &tv) { operator=(tv); }
Time(const timespec &ts) { operator=(ts); }
/**
* Accessors for getting and setting the current clock
*/
time_t sec() const { return _time.tv_sec; }
long msec() const { return _time.tv_nsec / NSEC_PER_MSEC; }
long usec() const { return _time.tv_nsec / NSEC_PER_USEC; }
long nsec() const { return _time.tv_nsec; }
void sec(time_t sec) { _time.tv_sec = sec; }
void msec(long msec) { _time.tv_nsec = msec * NSEC_PER_MSEC; }
void usec(long usec) { _time.tv_nsec = usec * NSEC_PER_USEC; }
void nsec(long nsec) { _time.tv_nsec = nsec; }
/**
* Clear the time
*/
void clear() { memset(&_time, 0, sizeof(_time)); }
/**
* Use this to set time for the purposes of time measurement (use
* a monotonic clock if it is available
*/
void setTimer() { _set(true); }
/**
* Use this to set the time to the actual current time
*/
void setWallclock() { _set(false); }
/**
* Set the current time
*/
void set(time_t _sec, long _nsec) { sec(_sec); nsec(_nsec); }
/**
* Set the current time from a value measured in Ticks
* @param ticks Number of ticks to convert into a time.
*/
void setTick(Tick ticks);
/**
* Get the current time from a value measured in Ticks
* @return Time value measured in Ticks.
*/
Tick getTick() const;
const Time &
operator=(const Time &other)
{
sec(other.sec());
nsec(other.nsec());
return *this;
}
const Time &
operator=(double new_time)
{
double seconds = floor(new_time);
sec((time_t)seconds);
nsec((long)((seconds - new_time) * 1e9));
return *this;
}
const Time &
operator=(const timeval &tv)
{
sec(tv.tv_sec);
nsec(tv.tv_usec * 1000);
return *this;
}
const Time &
operator=(const timespec &ts)
{
sec(ts.tv_sec);
nsec(ts.tv_nsec);
return *this;
}
/**
* Get the time in floating point seconds
*/
operator double() const
{
return (double)sec() + ((double)nsec()) * 1e-9;
}
/**
* operators for time conversion
*/
operator timespec() const { return _time; }
operator timeval() const
{
timeval tv;
tv.tv_sec = sec();
tv.tv_usec = usec();
return tv;
}
const Time &
operator+=(const Time &other)
{
_time.tv_sec += other.sec();
_time.tv_nsec += other.nsec();
if (_time.tv_nsec > NSEC_PER_SEC) {
_time.tv_sec++;
_time.tv_nsec -= NSEC_PER_SEC;
}
return *this;
}
const Time &
operator-=(const Time &other)
{
_time.tv_sec -= other.sec();
_time.tv_nsec -= other.nsec();
if (_time.tv_nsec < 0) {
_time.tv_sec--;
_time.tv_nsec += NSEC_PER_SEC;
}
return *this;
}
std::string date(const std::string &format = "") const;
std::string time() const;
void serialize(const std::string &base, std::ostream &os);
void unserialize(const std::string &base, Checkpoint *cp,
const std::string &section);
};
void sleep(const Time &time);
inline bool
operator==(const Time &l, const Time &r)
{
return l.sec() == r.sec() && l.nsec() == r.nsec();
}
inline bool
operator!=(const Time &l, const Time &r)
{
return l.sec() != r.sec() || l.nsec() != r.nsec();
}
inline bool
operator<(const Time &l, const Time &r)
{
return (l.sec() < r.sec()) ||
(l.sec() == r.sec() && l.nsec() < r.nsec());
}
inline bool
operator<=(const Time &l, const Time &r)
{
return (l.sec() < r.sec()) ||
(l.sec() == r.sec() && l.nsec() <= r.nsec());
}
inline bool
operator>(const Time &l, const Time &r)
{
return (l.sec() > r.sec()) ||
(l.sec() == r.sec() && l.nsec() > r.nsec());
}
inline bool
operator>=(const Time &l, const Time &r)
{
return (l.sec() > r.sec()) ||
(l.sec() == r.sec() && l.nsec() >= r.nsec());
}
inline Time
operator+(const Time &l, const Time &r)
{
Time time(l);
time += r;
return time;
}
inline Time
operator-(const Time &l, const Time &r)
{
Time time(l);
time -= r;
return time;
}
inline std::ostream &
operator<<(std::ostream &out, const Time &time)
{
out << time.date();
return out;
}
time_t mkutctime(struct tm *time);
#endif // __BASE_TIME_HH__

View File

@ -0,0 +1,152 @@
/*
* Copyright (c) 2001-2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
* Steve Reinhardt
*/
#include <cctype>
#include <fstream>
#include <iostream>
#include <string>
#include "base/misc.hh"
#include "base/output.hh"
#include "base/str.hh"
#include "base/trace.hh"
#include "base/varargs.hh"
using namespace std;
namespace Trace {
const string DefaultName("global");
bool enabled = false;
//
// This variable holds the output stream for debug information. Other
// than setting up/redirecting this stream, do *NOT* reference this
// directly; use DebugOut() (see below) to access this stream for
// output.
//
ostream *dprintf_stream = &cerr;
ostream &
output()
{
return *dprintf_stream;
}
void
setOutput(const string &filename)
{
dprintf_stream = simout.find(filename);
if (!dprintf_stream)
dprintf_stream = simout.create(filename);
}
ObjectMatch ignore;
void
dprintf(Tick when, const std::string &name, const char *format,
CPRINTF_DEFINITION)
{
if (!name.empty() && ignore.match(name))
return;
std::ostream &os = *dprintf_stream;
string fmt = "";
CPrintfArgsList args(VARARGS_ALLARGS);
if (!name.empty()) {
fmt = "%s: " + fmt;
args.push_front(name);
}
if (when != (Tick)-1) {
fmt = "%7d: " + fmt;
args.push_front(when);
}
fmt += format;
ccprintf(os, fmt.c_str(), args);
os.flush();
}
void
dump(Tick when, const std::string &name, const void *d, int len)
{
if (!name.empty() && ignore.match(name))
return;
std::ostream &os = *dprintf_stream;
string fmt = "";
CPrintfArgsList args;
if (!name.empty()) {
fmt = "%s: " + fmt;
args.push_front(name);
}
if (when != (Tick)-1) {
fmt = "%7d: " + fmt;
args.push_front(when);
}
const char *data = static_cast<const char *>(d);
int c, i, j;
for (i = 0; i < len; i += 16) {
ccprintf(os, fmt, args);
ccprintf(os, "%08x ", i);
c = len - i;
if (c > 16) c = 16;
for (j = 0; j < c; j++) {
ccprintf(os, "%02x ", data[i + j] & 0xff);
if ((j & 0xf) == 7 && j > 0)
ccprintf(os, " ");
}
for (; j < 16; j++)
ccprintf(os, " ");
ccprintf(os, " ");
for (j = 0; j < c; j++) {
int ch = data[i + j] & 0x7f;
ccprintf(os, "%c", (char)(isprint(ch) ? ch : ' '));
}
ccprintf(os, "\n");
if (c < 16)
break;
}
}
} // namespace Trace

View File

@ -0,0 +1,138 @@
/*
* Copyright (c) 2001-2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
* Steve Reinhardt
*/
#ifndef __BASE_TRACE_HH__
#define __BASE_TRACE_HH__
#include <string>
#include "base/cprintf.hh"
#include "base/debug.hh"
#include "base/match.hh"
#include "base/types.hh"
#include "sim/core.hh"
namespace Trace {
using Debug::SimpleFlag;
using Debug::CompoundFlag;
std::ostream &output();
void setOutput(const std::string &filename);
extern bool enabled;
bool changeFlag(const char *str, bool value);
void dumpStatus();
extern ObjectMatch ignore;
extern const std::string DefaultName;
void dprintf(Tick when, const std::string &name, const char *format,
CPRINTF_DECLARATION);
void dump(Tick when, const std::string &name, const void *data, int len);
} // namespace Trace
// This silly little class allows us to wrap a string in a functor
// object so that we can give a name() that DPRINTF will like
struct StringWrap
{
std::string str;
StringWrap(const std::string &s) : str(s) {}
const std::string &operator()() const { return str; }
};
inline const std::string &name() { return Trace::DefaultName; }
//
// DPRINTF is a debugging trace facility that allows one to
// selectively enable tracing statements. To use DPRINTF, there must
// be a function or functor called name() that returns a const
// std::string & in the current scope.
//
// If you desire that the automatic printing not occur, use DPRINTFR
// (R for raw)
//
#if TRACING_ON
#define DTRACE(x) ((Debug::x) && Trace::enabled)
#define DDUMP(x, data, count) do { \
using namespace Debug; \
if (DTRACE(x)) \
Trace::dump(curTick(), name(), data, count); \
} while (0)
#define DPRINTF(x, ...) do { \
using namespace Debug; \
if (DTRACE(x)) \
Trace::dprintf(curTick(), name(), __VA_ARGS__); \
} while (0)
#define DPRINTFS(x, s, ...) do { \
using namespace Debug; \
if (DTRACE(x)) \
Trace::dprintf(curTick(), s->name(), __VA_ARGS__); \
} while (0)
#define DPRINTFR(x, ...) do { \
using namespace Debug; \
if (DTRACE(x)) \
Trace::dprintf((Tick)-1, std::string(), __VA_ARGS__); \
} while (0)
#define DDUMPN(data, count) do { \
Trace::dump(curTick(), name(), data, count); \
} while (0)
#define DPRINTFN(...) do { \
Trace::dprintf(curTick(), name(), __VA_ARGS__); \
} while (0)
#define DPRINTFNR(...) do { \
Trace::dprintf((Tick)-1, string(), __VA_ARGS__); \
} while (0)
#else // !TRACING_ON
#define DTRACE(x) (false)
#define DDUMP(x, data, count) do {} while (0)
#define DPRINTF(x, ...) do {} while (0)
#define DPRINTFS(x, ...) do {} while (0)
#define DPRINTFR(...) do {} while (0)
#define DDUMPN(data, count) do {} while (0)
#define DPRINTFN(...) do {} while (0)
#define DPRINTFNR(...) do {} while (0)
#endif // TRACING_ON
#endif // __BASE_TRACE_HH__

View File

@ -0,0 +1,360 @@
/*
* Copyright (c) 2012 Google
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Gabe Black
*/
#ifndef __BASE_TRIE_HH__
#define __BASE_TRIE_HH__
#include <cassert>
#include "base/cprintf.hh"
#include "base/misc.hh"
#include "base/types.hh"
// Key has to be an integral type.
template <class Key, class Value>
class Trie
{
protected:
struct Node
{
Key key;
Key mask;
bool
matches(Key test)
{
return (test & mask) == key;
}
Value *value;
Node *parent;
Node *kids[2];
Node(Key _key, Key _mask, Value *_val) :
key(_key & _mask), mask(_mask), value(_val),
parent(NULL)
{
kids[0] = NULL;
kids[1] = NULL;
}
void
clear()
{
if (kids[1]) {
kids[1]->clear();
delete kids[1];
kids[1] = NULL;
}
if (kids[0]) {
kids[0]->clear();
delete kids[0];
kids[0] = NULL;
}
}
void
dump(int level)
{
for (int i = 1; i < level; i++) {
cprintf("|");
}
if (level == 0)
cprintf("Root ");
else
cprintf("+ ");
cprintf("(%p, %p, %#X, %#X, %p)\n", parent, this, key, mask, value);
if (kids[0])
kids[0]->dump(level + 1);
if (kids[1])
kids[1]->dump(level + 1);
}
};
protected:
Node head;
public:
typedef Node *Handle;
Trie() : head(0, 0, NULL)
{}
static const unsigned MaxBits = sizeof(Key) * 8;
private:
/**
* A utility method which checks whether the key being looked up lies
* beyond the Node being examined. If so, it returns true and advances the
* node being examined.
* @param parent The node we're currently "at", which can be updated.
* @param kid The node we may want to move to.
* @param key The key we're looking for.
* @param new_mask The mask to use when matching against the key.
* @return Whether the current Node was advanced.
*/
bool
goesAfter(Node **parent, Node *kid, Key key, Key new_mask)
{
if (kid && kid->matches(key) && (kid->mask & new_mask) == kid->mask) {
*parent = kid;
return true;
} else {
return false;
}
}
/**
* A utility method which extends a mask value one more bit towards the
* lsb. This is almost just a signed right shift, except that the shifted
* in bits are technically undefined. This is also slightly complicated by
* the zero case.
* @param orig The original mask to extend.
* @return The extended mask.
*/
Key
extendMask(Key orig)
{
// Just in case orig was 0.
const Key msb = ULL(1) << (MaxBits - 1);
return orig | (orig >> 1) | msb;
}
/**
* Method which looks up the Handle corresponding to a particular key. This
* is useful if you want to delete the Handle corresponding to a key since
* the "remove" function takes a Handle as its argument.
* @param key The key to look up.
* @return The first Handle matching this key, or NULL if none was found.
*/
Handle
lookupHandle(Key key)
{
Node *node = &head;
while (node) {
if (node->value)
return node;
if (node->kids[0] && node->kids[0]->matches(key))
node = node->kids[0];
else if (node->kids[1] && node->kids[1]->matches(key))
node = node->kids[1];
else
node = NULL;
}
return NULL;
}
public:
/**
* Method which inserts a key/value pair into the trie.
* @param key The key which can later be used to look up this value.
* @param width How many bits of the key (from msb) should be used.
* @param val A pointer to the value to store in the trie.
* @return A Handle corresponding to this value.
*/
Handle
insert(Key key, unsigned width, Value *val)
{
// Build a mask which masks off all the bits we don't care about.
Key new_mask = ~(Key)0;
if (width < MaxBits)
new_mask <<= (MaxBits - width);
// Use it to tidy up the key.
key &= new_mask;
// Walk past all the nodes this new node will be inserted after. They
// can be ignored for the purposes of this function.
Node *node = &head;
while (goesAfter(&node, node->kids[0], key, new_mask) ||
goesAfter(&node, node->kids[1], key, new_mask))
{}
assert(node);
Key cur_mask = node->mask;
// If we're already where the value needs to be...
if (cur_mask == new_mask) {
assert(!node->value);
node->value = val;
return node;
}
for (unsigned int i = 0; i < 2; i++) {
Node *&kid = node->kids[i];
Node *new_node;
if (!kid) {
// No kid. Add a new one.
new_node = new Node(key, new_mask, val);
new_node->parent = node;
kid = new_node;
return new_node;
}
// Walk down the leg until something doesn't match or we run out
// of bits.
Key last_mask;
bool done;
do {
last_mask = cur_mask;
cur_mask = extendMask(cur_mask);
done = ((key & cur_mask) != (kid->key & cur_mask)) ||
last_mask == new_mask;
} while (!done);
cur_mask = last_mask;
// If this isn't the right leg to go down at all, skip it.
if (cur_mask == node->mask)
continue;
// At the point we walked to above, add a new node.
new_node = new Node(key, cur_mask, NULL);
new_node->parent = node;
kid->parent = new_node;
new_node->kids[0] = kid;
kid = new_node;
// If we ran out of bits, the value goes right here.
if (cur_mask == new_mask) {
new_node->value = val;
return new_node;
}
// Still more bits to deal with, so add a new node for that path.
new_node = new Node(key, new_mask, val);
new_node->parent = kid;
kid->kids[1] = new_node;
return new_node;
}
panic("Reached the end of the Trie insert function!\n");
return NULL;
}
/**
* Method which looks up the Value corresponding to a particular key.
* @param key The key to look up.
* @return The first Value matching this key, or NULL if none was found.
*/
Value *
lookup(Key key)
{
Node *node = lookupHandle(key);
if (node)
return node->value;
else
return NULL;
}
/**
* Method to delete a value from the trie.
* @param node A Handle to remove.
* @return The Value pointer from the removed entry.
*/
Value *
remove(Handle handle)
{
Node *node = handle;
Value *val = node->value;
if (node->kids[1]) {
assert(node->value);
node->value = NULL;
return val;
}
if (!node->parent)
panic("Trie: Can't remove root node.\n");
Node *parent = node->parent;
// If there's a kid, fix up it's parent pointer.
if (node->kids[0])
node->kids[0]->parent = parent;
// Figure out which kid we are, and update our parent's pointers.
if (parent->kids[0] == node)
parent->kids[0] = node->kids[0];
else if (parent->kids[1] == node)
parent->kids[1] = node->kids[0];
else
panic("Trie: Inconsistent parent/kid relationship.\n");
// Make sure if the parent only has one kid, it's kid[0].
if (parent->kids[1] && !parent->kids[0]) {
parent->kids[0] = parent->kids[1];
parent->kids[1] = NULL;
}
// If the parent has less than two kids and no cargo and isn't the
// root, delete it too.
if (!parent->kids[1] && !parent->value && parent->parent)
remove(parent);
delete node;
return val;
}
/**
* Method to lookup a value from the trie and then delete it.
* @param key The key to look up and then remove.
* @return The Value pointer from the removed entry, if any.
*/
Value *
remove(Key key)
{
Handle handle = lookupHandle(key);
if (!handle)
return NULL;
return remove(handle);
}
/**
* A method which removes all key/value pairs from the trie. This is more
* efficient than trying to remove elements individually.
*/
void
clear()
{
head.clear();
}
/**
* A debugging method which prints the contents of this trie.
* @param title An identifying title to put in the dump header.
*/
void
dump(const char *title)
{
cprintf("**************************************************\n");
cprintf("*** Start of Trie: %s\n", title);
cprintf("*** (parent, me, key, mask, value pointer)\n");
cprintf("**************************************************\n");
head.dump(0);
}
};
#endif

View File

@ -0,0 +1,110 @@
/*
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
/**
* @file
* Defines global host-dependent types:
* Counter, Tick, and (indirectly) {int,uint}{8,16,32,64}_t.
*/
#ifndef __BASE_TYPES_HH__
#define __BASE_TYPES_HH__
#include <inttypes.h>
/** uint64_t constant */
#define ULL(N) ((uint64_t)N##ULL)
/** int64_t constant */
#define LL(N) ((int64_t)N##LL)
/** Statistics counter type. Not much excuse for not using a 64-bit
* integer here, but if you're desperate and only run short
* simulations you could make this 32 bits.
*/
typedef int64_t Counter;
/**
* Clock cycle count type.
* @note using an unsigned breaks the cache.
*/
typedef int64_t Tick;
typedef uint64_t UTick;
const Tick MaxTick = LL(0x7fffffffffffffff);
/**
* Address type
* This will probably be moved somewhere else in the near future.
* This should be at least as big as the biggest address width in use
* in the system, which will probably be 64 bits.
*/
typedef uint64_t Addr;
typedef uint16_t MicroPC;
static const MicroPC MicroPCRomBit = 1 << (sizeof(MicroPC) * 8 - 1);
static inline MicroPC
romMicroPC(MicroPC upc)
{
return upc | MicroPCRomBit;
}
static inline MicroPC
normalMicroPC(MicroPC upc)
{
return upc & ~MicroPCRomBit;
}
static inline bool
isRomMicroPC(MicroPC upc)
{
return MicroPCRomBit & upc;
}
const Addr MaxAddr = (Addr)-1;
/**
* Thread index/ID type
*/
typedef int16_t ThreadID;
const ThreadID InvalidThreadID = (ThreadID)-1;
/**
* Port index/ID type, and a symbolic name for an invalid port id.
*/
typedef int16_t PortID;
const PortID InvalidPortID = (PortID)-1;
class FaultBase;
template <class T> class RefCountingPtr;
typedef RefCountingPtr<FaultBase> Fault;
#endif // __BASE_TYPES_HH__

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2004-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#include <sys/types.h>
#include <pwd.h>
#include <unistd.h>
#include <string>
std::string
username()
{
struct passwd *pwd = getpwuid(getuid());
return pwd->pw_name;
}

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2004-2005 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#ifndef __BASE_USERINFO_HH__
#define __BASE_USERINFO_HH__
#include <string>
std::string username();
#endif // __BASE_USERINFO_HH__

View File

@ -0,0 +1,308 @@
/*
* Copyright (c) 2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#ifndef __BASE_VARARGS_HH__
#define __BASE_VARARGS_HH__
#include "base/refcnt.hh"
#define VARARGS_DECLARATION(receiver) \
VarArgs::Argument<receiver> a01 = VarArgs::Null(), \
VarArgs::Argument<receiver> a02 = VarArgs::Null(), \
VarArgs::Argument<receiver> a03 = VarArgs::Null(), \
VarArgs::Argument<receiver> a04 = VarArgs::Null(), \
VarArgs::Argument<receiver> a05 = VarArgs::Null(), \
VarArgs::Argument<receiver> a06 = VarArgs::Null(), \
VarArgs::Argument<receiver> a07 = VarArgs::Null(), \
VarArgs::Argument<receiver> a08 = VarArgs::Null(), \
VarArgs::Argument<receiver> a09 = VarArgs::Null(), \
VarArgs::Argument<receiver> a10 = VarArgs::Null(), \
VarArgs::Argument<receiver> a11 = VarArgs::Null(), \
VarArgs::Argument<receiver> a12 = VarArgs::Null(), \
VarArgs::Argument<receiver> a13 = VarArgs::Null(), \
VarArgs::Argument<receiver> a14 = VarArgs::Null(), \
VarArgs::Argument<receiver> a15 = VarArgs::Null(), \
VarArgs::Argument<receiver> a16 = VarArgs::Null()
#define VARARGS_DEFINITION(receiver) \
VarArgs::Argument<receiver> a01, \
VarArgs::Argument<receiver> a02, \
VarArgs::Argument<receiver> a03, \
VarArgs::Argument<receiver> a04, \
VarArgs::Argument<receiver> a05, \
VarArgs::Argument<receiver> a06, \
VarArgs::Argument<receiver> a07, \
VarArgs::Argument<receiver> a08, \
VarArgs::Argument<receiver> a09, \
VarArgs::Argument<receiver> a10, \
VarArgs::Argument<receiver> a11, \
VarArgs::Argument<receiver> a12, \
VarArgs::Argument<receiver> a13, \
VarArgs::Argument<receiver> a14, \
VarArgs::Argument<receiver> a15, \
VarArgs::Argument<receiver> a16
#define VARARGS_ALLARGS \
a01, a02, a03, a04, a05, a06, a07, a08, \
a09, a10, a11, a12, a13, a14, a15, a16
#define VARARGS_ADDARGS(receiver) do { \
do { \
if (!a01) break; \
a01.add_arg(receiver); \
if (!a02) break; \
a02.add_arg(receiver); \
if (!a03) break; \
a03.add_arg(receiver); \
if (!a04) break; \
a04.add_arg(receiver); \
if (!a05) break; \
a05.add_arg(receiver); \
if (!a06) break; \
a06.add_arg(receiver); \
if (!a07) break; \
a07.add_arg(receiver); \
if (!a08) break; \
a08.add_arg(receiver); \
if (!a09) break; \
a09.add_arg(receiver); \
if (!a10) break; \
a10.add_arg(receiver); \
if (!a11) break; \
a11.add_arg(receiver); \
if (!a12) break; \
a12.add_arg(receiver); \
if (!a13) break; \
a13.add_arg(receiver); \
if (!a14) break; \
a14.add_arg(receiver); \
if (!a15) break; \
a15.add_arg(receiver); \
if (!a16) break; \
a16.add_arg(receiver); \
} while (0); \
receiver.end_args(); \
} while (0)
namespace VarArgs {
struct Null {};
template <typename T>
struct Traits
{
enum { enabled = true };
};
template <>
struct Traits<Null>
{
enum { enabled = false };
};
template <class RECV>
struct Base : public RefCounted
{
virtual void add_arg(RECV &receiver) const = 0;
};
template <typename T, class RECV>
struct Any : public Base<RECV>
{
const T &argument;
Any(const T &arg) : argument(arg) {}
virtual void
add_arg(RECV &receiver) const
{
receiver.add_arg(argument);
}
};
template <typename T, class RECV>
struct Any<T *, RECV> : public Base<RECV>
{
const T *argument;
Any(const T *arg) : argument(arg) {}
virtual void
add_arg(RECV &receiver) const
{
receiver.add_arg(argument);
}
};
template <class RECV>
struct Argument : public RefCountingPtr<Base<RECV> >
{
typedef RefCountingPtr<VarArgs::Base<RECV> > Base;
Argument() { }
Argument(const Null &null) { }
template <typename T>
Argument(const T& arg) : Base(new Any<T, RECV>(arg)) { }
template <typename T>
Argument(const T* arg) : Base(new Any<T *, RECV>(arg)) { }
void
add_arg(RECV &receiver) const
{
if (this->data)
this->data->add_arg(receiver);
}
};
template<class RECV>
class List
{
public:
typedef VarArgs::Argument<RECV> Argument;
typedef std::list<Argument> list;
typedef typename list::iterator iterator;
typedef typename list::const_iterator const_iterator;
typedef typename list::size_type size_type;
protected:
list l;
public:
List() {}
List(Argument a01, Argument a02, Argument a03, Argument a04,
Argument a05, Argument a06, Argument a07, Argument a08,
Argument a09, Argument a10, Argument a11, Argument a12,
Argument a13, Argument a14, Argument a15, Argument a16)
{
if (!a01) return;
l.push_back(a01);
if (!a02) return;
l.push_back(a02);
if (!a03) return;
l.push_back(a03);
if (!a04) return;
l.push_back(a04);
if (!a05) return;
l.push_back(a05);
if (!a06) return;
l.push_back(a06);
if (!a07) return;
l.push_back(a07);
if (!a08) return;
l.push_back(a08);
if (!a09) return;
l.push_back(a09);
if (!a10) return;
l.push_back(a10);
if (!a11) return;
l.push_back(a11);
if (!a12) return;
l.push_back(a12);
if (!a13) return;
l.push_back(a13);
if (!a14) return;
l.push_back(a14);
if (!a15) return;
l.push_back(a15);
if (!a16) return;
l.push_back(a16);
}
size_type size() const { return l.size(); }
bool empty() const { return l.empty(); }
iterator begin() { return l.begin(); }
const_iterator begin() const { return l.begin(); }
iterator end() { return l.end(); }
const_iterator end() const { return l.end(); }
void
push_back(const Argument &arg)
{
if (arg)
l.push_back(arg);
}
void
push_front(const Argument &arg)
{
if (arg)
l.push_front(arg);
}
template <typename T>
void
push_back(const T &arg)
{
if (Traits<T>::enabled)
l.push_back(arg);
}
template <typename T>
void
push_front(const T &arg)
{
if (Traits<T>::enabled)
l.push_front(arg);
}
Argument& front() { return l.front(); }
const Argument& front() const { return l.front(); }
Argument& back() { return l.back(); }
const Argument& back() const { return l.back(); }
void erase(iterator position) { return l.erase(position); }
void erase(iterator first, iterator last) { return l.erase(first, last); }
void clear() { return l.clear(); }
void pop_front() { return l.pop_front(); }
void pop_back() { return l.pop_back(); }
void reverse() { l.reverse(); }
/*
* Functions specific to variable arguments
*/
void
add_args(RECV &recv) const
{
const_iterator i = l.begin();
const_iterator end = l.end();
while (i != end) {
i->add_arg(recv);
++i;
}
recv.end_args();
}
};
} // namespace VarArgs
#endif /* __BASE_VARARGS_HH__ */

View File

@ -0,0 +1,46 @@
# -*- mode:python -*-
# Copyright (c) 2010 ARM Limited
# All rights reserved.
#
# The license below extends only to copyright in the software and shall
# not be construed as granting a license to any other intellectual
# property including but not limited to intellectual property relating
# to a hardware implementation of the functionality of the software
# licensed hereunder. You may use the software subject to the license
# terms below provided that you ensure that this notice is replicated
# unmodified and in its entirety in all distributions of the software,
# modified or unmodified, in source code or in binary form.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met: redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer;
# redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution;
# neither the name of the copyright holders nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Authors: William Wang
Import('*')
Source('convert.cc')
SimObject('VncServer.py')
Source('vncserver.cc')
DebugFlag('VNC')

View File

@ -0,0 +1,46 @@
# Copyright (c) 2010 ARM Limited
# All rights reserved.
#
# The license below extends only to copyright in the software and shall
# not be construed as granting a license to any other intellectual
# property including but not limited to intellectual property relating
# to a hardware implementation of the functionality of the software
# licensed hereunder. You may use the software subject to the license
# terms below provided that you ensure that this notice is replicated
# unmodified and in its entirety in all distributions of the software,
# modified or unmodified, in source code or in binary form.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met: redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer;
# redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution;
# neither the name of the copyright holders nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Authors: William Wang
from m5.SimObject import SimObject
from m5.params import *
from m5.proxy import *
class VncServer(SimObject):
type = 'VncServer'
port = Param.TcpPort(5900, "listen port")
number = Param.Int(0, "vnc client number")
frame_capture = Param.Bool(False, "capture changed frames to files")

View File

@ -0,0 +1,156 @@
/*
* Copyright (c) 2011 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
* not be construed as granting a license to any other intellectual
* property including but not limited to intellectual property relating
* to a hardware implementation of the functionality of the software
* licensed hereunder. You may use the software subject to the license
* terms below provided that you ensure that this notice is replicated
* unmodified and in its entirety in all distributions of the software,
* modified or unmodified, in source code or in binary form.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Ali Saidi
* William Wang
*/
#include <cassert>
#include "base/vnc/convert.hh"
#include "base/misc.hh"
/** @file
* This file provides conversion functions for a variety of video modes
*/
VideoConvert::VideoConvert(Mode input_mode, Mode output_mode, int _width,
int _height)
: inputMode(input_mode), outputMode(output_mode), width(_width),
height(_height)
{
if (inputMode != bgr565 && inputMode != rgb565 && inputMode != bgr8888)
fatal("Only support converting from bgr565, rdb565, and bgr8888\n");
if (outputMode != rgb8888)
fatal("Only support converting to rgb8888\n");
assert(0 < height && height < 4000);
assert(0 < width && width < 4000);
}
VideoConvert::~VideoConvert()
{
}
uint8_t*
VideoConvert::convert(const uint8_t *fb) const
{
switch (inputMode) {
case bgr565:
return m565rgb8888(fb, true);
case rgb565:
return m565rgb8888(fb, false);
case bgr8888:
return bgr8888rgb8888(fb);
default:
panic("Unimplemented Mode\n");
}
}
uint8_t*
VideoConvert::m565rgb8888(const uint8_t *fb, bool bgr) const
{
uint8_t *out = new uint8_t[area() * sizeof(uint32_t)];
uint32_t *out32 = (uint32_t*)out;
uint16_t *in16 = (uint16_t*)fb;
for (int x = 0; x < area(); x++) {
Bgr565 inpx;
Rgb8888 outpx = 0;
inpx = in16[x];
if (bgr) {
outpx.red = inpx.blue << 3;
outpx.green = inpx.green << 2;
outpx.blue = inpx.red << 3;
} else {
outpx.blue = inpx.blue << 3;
outpx.green = inpx.green << 2;
outpx.red = inpx.red << 3;
}
out32[x] = outpx;
}
return out;
}
uint8_t*
VideoConvert::bgr8888rgb8888(const uint8_t *fb) const
{
uint8_t *out = new uint8_t[area() * sizeof(uint32_t)];
uint32_t *out32 = (uint32_t*)out;
uint32_t *in32 = (uint32_t*)fb;
for (int x = 0; x < area(); x++) {
Rgb8888 outpx = 0;
Bgr8888 inpx;
inpx = in32[x];
outpx.red = inpx.blue;
outpx.green = inpx.green;
outpx.blue = inpx.red;
out32[x] = outpx;
}
return out;
}
/*
uint64_t
VideoConvert::getHash(const uint8_t *fb) const
{
const uint8_t *fb_e = fb + area();
uint64_t hash = 1;
while (fb < fb_e - 8) {
hash += *((const uint64_t*)fb);
fb += 8;
}
while (fb < fb_e) {
hash += *(fb++);
}
return hash;
}*/

Some files were not shown because too many files have changed in this diff Show More