Merge linux tree with head

arch/alpha/alpha_memory.cc:
dev/alpha_console.cc:
dev/alpha_console.hh:
    Merge

--HG--
extra : convert_revision : 3233648f204338ab3f102ff117754dce955dcc37
This commit is contained in:
Andrew Schultz 2004-02-09 17:50:47 -05:00
commit eac2d6a668
17 changed files with 471 additions and 263 deletions

View file

@ -97,7 +97,8 @@ AlphaTlb::checkCacheability(MemReqPtr &req)
break; break;
default: default:
panic("IPR memory space not implemented! PA=%x\n", req->paddr); panic("IPR memory space not implemented! PA=%x\n",
req->paddr);
} }
} }
} else { } else {

View file

@ -1225,7 +1225,7 @@ declare {{
{ {
} }
Addr branchTarget(Addr branchPC) Addr branchTarget(Addr branchPC) const
{ {
return branchPC + 4 + disp; return branchPC + 4 + disp;
} }
@ -1287,7 +1287,7 @@ declare {{
{ {
} }
Addr branchTarget(ExecContext *xc) Addr branchTarget(ExecContext *xc) const
{ {
Addr NPC = xc->readPC() + 4; Addr NPC = xc->readPC() + 4;
uint64_t Rb = xc->readIntReg(_srcRegIdx[0]); uint64_t Rb = xc->readIntReg(_srcRegIdx[0]);
@ -2330,10 +2330,6 @@ decode OPCODE default Unknown::unknown() {
// miscellaneous mem-format ops // miscellaneous mem-format ops
0x18: decode MEMFUNC { 0x18: decode MEMFUNC {
format WarnUnimpl { format WarnUnimpl {
0x0000: trapb();
0x0400: excb();
0x4000: mb();
0x4400: wmb();
0x8000: fetch(); 0x8000: fetch();
0xa000: fetch_m(); 0xa000: fetch_m();
0xe800: ecb(); 0xe800: ecb();
@ -2347,6 +2343,27 @@ decode OPCODE default Unknown::unknown() {
format BasicOperate { format BasicOperate {
0xc000: rpcc({{ Ra = curTick; }}); 0xc000: rpcc({{ Ra = curTick; }});
// All of the barrier instructions below do nothing in
// their execute() methods (hence the empty code blocks).
// All of their functionality is hard-coded in the
// pipeline based on the flags IsSerializing,
// IsMemBarrier, and IsWriteBarrier. In the current
// detailed CPU model, the execute() function only gets
// called at fetch, so there's no way to generate pipeline
// behavior at any other stage. Once we go to an
// exec-in-exec CPU model we should be able to get rid of
// these flags and implement this behavior via the
// execute() methods.
// trapb is just a barrier on integer traps, where excb is
// a barrier on integer and FP traps. "EXCB is thus a
// superset of TRAPB." (Alpha ARM, Sec 4.11.4) We treat
// them the same though.
0x0000: trapb({{ }}, IsSerializing, No_OpClass);
0x0400: excb({{ }}, IsSerializing, No_OpClass);
0x4000: mb({{ }}, IsMemBarrier, RdPort);
0x4400: wmb({{ }}, IsWriteBarrier, WrPort);
} }
#ifdef FULL_SYSTEM #ifdef FULL_SYSTEM
@ -2356,13 +2373,13 @@ decode OPCODE default Unknown::unknown() {
if (!xc->misspeculating()) { if (!xc->misspeculating()) {
xc->regs.intrflag = 0; xc->regs.intrflag = 0;
} }
}}, No_OpClass); }});
0xf000: rs({{ 0xf000: rs({{
Ra = xc->regs.intrflag; Ra = xc->regs.intrflag;
if (!xc->misspeculating()) { if (!xc->misspeculating()) {
xc->regs.intrflag = 1; xc->regs.intrflag = 1;
} }
}}, No_OpClass); }});
} }
#else #else
format FailUnimpl { format FailUnimpl {
@ -2476,7 +2493,7 @@ decode OPCODE default Unknown::unknown() {
if (!xc->misspeculating()) if (!xc->misspeculating())
AlphaPseudo::m5exit(xc); AlphaPseudo::m5exit(xc);
}}, No_OpClass); }}, No_OpClass);
0x30: initparam({{ Ra = xc->cpu->system->init_param; }}); 0x30: initparam({{ Ra = cpu->system->init_param; }});
0x40: resetstats({{ 0x40: resetstats({{
if (!xc->misspeculating()) if (!xc->misspeculating())
AlphaPseudo::resetstats(xc); AlphaPseudo::resetstats(xc);

View file

@ -34,6 +34,10 @@
* This file defines a doNothing compression algorithm. * This file defines a doNothing compression algorithm.
*/ */
#include <inttypes.h> // for uint8_t
#include "base/misc.hh" // for fatal()
/** /**
* A dummy compression class to use when no data compression is desired. * A dummy compression class to use when no data compression is desired.
*/ */

83
base/range.cc Normal file
View file

@ -0,0 +1,83 @@
/*
* Copyright (c) 2003 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.
*/
#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 &start, T &end)
{
std::vector<std::string> values;
tokenize(values, str, ':');
T thestart, theend;
if (values.size() != 2)
return false;
std::string s = values[0];
std::string e = values[1];
if (!to_number(s, thestart))
return false;
bool increment = (e[0] == '+');
if (increment)
e = e.substr(1);
if (!to_number(e, theend))
return false;
if (increment)
theend += thestart;
start = thestart;
end = theend;
return true;
}
#define RANGE_PARSE(type) \
template<> bool \
__parse_range(const std::string &s, type &start, type &end) \
{ return __x_parse_range(s, start, end); }
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

@ -29,232 +29,351 @@
#ifndef __RANGE_HH__ #ifndef __RANGE_HH__
#define __RANGE_HH__ #define __RANGE_HH__
#include <assert.h> #include <cassert>
#include <string>
#include "base/intmath.hh" template <class T>
#include "base/str.hh" bool __parse_range(const std::string &s, T &start, T &end);
template<class T> template <class T>
class Range struct Range
{ {
private: private:
bool valid; /**
* @param s range string
* Ranges are in the following format:
* <range> := {<start_val>}:{<end>}
* <end> := <end_val> | +<delta>
*/
void
parse(const std::string &s)
{
if (!__parse_range(s, start, end))
invalidate();
}
public: public:
T start; T start;
T end; T end;
public: public:
Range() {} Range()
Range(const Range &r) { operator=(r); }
Range(const T &s, const T &e)
: start(s), end(e)
{ {
valid = (start <= end); invalidate();
} }
Range(const std::string &s) { valid = parse(s); } Range(T first, T second)
: start(first), end(second)
{}
~Range() {} template <class U>
Range(const Range<U> &r)
: start(r.start), end(r.end)
{}
int compare(const T &p); template <class U>
bool parse(const std::string &s); Range(const std::pair<U, U> &r)
const Range &operator=(const Range &r); : start(r.first), end(r.second)
{}
bool isValid() const { return valid; } Range(const std::string &s)
}; {
parse(s);
}
template <class U>
template<class T> const Range<T> &operator=(const Range<U> &r)
inline int {
Range<T>::compare(const T &p)
{
assert(isValid());
if (p < start)
return -1;
else if (p > end)
return 1;
else
return 0;
}
// Parse a range string
//
// Ranges are in the following format:
// <range> := {<start_val>}:{<end>}
// <end> := <end_val> | +<delta>
template<class T>
inline bool
Range<T>::parse(const std::string &str)
{
std::vector<std::string> values;
tokenize(values, str, ':');
T thestart, theend;
if (values.size() != 2)
return false;
std::string s = values[0];
std::string e = values[1];
if (!to_number(s, thestart))
return false;
bool increment = (e[0] == '+');
if (increment)
e = e.substr(1);
if (!to_number(e, theend))
return false;
if (increment)
theend += thestart;
start = thestart;
end = theend;
if (start > end)
return false;
return true;
}
template<class T>
inline const Range<T> &
Range<T>::operator=(const Range<T> &r)
{
if (this != &r) {
start = r.start; start = r.start;
end = r.end; end = r.end;
return *this;
valid = r.valid;
}
else {
valid = false;
} }
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)
{
parse(s);
return *this;
}
void invalidate() { start = 0; end = 0; }
T size() const { return end - start; }
bool valid() const { return start < end; }
};
template <class T>
inline Range<T>
make_range(T start, T end)
{
return Range<T>(start, end);
} }
template<class T> template <class T>
inline std::ostream & inline std::ostream &
operator<<(std::ostream &o, const Range<T> &r) operator<<(std::ostream &o, const Range<T> &r)
{ {
// don't currently support output of invalid ranges // don't currently support output of invalid ranges
assert(r.isValid()); assert(r.valid());
o << r.start << ":" << r.end; o << r.start << ":" << r.end;
return o; return o;
} }
////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// //
// Compare two ranges // Range to Range Comparisons
// //
template<class T>
/**
* @param range1 is a range.
* @param range2 is a range.
* @return if range1 and range2 are identical.
*/
template <class T, class U>
inline bool inline bool
operator==(const Range<T> &l, const Range<T> &r) operator==(const Range<T> &range1, const Range<U> &range2)
{ {
// ranges must both be valid to be equal assert(range1.valid() && range2.valid());
return (l.isValid() && r.isValid() && return range1.start == range2.start && range1.end == range2.end;
(l.start == r.start) && (l.end == r.end));
} }
template<class T> /**
* @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 inline bool
operator!=(const Range<T> &l, const Range<T> &r) operator!=(const Range<T> &range1, const Range<U> &range2)
{ {
// for symmetry with ==, an invalid range is not equal to any other assert(range1.valid() && range2.valid());
return (!l.isValid() || !r.isValid() || return range1.start != range2.start || range1.end != range2.end;
(l.start != r.start) || (l.end != r.end));
} }
////////////////////////////////////////// /**
// * @param range1 is a range.
// Compare position to a range * @param range2 is a range.
// * @return if range1 is less than range2 and does not overlap range1.
// - 'pos == range' indicates that position pos is within the given range. */
// This test always returns false if the range is invalid. template <class T, class U>
// inline bool
// - 'pos < range' and 'pos > range' indicate that the position is operator<(const Range<T> &range1, const Range<U> &range2)
// before the start of or after the end of the range, respectively. {
// The range must be valid for these comparisons to be made. assert(range1.valid() && range2.valid());
// return range1.end <= range2.start;
// All other comparisons do the obvious thing based on these definitions. }
/**
* @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)
{
assert(range1.valid() && range2.valid());
return range1.start <= range2.start && range1.end <= range2.end;
}
/**
* @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)
{
assert(range1.valid() && range2.valid());
return range1.start >= range2.end;
}
/**
* @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)
{
assert(range1.valid() && range2.valid());
return range1.start >= range2.start && range1.end >= range2.end;
}
////////////////////////////////////////////////////////////////////////
// //
// 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)
{
assert(range.valid());
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)
{
assert(range.valid());
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)
{
assert(range.valid());
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)
{
assert(range.valid());
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)
{
assert(range.valid());
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)
{
assert(range.valid());
return pos >= range.start;
}
////////////////////////////////////////////////////////////////////////
// //
// Basic comparisons // Range to Position Comparisons (for symmetry)
// //
template<class T>
inline bool
operator==(const T &pos, const Range<T> &range)
{ return range.isValid() && pos >= range.start && pos <= range.end; }
template<class T> /**
* @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 inline bool
operator<(const T &pos, const Range<T> &range) operator==(const Range<T> &range, const U &pos)
{ assert(range.isValid()); return pos < range.start; } {
assert(range.valid());
return pos >= range.start && pos < range.end;
}
template<class T> /**
* @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 inline bool
operator>(const T &pos, const Range<T> &range) operator!=(const Range<T> &range, const U &pos)
{ assert(range.isValid()); return pos > range.end; } {
assert(range.valid());
return pos < range.start || pos >= range.end;
}
// /**
// Derived comparisons * @param range range compared against.
// * @param pos position compared to the range.
template<class T> * @return indicates that position pos is above the range.
*/
template <class T, class U>
inline bool inline bool
operator<=(const T &pos, const Range<T> &range) operator<(const Range<T> &range, const U &pos)
{ assert(range.isValid()); return pos <= range.end; } {
assert(range.valid());
return range.end <= pos;
}
template<class T> /**
* @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 inline bool
operator>=(const T &pos, const Range<T> &range) operator<=(const Range<T> &range, const U &pos)
{ assert(range.isValid()); return pos >= range.start; } {
assert(range.valid());
return range.start <= pos;
}
template<class T> /**
* @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 inline bool
operator!=(const T &pos, const Range<T> &range) operator>(const Range<T> &range, const U &pos)
{ return !(pos == range); } {
assert(range.valid());
return range.start > pos;
}
// /**
// Define symmetric comparisons based on above * @param range range compared against.
// * @param pos position compared to the range.
template<class T> * 'range >= pos' indicates that position pos is below or in the range.
*/
template <class T, class U>
inline bool inline bool
operator>(const Range<T> &range, const T &pos) operator>=(const Range<T> &range, const U &pos)
{ return pos < range; } {
assert(range.valid());
template<class T> return range.end > pos;
inline bool }
operator<(const Range<T> &range, const T &pos)
{ return pos > range; }
template<class T>
inline bool
operator<=(const Range<T> &range, const T &pos)
{ return pos >= range; }
template<class T>
inline bool
operator>=(const Range<T> &range, const T &pos)
{ return pos <= range; }
template<class T>
inline bool
operator==(const Range<T> &range, const T &pos)
{ return (pos == range); }
template<class T>
inline bool
operator!=(const Range<T> &range, const T &pos)
{ return (pos != range); }
#endif // __RANGE_HH__ #endif // __RANGE_HH__

View file

@ -338,7 +338,7 @@ RemoteGDB::acc(Addr va, size_t len)
} }
if (va < ALPHA_K1SEG_BASE) { if (va < ALPHA_K1SEG_BASE) {
if (va < (ALPHA_K0SEG_BASE + pmem->getSize())) { if (va < (ALPHA_K0SEG_BASE + pmem->size())) {
DPRINTF(GDBAcc, "acc: Mapping is valid K0SEG <= " DPRINTF(GDBAcc, "acc: Mapping is valid K0SEG <= "
"%#x < K0SEG + size\n", va); "%#x < K0SEG + size\n", va);
return true; return true;

View file

@ -78,6 +78,12 @@ class StaticInstBase : public RefCounted
/// - If IsControl is set, then exactly one of IsDirectControl or /// - If IsControl is set, then exactly one of IsDirectControl or
/// IsIndirect Control will be set, and exactly one of /// IsIndirect Control will be set, and exactly one of
/// IsCondControl or IsUncondControl will be set. /// IsCondControl or IsUncondControl will be set.
/// - IsSerializing, IsMemBarrier, and IsWriteBarrier are
/// implemented as flags since in the current model there's no
/// other way for instructions to inject behavior into the
/// pipeline outside of fetch. Once we go to an exec-in-exec CPU
/// model we should be able to get rid of these flags and
/// implement this behavior via the execute() methods.
/// ///
enum Flags { enum Flags {
IsNop, ///< Is a no-op (no effect at all). IsNop, ///< Is a no-op (no effect at all).
@ -99,7 +105,12 @@ class StaticInstBase : public RefCounted
IsCall, ///< Subroutine call. IsCall, ///< Subroutine call.
IsReturn, ///< Subroutine return. IsReturn, ///< Subroutine return.
IsThreadSync, ///< Thread synchronization operation. IsThreadSync, ///< Thread synchronization operation.
IsSerializing, ///< Serializes pipeline: won't until all
/// older instructions have committed.
IsMemBarrier, ///< Is a memory barrier
IsWriteBarrier, ///< Is a write barrier
NumFlags NumFlags
}; };
@ -178,6 +189,9 @@ class StaticInstBase : public RefCounted
bool isUncondCtrl() const { return flags[IsUncondControl]; } bool isUncondCtrl() const { return flags[IsUncondControl]; }
bool isThreadSync() const { return flags[IsThreadSync]; } bool isThreadSync() const { return flags[IsThreadSync]; }
bool isSerializing() const { return flags[IsSerializing]; }
bool isMemBarrier() const { return flags[IsMemBarrier]; }
bool isWriteBarrier() const { return flags[IsWriteBarrier]; }
//@} //@}
/// Operation class. Used to select appropriate function unit in issue. /// Operation class. Used to select appropriate function unit in issue.
@ -216,11 +230,11 @@ class StaticInst : public StaticInstBase
/// Return logical index (architectural reg num) of i'th destination reg. /// Return logical index (architectural reg num) of i'th destination reg.
/// Only the entries from 0 through numDestRegs()-1 are valid. /// Only the entries from 0 through numDestRegs()-1 are valid.
RegIndex destRegIdx(int i) { return _destRegIdx[i]; } RegIndex destRegIdx(int i) const { return _destRegIdx[i]; }
/// Return logical index (architectural reg num) of i'th source reg. /// Return logical index (architectural reg num) of i'th source reg.
/// Only the entries from 0 through numSrcRegs()-1 are valid. /// Only the entries from 0 through numSrcRegs()-1 are valid.
RegIndex srcRegIdx(int i) { return _srcRegIdx[i]; } RegIndex srcRegIdx(int i) const { return _srcRegIdx[i]; }
/// Pointer to a statically allocated "null" instruction object. /// Pointer to a statically allocated "null" instruction object.
/// Used to give eaCompInst() and memAccInst() something to return /// Used to give eaCompInst() and memAccInst() something to return
@ -305,7 +319,7 @@ class StaticInst : public StaticInstBase
* Invalid if not a PC-relative branch (i.e. isDirectCtrl() * Invalid if not a PC-relative branch (i.e. isDirectCtrl()
* should be true). * should be true).
*/ */
virtual Addr branchTarget(Addr branchPC) virtual Addr branchTarget(Addr branchPC) const
{ {
panic("StaticInst::branchTarget() called on instruction " panic("StaticInst::branchTarget() called on instruction "
"that is not a PC-relative branch."); "that is not a PC-relative branch.");
@ -318,7 +332,7 @@ class StaticInst : public StaticInstBase
* execute the branch in question. Invalid if not an indirect * execute the branch in question. Invalid if not an indirect
* branch (i.e. isIndirectCtrl() should be true). * branch (i.e. isIndirectCtrl() should be true).
*/ */
virtual Addr branchTarget(ExecContext *xc) virtual Addr branchTarget(ExecContext *xc) const
{ {
panic("StaticInst::branchTarget() called on instruction " panic("StaticInst::branchTarget() called on instruction "
"that is not an indirect branch."); "that is not an indirect branch.");

View file

@ -36,7 +36,7 @@
#define ALPHA_ACCESS_VERSION (1301) /* CH++*/ #define ALPHA_ACCESS_VERSION (1301) /* CH++*/
#ifndef CONSOLE #ifndef CONSOLE
#include <ostream> #include <iosfwd>
#include <string> #include <string>
class Checkpoint; class Checkpoint;
#endif #endif

View file

@ -56,6 +56,8 @@ AlphaConsole::AlphaConsole(const string &name, SimConsole *cons,
Addr addr, Addr mask, MemoryController *mmu) Addr addr, Addr mask, MemoryController *mmu)
: MmapDevice(name, addr, mask, mmu), disk(d), console(cons) : MmapDevice(name, addr, mask, mmu), disk(d), console(cons)
{ {
mmu->add_child(this, Range<Addr>(addr, addr + size));
consoleData = new uint8_t[size]; consoleData = new uint8_t[size];
memset(consoleData, 0, size); memset(consoleData, 0, size);
@ -66,7 +68,7 @@ AlphaConsole::AlphaConsole(const string &name, SimConsole *cons,
alphaAccess->version = ALPHA_ACCESS_VERSION; alphaAccess->version = ALPHA_ACCESS_VERSION;
alphaAccess->numCPUs = num_cpus; alphaAccess->numCPUs = num_cpus;
alphaAccess->mem_size = system->physmem->getSize(); alphaAccess->mem_size = system->physmem->size();
alphaAccess->cpuClock = cpu->getFreq() / 1000000; alphaAccess->cpuClock = cpu->getFreq() / 1000000;
alphaAccess->intrClockFrequency = clock->frequency(); alphaAccess->intrClockFrequency = clock->frequency();
@ -79,7 +81,8 @@ AlphaConsole::read(MemReqPtr &req, uint8_t *data)
memset(data, 0, req->size); memset(data, 0, req->size);
uint64_t val; uint64_t val;
Addr daddr = req->paddr & addr_mask; Addr daddr = req->paddr - addr;
switch (daddr) { switch (daddr) {
case offsetof(AlphaAccess, inputChar): case offsetof(AlphaAccess, inputChar):
val = console->console_in(); val = console->console_in();
@ -126,7 +129,7 @@ AlphaConsole::write(MemReqPtr &req, const uint8_t *data)
return Machine_Check_Fault; return Machine_Check_Fault;
} }
Addr daddr = req->paddr & addr_mask; Addr daddr = req->paddr - addr;
ExecContext *other_xc; ExecContext *other_xc;
switch (daddr) { switch (daddr) {
@ -244,11 +247,9 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole)
SimObjectParam<SimConsole *> sim_console; SimObjectParam<SimConsole *> sim_console;
SimObjectParam<SimpleDisk *> disk; SimObjectParam<SimpleDisk *> disk;
Param<int> size;
Param<int> num_cpus; Param<int> num_cpus;
SimObjectParam<MemoryController *> mmu; SimObjectParam<MemoryController *> mmu;
Param<Addr> addr; Param<Addr> addr;
Param<Addr> mask;
SimObjectParam<System *> system; SimObjectParam<System *> system;
SimObjectParam<BaseCPU *> cpu; SimObjectParam<BaseCPU *> cpu;
SimObjectParam<TsunamiIO *> clock; SimObjectParam<TsunamiIO *> clock;
@ -259,11 +260,9 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(AlphaConsole)
INIT_PARAM(sim_console, "The Simulator Console"), INIT_PARAM(sim_console, "The Simulator Console"),
INIT_PARAM(disk, "Simple Disk"), INIT_PARAM(disk, "Simple Disk"),
INIT_PARAM_DFLT(size, "AlphaConsole size", sizeof(AlphaAccess)),
INIT_PARAM_DFLT(num_cpus, "Number of CPU's", 1), INIT_PARAM_DFLT(num_cpus, "Number of CPU's", 1),
INIT_PARAM(mmu, "Memory Controller"), INIT_PARAM(mmu, "Memory Controller"),
INIT_PARAM(addr, "Device Address"), INIT_PARAM(addr, "Device Address"),
INIT_PARAM(mask, "Address Mask"),
INIT_PARAM(system, "system object"), INIT_PARAM(system, "system object"),
INIT_PARAM(cpu, "Processor"), INIT_PARAM(cpu, "Processor"),
INIT_PARAM(clock, "Turbolaser Clock") INIT_PARAM(clock, "Turbolaser Clock")
@ -272,10 +271,8 @@ END_INIT_SIM_OBJECT_PARAMS(AlphaConsole)
CREATE_SIM_OBJECT(AlphaConsole) CREATE_SIM_OBJECT(AlphaConsole)
{ {
return new AlphaConsole(getInstanceName(), sim_console, return new AlphaConsole(getInstanceName(), sim_console, disk,
disk, size, system, system, cpu, clock, num_cpus, mmu, addr);
cpu, clock, num_cpus,
addr, mask, mmu);
} }
REGISTER_SIM_OBJECT("AlphaConsole", AlphaConsole) REGISTER_SIM_OBJECT("AlphaConsole", AlphaConsole)

View file

@ -33,9 +33,10 @@
#ifndef __ALPHA_CONSOLE_HH__ #ifndef __ALPHA_CONSOLE_HH__
#define __ALPHA_CONSOLE_HH__ #define __ALPHA_CONSOLE_HH__
#include "sim/host.hh" #include "base/range.hh"
#include "dev/alpha_access.h" #include "dev/alpha_access.h"
#include "mem/functional_mem/mmap_device.hh" #include "mem/functional_mem/functional_memory.hh"
#include "sim/host.hh"
#include "dev/tsunami_io.hh" #include "dev/tsunami_io.hh"
class BaseCPU; class BaseCPU;
@ -69,7 +70,7 @@ class SimpleDisk;
* primarily used doing boot before the kernel has loaded its device * primarily used doing boot before the kernel has loaded its device
* drivers. * drivers.
*/ */
class AlphaConsole : public MmapDevice class AlphaConsole : public FunctionalMemory
{ {
protected: protected:
union { union {
@ -83,6 +84,9 @@ class AlphaConsole : public MmapDevice
/** the system console (the terminal) is accessable from the console */ /** the system console (the terminal) is accessable from the console */
SimConsole *console; SimConsole *console;
Addr addr;
static const Addr size = 0x80; // equal to sizeof(alpha_access);
public: public:
/** Standard Constructor */ /** Standard Constructor */
AlphaConsole(const std::string &name, SimConsole *cons, AlphaConsole(const std::string &name, SimConsole *cons,
@ -91,7 +95,6 @@ class AlphaConsole : public MmapDevice
TsunamiIO *clock, int num_cpus, TsunamiIO *clock, int num_cpus,
Addr addr, Addr mask, MemoryController *mmu); Addr addr, Addr mask, MemoryController *mmu);
public:
/** /**
* memory mapped reads and writes * memory mapped reads and writes
*/ */

View file

@ -89,7 +89,7 @@ class EtherLink : public SimObject
Link(const std::string &name, double rate, EtherDump *dump); Link(const std::string &name, double rate, EtherDump *dump);
~Link() {} ~Link() {}
virtual std::string name() const { return objName; } virtual const std::string name() const { return objName; }
bool busy() const { return (bool)packet; } bool busy() const { return (bool)packet; }
bool transmit(PacketPtr &packet); bool transmit(PacketPtr &packet);

View file

@ -153,7 +153,7 @@ class Event : public Serializable, public FastAlloc
~Event() {} ~Event() {}
virtual std::string name() const { virtual const std::string name() const {
return csprintf("Event_%x", (uintptr_t)this); return csprintf("Event_%x", (uintptr_t)this);
} }
@ -257,7 +257,7 @@ class EventQueue : public Serializable
: objName(n), head(NULL) : objName(n), head(NULL)
{} {}
virtual std::string name() const { return objName; } virtual const std::string name() const { return objName; }
// schedule the given event on this queue // schedule the given event on this queue
void schedule(Event *ev); void schedule(Event *ev);

View file

@ -186,7 +186,7 @@ INSTANTIATE_PARAM_TEMPLATES(string)
class Globals : public Serializable class Globals : public Serializable
{ {
public: public:
string name() const; const string name() const;
void serialize(ostream &os); void serialize(ostream &os);
void unserialize(Checkpoint *cp); void unserialize(Checkpoint *cp);
}; };
@ -194,7 +194,7 @@ class Globals : public Serializable
/// The one and only instance of the Globals class. /// The one and only instance of the Globals class.
Globals globals; Globals globals;
string const string
Globals::name() const Globals::name() const
{ {
return "Globals"; return "Globals";

View file

@ -111,7 +111,7 @@ class Serializable
virtual ~Serializable() {} virtual ~Serializable() {}
// manditory virtual function, so objects must provide names // manditory virtual function, so objects must provide names
virtual std::string name() const = 0; virtual const std::string name() const = 0;
virtual void serialize(std::ostream &os) {} virtual void serialize(std::ostream &os) {}
virtual void unserialize(Checkpoint *cp, const std::string &section) {} virtual void unserialize(Checkpoint *cp, const std::string &section) {}

View file

@ -63,7 +63,7 @@ class SimObject : public Serializable
virtual ~SimObject() {} virtual ~SimObject() {}
virtual std::string name() const { return objName; } virtual const std::string name() const { return objName; }
// initialization pass of all objects. Gets invoked by SimInit() // initialization pass of all objects. Gets invoked by SimInit()
virtual void init(); virtual void init();

View file

@ -49,7 +49,7 @@ nmtest: nmtest.o object_file.o symtab.o misc.o str.o
offtest: offtest.o offtest: offtest.o
$(CXX) $(LFLAGS) -o $@ $^ $(CXX) $(LFLAGS) -o $@ $^
rangetest: rangetest.o str.o rangetest: rangetest.o range.o str.o
$(CXX) $(LFLAGS) -o $@ $^ $(CXX) $(LFLAGS) -o $@ $^
stattest: cprintf.o hostinfo.o misc.o python.o statistics.o stattest.o \ stattest: cprintf.o hostinfo.o misc.o python.o statistics.o stattest.o \

View file

@ -31,11 +31,12 @@
#include "base/range.hh" #include "base/range.hh"
using namespace std;
int int
main() main()
{ {
Range<int> r1(9, 28); Range<int> r1(make_pair(9, 28));
Range<unsigned> r2("0x1000:+0x100"); Range<unsigned> r2("0x1000:+0x100");
cout << r1 << "\n" cout << r1 << "\n"
@ -44,61 +45,30 @@ main()
#define RANGETEST(X, C, Y) \ #define RANGETEST(X, C, Y) \
cout << X << " "#C" " << Y << " => " << ((X C Y) ? "true" : "false") << "\n" cout << X << " "#C" " << Y << " => " << ((X C Y) ? "true" : "false") << "\n"
int i1 = 10; #define TESTEM(X, Y) do { \
int i2 = 0x1001; RANGETEST(X, < , Y); \
RANGETEST(i1, < , r1); RANGETEST(X, <=, Y); \
RANGETEST(i1, <=, r1); RANGETEST(X, > , Y); \
RANGETEST(i1, > , r1); RANGETEST(X, >=, Y); \
RANGETEST(i1, >=, r1); RANGETEST(X, ==, Y); \
RANGETEST(i1, ==, r1); RANGETEST(X, !=, Y); \
RANGETEST(i1, !=, r1); RANGETEST(Y, < , X); \
RANGETEST(r1, < , i1); RANGETEST(Y, <=, X); \
RANGETEST(r1, <=, i1); RANGETEST(Y, > , X); \
RANGETEST(r1, > , i1); RANGETEST(Y, >=, X); \
RANGETEST(r1, >=, i1); RANGETEST(Y, ==, X); \
RANGETEST(r1, ==, i1); RANGETEST(Y, !=, X); \
RANGETEST(r1, !=, i1); } while (0)
RANGETEST(i2, < , r1); TESTEM(8, r1);
RANGETEST(i2, <=, r1); TESTEM(9, r1);
RANGETEST(i2, > , r1); TESTEM(27, r1);
RANGETEST(i2, >=, r1); TESTEM(28, r1);
RANGETEST(i2, ==, r1);
RANGETEST(i2, !=, r1);
RANGETEST(r1, < , i2);
RANGETEST(r1, <=, i2);
RANGETEST(r1, > , i2);
RANGETEST(r1, >=, i2);
RANGETEST(r1, ==, i2);
RANGETEST(r1, !=, i2);
unsigned u1 = 10; TESTEM(0x0fff, r2);
unsigned u2 = 0x1001; TESTEM(0x1000, r2);
RANGETEST(u1, < , r2); TESTEM(0x10ff, r2);
RANGETEST(u1, <=, r2); TESTEM(0x1100, r2);
RANGETEST(u1, > , r2);
RANGETEST(u1, >=, r2);
RANGETEST(u1, ==, r2);
RANGETEST(u1, !=, r2);
RANGETEST(r2, < , u1);
RANGETEST(r2, <=, u1);
RANGETEST(r2, > , u1);
RANGETEST(r2, >=, u1);
RANGETEST(r2, ==, u1);
RANGETEST(r2, !=, u1);
RANGETEST(u2, < , r2);
RANGETEST(u2, <=, r2);
RANGETEST(u2, > , r2);
RANGETEST(u2, >=, r2);
RANGETEST(u2, ==, r2);
RANGETEST(u2, !=, r2);
RANGETEST(r2, < , u2);
RANGETEST(r2, <=, u2);
RANGETEST(r2, > , u2);
RANGETEST(r2, >=, u2);
RANGETEST(r2, ==, u2);
RANGETEST(r2, !=, u2);
return 0; return 0;
} }