summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2007-03-05 11:00:44 +0000
committerGabe Black <gblack@eecs.umich.edu>2007-03-05 11:00:44 +0000
commit6a19b64de2044e5b166a9883be6531166cd69900 (patch)
treee463581d5611ac0a2223a292cc4d1231f3de6b1f /src
parent5498d5298577c07189ff3f7026eba5c1ee09cc1b (diff)
parentba042842c61339e33c0b684f9854e8fe818160fe (diff)
downloadgem5-6a19b64de2044e5b166a9883be6531166cd69900.tar.xz
Merge zizzer.eecs.umich.edu:/bk/newmem
into ahchoo.blinky.homelinux.org:/home/gblack/m5/newmem-x86 --HG-- extra : convert_revision : b585cea2221377eb2fceea8976c46a17c0034f51
Diffstat (limited to 'src')
-rw-r--r--src/SConscript7
-rw-r--r--src/arch/alpha/interrupts.hh12
-rw-r--r--src/arch/alpha/linux/linux.hh18
-rw-r--r--src/arch/alpha/tru64/tru64.hh18
-rw-r--r--src/arch/mips/linux/linux.hh18
-rw-r--r--src/arch/sparc/asi.cc3
-rw-r--r--src/arch/sparc/faults.cc4
-rw-r--r--src/arch/sparc/faults.hh2
-rw-r--r--src/arch/sparc/interrupts.hh163
-rw-r--r--src/arch/sparc/isa_traits.hh12
-rw-r--r--src/arch/sparc/linux/process.cc2
-rw-r--r--src/arch/sparc/miscregfile.cc17
-rw-r--r--src/arch/sparc/miscregfile.hh3
-rw-r--r--src/arch/sparc/process.cc48
-rw-r--r--src/arch/sparc/regfile.cc13
-rw-r--r--src/arch/sparc/regfile.hh2
-rw-r--r--src/arch/sparc/tlb.cc46
-rw-r--r--src/arch/sparc/ua2005.cc80
-rw-r--r--src/base/bitfield.hh25
-rw-r--r--src/base/stats/mysql.cc5
-rw-r--r--src/base/stats/mysql.hh10
-rw-r--r--src/cpu/base.cc11
-rw-r--r--src/cpu/base.hh2
-rw-r--r--src/cpu/intr_control.cc22
-rw-r--r--src/cpu/intr_control.hh4
-rw-r--r--src/dev/alpha/tsunami_cchip.cc12
-rw-r--r--src/dev/sparc/SConscript1
-rw-r--r--src/dev/sparc/iob.cc365
-rw-r--r--src/dev/sparc/iob.hh153
-rw-r--r--src/python/SConscript3
-rw-r--r--src/python/m5/SimObject.py6
-rw-r--r--src/python/m5/__init__.py95
-rw-r--r--src/python/m5/main.py4
-rw-r--r--src/python/m5/objects/IntrControl.py2
-rw-r--r--src/python/m5/objects/T1000.py20
-rw-r--r--src/python/m5/params.py5
-rw-r--r--src/python/m5/stats.py46
-rw-r--r--src/python/swig/core.i57
-rw-r--r--src/python/swig/event.i45
-rw-r--r--src/python/swig/pyevent.hh26
-rw-r--r--src/python/swig/pyobject.cc137
-rw-r--r--src/python/swig/pyobject.hh94
-rw-r--r--src/python/swig/sim_object.i101
-rw-r--r--src/python/swig/stats.i7
-rw-r--r--src/sim/async.cc38
-rw-r--r--src/sim/async.hh3
-rw-r--r--src/sim/core.cc76
-rw-r--r--src/sim/core.hh40
-rw-r--r--src/sim/main.cc354
-rw-r--r--src/sim/process.cc18
-rw-r--r--src/sim/process.hh24
-rw-r--r--src/sim/simulate.cc121
-rw-r--r--src/sim/simulate.hh35
-rw-r--r--src/sim/syscall_emul.cc33
-rw-r--r--src/sim/syscall_emul.hh20
55 files changed, 1831 insertions, 657 deletions
diff --git a/src/SConscript b/src/SConscript
index c93605ff7..9d7248213 100644
--- a/src/SConscript
+++ b/src/SConscript
@@ -131,15 +131,19 @@ base_sources = Split('''
mem/cache/cache_builder.cc
python/swig/init.cc
+ python/swig/core_wrap.cc
python/swig/debug_wrap.cc
- python/swig/main_wrap.cc
python/swig/event_wrap.cc
python/swig/random_wrap.cc
+ python/swig/sim_object_wrap.cc
python/swig/stats_wrap.cc
python/swig/trace_wrap.cc
python/swig/pyevent.cc
+ python/swig/pyobject.cc
+ sim/async.cc
sim/builder.cc
+ sim/core.cc
sim/debug.cc
sim/eventq.cc
sim/faults.cc
@@ -149,6 +153,7 @@ base_sources = Split('''
sim/serialize.cc
sim/sim_events.cc
sim/sim_object.cc
+ sim/simulate.cc
sim/startup.cc
sim/stat_control.cc
sim/system.cc
diff --git a/src/arch/alpha/interrupts.hh b/src/arch/alpha/interrupts.hh
index a522dec6c..0500714ad 100644
--- a/src/arch/alpha/interrupts.hh
+++ b/src/arch/alpha/interrupts.hh
@@ -34,6 +34,7 @@
#include "arch/alpha/faults.hh"
#include "arch/alpha/isa_traits.hh"
+#include "base/compiler.hh"
#include "cpu/thread_context.hh"
namespace AlphaISA
@@ -52,11 +53,6 @@ namespace AlphaISA
newInfoSet = false;
}
- void post(int int_type)
- {
- // sparc only
- }
-
void post(int int_num, int index)
{
DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index);
@@ -163,6 +159,12 @@ namespace AlphaISA
newInfoSet = false;
}
+ uint64_t get_vec(int int_num)
+ {
+ panic("Shouldn't be called for Alpha\n");
+ M5_DUMMY_RETURN
+ }
+
private:
bool newInfoSet;
int newIpl;
diff --git a/src/arch/alpha/linux/linux.hh b/src/arch/alpha/linux/linux.hh
index 09988bab2..84c04ebc3 100644
--- a/src/arch/alpha/linux/linux.hh
+++ b/src/arch/alpha/linux/linux.hh
@@ -96,15 +96,15 @@ class AlphaLinux : public Linux
//@{
/// ioctl() command codes.
- static const unsigned TIOCGETP = 0x40067408;
- static const unsigned TIOCSETP = 0x80067409;
- static const unsigned TIOCSETN = 0x8006740a;
- static const unsigned TIOCSETC = 0x80067411;
- static const unsigned TIOCGETC = 0x40067412;
- static const unsigned FIONREAD = 0x4004667f;
- static const unsigned TIOCISATTY = 0x2000745e;
- static const unsigned TIOCGETS = 0x402c7413;
- static const unsigned TIOCGETA = 0x40127417;
+ static const unsigned TIOCGETP_ = 0x40067408;
+ static const unsigned TIOCSETP_ = 0x80067409;
+ static const unsigned TIOCSETN_ = 0x8006740a;
+ static const unsigned TIOCSETC_ = 0x80067411;
+ static const unsigned TIOCGETC_ = 0x40067412;
+ static const unsigned FIONREAD_ = 0x4004667f;
+ static const unsigned TIOCISATTY_ = 0x2000745e;
+ static const unsigned TIOCGETS_ = 0x402c7413;
+ static const unsigned TIOCGETA_ = 0x40127417;
//@}
/// For table().
diff --git a/src/arch/alpha/tru64/tru64.hh b/src/arch/alpha/tru64/tru64.hh
index f0711b995..90e5f12dc 100644
--- a/src/arch/alpha/tru64/tru64.hh
+++ b/src/arch/alpha/tru64/tru64.hh
@@ -91,15 +91,15 @@ class AlphaTru64 : public Tru64
//@{
/// ioctl() command codes.
- static const unsigned TIOCGETP = 0x40067408;
- static const unsigned TIOCSETP = 0x80067409;
- static const unsigned TIOCSETN = 0x8006740a;
- static const unsigned TIOCSETC = 0x80067411;
- static const unsigned TIOCGETC = 0x40067412;
- static const unsigned FIONREAD = 0x4004667f;
- static const unsigned TIOCISATTY = 0x2000745e;
- static const unsigned TIOCGETS = 0x402c7413;
- static const unsigned TIOCGETA = 0x40127417;
+ static const unsigned TIOCGETP_ = 0x40067408;
+ static const unsigned TIOCSETP_ = 0x80067409;
+ static const unsigned TIOCSETN_ = 0x8006740a;
+ static const unsigned TIOCSETC_ = 0x80067411;
+ static const unsigned TIOCGETC_ = 0x40067412;
+ static const unsigned FIONREAD_ = 0x4004667f;
+ static const unsigned TIOCISATTY_ = 0x2000745e;
+ static const unsigned TIOCGETS_ = 0x402c7413;
+ static const unsigned TIOCGETA_ = 0x40127417;
//@}
//@{
diff --git a/src/arch/mips/linux/linux.hh b/src/arch/mips/linux/linux.hh
index f85935bb9..a20221e9b 100644
--- a/src/arch/mips/linux/linux.hh
+++ b/src/arch/mips/linux/linux.hh
@@ -91,15 +91,15 @@ class MipsLinux : public Linux
//@{
/// ioctl() command codes.
- static const unsigned TIOCGETP = 0x7408;
- static const unsigned TIOCSETP = 0x7409;
- static const unsigned TIOCSETN = 0x740a;
- static const unsigned TIOCSETC = 0x7411;
- static const unsigned TIOCGETC = 0x7412;
- static const unsigned FIONREAD = 0x467f;
- static const unsigned TIOCISATTY = 0x5480;
- static const unsigned TIOCGETS = 0x7413;
- static const unsigned TIOCGETA = 0x7417;
+ static const unsigned TIOCGETP_ = 0x7408;
+ static const unsigned TIOCSETP_ = 0x7409;
+ static const unsigned TIOCSETN_ = 0x740a;
+ static const unsigned TIOCSETC_ = 0x7411;
+ static const unsigned TIOCGETC_ = 0x7412;
+ static const unsigned FIONREAD_ = 0x467f;
+ static const unsigned TIOCISATTY_ = 0x5480;
+ static const unsigned TIOCGETS_ = 0x7413;
+ static const unsigned TIOCGETA_ = 0x7417;
//@}
/// For table().
diff --git a/src/arch/sparc/asi.cc b/src/arch/sparc/asi.cc
index 3d553955f..d8cd84af5 100644
--- a/src/arch/sparc/asi.cc
+++ b/src/arch/sparc/asi.cc
@@ -294,7 +294,8 @@ namespace SparcISA
bool AsiIsReg(ASI asi)
{
- return AsiIsMmu(asi) || AsiIsScratchPad(asi) | AsiIsSparcError(asi);
+ return AsiIsMmu(asi) || AsiIsScratchPad(asi) ||
+ AsiIsSparcError(asi) || AsiIsInterrupt(asi);
}
bool AsiIsSparcError(ASI asi)
diff --git a/src/arch/sparc/faults.cc b/src/arch/sparc/faults.cc
index 391dd7134..b1a6ae919 100644
--- a/src/arch/sparc/faults.cc
+++ b/src/arch/sparc/faults.cc
@@ -208,6 +208,10 @@ template<> SparcFaultBase::FaultVals
{"trap_level_zero", 0x05F, 202, {H, H, SH}};
template<> SparcFaultBase::FaultVals
+ SparcFault<InterruptVector>::vals =
+ {"interrupt_vector", 0x060, 2630, {H, H, H}};
+
+template<> SparcFaultBase::FaultVals
SparcFault<PAWatchpoint>::vals =
{"PA_watchpoint", 0x061, 1209, {H, H, H}};
diff --git a/src/arch/sparc/faults.hh b/src/arch/sparc/faults.hh
index 5facc081d..0ba897e67 100644
--- a/src/arch/sparc/faults.hh
+++ b/src/arch/sparc/faults.hh
@@ -193,6 +193,8 @@ class HstickMatch : public SparcFault<HstickMatch> {};
class TrapLevelZero : public SparcFault<TrapLevelZero> {};
+class InterruptVector : public SparcFault<InterruptVector> {};
+
class PAWatchpoint : public SparcFault<PAWatchpoint> {};
class VAWatchpoint : public SparcFault<VAWatchpoint> {};
diff --git a/src/arch/sparc/interrupts.hh b/src/arch/sparc/interrupts.hh
index dc3b235fe..3234002c5 100644
--- a/src/arch/sparc/interrupts.hh
+++ b/src/arch/sparc/interrupts.hh
@@ -24,76 +24,80 @@
* 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
+ * Lisa Hsu
*/
#ifndef __ARCH_SPARC_INTERRUPT_HH__
#define __ARCH_SPARC_INTERRUPT_HH__
#include "arch/sparc/faults.hh"
+#include "arch/sparc/isa_traits.hh"
#include "cpu/thread_context.hh"
namespace SparcISA
{
-enum interrupts_t {
- trap_level_zero,
- hstick_match,
- interrupt_vector,
- cpu_mondo,
- dev_mondo,
- resumable_error,
- soft_interrupt,
- num_interrupt_types
-};
-
class Interrupts
{
private:
- bool interrupts[num_interrupt_types];
- int numPosted;
+ uint64_t interrupts[NumInterruptTypes];
+ uint64_t intStatus;
public:
Interrupts()
{
- for (int i = 0; i < num_interrupt_types; ++i) {
- interrupts[i] = false;
- }
- numPosted = 0;
+ clear_all();
}
- void post(int int_type)
+ int InterruptLevel(uint64_t softint)
{
- if (int_type < 0 || int_type >= num_interrupt_types)
- panic("posting unknown interrupt!\n");
- if (interrupts[int_type] == false) {
- interrupts[int_type] = true;
- ++numPosted;
- }
+ if (softint & 0x10000 || softint & 0x1)
+ return 14;
+
+ int level = 15;
+ while (level > 0 && !(1 << level & softint))
+ level--;
+ if (1 << level & softint)
+ return level;
+ return 0;
}
void post(int int_num, int index)
{
+ DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index);
+ assert(int_num >= 0 && int_num < NumInterruptTypes);
+ assert(index >= 0 && index < 64);
+ interrupts[int_num] |= ULL(1) << index;
+ intStatus |= ULL(1) << int_num;
}
void clear(int int_num, int index)
{
+ DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index);
+ assert(int_num >= 0 && int_num < NumInterruptTypes);
+ assert(index >= 0 && index < 64);
+ interrupts[int_num] &= ~(ULL(1) << index);
+ if (!interrupts[int_num])
+ intStatus &= ~(ULL(1) << int_num);
}
void clear_all()
{
-
+ for (int i = 0; i < NumInterruptTypes; ++i) {
+ interrupts[i] = 0;
+ }
+ intStatus = 0;
}
bool check_interrupts(ThreadContext * tc) const
{
- if (numPosted)
- return true;
- else
- return false;
+ return intStatus;
}
Fault getInterrupt(ThreadContext * tc)
@@ -109,84 +113,45 @@ class Interrupts
// in the right order of processing
if (hpstate & HPSTATE::hpriv) {
if (ie) {
- if (interrupts[hstick_match]) {
- if (tc->readMiscReg(MISCREG_HINTP) & 1) {
- interrupts[hstick_match] = false;
- --numPosted;
- return new HstickMatch;
- }
- }
- if (interrupts[interrupt_vector]) {
- interrupts[interrupt_vector] = false;
- --numPosted;
- //HAVEN'T IMPLed THIS YET
- return NoFault;
+ if (interrupts[IT_HINTP]) {
+ // This will be cleaned by a HINTP write
+ return new HstickMatch;
}
- } else {
- if (interrupts[hstick_match]) {
- return NoFault;
+ if (interrupts[IT_INT_VEC]) {
+ // this will be cleared by an ASI read (or write)
+ return new InterruptVector;
}
-
}
} else {
- if (interrupts[trap_level_zero]) {
- if ((pstate & HPSTATE::tlz) && (tc->readMiscReg(MISCREG_TL) == 0)) {
- interrupts[trap_level_zero] = false;
- --numPosted;
+ if (interrupts[IT_TRAP_LEVEL_ZERO]) {
+ // this is cleared by deasserting HPSTATE::tlz
return new TrapLevelZero;
- }
}
- if (interrupts[hstick_match]) {
- if (tc->readMiscReg(MISCREG_HINTP) & 1) {
- interrupts[hstick_match] = false;
- --numPosted;
- return new HstickMatch;
- }
+ // HStick matches always happen in priv mode (ie doesn't matter)
+ if (interrupts[IT_HINTP]) {
+ return new HstickMatch;
+ }
+ if (interrupts[IT_INT_VEC]) {
+ // this will be cleared by an ASI read (or write)
+ return new InterruptVector;
}
if (ie) {
- if (interrupts[cpu_mondo]) {
- interrupts[cpu_mondo] = false;
- --numPosted;
+ if (interrupts[IT_CPU_MONDO]) {
return new CpuMondo;
}
- if (interrupts[dev_mondo]) {
- interrupts[dev_mondo] = false;
- --numPosted;
+ if (interrupts[IT_DEV_MONDO]) {
return new DevMondo;
}
- if (interrupts[soft_interrupt]) {
- int il = InterruptLevel(tc->readMiscReg(MISCREG_SOFTINT));
- // it seems that interrupt vectors are right in
- // the middle of interrupt levels with regard to
- // priority, so have to check
- if ((il < 6) &&
- interrupts[interrupt_vector]) {
- // may require more details here since there
- // may be lots of interrupts embedded in an
- // platform interrupt vector
- interrupts[interrupt_vector] = false;
- --numPosted;
- //HAVEN'T IMPLed YET
- return NoFault;
- } else {
- if (il > tc->readMiscReg(MISCREG_PIL)) {
- uint64_t si = tc->readMiscReg(MISCREG_SOFTINT);
- uint64_t more = si & ~(1 << (il + 1));
- if (!InterruptLevel(more)) {
- interrupts[soft_interrupt] = false;
- --numPosted;
- }
- return new InterruptLevelN(il);
- }
- }
+ if (interrupts[IT_SOFT_INT]) {
+ return new
+ InterruptLevelN(InterruptLevel(interrupts[IT_SOFT_INT]));
}
- if (interrupts[resumable_error]) {
- interrupts[resumable_error] = false;
- --numPosted;
+
+ if (interrupts[IT_RES_ERROR]) {
return new ResumableError;
}
- }
- }
+ } // !hpriv && ie
+ } // !hpriv
return NoFault;
}
@@ -195,16 +160,22 @@ class Interrupts
}
+ uint64_t get_vec(int int_num)
+ {
+ assert(int_num >= 0 && int_num < NumInterruptTypes);
+ return interrupts[int_num];
+ }
+
void serialize(std::ostream &os)
{
- SERIALIZE_ARRAY(interrupts,num_interrupt_types);
- SERIALIZE_SCALAR(numPosted);
+ SERIALIZE_ARRAY(interrupts,NumInterruptTypes);
+ SERIALIZE_SCALAR(intStatus);
}
void unserialize(Checkpoint *cp, const std::string &section)
{
- UNSERIALIZE_ARRAY(interrupts,num_interrupt_types);
- UNSERIALIZE_SCALAR(numPosted);
+ UNSERIALIZE_ARRAY(interrupts,NumInterruptTypes);
+ UNSERIALIZE_SCALAR(intStatus);
}
};
} // namespace SPARC_ISA
diff --git a/src/arch/sparc/isa_traits.hh b/src/arch/sparc/isa_traits.hh
index 1fbdd160d..d0b8827f3 100644
--- a/src/arch/sparc/isa_traits.hh
+++ b/src/arch/sparc/isa_traits.hh
@@ -113,6 +113,18 @@ namespace SparcISA
const Addr PAddrImplMask = ULL(0x000000FFFFFFFFFF);
const Addr BytesInPageMask = ULL(0x1FFF);
+ enum InterruptTypes
+ {
+ IT_TRAP_LEVEL_ZERO,
+ IT_HINTP,
+ IT_INT_VEC,
+ IT_CPU_MONDO,
+ IT_DEV_MONDO,
+ IT_RES_ERROR,
+ IT_SOFT_INT,
+ NumInterruptTypes
+ };
+
#endif
}
diff --git a/src/arch/sparc/linux/process.cc b/src/arch/sparc/linux/process.cc
index 9c7c0e643..10cde3af8 100644
--- a/src/arch/sparc/linux/process.cc
+++ b/src/arch/sparc/linux/process.cc
@@ -333,7 +333,7 @@ SyscallDesc SparcLinuxProcess::syscallDescs[] = {
/* 233 */ SyscallDesc("stime", unimplementedFunc),
/* 234 */ SyscallDesc("statfs64", unimplementedFunc),
/* 235 */ SyscallDesc("fstatfs64", unimplementedFunc),
- /* 236 */ SyscallDesc("_llseek", unimplementedFunc),
+ /* 236 */ SyscallDesc("_llseek", _llseekFunc),
/* 237 */ SyscallDesc("mlock", unimplementedFunc),
/* 238 */ SyscallDesc("munlock", unimplementedFunc),
/* 239 */ SyscallDesc("mlockall", unimplementedFunc),
diff --git a/src/arch/sparc/miscregfile.cc b/src/arch/sparc/miscregfile.cc
index 9a69d3374..849eed1cc 100644
--- a/src/arch/sparc/miscregfile.cc
+++ b/src/arch/sparc/miscregfile.cc
@@ -54,7 +54,15 @@ string SparcISA::getMiscRegName(RegIndex index)
"wstate",*/ "gl",
"hpstate", "htstate", "hintp", "htba", "hver", "strand_sts_reg",
"hstick_cmpr",
- "fsr"};
+ "fsr", "prictx", "secctx", "partId", "lsuCtrlReg", "itbTsbC0Ps0",
+ "itbTsbC0Ps1", "iTlbC0Cnfg", "itbTsbCXPs0", "itbTsbCXPs1",
+ "iTlbCXCnfg","iTlbSfsr", "iTlbTagAcs", "dtbTsbC0Ps0",
+ "dtbTsbC0Ps1", "dTlbC0Cnfg", "dtbTsbCXPs0", "dtbTsbCXPs1",
+ "dTlbCXCnfg","dTlbSfsr", "dTlbSfar", "dTlbTagAcs",
+ "scratch0", "scratch1", "scratch2", "scratch3", "scratch4",
+ "scratch5", "scratch6", "scratch7", "cpuMondoHead", "cpuMondoTail",
+ "devMondoHead", "devMondoTail", "resErrorHead", "resErrorTail",
+ "nresErrorHead", "nresErrorTail", "TlbData" };
return miscRegName[index];
}
@@ -608,7 +616,6 @@ void MiscRegFile::setReg(int miscReg, const MiscReg &val)
case MISCREG_QUEUE_NRES_ERROR_TAIL:
nres_error_tail = val;
break;
-
default:
panic("Miscellaneous register %d not implemented\n", miscReg);
}
@@ -639,6 +646,12 @@ void MiscRegFile::setRegWithEffect(int miscReg,
return;
case MISCREG_TL:
tl = val;
+#if FULL_SYSTEM
+ if (hpstate & HPSTATE::tlz && tl == 0 && !(hpstate & HPSTATE::hpriv))
+ tc->getCpuPtr()->post_interrupt(IT_TRAP_LEVEL_ZERO,0);
+ else
+ tc->getCpuPtr()->clear_interrupt(IT_TRAP_LEVEL_ZERO,0);
+#endif
return;
case MISCREG_CWP:
new_val = val > NWindows ? NWindows - 1 : val;
diff --git a/src/arch/sparc/miscregfile.hh b/src/arch/sparc/miscregfile.hh
index 66c9f17df..4207de823 100644
--- a/src/arch/sparc/miscregfile.hh
+++ b/src/arch/sparc/miscregfile.hh
@@ -259,6 +259,9 @@ namespace SparcISA
ThreadContext *tc);
MiscReg readFSRegWithEffect(int miscReg, ThreadContext * tc);
+ // Update interrupt state on softint or pil change
+ void checkSoftInt(ThreadContext *tc);
+
/** Process a tick compare event and generate an interrupt on the cpu if
* appropriate. */
void processTickCompare(ThreadContext *tc);
diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc
index d5a95e0c0..c3b833562 100644
--- a/src/arch/sparc/process.cc
+++ b/src/arch/sparc/process.cc
@@ -425,7 +425,9 @@ Sparc32LiveProcess::argsInit(int intSize, int pageSize)
else
filename = argv[0];
- Addr alignmentMask = ~(intSize - 1);
+ //Even though this is a 32 bit process, the ABI says we still need to
+ //maintain double word alignment of the stack pointer.
+ Addr alignmentMask = ~(8 - 1);
// load object file into target memory
objFile->loadSections(initVirtMem);
@@ -525,21 +527,11 @@ Sparc32LiveProcess::argsInit(int intSize, int pageSize)
arg_data_size += argv[i].size() + 1;
}
- //The info_block needs to be padded so it's size is a multiple of the
- //alignment mask. Also, it appears that there needs to be at least some
- //padding, so if the size is already a multiple, we need to increase it
- //anyway.
+ //The info_block
int info_block_size =
(file_name_size +
env_data_size +
- arg_data_size +
- intSize) & alignmentMask;
-
- int info_block_padding =
- info_block_size -
- file_name_size -
- env_data_size -
- arg_data_size;
+ arg_data_size);
//Each auxilliary vector is two 8 byte words
int aux_array_size = intSize * 2 * (auxv.size() + 1);
@@ -552,7 +544,6 @@ Sparc32LiveProcess::argsInit(int intSize, int pageSize)
int space_needed =
mysterious_size +
- info_block_size +
aux_array_size +
envp_array_size +
argv_array_size +
@@ -568,18 +559,17 @@ Sparc32LiveProcess::argsInit(int intSize, int pageSize)
roundUp(stack_size, pageSize));
// map out initial stack contents
- Addr mysterious_base = stack_base - mysterious_size;
- Addr file_name_base = mysterious_base - file_name_size;
- Addr env_data_base = file_name_base - env_data_size;
- Addr arg_data_base = env_data_base - arg_data_size;
- Addr auxv_array_base = arg_data_base - aux_array_size - info_block_padding;
- Addr envp_array_base = auxv_array_base - envp_array_size;
- Addr argv_array_base = envp_array_base - argv_array_size;
- Addr argc_base = argv_array_base - argc_size;
-#ifndef NDEBUG
- // only used in DPRINTF
- Addr window_save_base = argc_base - window_save_size;
-#endif
+ uint32_t window_save_base = stack_min;
+ uint32_t argc_base = window_save_base + window_save_size;
+ uint32_t argv_array_base = argc_base + argc_size;
+ uint32_t envp_array_base = argv_array_base + argv_array_size;
+ uint32_t auxv_array_base = envp_array_base + envp_array_size;
+ //The info block is pushed up against the top of the stack, while
+ //the rest of the initial stack frame is aligned to an 8 byte boudary.
+ uint32_t arg_data_base = stack_base - info_block_size;
+ uint32_t env_data_base = arg_data_base + arg_data_size;
+ uint32_t file_name_base = env_data_base + env_data_size;
+ uint32_t mysterious_base = file_name_base + file_name_size;
DPRINTF(Sparc, "The addresses of items on the initial stack:\n");
DPRINTF(Sparc, "0x%x - file name\n", file_name_base);
@@ -619,8 +609,8 @@ Sparc32LiveProcess::argsInit(int intSize, int pageSize)
initVirtMem->writeBlob(auxv_array_base + 2 * intSize * auxv.size(),
(uint8_t*)&zero, 2 * intSize);
- copyStringArray(envp, envp_array_base, env_data_base, initVirtMem, intSize);
- copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem, intSize);
+ copyStringArray(envp, envp_array_base, env_data_base, initVirtMem);
+ copyStringArray(argv, argv_array_base, arg_data_base, initVirtMem);
initVirtMem->writeBlob(argc_base, (uint8_t*)&guestArgc, intSize);
@@ -639,7 +629,7 @@ Sparc32LiveProcess::argsInit(int intSize, int pageSize)
threadContexts[0]->setIntReg(ArgumentReg1, argv_array_base);
threadContexts[0]->setIntReg(StackPointerReg, stack_min);
- Addr prog_entry = objFile->entryPoint();
+ uint32_t prog_entry = objFile->entryPoint();
threadContexts[0]->setPC(prog_entry);
threadContexts[0]->setNextPC(prog_entry + sizeof(MachInst));
threadContexts[0]->setNextNPC(prog_entry + (2 * sizeof(MachInst)));
diff --git a/src/arch/sparc/regfile.cc b/src/arch/sparc/regfile.cc
index 827e22c31..944b1f401 100644
--- a/src/arch/sparc/regfile.cc
+++ b/src/arch/sparc/regfile.cc
@@ -254,19 +254,6 @@ void RegFile::changeContext(RegContextParam param, RegContextVal val)
}
}
-int SparcISA::InterruptLevel(uint64_t softint)
-{
- if (softint & 0x10000 || softint & 0x1)
- return 14;
-
- int level = 15;
- while (level > 0 && !(1 << level & softint))
- level--;
- if (1 << level & softint)
- return level;
- return 0;
-}
-
void SparcISA::copyMiscRegs(ThreadContext *src, ThreadContext *dest)
{
diff --git a/src/arch/sparc/regfile.hh b/src/arch/sparc/regfile.hh
index d9af0757c..9e0b3beb3 100644
--- a/src/arch/sparc/regfile.hh
+++ b/src/arch/sparc/regfile.hh
@@ -126,8 +126,6 @@ namespace SparcISA
void copyMiscRegs(ThreadContext *src, ThreadContext *dest);
- int InterruptLevel(uint64_t softint);
-
} // namespace SparcISA
#endif
diff --git a/src/arch/sparc/tlb.cc b/src/arch/sparc/tlb.cc
index 2dca6d5e7..41d55158e 100644
--- a/src/arch/sparc/tlb.cc
+++ b/src/arch/sparc/tlb.cc
@@ -40,6 +40,7 @@
#include "mem/packet_access.hh"
#include "mem/request.hh"
#include "sim/builder.hh"
+#include "sim/system.hh"
/* @todo remove some of the magic constants. -- ali
* */
@@ -691,9 +692,9 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
if (AsiIsPartialStore(asi))
panic("Partial Store ASIs not supported\n");
- if (AsiIsInterrupt(asi))
- panic("Interrupt ASIs not supported\n");
+ if (AsiIsInterrupt(asi))
+ goto handleIntRegAccess;
if (AsiIsMmu(asi))
goto handleMmuRegAccess;
if (AsiIsScratchPad(asi))
@@ -793,7 +794,25 @@ DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
vaddr & e->pte.size()-1);
DPRINTF(TLB, "TLB: %#X -> %#X\n", vaddr, req->getPaddr());
return NoFault;
+
/** Normal flow ends here. */
+handleIntRegAccess:
+ if (!hpriv) {
+ writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi);
+ if (priv)
+ return new DataAccessException;
+ else
+ return new PrivilegedAction;
+ }
+
+ if (asi == ASI_SWVR_UDB_INTR_W && !write ||
+ asi == ASI_SWVR_UDB_INTR_R && write) {
+ writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi);
+ return new DataAccessException;
+ }
+
+ goto regAccessOk;
+
handleScratchRegAccess:
if (vaddr > 0x38 || (vaddr >= 0x20 && vaddr < 0x30 && !hpriv)) {
@@ -988,7 +1007,14 @@ DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt)
tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS1),
tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG)));
break;
-
+ case ASI_SWVR_INTR_RECEIVE:
+ pkt->set(tc->getCpuPtr()->get_interrupts(IT_INT_VEC));
+ break;
+ case ASI_SWVR_UDB_INTR_R:
+ temp = findMsbSet(tc->getCpuPtr()->get_interrupts(IT_INT_VEC));
+ tc->getCpuPtr()->clear_interrupt(IT_INT_VEC, temp);
+ pkt->set(temp);
+ break;
default:
doMmuReadError:
panic("need to impl DTB::doMmuRegRead() got asi=%#x, va=%#x\n",
@@ -1222,7 +1248,19 @@ DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt)
panic("Invalid type for IMMU demap\n");
}
break;
- default:
+ case ASI_SWVR_INTR_RECEIVE:
+ int msb;
+ // clear all the interrupts that aren't set in the write
+ while(tc->getCpuPtr()->get_interrupts(IT_INT_VEC) & data) {
+ msb = findMsbSet(tc->getCpuPtr()->get_interrupts(IT_INT_VEC) & data);
+ tc->getCpuPtr()->clear_interrupt(IT_INT_VEC, msb);
+ }
+ break;
+ case ASI_SWVR_UDB_INTR_W:
+ tc->getSystemPtr()->threadContexts[bits(data,12,8)]->getCpuPtr()->
+ post_interrupt(bits(data,5,0),0);
+ break;
+ default:
doMmuWriteError:
panic("need to impl DTB::doMmuRegWrite() got asi=%#x, va=%#x d=%#x\n",
(uint32_t)pkt->req->getAsi(), pkt->getAddr(), data);
diff --git a/src/arch/sparc/ua2005.cc b/src/arch/sparc/ua2005.cc
index ecb63bb9a..5b13cd041 100644
--- a/src/arch/sparc/ua2005.cc
+++ b/src/arch/sparc/ua2005.cc
@@ -34,6 +34,30 @@
using namespace SparcISA;
+
+void
+MiscRegFile::checkSoftInt(ThreadContext *tc)
+{
+ // If PIL < 14, copy over the tm and sm bits
+ if (pil < 14 && softint & 0x10000)
+ tc->getCpuPtr()->post_interrupt(IT_SOFT_INT,16);
+ else
+ tc->getCpuPtr()->clear_interrupt(IT_SOFT_INT,16);
+ if (pil < 14 && softint & 0x1)
+ tc->getCpuPtr()->post_interrupt(IT_SOFT_INT,0);
+ else
+ tc->getCpuPtr()->clear_interrupt(IT_SOFT_INT,0);
+
+ // Copy over any of the other bits that are set
+ for (int bit = 15; bit > 0; --bit) {
+ if (1 << bit & softint && bit > pil)
+ tc->getCpuPtr()->post_interrupt(IT_SOFT_INT,bit);
+ else
+ tc->getCpuPtr()->clear_interrupt(IT_SOFT_INT,bit);
+ }
+}
+
+
void
MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val,
ThreadContext *tc)
@@ -43,23 +67,25 @@ MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val,
/* Full system only ASRs */
case MISCREG_SOFTINT:
setReg(miscReg, val);;
+ checkSoftInt(tc);
break;
-
case MISCREG_SOFTINT_CLR:
return setRegWithEffect(MISCREG_SOFTINT, ~val & softint, tc);
case MISCREG_SOFTINT_SET:
- tc->getCpuPtr()->post_interrupt(soft_interrupt);
return setRegWithEffect(MISCREG_SOFTINT, val | softint, tc);
case MISCREG_TICK_CMPR:
if (tickCompare == NULL)
tickCompare = new TickCompareEvent(this, tc);
setReg(miscReg, val);
- if ((tick_cmpr & mask(63)) && tickCompare->scheduled())
+ if ((tick_cmpr & ~mask(63)) && tickCompare->scheduled())
tickCompare->deschedule();
time = (tick_cmpr & mask(63)) - (tick & mask(63));
- if (!(tick_cmpr & ~mask(63)) && time > 0)
+ if (!(tick_cmpr & ~mask(63)) && time > 0) {
+ if (tickCompare->scheduled())
+ tickCompare->deschedule();
tickCompare->schedule(time * tc->getCpuPtr()->cycles(1));
+ }
panic("writing to TICK compare register %#X\n", val);
break;
@@ -71,8 +97,11 @@ MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val,
sTickCompare->deschedule();
time = ((int64_t)(stick_cmpr & mask(63)) - (int64_t)stick) -
tc->getCpuPtr()->instCount();
- if (!(stick_cmpr & ~mask(63)) && time > 0)
+ if (!(stick_cmpr & ~mask(63)) && time > 0) {
+ if (sTickCompare->scheduled())
+ sTickCompare->deschedule();
sTickCompare->schedule(time * tc->getCpuPtr()->cycles(1) + curTick);
+ }
DPRINTF(Timer, "writing to sTICK compare register value %#X\n", val);
break;
@@ -81,6 +110,7 @@ MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val,
case MISCREG_PIL:
setReg(miscReg, val);
+ checkSoftInt(tc);
break;
case MISCREG_HVER:
@@ -88,6 +118,11 @@ MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val,
case MISCREG_HINTP:
setReg(miscReg, val);
+ if (hintp)
+ tc->getCpuPtr()->post_interrupt(IT_HINTP,0);
+ else
+ tc->getCpuPtr()->clear_interrupt(IT_HINTP,0);
+ break;
case MISCREG_HTBA:
// clear lower 7 bits on writes.
@@ -96,14 +131,32 @@ MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val,
case MISCREG_QUEUE_CPU_MONDO_HEAD:
case MISCREG_QUEUE_CPU_MONDO_TAIL:
+ setReg(miscReg, val);
+ if (cpu_mondo_head != cpu_mondo_tail)
+ tc->getCpuPtr()->post_interrupt(IT_CPU_MONDO,0);
+ else
+ tc->getCpuPtr()->clear_interrupt(IT_CPU_MONDO,0);
+ break;
case MISCREG_QUEUE_DEV_MONDO_HEAD:
case MISCREG_QUEUE_DEV_MONDO_TAIL:
+ setReg(miscReg, val);
+ if (dev_mondo_head != dev_mondo_tail)
+ tc->getCpuPtr()->post_interrupt(IT_DEV_MONDO,0);
+ else
+ tc->getCpuPtr()->clear_interrupt(IT_DEV_MONDO,0);
+ break;
case MISCREG_QUEUE_RES_ERROR_HEAD:
case MISCREG_QUEUE_RES_ERROR_TAIL:
+ setReg(miscReg, val);
+ if (res_error_head != res_error_tail)
+ tc->getCpuPtr()->post_interrupt(IT_RES_ERROR,0);
+ else
+ tc->getCpuPtr()->clear_interrupt(IT_RES_ERROR,0);
+ break;
case MISCREG_QUEUE_NRES_ERROR_HEAD:
case MISCREG_QUEUE_NRES_ERROR_TAIL:
setReg(miscReg, val);
- //do something to post mondo interrupt
+ // This one doesn't have an interrupt to report to the guest OS
break;
case MISCREG_HSTICK_CMPR:
@@ -114,14 +167,23 @@ MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val,
hSTickCompare->deschedule();
time = ((int64_t)(hstick_cmpr & mask(63)) - (int64_t)stick) -
tc->getCpuPtr()->instCount();
- if (!(hstick_cmpr & ~mask(63)) && time > 0)
+ if (!(hstick_cmpr & ~mask(63)) && time > 0) {
+ if (hSTickCompare->scheduled())
+ hSTickCompare->deschedule();
hSTickCompare->schedule(curTick + time * tc->getCpuPtr()->cycles(1));
+ }
DPRINTF(Timer, "writing to hsTICK compare register value %#X\n", val);
break;
case MISCREG_HPSTATE:
// T1000 spec says impl. dependent val must always be 1
setReg(miscReg, val | HPSTATE::id);
+#if FULL_SYSTEM
+ if (hpstate & HPSTATE::tlz && tl == 0 && !(hpstate & HPSTATE::hpriv))
+ tc->getCpuPtr()->post_interrupt(IT_TRAP_LEVEL_ZERO,0);
+ else
+ tc->getCpuPtr()->clear_interrupt(IT_TRAP_LEVEL_ZERO,0);
+#endif
break;
case MISCREG_HTSTATE:
case MISCREG_STRAND_STS_REG:
@@ -198,7 +260,6 @@ MiscRegFile::processSTickCompare(ThreadContext *tc)
DPRINTF(Timer, "STick compare cycle reached at %#x\n",
(stick_cmpr & mask(63)));
if (!(tc->readMiscReg(MISCREG_STICK_CMPR) & (ULL(1) << 63))) {
- tc->getCpuPtr()->post_interrupt(soft_interrupt);
setRegWithEffect(MISCREG_SOFTINT, softint | (ULL(1) << 16), tc);
}
} else
@@ -221,10 +282,9 @@ MiscRegFile::processHSTickCompare(ThreadContext *tc)
(stick_cmpr & mask(63)));
if (!(tc->readMiscReg(MISCREG_HSTICK_CMPR) & (ULL(1) << 63))) {
setRegWithEffect(MISCREG_HINTP, 1, tc);
- tc->getCpuPtr()->post_interrupt(hstick_match);
}
// Need to do something to cause interrupt to happen here !!! @todo
} else
- sTickCompare->schedule(ticks * tc->getCpuPtr()->cycles(1) + curTick);
+ hSTickCompare->schedule(ticks * tc->getCpuPtr()->cycles(1) + curTick);
}
diff --git a/src/base/bitfield.hh b/src/base/bitfield.hh
index 0f1233677..83b9138b4 100644
--- a/src/base/bitfield.hh
+++ b/src/base/bitfield.hh
@@ -112,4 +112,29 @@ replaceBits(T& val, int first, int last, B bit_val)
val = insertBits(val, first, last, 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;
+}
+
+
+
#endif // __BASE_BITFIELD_HH__
diff --git a/src/base/stats/mysql.cc b/src/base/stats/mysql.cc
index d4035986b..39a687fff 100644
--- a/src/base/stats/mysql.cc
+++ b/src/base/stats/mysql.cc
@@ -930,7 +930,7 @@ MySql::visit(const FormulaData &data)
bool
initMySQL(string host, string user, string password, string database,
- string name, string sample, string project)
+ string project, string name, string sample)
{
extern list<Output *> OutputList;
static MySql mysql;
@@ -938,9 +938,6 @@ initMySQL(string host, string user, string password, string database,
if (mysql.connected())
return false;
- if (user.empty())
- user = username();
-
mysql.connect(host, user, password, database, name, sample, project);
OutputList.push_back(&mysql);
diff --git a/src/base/stats/mysql.hh b/src/base/stats/mysql.hh
index 52f93ac61..0ce381c2f 100644
--- a/src/base/stats/mysql.hh
+++ b/src/base/stats/mysql.hh
@@ -187,15 +187,15 @@ class MySql : public Output
void configure(const FormulaData &data);
};
-bool initMySQL(std::string host, std::string database, std::string user = "",
- std::string passwd = "", std::string name = "test",
- std::string sample = "0", std::string project = "test");
+bool initMySQL(std::string host, std::string database, std::string user,
+ std::string passwd, std::string project, std::string name,
+ std::string sample);
#if !USE_MYSQL
inline bool
initMySQL(std::string host, std::string user, std::string password,
- std::string database, std::string name, std::string sample,
- std::string project)
+ std::string database, std::string project, std::string name,
+ std::string sample)
{
return false;
}
diff --git a/src/cpu/base.cc b/src/cpu/base.cc
index d5a023c59..104b3b6bb 100644
--- a/src/cpu/base.cc
+++ b/src/cpu/base.cc
@@ -372,12 +372,6 @@ BaseCPU::ProfileEvent::process()
}
void
-BaseCPU::post_interrupt(int int_type)
-{
- interrupts.post(int_type);
-}
-
-void
BaseCPU::post_interrupt(int int_num, int index)
{
interrupts.post(int_num, index);
@@ -395,6 +389,11 @@ BaseCPU::clear_interrupts()
interrupts.clear_all();
}
+uint64_t
+BaseCPU::get_interrupts(int int_num)
+{
+ return interrupts.get_vec(int_num);
+}
void
BaseCPU::serialize(std::ostream &os)
diff --git a/src/cpu/base.hh b/src/cpu/base.hh
index a1265b748..d4213887d 100644
--- a/src/cpu/base.hh
+++ b/src/cpu/base.hh
@@ -102,10 +102,10 @@ class BaseCPU : public MemObject
TheISA::Interrupts interrupts;
public:
- virtual void post_interrupt(int int_type);
virtual void post_interrupt(int int_num, int index);
virtual void clear_interrupt(int int_num, int index);
virtual void clear_interrupts();
+ virtual uint64_t get_interrupts(int int_num);
bool check_interrupts(ThreadContext * tc) const
{ return interrupts.check_interrupts(tc); }
diff --git a/src/cpu/intr_control.cc b/src/cpu/intr_control.cc
index 4cbc86891..be0f6599b 100644
--- a/src/cpu/intr_control.cc
+++ b/src/cpu/intr_control.cc
@@ -40,18 +40,14 @@
using namespace std;
-IntrControl::IntrControl(const string &name, BaseCPU *c)
- : SimObject(name), cpu(c)
+IntrControl::IntrControl(const string &name, System *s)
+ : SimObject(name), sys(s)
{}
-/* @todo
- *Fix the cpu sim object parameter to be a system pointer
- *instead, to avoid some extra dereferencing
- */
void
IntrControl::post(int int_num, int index)
{
- std::vector<ThreadContext *> &tcvec = cpu->system->threadContexts;
+ std::vector<ThreadContext *> &tcvec = sys->threadContexts;
BaseCPU *temp = tcvec[0]->getCpuPtr();
temp->post_interrupt(int_num, index);
}
@@ -59,7 +55,7 @@ IntrControl::post(int int_num, int index)
void
IntrControl::post(int cpu_id, int int_num, int index)
{
- std::vector<ThreadContext *> &tcvec = cpu->system->threadContexts;
+ std::vector<ThreadContext *> &tcvec = sys->threadContexts;
BaseCPU *temp = tcvec[cpu_id]->getCpuPtr();
temp->post_interrupt(int_num, index);
}
@@ -67,7 +63,7 @@ IntrControl::post(int cpu_id, int int_num, int index)
void
IntrControl::clear(int int_num, int index)
{
- std::vector<ThreadContext *> &tcvec = cpu->system->threadContexts;
+ std::vector<ThreadContext *> &tcvec = sys->threadContexts;
BaseCPU *temp = tcvec[0]->getCpuPtr();
temp->clear_interrupt(int_num, index);
}
@@ -75,26 +71,26 @@ IntrControl::clear(int int_num, int index)
void
IntrControl::clear(int cpu_id, int int_num, int index)
{
- std::vector<ThreadContext *> &tcvec = cpu->system->threadContexts;
+ std::vector<ThreadContext *> &tcvec = sys->threadContexts;
BaseCPU *temp = tcvec[cpu_id]->getCpuPtr();
temp->clear_interrupt(int_num, index);
}
BEGIN_DECLARE_SIM_OBJECT_PARAMS(IntrControl)
- SimObjectParam<BaseCPU *> cpu;
+ SimObjectParam<System *> sys;
END_DECLARE_SIM_OBJECT_PARAMS(IntrControl)
BEGIN_INIT_SIM_OBJECT_PARAMS(IntrControl)
- INIT_PARAM(cpu, "the cpu")
+ INIT_PARAM(sys, "the system we are part of")
END_INIT_SIM_OBJECT_PARAMS(IntrControl)
CREATE_SIM_OBJECT(IntrControl)
{
- return new IntrControl(getInstanceName(), cpu);
+ return new IntrControl(getInstanceName(), sys);
}
REGISTER_SIM_OBJECT("IntrControl", IntrControl)
diff --git a/src/cpu/intr_control.hh b/src/cpu/intr_control.hh
index 2e3f9e038..c6f75abf0 100644
--- a/src/cpu/intr_control.hh
+++ b/src/cpu/intr_control.hh
@@ -42,8 +42,8 @@
class IntrControl : public SimObject
{
public:
- BaseCPU *cpu;
- IntrControl(const std::string &name, BaseCPU *c);
+ System *sys;
+ IntrControl(const std::string &name, System *s);
void clear(int int_num, int index = 0);
void post(int int_num, int index = 0);
diff --git a/src/dev/alpha/tsunami_cchip.cc b/src/dev/alpha/tsunami_cchip.cc
index 15c47984b..118160adf 100644
--- a/src/dev/alpha/tsunami_cchip.cc
+++ b/src/dev/alpha/tsunami_cchip.cc
@@ -372,7 +372,7 @@ TsunamiCChip::write(PacketPtr pkt)
void
TsunamiCChip::clearIPI(uint64_t ipintr)
{
- int numcpus = tsunami->intrctrl->cpu->system->threadContexts.size();
+ int numcpus = sys->threadContexts.size();
assert(numcpus <= Tsunami::Max_CPUs);
if (ipintr) {
@@ -398,7 +398,7 @@ TsunamiCChip::clearIPI(uint64_t ipintr)
void
TsunamiCChip::clearITI(uint64_t itintr)
{
- int numcpus = tsunami->intrctrl->cpu->system->threadContexts.size();
+ int numcpus = sys->threadContexts.size();
assert(numcpus <= Tsunami::Max_CPUs);
if (itintr) {
@@ -418,7 +418,7 @@ TsunamiCChip::clearITI(uint64_t itintr)
void
TsunamiCChip::reqIPI(uint64_t ipreq)
{
- int numcpus = tsunami->intrctrl->cpu->system->threadContexts.size();
+ int numcpus = sys->threadContexts.size();
assert(numcpus <= Tsunami::Max_CPUs);
if (ipreq) {
@@ -445,7 +445,7 @@ TsunamiCChip::reqIPI(uint64_t ipreq)
void
TsunamiCChip::postRTC()
{
- int size = tsunami->intrctrl->cpu->system->threadContexts.size();
+ int size = sys->threadContexts.size();
assert(size <= Tsunami::Max_CPUs);
for (int i = 0; i < size; i++) {
@@ -463,7 +463,7 @@ void
TsunamiCChip::postDRIR(uint32_t interrupt)
{
uint64_t bitvector = ULL(1) << interrupt;
- uint64_t size = tsunami->intrctrl->cpu->system->threadContexts.size();
+ uint64_t size = sys->threadContexts.size();
assert(size <= Tsunami::Max_CPUs);
drir |= bitvector;
@@ -481,7 +481,7 @@ void
TsunamiCChip::clearDRIR(uint32_t interrupt)
{
uint64_t bitvector = ULL(1) << interrupt;
- uint64_t size = tsunami->intrctrl->cpu->system->threadContexts.size();
+ uint64_t size = sys->threadContexts.size();
assert(size <= Tsunami::Max_CPUs);
if (drir & bitvector)
diff --git a/src/dev/sparc/SConscript b/src/dev/sparc/SConscript
index 44b082b68..4d63690c2 100644
--- a/src/dev/sparc/SConscript
+++ b/src/dev/sparc/SConscript
@@ -38,6 +38,7 @@ sources = []
sources += Split('''
dtod.cc
+ iob.cc
t1000.cc
mm_disk.cc
''')
diff --git a/src/dev/sparc/iob.cc b/src/dev/sparc/iob.cc
new file mode 100644
index 000000000..2cff02a99
--- /dev/null
+++ b/src/dev/sparc/iob.cc
@@ -0,0 +1,365 @@
+/*
+ * 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
+ */
+
+/** @file
+ * This device implemetns the niagara I/O bridge chip. It manages incomming
+ * interrupts and posts them to the CPU when needed. It holds mask registers and
+ * various status registers for CPUs to check what interrupts are pending as
+ * well as facilities to send IPIs to other cpus.
+ */
+
+#include <cstring>
+
+#include "arch/sparc/isa_traits.hh"
+#include "base/trace.hh"
+#include "cpu/intr_control.hh"
+#include "dev/sparc/iob.hh"
+#include "dev/platform.hh"
+#include "mem/port.hh"
+#include "mem/packet_access.hh"
+#include "sim/builder.hh"
+#include "sim/system.hh"
+
+Iob::Iob(Params *p)
+ : PioDevice(p), ic(p->platform->intrctrl)
+{
+ iobManAddr = ULL(0x9800000000);
+ iobManSize = ULL(0x0100000000);
+ iobJBusAddr = ULL(0x9F00000000);
+ iobJBusSize = ULL(0x0100000000);
+ assert (params()->system->threadContexts.size() <= MaxNiagaraProcs);
+ // Get the interrupt controller from the platform
+ ic = platform->intrctrl;
+
+ for (int x = 0; x < NumDeviceIds; ++x) {
+ intMan[x].cpu = 0;
+ intMan[x].vector = 0;
+ intCtl[x].mask = true;
+ intCtl[x].pend = false;
+ }
+
+}
+
+Tick
+Iob::read(PacketPtr pkt)
+{
+ assert(pkt->result == Packet::Unknown);
+
+ if (pkt->getAddr() >= iobManAddr && pkt->getAddr() < iobManAddr + iobManSize)
+ readIob(pkt);
+ else if (pkt->getAddr() >= iobJBusAddr && pkt->getAddr() < iobJBusAddr+iobJBusSize)
+ readJBus(pkt);
+ else
+ panic("Invalid address reached Iob\n");
+
+ pkt->result = Packet::Success;
+ return pioDelay;
+}
+
+void
+Iob::readIob(PacketPtr pkt)
+{
+ Addr accessAddr = pkt->getAddr() - iobManAddr;
+ int index;
+ uint64_t data;
+
+ if (accessAddr >= IntManAddr && accessAddr < IntManAddr + IntManSize) {
+ index = (accessAddr - IntManAddr) >> 3;
+ data = intMan[index].cpu << 8 | intMan[index].vector << 0;
+ pkt->set(data);
+ return;
+ }
+
+ if (accessAddr >= IntCtlAddr && accessAddr < IntCtlAddr + IntCtlSize) {
+ index = (accessAddr - IntManAddr) >> 3;
+ data = intCtl[index].mask ? 1 << 2 : 0 |
+ intCtl[index].pend ? 1 << 0 : 0;
+ pkt->set(data);
+ return;
+ }
+
+ if (accessAddr == JIntVecAddr) {
+ pkt->set(jIntVec);
+ return;
+ }
+
+ panic("Read to unknown IOB offset 0x%x\n", accessAddr);
+}
+
+void
+Iob::readJBus(PacketPtr pkt)
+{
+ Addr accessAddr = pkt->getAddr() - iobJBusAddr;
+ int cpuid = pkt->req->getCpuNum();
+ int index;
+ uint64_t data;
+
+
+
+
+ if (accessAddr >= JIntData0Addr && accessAddr < JIntData1Addr) {
+ index = (accessAddr - JIntData0Addr) >> 3;
+ pkt->set(jBusData0[index]);
+ return;
+ }
+
+ if (accessAddr >= JIntData1Addr && accessAddr < JIntDataA0Addr) {
+ index = (accessAddr - JIntData1Addr) >> 3;
+ pkt->set(jBusData1[index]);
+ return;
+ }
+
+ if (accessAddr == JIntDataA0Addr) {
+ pkt->set(jBusData0[cpuid]);
+ return;
+ }
+
+ if (accessAddr == JIntDataA1Addr) {
+ pkt->set(jBusData1[cpuid]);
+ return;
+ }
+
+ if (accessAddr >= JIntBusyAddr && accessAddr < JIntBusyAddr + JIntBusySize) {
+ index = (accessAddr - JIntBusyAddr) >> 3;
+ data = jIntBusy[index].busy ? 1 << 5 : 0 |
+ jIntBusy[index].source;
+ pkt->set(data);
+ return;
+ }
+ if (accessAddr == JIntABusyAddr) {
+ data = jIntBusy[cpuid].busy ? 1 << 5 : 0 |
+ jIntBusy[cpuid].source;
+ pkt->set(data);
+ return;
+ };
+
+ panic("Read to unknown JBus offset 0x%x\n", accessAddr);
+}
+
+Tick
+Iob::write(PacketPtr pkt)
+{
+ if (pkt->getAddr() >= iobManAddr && pkt->getAddr() < iobManAddr + iobManSize)
+ writeIob(pkt);
+ else if (pkt->getAddr() >= iobJBusAddr && pkt->getAddr() < iobJBusAddr+iobJBusSize)
+ writeJBus(pkt);
+ else
+ panic("Invalid address reached Iob\n");
+
+
+ pkt->result = Packet::Success;
+ return pioDelay;
+}
+
+void
+Iob::writeIob(PacketPtr pkt)
+{
+ Addr accessAddr = pkt->getAddr() - iobManAddr;
+ int index;
+ uint64_t data;
+
+ if (accessAddr >= IntManAddr && accessAddr < IntManAddr + IntManSize) {
+ index = (accessAddr - IntManAddr) >> 3;
+ data = pkt->get<uint64_t>();
+ intMan[index].cpu = bits(data,12,8);
+ intMan[index].vector = bits(data,5,0);
+ return;
+ }
+
+ if (accessAddr >= IntCtlAddr && accessAddr < IntCtlAddr + IntCtlSize) {
+ index = (accessAddr - IntManAddr) >> 3;
+ data = pkt->get<uint64_t>();
+ intCtl[index].mask = bits(data,2,2);
+ if (bits(data,1,1))
+ intCtl[index].pend = false;
+ return;
+ }
+
+ if (accessAddr == JIntVecAddr) {
+ jIntVec = bits(pkt->get<uint64_t>(), 5,0);
+ return;
+ }
+
+ if (accessAddr >= IntVecDisAddr && accessAddr < IntVecDisAddr + IntVecDisSize) {
+ Type type;
+ int cpu_id;
+ int vector;
+ index = (accessAddr - IntManAddr) >> 3;
+ data = pkt->get<uint64_t>();
+ type = (Type)bits(data,17,16);
+ cpu_id = bits(data, 12,8);
+ vector = bits(data,5,0);
+ generateIpi(type,cpu_id, vector);
+ return;
+ }
+
+ panic("Write to unknown IOB offset 0x%x\n", accessAddr);
+}
+
+void
+Iob::writeJBus(PacketPtr pkt)
+{
+ Addr accessAddr = pkt->getAddr() - iobJBusAddr;
+ int cpuid = pkt->req->getCpuNum();
+ int index;
+ uint64_t data;
+
+ if (accessAddr >= JIntBusyAddr && accessAddr < JIntBusyAddr + JIntBusySize) {
+ index = (accessAddr - JIntBusyAddr) >> 3;
+ data = pkt->get<uint64_t>();
+ jIntBusy[index].busy = bits(data,5,5);
+ return;
+ }
+ if (accessAddr == JIntABusyAddr) {
+ data = pkt->get<uint64_t>();
+ jIntBusy[cpuid].busy = bits(data,5,5);
+ return;
+ };
+
+ panic("Write to unknown JBus offset 0x%x\n", accessAddr);
+}
+
+void
+Iob::receiveDeviceInterrupt(DeviceId devid)
+{
+ assert(devid < NumDeviceIds);
+ if (intCtl[devid].mask)
+ return;
+ intCtl[devid].mask = true;
+ intCtl[devid].pend = true;
+ ic->post(intMan[devid].cpu, SparcISA::IT_INT_VEC, intMan[devid].vector);
+}
+
+
+void
+Iob::generateIpi(Type type, int cpu_id, int vector)
+{
+ // Only handle interrupts for the moment... Cpu Idle/reset/resume will be
+ // later
+ if (type != 0)
+ return;
+
+ assert(type == 0);
+ ic->post(cpu_id, SparcISA::IT_INT_VEC, vector);
+}
+
+bool
+Iob::receiveJBusInterrupt(int cpu_id, int source, uint64_t d0, uint64_t d1)
+{
+ // If we are already dealing with an interrupt for that cpu we can't deal
+ // with another one right now... come back later
+ if (jIntBusy[cpu_id].busy)
+ return false;
+
+ jIntBusy[cpu_id].busy = true;
+ jIntBusy[cpu_id].source = source;
+ jBusData0[cpu_id] = d0;
+ jBusData1[cpu_id] = d1;
+
+ ic->post(cpu_id, SparcISA::IT_INT_VEC, jIntVec);
+ return true;
+}
+
+void
+Iob::addressRanges(AddrRangeList &range_list)
+{
+ range_list.clear();
+ range_list.push_back(RangeSize(iobManAddr, iobManSize));
+ range_list.push_back(RangeSize(iobJBusAddr, iobJBusSize));
+}
+
+
+void
+Iob::serialize(std::ostream &os)
+{
+
+ SERIALIZE_SCALAR(jIntVec);
+ SERIALIZE_ARRAY(jBusData0, MaxNiagaraProcs);
+ SERIALIZE_ARRAY(jBusData1, MaxNiagaraProcs);
+ for (int x = 0; x < NumDeviceIds; x++) {
+ nameOut(os, csprintf("%s.Int%d", name(), x));
+ paramOut(os, "cpu", intMan[x].cpu);
+ paramOut(os, "vector", intMan[x].vector);
+ paramOut(os, "mask", intCtl[x].mask);
+ paramOut(os, "pend", intCtl[x].pend);
+ };
+ for (int x = 0; x < MaxNiagaraProcs; x++) {
+ nameOut(os, csprintf("%s.jIntBusy%d", name(), x));
+ paramOut(os, "busy", jIntBusy[x].busy);
+ paramOut(os, "source", jIntBusy[x].source);
+ };
+}
+
+void
+Iob::unserialize(Checkpoint *cp, const std::string &section)
+{
+ UNSERIALIZE_SCALAR(jIntVec);
+ UNSERIALIZE_ARRAY(jBusData0, MaxNiagaraProcs);
+ UNSERIALIZE_ARRAY(jBusData1, MaxNiagaraProcs);
+ for (int x = 0; x < NumDeviceIds; x++) {
+ paramIn(cp, csprintf("%s.Int%d", name(), x), "cpu", intMan[x].cpu);
+ paramIn(cp, csprintf("%s.Int%d", name(), x), "vector", intMan[x].vector);
+ paramIn(cp, csprintf("%s.Int%d", name(), x), "mask", intCtl[x].mask);
+ paramIn(cp, csprintf("%s.Int%d", name(), x), "pend", intCtl[x].pend);
+ };
+ for (int x = 0; x < MaxNiagaraProcs; x++) {
+ paramIn(cp, csprintf("%s.jIntBusy%d", name(), x), "busy", jIntBusy[x].busy);
+ paramIn(cp, csprintf("%s.jIntBusy%d", name(), x), "source", jIntBusy[x].source);
+ };
+}
+
+
+
+
+BEGIN_DECLARE_SIM_OBJECT_PARAMS(Iob)
+ Param<Tick> pio_latency;
+ SimObjectParam<Platform *> platform;
+ SimObjectParam<System *> system;
+END_DECLARE_SIM_OBJECT_PARAMS(Iob)
+
+BEGIN_INIT_SIM_OBJECT_PARAMS(Iob)
+
+ INIT_PARAM(pio_latency, "Programmed IO latency"),
+ INIT_PARAM(platform, "platform"),
+ INIT_PARAM(system, "system object")
+
+END_INIT_SIM_OBJECT_PARAMS(Iob)
+
+CREATE_SIM_OBJECT(Iob)
+{
+ Iob::Params *p = new Iob::Params;
+ p->name = getInstanceName();
+ p->pio_delay = pio_latency;
+ p->platform = platform;
+ p->system = system;
+ return new Iob(p);
+}
+
+REGISTER_SIM_OBJECT("Iob", Iob)
diff --git a/src/dev/sparc/iob.hh b/src/dev/sparc/iob.hh
new file mode 100644
index 000000000..c05c4f2ef
--- /dev/null
+++ b/src/dev/sparc/iob.hh
@@ -0,0 +1,153 @@
+/*
+ * 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
+ */
+
+/** @file
+ * This device implements the niagara I/O Bridge chip. The device manages
+ * internal (ipi) and external (serial, pci via jbus).
+ */
+
+#ifndef __DEV_SPARC_IOB_HH__
+#define __DEV_SPARC_IOB_HH__
+
+#include "base/range.hh"
+#include "dev/io_device.hh"
+#include "dev/disk_image.hh"
+
+class IntrControl;
+
+const int MaxNiagaraProcs = 32;
+// IOB Managment Addresses
+const Addr IntManAddr = 0x0000;
+const Addr IntManSize = 0x0020;
+const Addr IntCtlAddr = 0x0400;
+const Addr IntCtlSize = 0x0020;
+const Addr JIntVecAddr = 0x0A00;
+const Addr IntVecDisAddr = 0x0800;
+const Addr IntVecDisSize = 0x0100;
+
+
+// IOB Control Addresses
+const Addr JIntData0Addr = 0x0400;
+const Addr JIntData1Addr = 0x0500;
+const Addr JIntDataA0Addr = 0x0600;
+const Addr JIntDataA1Addr = 0x0700;
+const Addr JIntBusyAddr = 0x0900;
+const Addr JIntBusySize = 0x0100;
+const Addr JIntABusyAddr = 0x0B00;
+
+
+// IOB Masks
+const uint64_t IntManMask = 0x01F3F;
+const uint64_t IntCtlMask = 0x00006;
+const uint64_t JIntVecMask = 0x0003F;
+const uint64_t IntVecDis = 0x31F3F;
+const uint64_t JIntBusyMask = 0x0003F;
+
+
+class Iob : public PioDevice
+{
+ private:
+ IntrControl *ic;
+ Addr iobManAddr;
+ Addr iobManSize;
+ Addr iobJBusAddr;
+ Addr iobJBusSize;
+ Tick pioDelay;
+
+ enum DeviceId {
+ Interal = 0,
+ Error = 1,
+ SSI = 2,
+ Reserved = 3,
+ NumDeviceIds
+ };
+
+ struct IntMan {
+ int cpu;
+ int vector;
+ };
+
+ struct IntCtl {
+ bool mask;
+ bool pend;
+ };
+
+ struct IntBusy {
+ bool busy;
+ int source;
+ };
+
+ enum Type {
+ Interrupt,
+ Reset,
+ Idle,
+ Resume
+ };
+
+ IntMan intMan[NumDeviceIds];
+ IntCtl intCtl[NumDeviceIds];
+ uint64_t jIntVec;
+ uint64_t jBusData0[MaxNiagaraProcs];
+ uint64_t jBusData1[MaxNiagaraProcs];
+ IntBusy jIntBusy[MaxNiagaraProcs];
+
+ void writeIob(PacketPtr pkt);
+ void writeJBus(PacketPtr pkt);
+ void readIob(PacketPtr pkt);
+ void readJBus(PacketPtr pkt);
+
+
+ public:
+ struct Params : public PioDevice::Params
+ {
+ Tick pio_delay;
+ };
+ protected:
+ const Params *params() const { return (const Params*)_params; }
+
+ public:
+ Iob(Params *p);
+
+ virtual Tick read(PacketPtr pkt);
+ virtual Tick write(PacketPtr pkt);
+ void generateIpi(Type type, int cpu_id, int vector);
+ void receiveDeviceInterrupt(DeviceId devid);
+ bool receiveJBusInterrupt(int cpu_id, int source, uint64_t d0, uint64_t d1);
+
+
+ void addressRanges(AddrRangeList &range_list);
+
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string &section);
+
+};
+
+#endif //__DEV_SPARC_IOB_HH__
+
diff --git a/src/python/SConscript b/src/python/SConscript
index 8c7e47909..94db1a747 100644
--- a/src/python/SConscript
+++ b/src/python/SConscript
@@ -107,10 +107,11 @@ def swig_it(module):
'-o ${TARGETS[0]} $SOURCES')
swig_modules.append(module)
-swig_it('main')
+swig_it('core')
swig_it('debug')
swig_it('event')
swig_it('random')
+swig_it('sim_object')
swig_it('stats')
swig_it('trace')
diff --git a/src/python/m5/SimObject.py b/src/python/m5/SimObject.py
index ba79d3729..42266a80e 100644
--- a/src/python/m5/SimObject.py
+++ b/src/python/m5/SimObject.py
@@ -693,7 +693,7 @@ class SimObject(object):
def getCCObject(self):
if not self._ccObject:
self._ccObject = -1 # flag to catch cycles in recursion
- self._ccObject = internal.main.createSimObject(self.path())
+ self._ccObject = internal.sim_object.createSimObject(self.path())
elif self._ccObject == -1:
raise RuntimeError, "%s: recursive call to getCCObject()" \
% self.path()
@@ -727,13 +727,13 @@ class SimObject(object):
# i don't know if there's a better way to do this - calling
# setMemoryMode directly from self._ccObject results in calling
# SimObject::setMemoryMode, not the System::setMemoryMode
- system_ptr = internal.main.convertToSystemPtr(self._ccObject)
+ system_ptr = internal.sim_object.convertToSystemPtr(self._ccObject)
system_ptr.setMemoryMode(mode)
for child in self._children.itervalues():
child.changeTiming(mode)
def takeOverFrom(self, old_cpu):
- cpu_ptr = internal.main.convertToBaseCPUPtr(old_cpu._ccObject)
+ cpu_ptr = internal.sim_object.convertToBaseCPUPtr(old_cpu._ccObject)
self._ccObject.takeOverFrom(cpu_ptr)
# generate output file for 'dot' to display as a pretty graph.
diff --git a/src/python/m5/__init__.py b/src/python/m5/__init__.py
index f39cc670a..1c4a79020 100644
--- a/src/python/m5/__init__.py
+++ b/src/python/m5/__init__.py
@@ -27,14 +27,16 @@
# Authors: Nathan Binkert
# Steve Reinhardt
-import atexit, os, sys
+import atexit
+import os
+import sys
# import the SWIG-wrapped main C++ functions
import internal
# import a few SWIG-wrapped items (those that are likely to be used
# directly by user scripts) completely into this module for
# convenience
-from internal.main import simulate, SimLoopExitEvent
+from internal.event import SimLoopExitEvent
# import the m5 compile options
import defines
@@ -85,27 +87,60 @@ def instantiate(root):
root.print_ini()
sys.stdout.close() # close config.ini
sys.stdout = sys.__stdout__ # restore to original
- internal.main.loadIniFile(resolveSimObject) # load config.ini into C++
+
+ # load config.ini into C++
+ internal.core.loadIniFile(resolveSimObject)
+
+ # Initialize the global statistics
+ internal.stats.initSimStats()
+
root.createCCObject()
root.connectPorts()
- internal.main.finalInit()
- noDot = True # temporary until we fix dot
- if not noDot:
- dot = pydot.Dot()
- instance.outputDot(dot)
- dot.orientation = "portrait"
- dot.size = "8.5,11"
- dot.ranksep="equally"
- dot.rank="samerank"
- dot.write("config.dot")
- dot.write_ps("config.ps")
+
+ # Do a second pass to finish initializing the sim objects
+ internal.sim_object.initAll()
+
+ # Do a third pass to initialize statistics
+ internal.sim_object.regAllStats()
+
+ # Check to make sure that the stats package is properly initialized
+ internal.stats.check()
+
+ # Reset to put the stats in a consistent state.
+ internal.stats.reset()
+
+def doDot(root):
+ dot = pydot.Dot()
+ instance.outputDot(dot)
+ dot.orientation = "portrait"
+ dot.size = "8.5,11"
+ dot.ranksep="equally"
+ dot.rank="samerank"
+ dot.write("config.dot")
+ dot.write_ps("config.ps")
+
+need_resume = []
+need_startup = True
+def simulate(*args, **kwargs):
+ global need_resume, need_startup
+
+ if need_startup:
+ internal.core.SimStartup()
+ need_startup = False
+
+ for root in need_resume:
+ resume(root)
+ need_resume = []
+
+ return internal.event.simulate(*args, **kwargs)
# Export curTick to user script.
def curTick():
- return internal.main.cvar.curTick
+ return internal.event.cvar.curTick
# register our C++ exit callback function with Python
-atexit.register(internal.main.doExitCleanup)
+atexit.register(internal.core.doExitCleanup)
+atexit.register(internal.stats.dump)
# This loops until all objects have been fully drained.
def doDrain(root):
@@ -119,7 +154,7 @@ def doDrain(root):
# be drained.
def drain(root):
all_drained = False
- drain_event = internal.main.createCountedDrain()
+ drain_event = internal.event.createCountedDrain()
unready_objects = root.startDrain(drain_event, True)
# If we've got some objects that can't drain immediately, then simulate
if unready_objects > 0:
@@ -127,7 +162,7 @@ def drain(root):
simulate()
else:
all_drained = True
- internal.main.cleanupCountedDrain(drain_event)
+ internal.event.cleanupCountedDrain(drain_event)
return all_drained
def resume(root):
@@ -135,16 +170,16 @@ def resume(root):
def checkpoint(root, dir):
if not isinstance(root, objects.Root):
- raise TypeError, "Object is not a root object. Checkpoint must be called on a root object."
+ raise TypeError, "Checkpoint must be called on a root object."
doDrain(root)
print "Writing checkpoint"
- internal.main.serializeAll(dir)
+ internal.sim_object.serializeAll(dir)
resume(root)
def restoreCheckpoint(root, dir):
print "Restoring from checkpoint"
- internal.main.unserializeAll(dir)
- resume(root)
+ internal.sim_object.unserializeAll(dir)
+ need_resume.append(root)
def changeToAtomic(system):
if not isinstance(system, objects.Root) and not isinstance(system, objects.System):
@@ -152,7 +187,7 @@ def changeToAtomic(system):
"called on a root object."
doDrain(system)
print "Changing memory mode to atomic"
- system.changeTiming(internal.main.SimObject.Atomic)
+ system.changeTiming(internal.sim_object.SimObject.Atomic)
def changeToTiming(system):
if not isinstance(system, objects.Root) and not isinstance(system, objects.System):
@@ -160,7 +195,7 @@ def changeToTiming(system):
"called on a root object."
doDrain(system)
print "Changing memory mode to timing"
- system.changeTiming(internal.main.SimObject.Timing)
+ system.changeTiming(internal.sim_object.SimObject.Timing)
def switchCpus(cpuList):
print "switching cpus"
@@ -180,7 +215,7 @@ def switchCpus(cpuList):
raise TypeError, "%s is not of type BaseCPU" % cpu
# Drain all of the individual CPUs
- drain_event = internal.main.createCountedDrain()
+ drain_event = internal.event.createCountedDrain()
unready_cpus = 0
for old_cpu in old_cpus:
unready_cpus += old_cpu.startDrain(drain_event, False)
@@ -188,7 +223,7 @@ def switchCpus(cpuList):
if unready_cpus > 0:
drain_event.setCount(unready_cpus)
simulate()
- internal.main.cleanupCountedDrain(drain_event)
+ internal.event.cleanupCountedDrain(drain_event)
# Now all of the CPUs are ready to be switched out
for old_cpu in old_cpus:
old_cpu._ccObject.switchOut()
@@ -198,6 +233,14 @@ def switchCpus(cpuList):
new_cpu._ccObject.resume()
index += 1
+def dumpStats():
+ print 'Dumping stats'
+ internal.stats.dump()
+
+def resetStats():
+ print 'Resetting stats'
+ internal.stats.reset()
+
# Since we have so many mutual imports in this package, we should:
# 1. Put all intra-package imports at the *bottom* of the file, unless
# they're absolutely needed before that (for top-level statements
diff --git a/src/python/m5/main.py b/src/python/m5/main.py
index 37df884d0..54368b91e 100644
--- a/src/python/m5/main.py
+++ b/src/python/m5/main.py
@@ -240,7 +240,7 @@ def main():
print "M5 Simulator System"
print brief_copyright
print
- print "M5 compiled %s" % internal.main.cvar.compileDate;
+ print "M5 compiled %s" % internal.core.cvar.compileDate;
print "M5 started %s" % datetime.now().ctime()
print "M5 executing on %s" % socket.gethostname()
print "command line:",
@@ -256,7 +256,7 @@ def main():
usage(2)
# tell C++ about output directory
- internal.main.setOutputDir(options.outdir)
+ internal.core.setOutputDir(options.outdir)
# update the system path with elements from the -p option
sys.path[0:0] = options.path
diff --git a/src/python/m5/objects/IntrControl.py b/src/python/m5/objects/IntrControl.py
index a7cf5cc84..398ba47f9 100644
--- a/src/python/m5/objects/IntrControl.py
+++ b/src/python/m5/objects/IntrControl.py
@@ -3,4 +3,4 @@ from m5.params import *
from m5.proxy import *
class IntrControl(SimObject):
type = 'IntrControl'
- cpu = Param.BaseCPU(Parent.cpu[0], "the cpu")
+ sys = Param.System(Parent.any, "the system we are part of")
diff --git a/src/python/m5/objects/T1000.py b/src/python/m5/objects/T1000.py
index aeca491c4..0acfa0920 100644
--- a/src/python/m5/objects/T1000.py
+++ b/src/python/m5/objects/T1000.py
@@ -1,6 +1,6 @@
from m5.params import *
from m5.proxy import *
-from Device import BasicPioDevice, IsaFake, BadAddr
+from Device import BasicPioDevice, PioDevice, IsaFake, BadAddr
from Uart import Uart8250
from Platform import Platform
from SimConsole import SimConsole
@@ -16,6 +16,10 @@ class DumbTOD(BasicPioDevice):
time = Param.Time('01/01/2009', "System time to use ('Now' for real time)")
pio_addr = 0xfff0c1fff8
+class Iob(PioDevice):
+ type = 'Iob'
+ pio_latency = Param.Latency('1ns', "Programed IO latency in simticks")
+
class T1000(Platform):
type = 'T1000'
@@ -28,9 +32,6 @@ class T1000(Platform):
ret_data64=0x0000000000000000, update_data=False)
#warn_access="Accessing Memory Banks -- Unimplemented!")
- fake_iob = IsaFake(pio_addr=0x9800000000, pio_size=0x100000000)
- #warn_access="Accessing IOB -- Unimplemented!")
-
fake_jbi = IsaFake(pio_addr=0x8000000000, pio_size=0x100000000)
#warn_access="Accessing JBI -- Unimplemented!")
@@ -76,6 +77,13 @@ class T1000(Platform):
pconsole = SimConsole()
puart0 = Uart8250(pio_addr=0x1f10000000)
+ iob = Iob()
+ # Attach I/O devices that are on chip
+ def attachOnChipIO(self, bus):
+ self.iob.pio = bus.port
+ self.htod.pio = bus.port
+
+
# Attach I/O devices to specified bus object. Can't do this
# earlier, since the bus object itself is typically defined at the
# System level.
@@ -84,8 +92,6 @@ class T1000(Platform):
self.puart0.sim_console = self.pconsole
self.fake_clk.pio = bus.port
self.fake_membnks.pio = bus.port
- self.fake_iob.pio = bus.port
- self.fake_jbi.pio = bus.port
self.fake_l2_1.pio = bus.port
self.fake_l2_2.pio = bus.port
self.fake_l2_3.pio = bus.port
@@ -95,6 +101,6 @@ class T1000(Platform):
self.fake_l2esr_3.pio = bus.port
self.fake_l2esr_4.pio = bus.port
self.fake_ssi.pio = bus.port
+ self.fake_jbi.pio = bus.port
self.puart0.pio = bus.port
self.hvuart.pio = bus.port
- self.htod.pio = bus.port
diff --git a/src/python/m5/params.py b/src/python/m5/params.py
index f8a9f9ddd..e71e1c3c5 100644
--- a/src/python/m5/params.py
+++ b/src/python/m5/params.py
@@ -894,9 +894,8 @@ class PortRef(object):
if self.ccConnected: # already done this
return
peer = self.peer
- internal.main.connectPorts(self.simobj.getCCObject(), self.name,
- self.index, peer.simobj.getCCObject(),
- peer.name, peer.index)
+ internal.sim_object.connectPorts(self.simobj.getCCObject(), self.name,
+ self.index, peer.simobj.getCCObject(), peer.name, peer.index)
self.ccConnected = True
peer.ccConnected = True
diff --git a/src/python/m5/stats.py b/src/python/m5/stats.py
new file mode 100644
index 000000000..041a3f58d
--- /dev/null
+++ b/src/python/m5/stats.py
@@ -0,0 +1,46 @@
+# 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: Nathan Binkert
+
+import internal
+
+from internal.stats import dump
+from internal.stats import initSimStats
+from internal.stats import reset
+from internal.stats import StatEvent as event
+
+def initText(filename, desc=True, compat=True):
+ internal.stats.initText(filename, desc, compat)
+
+def initMySQL(host, database, user='', passwd='', project='test', name='test',
+ sample='0'):
+ if not user:
+ import getpass
+ user = getpass.getuser()
+
+ internal.stats.initMySQL(host, database, user, passwd, project, name,
+ sample)
diff --git a/src/python/swig/core.i b/src/python/swig/core.i
new file mode 100644
index 000000000..116890763
--- /dev/null
+++ b/src/python/swig/core.i
@@ -0,0 +1,57 @@
+/*
+ * 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
+ * Steve Reinhardt
+ */
+
+%module core
+
+%{
+#include "python/swig/pyobject.hh"
+
+#include "sim/core.hh"
+#include "sim/host.hh"
+#include "sim/startup.hh"
+
+extern const char *compileDate;
+%}
+
+%include "std_string.i"
+
+void setOutputDir(const std::string &dir);
+void loadIniFile(PyObject *);
+void SimStartup();
+void doExitCleanup();
+
+char *compileDate;
+
+%wrapper %{
+// fix up module name to reflect the fact that it's inside the m5 package
+#undef SWIG_name
+#define SWIG_name "m5.internal._core"
+%}
diff --git a/src/python/swig/event.i b/src/python/swig/event.i
index 554c9fa0e..51d7d89f0 100644
--- a/src/python/swig/event.i
+++ b/src/python/swig/event.i
@@ -33,19 +33,48 @@
%{
#include "python/swig/pyevent.hh"
-inline void
-create(PyObject *object, Tick when)
-{
- new PythonEvent(object, when);
-}
+#include "sim/sim_events.hh"
+#include "sim/sim_exit.hh"
+#include "sim/simulate.hh"
%}
%include "stdint.i"
+%include "std_string.i"
%include "sim/host.hh"
-%inline %{
-extern void create(PyObject *object, Tick when);
-%}
+void create(PyObject *object, Tick when);
+
+class Event;
+class CountedDrainEvent : public Event {
+ public:
+ void setCount(int _count);
+};
+
+CountedDrainEvent *createCountedDrain();
+void cleanupCountedDrain(Event *drain_event);
+
+%immutable curTick;
+Tick curTick;
+
+// minimal definition of SimExitEvent interface to wrap
+class SimLoopExitEvent {
+ public:
+ std::string getCause();
+ int getCode();
+ SimLoopExitEvent(EventQueue *q, Tick _when, Tick _repeat,
+ const std::string &_cause, int c = 0);
+};
+
+%exception simulate {
+ $action
+ if (!result) {
+ return NULL;
+ }
+}
+SimLoopExitEvent *simulate(Tick num_cycles = MaxTick);
+void exitSimLoop(const std::string &message, int exit_code);
+
+Tick curTick;
%wrapper %{
// fix up module name to reflect the fact that it's inside the m5 package
diff --git a/src/python/swig/pyevent.hh b/src/python/swig/pyevent.hh
index 16af85a84..65e80e9e4 100644
--- a/src/python/swig/pyevent.hh
+++ b/src/python/swig/pyevent.hh
@@ -32,6 +32,7 @@
#define __PYTHON_SWIG_PYEVENT_HH__
#include "sim/eventq.hh"
+#include "sim/sim_events.hh"
class PythonEvent : public Event
{
@@ -45,4 +46,29 @@ class PythonEvent : public Event
virtual void process();
};
+inline void
+create(PyObject *object, Tick when)
+{
+ new PythonEvent(object, when);
+}
+
+inline Event *
+createCountedDrain()
+{
+ return new CountedDrainEvent();
+}
+
+inline void
+cleanupCountedDrain(Event *counted_drain)
+{
+ CountedDrainEvent *event =
+ dynamic_cast<CountedDrainEvent *>(counted_drain);
+ if (event == NULL) {
+ fatal("Called cleanupCountedDrain() on an event that was not "
+ "a CountedDrainEvent.");
+ }
+ assert(event->getCount() == 0);
+ delete event;
+}
+
#endif // __PYTHON_SWIG_PYEVENT_HH__
diff --git a/src/python/swig/pyobject.cc b/src/python/swig/pyobject.cc
new file mode 100644
index 000000000..11141fa84
--- /dev/null
+++ b/src/python/swig/pyobject.cc
@@ -0,0 +1,137 @@
+/*
+ * 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
+ */
+
+#include <Python.h>
+
+#include <string>
+
+#include "base/inifile.hh"
+#include "base/output.hh"
+#include "mem/mem_object.hh"
+#include "mem/port.hh"
+#include "sim/builder.hh"
+#include "sim/sim_object.hh"
+
+using namespace std;
+
+/**
+ * Look up a MemObject port. Helper function for connectPorts().
+ */
+Port *
+lookupPort(SimObject *so, const std::string &name, int i)
+{
+ MemObject *mo = dynamic_cast<MemObject *>(so);
+ if (mo == NULL) {
+ warn("error casting SimObject %s to MemObject", so->name());
+ return NULL;
+ }
+
+ Port *p = mo->getPort(name, i);
+ if (p == NULL)
+ warn("error looking up port %s on object %s", name, so->name());
+ return p;
+}
+
+
+/**
+ * Connect the described MemObject ports. Called from Python via SWIG.
+ */
+int
+connectPorts(SimObject *o1, const std::string &name1, int i1,
+ SimObject *o2, const std::string &name2, int i2)
+{
+ Port *p1 = lookupPort(o1, name1, i1);
+ Port *p2 = lookupPort(o2, name2, i2);
+
+ if (p1 == NULL || p2 == NULL) {
+ warn("connectPorts: port lookup error");
+ return 0;
+ }
+
+ p1->setPeer(p2);
+ p2->setPeer(p1);
+
+ return 1;
+}
+
+inline IniFile &
+inifile()
+{
+ static IniFile inifile;
+ return inifile;
+}
+
+SimObject *
+createSimObject(const string &name)
+{
+ return SimObjectClass::createObject(inifile(), name);
+}
+
+/**
+ * Pointer to the Python function that maps names to SimObjects.
+ */
+PyObject *resolveFunc = NULL;
+
+/**
+ * Convert a pointer to the Python object that SWIG wraps around a C++
+ * SimObject pointer back to the actual C++ pointer. See main.i.
+ */
+extern "C" SimObject *convertSwigSimObjectPtr(PyObject *);
+
+SimObject *
+resolveSimObject(const string &name)
+{
+ PyObject *pyPtr = PyEval_CallFunction(resolveFunc, "(s)", name.c_str());
+ if (pyPtr == NULL) {
+ PyErr_Print();
+ panic("resolveSimObject: failure on call to Python for %s", name);
+ }
+
+ SimObject *simObj = convertSwigSimObjectPtr(pyPtr);
+ if (simObj == NULL)
+ panic("resolveSimObject: failure on pointer conversion for %s", name);
+
+ return simObj;
+}
+
+/**
+ * Load config.ini into C++ database. Exported to Python via SWIG;
+ * invoked from m5.instantiate().
+ */
+void
+loadIniFile(PyObject *_resolveFunc)
+{
+ resolveFunc = _resolveFunc;
+ configStream = simout.find("config.out");
+
+ // The configuration database is now complete; start processing it.
+ inifile().load(simout.resolve("config.ini"));
+}
+
diff --git a/src/python/swig/pyobject.hh b/src/python/swig/pyobject.hh
new file mode 100644
index 000000000..d8efc9149
--- /dev/null
+++ b/src/python/swig/pyobject.hh
@@ -0,0 +1,94 @@
+/*
+ * 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
+ */
+
+#include <Python.h>
+
+#include "cpu/base.hh"
+#include "sim/host.hh"
+#include "sim/serialize.hh"
+#include "sim/sim_object.hh"
+#include "sim/system.hh"
+
+SimObject *createSimObject(const std::string &name);
+extern "C" SimObject *convertSwigSimObjectPtr(PyObject *);
+SimObject *resolveSimObject(const std::string &name);
+void loadIniFile(PyObject *_resolveFunc);
+
+
+/**
+ * Connect the described MemObject ports. Called from Python via SWIG.
+ */
+int connectPorts(SimObject *o1, const std::string &name1, int i1,
+ SimObject *o2, const std::string &name2, int i2);
+
+inline BaseCPU *
+convertToBaseCPUPtr(SimObject *obj)
+{
+ BaseCPU *ptr = dynamic_cast<BaseCPU *>(obj);
+
+ if (ptr == NULL)
+ warn("Casting to BaseCPU pointer failed");
+ return ptr;
+}
+
+inline System *
+convertToSystemPtr(SimObject *obj)
+{
+ System *ptr = dynamic_cast<System *>(obj);
+
+ if (ptr == NULL)
+ warn("Casting to System pointer failed");
+ return ptr;
+}
+
+inline void
+initAll()
+{
+ SimObject::initAll();
+}
+
+inline void
+regAllStats()
+{
+ SimObject::regAllStats();
+}
+
+inline void
+serializeAll(const std::string &cpt_dir)
+{
+ Serializable::serializeAll(cpt_dir);
+}
+
+inline void
+unserializeAll(const std::string &cpt_dir)
+{
+ Serializable::unserializeAll(cpt_dir);
+}
+
diff --git a/src/python/swig/sim_object.i b/src/python/swig/sim_object.i
new file mode 100644
index 000000000..b2af72c61
--- /dev/null
+++ b/src/python/swig/sim_object.i
@@ -0,0 +1,101 @@
+/*
+ * 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
+ */
+
+%module sim_object
+
+%{
+#include "python/swig/pyobject.hh"
+%}
+
+// import these files for SWIG to wrap
+%include "stdint.i"
+%include "std_string.i"
+%include "sim/host.hh"
+
+class BaseCPU;
+
+class SimObject {
+ public:
+ enum State {
+ Running,
+ Draining,
+ Drained
+ };
+
+ enum MemoryMode {
+ Invalid,
+ Atomic,
+ Timing
+ };
+
+ unsigned int drain(Event *drain_event);
+ void resume();
+ void switchOut();
+ void takeOverFrom(BaseCPU *cpu);
+ SimObject(const std::string &_name);
+};
+
+class System {
+ private:
+ System();
+ public:
+ void setMemoryMode(SimObject::MemoryMode mode);
+};
+
+SimObject *createSimObject(const std::string &name);
+
+int connectPorts(SimObject *o1, const std::string &name1, int i1,
+ SimObject *o2, const std::string &name2, int i2);
+
+BaseCPU *convertToBaseCPUPtr(SimObject *obj);
+System *convertToSystemPtr(SimObject *obj);
+
+void serializeAll(const std::string &cpt_dir);
+void unserializeAll(const std::string &cpt_dir);
+
+void initAll();
+void regAllStats();
+
+%wrapper %{
+// fix up module name to reflect the fact that it's inside the m5 package
+#undef SWIG_name
+#define SWIG_name "m5.internal._sim_object"
+
+// Convert a pointer to the Python object that SWIG wraps around a
+// C++ SimObject pointer back to the actual C++ pointer.
+SimObject *
+convertSwigSimObjectPtr(PyObject *pyObj)
+{
+ SimObject *so;
+ if (SWIG_ConvertPtr(pyObj, (void **) &so, SWIGTYPE_p_SimObject, 0) == -1)
+ return NULL;
+ return so;
+}
+%}
diff --git a/src/python/swig/stats.i b/src/python/swig/stats.i
index d6b39c2cb..d36f82dbc 100644
--- a/src/python/swig/stats.i
+++ b/src/python/swig/stats.i
@@ -42,12 +42,13 @@
namespace Stats {
void initSimStats();
void initText(const std::string &filename, bool desc=true, bool compat=true);
-void initMySQL(std::string host, std::string database, std::string user = "",
- std::string passwd = "", std::string name = "test",
- std::string sample = "0", std::string project = "test");
+void initMySQL(std::string host, std::string database, std::string user,
+ std::string passwd, std::string project, std::string name,
+ std::string sample);
void StatEvent(bool dump, bool reset, Tick when = curTick, Tick repeat = 0);
+void check();
void dump();
void reset();
diff --git a/src/sim/async.cc b/src/sim/async.cc
new file mode 100644
index 000000000..1a8e499f7
--- /dev/null
+++ b/src/sim/async.cc
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2000-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
+ */
+
+volatile bool async_event = false;
+volatile bool async_statdump = false;
+volatile bool async_statreset = false;
+volatile bool async_exit = false;
+volatile bool async_io = false;
+volatile bool async_alarm = false;
+volatile bool async_exception = false;
+
diff --git a/src/sim/async.hh b/src/sim/async.hh
index 6ee5eb46a..932f975d2 100644
--- a/src/sim/async.hh
+++ b/src/sim/async.hh
@@ -43,7 +43,8 @@
/// @note See the PollQueue object (in pollevent.hh) for the use of async_io and async_alarm.
//@{
extern volatile bool async_event; ///< Some asynchronous event has happened.
-extern volatile bool async_dump; ///< Async request to dump stats.
+extern volatile bool async_statdump; ///< Async request to dump stats.
+extern volatile bool async_statreset; ///< Async request to reset stats.
extern volatile bool async_exit; ///< Async request to exit simulator.
extern volatile bool async_io; ///< Async I/O request (SIGIO).
extern volatile bool async_alarm; ///< Async alarm event (SIGALRM).
diff --git a/src/sim/core.cc b/src/sim/core.cc
new file mode 100644
index 000000000..24cc33da2
--- /dev/null
+++ b/src/sim/core.cc
@@ -0,0 +1,76 @@
+/*
+ * 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
+ * Steve Reinhardt
+ */
+
+#include <iostream>
+#include <string>
+
+#include "base/callback.hh"
+#include "base/output.hh"
+
+using namespace std;
+
+void
+setOutputDir(const string &dir)
+{
+ simout.setDirectory(dir);
+}
+
+/**
+ * Queue of C++ callbacks to invoke on simulator exit.
+ */
+inline CallbackQueue &
+exitCallbacks()
+{
+ static CallbackQueue theQueue;
+ return theQueue;
+}
+
+/**
+ * Register an exit callback.
+ */
+void
+registerExitCallback(Callback *callback)
+{
+ exitCallbacks().add(callback);
+}
+
+/**
+ * Do C++ simulator exit processing. Exported to SWIG to be invoked
+ * when simulator terminates via Python's atexit mechanism.
+ */
+void
+doExitCleanup()
+{
+ exitCallbacks().process();
+ exitCallbacks().clear();
+
+ cout.flush();
+}
diff --git a/src/sim/core.hh b/src/sim/core.hh
new file mode 100644
index 000000000..2ef21c4b6
--- /dev/null
+++ b/src/sim/core.hh
@@ -0,0 +1,40 @@
+/*
+ * 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
+ * Steve Reinhardt
+ */
+
+#include <Python.h>
+#include <string>
+
+#include "base/callback.hh"
+
+void setOutputDir(const std::string &dir);
+
+void registerExitCallback(Callback *callback);
+void doExitCleanup();
diff --git a/src/sim/main.cc b/src/sim/main.cc
index 8e47ac6a0..0341b7d5f 100644
--- a/src/sim/main.cc
+++ b/src/sim/main.cc
@@ -25,79 +25,39 @@
* (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
- * Nathan Binkert
- * Steve Reinhardt
+ * Authors: Nathan Binkert
*/
-///
-/// @file sim/main.cc
-///
-#include <Python.h> // must be before system headers... see Python docs
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <libgen.h>
-#include <stdlib.h>
+#include <Python.h>
#include <signal.h>
-#include <getopt.h>
-#include <list>
+#include <iostream>
#include <string>
-#include <vector>
-#include "base/callback.hh"
-#include "base/inifile.hh"
+#include "base/cprintf.hh"
#include "base/misc.hh"
-#include "base/output.hh"
-#include "base/pollevent.hh"
-#include "base/statistics.hh"
-#include "base/stats/output.hh"
-#include "base/str.hh"
-#include "base/time.hh"
#include "config/pythonhome.hh"
-#include "cpu/base.hh"
-#include "cpu/smt.hh"
-#include "mem/mem_object.hh"
-#include "mem/port.hh"
#include "python/swig/init.hh"
#include "sim/async.hh"
-#include "sim/builder.hh"
#include "sim/host.hh"
-#include "sim/serialize.hh"
-#include "sim/sim_events.hh"
-#include "sim/sim_exit.hh"
-#include "sim/sim_object.hh"
-#include "sim/system.hh"
-#include "sim/stat_control.hh"
-#include "sim/stats.hh"
#include "sim/root.hh"
using namespace std;
-// See async.h.
-volatile bool async_event = false;
-volatile bool async_dump = false;
-volatile bool async_dumpreset = false;
-volatile bool async_exit = false;
-volatile bool async_io = false;
-volatile bool async_alarm = false;
-volatile bool async_exception = false;
-
/// Stats signal handler.
void
dumpStatsHandler(int sigtype)
{
async_event = true;
- async_dump = true;
+ async_statdump = true;
}
void
dumprstStatsHandler(int sigtype)
{
async_event = true;
- async_dumpreset = true;
+ async_statdump = true;
+ async_statreset = true;
}
/// Exit signal handler.
@@ -112,7 +72,7 @@ exitNowHandler(int sigtype)
void
abortHandler(int sigtype)
{
- cerr << "Program aborted at cycle " << curTick << endl;
+ ccprintf(cerr, "Program aborted at cycle %d\n", curTick);
}
int
@@ -160,301 +120,3 @@ main(int argc, char **argv)
// clean up Python intepreter.
Py_Finalize();
}
-
-
-void
-setOutputDir(const string &dir)
-{
- simout.setDirectory(dir);
-}
-
-
-IniFile inifile;
-
-SimObject *
-createSimObject(const string &name)
-{
- return SimObjectClass::createObject(inifile, name);
-}
-
-
-/**
- * Pointer to the Python function that maps names to SimObjects.
- */
-PyObject *resolveFunc = NULL;
-
-/**
- * Convert a pointer to the Python object that SWIG wraps around a C++
- * SimObject pointer back to the actual C++ pointer. See main.i.
- */
-extern "C" SimObject *convertSwigSimObjectPtr(PyObject *);
-
-
-SimObject *
-resolveSimObject(const string &name)
-{
- PyObject *pyPtr = PyEval_CallFunction(resolveFunc, "(s)", name.c_str());
- if (pyPtr == NULL) {
- PyErr_Print();
- panic("resolveSimObject: failure on call to Python for %s", name);
- }
-
- SimObject *simObj = convertSwigSimObjectPtr(pyPtr);
- if (simObj == NULL)
- panic("resolveSimObject: failure on pointer conversion for %s", name);
-
- return simObj;
-}
-
-
-/**
- * Load config.ini into C++ database. Exported to Python via SWIG;
- * invoked from m5.instantiate().
- */
-void
-loadIniFile(PyObject *_resolveFunc)
-{
- resolveFunc = _resolveFunc;
- configStream = simout.find("config.out");
-
- // The configuration database is now complete; start processing it.
- inifile.load(simout.resolve("config.ini"));
-
- // Initialize statistics database
- Stats::initSimStats();
-}
-
-
-/**
- * Look up a MemObject port. Helper function for connectPorts().
- */
-Port *
-lookupPort(SimObject *so, const std::string &name, int i)
-{
- MemObject *mo = dynamic_cast<MemObject *>(so);
- if (mo == NULL) {
- warn("error casting SimObject %s to MemObject", so->name());
- return NULL;
- }
-
- Port *p = mo->getPort(name, i);
- if (p == NULL)
- warn("error looking up port %s on object %s", name, so->name());
- return p;
-}
-
-
-/**
- * Connect the described MemObject ports. Called from Python via SWIG.
- */
-int
-connectPorts(SimObject *o1, const std::string &name1, int i1,
- SimObject *o2, const std::string &name2, int i2)
-{
- Port *p1 = lookupPort(o1, name1, i1);
- Port *p2 = lookupPort(o2, name2, i2);
-
- if (p1 == NULL || p2 == NULL) {
- warn("connectPorts: port lookup error");
- return 0;
- }
-
- p1->setPeer(p2);
- p2->setPeer(p1);
-
- return 1;
-}
-
-/**
- * Do final initialization steps after object construction but before
- * start of simulation.
- */
-void
-finalInit()
-{
- // Do a second pass to finish initializing the sim objects
- SimObject::initAll();
-
- // Restore checkpointed state, if any.
-#if 0
- configHierarchy.unserializeSimObjects();
-#endif
-
- SimObject::regAllStats();
-
- // Check to make sure that the stats package is properly initialized
- Stats::check();
-
- // Reset to put the stats in a consistent state.
- Stats::reset();
-
- SimStartup();
-}
-
-/** Simulate for num_cycles additional cycles. If num_cycles is -1
- * (the default), do not limit simulation; some other event must
- * terminate the loop. Exported to Python via SWIG.
- * @return The SimLoopExitEvent that caused the loop to exit.
- */
-SimLoopExitEvent *
-simulate(Tick num_cycles = MaxTick)
-{
- warn("Entering event queue @ %d. Starting simulation...\n", curTick);
-
- if (num_cycles < 0)
- fatal("simulate: num_cycles must be >= 0 (was %d)\n", num_cycles);
- else if (curTick + num_cycles < 0) //Overflow
- num_cycles = MaxTick;
- else
- num_cycles = curTick + num_cycles;
-
- Event *limit_event = schedExitSimLoop("simulate() limit reached",
- num_cycles);
-
- while (1) {
- // there should always be at least one event (the SimLoopExitEvent
- // we just scheduled) in the queue
- assert(!mainEventQueue.empty());
- assert(curTick <= mainEventQueue.nextTick() &&
- "event scheduled in the past");
-
- // forward current cycle to the time of the first event on the
- // queue
- curTick = mainEventQueue.nextTick();
- Event *exit_event = mainEventQueue.serviceOne();
- if (exit_event != NULL) {
- // hit some kind of exit event; return to Python
- // event must be subclass of SimLoopExitEvent...
- SimLoopExitEvent *se_event = dynamic_cast<SimLoopExitEvent *>(exit_event);
- if (se_event == NULL)
- panic("Bogus exit event class!");
-
- // if we didn't hit limit_event, delete it
- if (se_event != limit_event) {
- assert(limit_event->scheduled());
- limit_event->deschedule();
- delete limit_event;
- }
-
- return se_event;
- }
-
- if (async_event) {
- async_event = false;
- if (async_dump) {
- async_dump = false;
- Stats::StatEvent(true, false);
- }
-
- if (async_dumpreset) {
- async_dumpreset = false;
- Stats::StatEvent(true, true);
- }
-
- if (async_exit) {
- async_exit = false;
- exitSimLoop("user interrupt received");
- }
-
- if (async_io || async_alarm) {
- async_io = false;
- async_alarm = false;
- pollQueue.service();
- }
-
- if (async_exception) {
- async_exception = false;
- return NULL;
- }
- }
- }
-
- // not reached... only exit is return on SimLoopExitEvent
-}
-
-Event *
-createCountedDrain()
-{
- return new CountedDrainEvent();
-}
-
-void
-cleanupCountedDrain(Event *counted_drain)
-{
- CountedDrainEvent *event =
- dynamic_cast<CountedDrainEvent *>(counted_drain);
- if (event == NULL) {
- fatal("Called cleanupCountedDrain() on an event that was not "
- "a CountedDrainEvent.");
- }
- assert(event->getCount() == 0);
- delete event;
-}
-
-void
-serializeAll(const std::string &cpt_dir)
-{
- Serializable::serializeAll(cpt_dir);
-}
-
-void
-unserializeAll(const std::string &cpt_dir)
-{
- Serializable::unserializeAll(cpt_dir);
-}
-
-/**
- * Queue of C++ callbacks to invoke on simulator exit.
- */
-CallbackQueue&
-exitCallbacks()
-{
- static CallbackQueue theQueue;
- return theQueue;
-}
-
-/**
- * Register an exit callback.
- */
-void
-registerExitCallback(Callback *callback)
-{
- exitCallbacks().add(callback);
-}
-
-BaseCPU *
-convertToBaseCPUPtr(SimObject *obj)
-{
- BaseCPU *ptr = dynamic_cast<BaseCPU *>(obj);
-
- if (ptr == NULL)
- warn("Casting to BaseCPU pointer failed");
- return ptr;
-}
-
-System *
-convertToSystemPtr(SimObject *obj)
-{
- System *ptr = dynamic_cast<System *>(obj);
-
- if (ptr == NULL)
- warn("Casting to System pointer failed");
- return ptr;
-}
-
-
-/**
- * Do C++ simulator exit processing. Exported to SWIG to be invoked
- * when simulator terminates via Python's atexit mechanism.
- */
-void
-doExitCleanup()
-{
- exitCallbacks().process();
- exitCallbacks().clear();
-
- cout.flush();
-
- // print simulation stats
- Stats::dump();
-}
diff --git a/src/sim/process.cc b/src/sim/process.cc
index acc509a6f..b3ce182e5 100644
--- a/src/sim/process.cc
+++ b/src/sim/process.cc
@@ -300,24 +300,6 @@ DEFINE_SIM_OBJECT_CLASS_NAME("Process", Process)
////////////////////////////////////////////////////////////////////////
-void
-copyStringArray(vector<string> &strings, Addr array_ptr, Addr data_ptr,
- TranslatingPort* memPort, int ptr_size)
-{
- Addr data_ptr_swap;
- for (int i = 0; i < strings.size(); ++i) {
- data_ptr_swap = htog(data_ptr);
- memPort->writeBlob(array_ptr, (uint8_t*)&data_ptr_swap, ptr_size);
- memPort->writeString(data_ptr, strings[i].c_str());
- array_ptr += ptr_size;
- data_ptr += strings[i].size() + 1;
- }
- // add NULL terminator
- data_ptr = 0;
-
- memPort->writeBlob(array_ptr, (uint8_t*)&data_ptr, ptr_size);
-}
-
LiveProcess::LiveProcess(const string &nm, ObjectFile *_objFile,
System *_system,
int stdin_fd, int stdout_fd, int stderr_fd,
diff --git a/src/sim/process.hh b/src/sim/process.hh
index 1226db81b..dd64fa607 100644
--- a/src/sim/process.hh
+++ b/src/sim/process.hh
@@ -41,9 +41,11 @@
#if !FULL_SYSTEM
+#include <string>
#include <vector>
#include "base/statistics.hh"
+#include "mem/translating_port.hh"
#include "sim/host.hh"
#include "sim/sim_object.hh"
@@ -58,9 +60,27 @@ namespace TheISA
class RemoteGDB;
}
+//This needs to be templated for cases where 32 bit pointers are needed.
+template<class AddrType>
void
-copyStringArray(std::vector<std::string> &strings, Addr array_ptr,
- Addr data_ptr, TranslatingPort* memPort, int ptr_size = sizeof(Addr));
+copyStringArray(std::vector<std::string> &strings,
+ AddrType array_ptr, AddrType data_ptr,
+ TranslatingPort* memPort)
+{
+ AddrType data_ptr_swap;
+ for (int i = 0; i < strings.size(); ++i) {
+ data_ptr_swap = htog(data_ptr);
+ memPort->writeBlob(array_ptr, (uint8_t*)&data_ptr_swap,
+ sizeof(AddrType));
+ memPort->writeString(data_ptr, strings[i].c_str());
+ array_ptr += sizeof(AddrType);
+ data_ptr += strings[i].size() + 1;
+ }
+ // add NULL terminator
+ data_ptr = 0;
+
+ memPort->writeBlob(array_ptr, (uint8_t*)&data_ptr, sizeof(AddrType));
+}
class Process : public SimObject
{
diff --git a/src/sim/simulate.cc b/src/sim/simulate.cc
new file mode 100644
index 000000000..55cbb50a9
--- /dev/null
+++ b/src/sim/simulate.cc
@@ -0,0 +1,121 @@
+/*
+ * 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
+ * Steve Reinhardt
+ */
+
+#include "base/misc.hh"
+#include "base/pollevent.hh"
+#include "sim/stat_control.hh"
+#include "sim/async.hh"
+#include "sim/eventq.hh"
+#include "sim/host.hh"
+#include "sim/sim_events.hh"
+#include "sim/sim_exit.hh"
+#include "sim/simulate.hh"
+
+/** Simulate for num_cycles additional cycles. If num_cycles is -1
+ * (the default), do not limit simulation; some other event must
+ * terminate the loop. Exported to Python via SWIG.
+ * @return The SimLoopExitEvent that caused the loop to exit.
+ */
+SimLoopExitEvent *
+simulate(Tick num_cycles)
+{
+ warn("Entering event queue @ %d. Starting simulation...\n", curTick);
+
+ if (num_cycles < 0)
+ fatal("simulate: num_cycles must be >= 0 (was %d)\n", num_cycles);
+ else if (curTick + num_cycles < 0) //Overflow
+ num_cycles = MaxTick;
+ else
+ num_cycles = curTick + num_cycles;
+
+ Event *limit_event;
+ limit_event = schedExitSimLoop("simulate() limit reached", num_cycles);
+
+ while (1) {
+ // there should always be at least one event (the SimLoopExitEvent
+ // we just scheduled) in the queue
+ assert(!mainEventQueue.empty());
+ assert(curTick <= mainEventQueue.nextTick() &&
+ "event scheduled in the past");
+
+ // forward current cycle to the time of the first event on the
+ // queue
+ curTick = mainEventQueue.nextTick();
+ Event *exit_event = mainEventQueue.serviceOne();
+ if (exit_event != NULL) {
+ // hit some kind of exit event; return to Python
+ // event must be subclass of SimLoopExitEvent...
+ SimLoopExitEvent *se_event;
+ se_event = dynamic_cast<SimLoopExitEvent *>(exit_event);
+
+ if (se_event == NULL)
+ panic("Bogus exit event class!");
+
+ // if we didn't hit limit_event, delete it
+ if (se_event != limit_event) {
+ assert(limit_event->scheduled());
+ limit_event->deschedule();
+ delete limit_event;
+ }
+
+ return se_event;
+ }
+
+ if (async_event) {
+ async_event = false;
+ if (async_statdump || async_statreset) {
+ async_statdump = false;
+ async_statreset = false;
+
+ Stats::StatEvent(async_statdump, async_statreset);
+ }
+
+ if (async_exit) {
+ async_exit = false;
+ exitSimLoop("user interrupt received");
+ }
+
+ if (async_io || async_alarm) {
+ async_io = false;
+ async_alarm = false;
+ pollQueue.service();
+ }
+
+ if (async_exception) {
+ async_exception = false;
+ return NULL;
+ }
+ }
+ }
+
+ // not reached... only exit is return on SimLoopExitEvent
+}
+
diff --git a/src/sim/simulate.hh b/src/sim/simulate.hh
new file mode 100644
index 000000000..139bddb82
--- /dev/null
+++ b/src/sim/simulate.hh
@@ -0,0 +1,35 @@
+/*
+ * 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
+ * Steve Reinhardt
+ */
+
+#include "sim/host.hh"
+#include "sim/sim_events.hh"
+
+SimLoopExitEvent *simulate(Tick num_cycles = MaxTick);
diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc
index ab44c0a35..876f39e99 100644
--- a/src/sim/syscall_emul.cc
+++ b/src/sim/syscall_emul.cc
@@ -184,6 +184,39 @@ lseekFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
SyscallReturn
+_llseekFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
+{
+ int fd = p->sim_fd(tc->getSyscallArg(0));
+ uint64_t offset_high = tc->getSyscallArg(1);
+ uint32_t offset_low = tc->getSyscallArg(2);
+ Addr result_ptr = tc->getSyscallArg(3);
+ int whence = tc->getSyscallArg(4);
+
+ uint64_t offset = (offset_high << 32) | offset_low;
+
+ uint64_t result = lseek(fd, offset, whence);
+ result = TheISA::htog(result);
+
+ if (result == (off_t)-1) {
+ //The seek failed.
+ return -errno;
+ } else {
+ //The seek succeeded.
+ //Copy "result" to "result_ptr"
+ //XXX We'll assume that the size of loff_t is 64 bits on the
+ //target platform
+ BufferArg result_buf(result_ptr, sizeof(result));
+ memcpy(result_buf.bufferPtr(), &result, sizeof(result));
+ result_buf.copyOut(tc->getMemPort());
+ return 0;
+ }
+
+
+ return (result == (off_t)-1) ? -errno : result;
+}
+
+
+SyscallReturn
munmapFunc(SyscallDesc *desc, int num, LiveProcess *p, ThreadContext *tc)
{
// given that we don't really implement mmap, munmap is really easy
diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh
index f57bd5272..94ae8e3e6 100644
--- a/src/sim/syscall_emul.hh
+++ b/src/sim/syscall_emul.hh
@@ -211,6 +211,10 @@ SyscallReturn writeFunc(SyscallDesc *desc, int num,
SyscallReturn lseekFunc(SyscallDesc *desc, int num,
LiveProcess *p, ThreadContext *tc);
+/// Target _llseek() handler.
+SyscallReturn _llseekFunc(SyscallDesc *desc, int num,
+ LiveProcess *p, ThreadContext *tc);
+
/// Target munmap() handler.
SyscallReturn munmapFunc(SyscallDesc *desc, int num,
LiveProcess *p, ThreadContext *tc);
@@ -448,14 +452,14 @@ ioctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
}
switch (req) {
- case OS::TIOCISATTY:
- case OS::TIOCGETP:
- case OS::TIOCSETP:
- case OS::TIOCSETN:
- case OS::TIOCSETC:
- case OS::TIOCGETC:
- case OS::TIOCGETS:
- case OS::TIOCGETA:
+ case OS::TIOCISATTY_:
+ case OS::TIOCGETP_:
+ case OS::TIOCSETP_:
+ case OS::TIOCSETN_:
+ case OS::TIOCSETC_:
+ case OS::TIOCGETC_:
+ case OS::TIOCGETS_:
+ case OS::TIOCGETA_:
return -ENOTTY;
default: