gem5/src/arch/sparc/isa.cc

807 lines
23 KiB
C++
Raw Normal View History

/*
* Copyright (c) 2009 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Gabe Black
*/
#include "arch/sparc/isa.hh"
#include "arch/sparc/asi.hh"
#include "arch/sparc/decoder.hh"
#include "base/bitfield.hh"
#include "base/trace.hh"
#include "cpu/base.hh"
#include "cpu/thread_context.hh"
#include "debug/MiscRegs.hh"
#include "debug/Timer.hh"
#include "params/SparcISA.hh"
namespace SparcISA
{
static PSTATE
buildPstateMask()
{
PSTATE mask = 0;
mask.ie = 1;
mask.priv = 1;
mask.am = 1;
mask.pef = 1;
mask.mm = 3;
mask.tle = 1;
mask.cle = 1;
mask.pid1 = 1;
return mask;
}
static const PSTATE PstateMask = buildPstateMask();
ISA::ISA(Params *p)
: SimObject(p)
{
tickCompare = NULL;
sTickCompare = NULL;
hSTickCompare = NULL;
clear();
}
const SparcISAParams *
ISA::params() const
{
return dynamic_cast<const Params *>(_params);
}
void
ISA::reloadRegMap()
{
installGlobals(gl, CurrentGlobalsOffset);
installWindow(cwp, CurrentWindowOffset);
// Microcode registers.
for (int i = 0; i < NumMicroIntRegs; i++)
intRegMap[MicroIntOffset + i] = i + TotalGlobals + NWindows * 16;
installGlobals(gl, NextGlobalsOffset);
installWindow(cwp - 1, NextWindowOffset);
installGlobals(gl, PreviousGlobalsOffset);
installWindow(cwp + 1, PreviousWindowOffset);
}
void
ISA::installWindow(int cwp, int offset)
{
assert(offset >= 0 && offset + NumWindowedRegs <= NumIntRegs);
RegIndex *mapChunk = intRegMap + offset;
for (int i = 0; i < NumWindowedRegs; i++)
mapChunk[i] = TotalGlobals +
((i - cwp * RegsPerWindow + TotalWindowed) % (TotalWindowed));
}
void
ISA::installGlobals(int gl, int offset)
{
assert(offset >= 0 && offset + NumGlobalRegs <= NumIntRegs);
RegIndex *mapChunk = intRegMap + offset;
mapChunk[0] = 0;
for (int i = 1; i < NumGlobalRegs; i++)
mapChunk[i] = i + gl * NumGlobalRegs;
}
void
ISA::clear()
{
cwp = 0;
gl = 0;
reloadRegMap();
// y = 0;
// ccr = 0;
asi = 0;
tick = ULL(1) << 63;
fprs = 0;
gsr = 0;
softint = 0;
tick_cmpr = 0;
stick = 0;
stick_cmpr = 0;
memset(tpc, 0, sizeof(tpc));
memset(tnpc, 0, sizeof(tnpc));
memset(tstate, 0, sizeof(tstate));
memset(tt, 0, sizeof(tt));
tba = 0;
pstate = 0;
tl = 0;
pil = 0;
// cansave = 0;
// canrestore = 0;
// cleanwin = 0;
// otherwin = 0;
// wstate = 0;
// In a T1, bit 11 is apparently always 1
hpstate = 0;
hpstate.id = 1;
memset(htstate, 0, sizeof(htstate));
hintp = 0;
htba = 0;
hstick_cmpr = 0;
// This is set this way in Legion for some reason
strandStatusReg = 0x50000;
fsr = 0;
priContext = 0;
secContext = 0;
partId = 0;
lsuCtrlReg = 0;
memset(scratchPad, 0, sizeof(scratchPad));
cpu_mondo_head = 0;
cpu_mondo_tail = 0;
dev_mondo_head = 0;
dev_mondo_tail = 0;
res_error_head = 0;
res_error_tail = 0;
nres_error_head = 0;
nres_error_tail = 0;
// If one of these events is active, it's not obvious to me how to get
// rid of it cleanly. For now we'll just assert that they're not.
if (tickCompare != NULL && sTickCompare != NULL && hSTickCompare != NULL)
panic("Tick comparison event active when clearing the ISA object.\n");
}
MiscReg
ISA::readMiscRegNoEffect(int miscReg) const
{
// The three miscRegs are moved up from the switch statement
// due to more frequent calls.
if (miscReg == MISCREG_GL)
return gl;
if (miscReg == MISCREG_CWP)
return cwp;
if (miscReg == MISCREG_TLB_DATA) {
/* Package up all the data for the tlb:
* 6666555555555544444444443333333333222222222211111111110000000000
* 3210987654321098765432109876543210987654321098765432109876543210
* secContext | priContext | |tl|partid| |||||^hpriv
* ||||^red
* |||^priv
* ||^am
* |^lsuim
* ^lsudm
*/
return (uint64_t)hpstate.hpriv |
(uint64_t)hpstate.red << 1 |
(uint64_t)pstate.priv << 2 |
(uint64_t)pstate.am << 3 |
bits((uint64_t)lsuCtrlReg,3,2) << 4 |
bits((uint64_t)partId,7,0) << 8 |
bits((uint64_t)tl,2,0) << 16 |
(uint64_t)priContext << 32 |
(uint64_t)secContext << 48;
}
switch (miscReg) {
// case MISCREG_TLB_DATA:
// [original contents see above]
// case MISCREG_Y:
// return y;
// case MISCREG_CCR:
// return ccr;
case MISCREG_ASI:
return asi;
case MISCREG_FPRS:
return fprs;
case MISCREG_TICK:
return tick;
case MISCREG_PCR:
panic("PCR not implemented\n");
case MISCREG_PIC:
panic("PIC not implemented\n");
case MISCREG_GSR:
return gsr;
case MISCREG_SOFTINT:
return softint;
case MISCREG_TICK_CMPR:
return tick_cmpr;
case MISCREG_STICK:
return stick;
case MISCREG_STICK_CMPR:
return stick_cmpr;
/** Privilged Registers */
case MISCREG_TPC:
return tpc[tl-1];
case MISCREG_TNPC:
return tnpc[tl-1];
case MISCREG_TSTATE:
return tstate[tl-1];
case MISCREG_TT:
return tt[tl-1];
case MISCREG_PRIVTICK:
panic("Priviliged access to tick registers not implemented\n");
case MISCREG_TBA:
return tba;
case MISCREG_PSTATE:
return (MiscReg)pstate;
case MISCREG_TL:
return tl;
case MISCREG_PIL:
return pil;
// CWP, GL moved
// case MISCREG_CWP:
// return cwp;
// case MISCREG_CANSAVE:
// return cansave;
// case MISCREG_CANRESTORE:
// return canrestore;
// case MISCREG_CLEANWIN:
// return cleanwin;
// case MISCREG_OTHERWIN:
// return otherwin;
// case MISCREG_WSTATE:
// return wstate;
// case MISCREG_GL:
// return gl;
/** Hyper privileged registers */
case MISCREG_HPSTATE:
return (MiscReg)hpstate;
case MISCREG_HTSTATE:
return htstate[tl-1];
case MISCREG_HINTP:
return hintp;
case MISCREG_HTBA:
return htba;
case MISCREG_STRAND_STS_REG:
return strandStatusReg;
case MISCREG_HSTICK_CMPR:
return hstick_cmpr;
/** Floating Point Status Register */
case MISCREG_FSR:
DPRINTF(MiscRegs, "FSR read as: %#x\n", fsr);
return fsr;
case MISCREG_MMU_P_CONTEXT:
return priContext;
case MISCREG_MMU_S_CONTEXT:
return secContext;
case MISCREG_MMU_PART_ID:
return partId;
case MISCREG_MMU_LSU_CTRL:
return lsuCtrlReg;
case MISCREG_SCRATCHPAD_R0:
return scratchPad[0];
case MISCREG_SCRATCHPAD_R1:
return scratchPad[1];
case MISCREG_SCRATCHPAD_R2:
return scratchPad[2];
case MISCREG_SCRATCHPAD_R3:
return scratchPad[3];
case MISCREG_SCRATCHPAD_R4:
return scratchPad[4];
case MISCREG_SCRATCHPAD_R5:
return scratchPad[5];
case MISCREG_SCRATCHPAD_R6:
return scratchPad[6];
case MISCREG_SCRATCHPAD_R7:
return scratchPad[7];
case MISCREG_QUEUE_CPU_MONDO_HEAD:
return cpu_mondo_head;
case MISCREG_QUEUE_CPU_MONDO_TAIL:
return cpu_mondo_tail;
case MISCREG_QUEUE_DEV_MONDO_HEAD:
return dev_mondo_head;
case MISCREG_QUEUE_DEV_MONDO_TAIL:
return dev_mondo_tail;
case MISCREG_QUEUE_RES_ERROR_HEAD:
return res_error_head;
case MISCREG_QUEUE_RES_ERROR_TAIL:
return res_error_tail;
case MISCREG_QUEUE_NRES_ERROR_HEAD:
return nres_error_head;
case MISCREG_QUEUE_NRES_ERROR_TAIL:
return nres_error_tail;
default:
panic("Miscellaneous register %d not implemented\n", miscReg);
}
}
MiscReg
ISA::readMiscReg(int miscReg, ThreadContext * tc)
{
switch (miscReg) {
// tick and stick are aliased to each other in niagra
// well store the tick data in stick and the interrupt bit in tick
case MISCREG_STICK:
case MISCREG_TICK:
case MISCREG_PRIVTICK:
// I'm not sure why legion ignores the lowest two bits, but we'll go
// with it
// change from curCycle() to instCount() until we're done with legion
DPRINTF(Timer, "Instruction Count when TICK read: %#X stick=%#X\n",
tc->getCpuPtr()->instCount(), stick);
return mbits(tc->getCpuPtr()->instCount() + (int64_t)stick,62,2) |
mbits(tick,63,63);
case MISCREG_FPRS:
// in legion if fp is enabled du and dl are set
return fprs | 0x3;
case MISCREG_PCR:
case MISCREG_PIC:
panic("Performance Instrumentation not impl\n");
case MISCREG_SOFTINT_CLR:
case MISCREG_SOFTINT_SET:
panic("Can read from softint clr/set\n");
case MISCREG_SOFTINT:
case MISCREG_TICK_CMPR:
case MISCREG_STICK_CMPR:
case MISCREG_HINTP:
case MISCREG_HTSTATE:
case MISCREG_HTBA:
case MISCREG_HVER:
case MISCREG_STRAND_STS_REG:
case MISCREG_HSTICK_CMPR:
case MISCREG_QUEUE_CPU_MONDO_HEAD:
case MISCREG_QUEUE_CPU_MONDO_TAIL:
case MISCREG_QUEUE_DEV_MONDO_HEAD:
case MISCREG_QUEUE_DEV_MONDO_TAIL:
case MISCREG_QUEUE_RES_ERROR_HEAD:
case MISCREG_QUEUE_RES_ERROR_TAIL:
case MISCREG_QUEUE_NRES_ERROR_HEAD:
case MISCREG_QUEUE_NRES_ERROR_TAIL:
case MISCREG_HPSTATE:
return readFSReg(miscReg, tc);
}
return readMiscRegNoEffect(miscReg);
}
void
ISA::setMiscRegNoEffect(int miscReg, MiscReg val)
{
switch (miscReg) {
// case MISCREG_Y:
// y = val;
// break;
// case MISCREG_CCR:
// ccr = val;
// break;
case MISCREG_ASI:
asi = val;
break;
case MISCREG_FPRS:
fprs = val;
break;
case MISCREG_TICK:
tick = val;
break;
case MISCREG_PCR:
panic("PCR not implemented\n");
case MISCREG_PIC:
panic("PIC not implemented\n");
case MISCREG_GSR:
gsr = val;
break;
case MISCREG_SOFTINT:
softint = val;
break;
case MISCREG_TICK_CMPR:
tick_cmpr = val;
break;
case MISCREG_STICK:
stick = val;
break;
case MISCREG_STICK_CMPR:
stick_cmpr = val;
break;
/** Privilged Registers */
case MISCREG_TPC:
tpc[tl-1] = val;
break;
case MISCREG_TNPC:
tnpc[tl-1] = val;
break;
case MISCREG_TSTATE:
tstate[tl-1] = val;
break;
case MISCREG_TT:
tt[tl-1] = val;
break;
case MISCREG_PRIVTICK:
panic("Priviliged access to tick regesiters not implemented\n");
case MISCREG_TBA:
// clear lower 7 bits on writes.
tba = val & ULL(~0x7FFF);
break;
case MISCREG_PSTATE:
pstate = (val & PstateMask);
break;
case MISCREG_TL:
tl = val;
break;
case MISCREG_PIL:
pil = val;
break;
case MISCREG_CWP:
cwp = val;
break;
// case MISCREG_CANSAVE:
// cansave = val;
// break;
// case MISCREG_CANRESTORE:
// canrestore = val;
// break;
// case MISCREG_CLEANWIN:
// cleanwin = val;
// break;
// case MISCREG_OTHERWIN:
// otherwin = val;
// break;
// case MISCREG_WSTATE:
// wstate = val;
// break;
case MISCREG_GL:
gl = val;
break;
/** Hyper privileged registers */
case MISCREG_HPSTATE:
hpstate = val;
break;
case MISCREG_HTSTATE:
htstate[tl-1] = val;
break;
case MISCREG_HINTP:
hintp = val;
case MISCREG_HTBA:
htba = val;
break;
case MISCREG_STRAND_STS_REG:
strandStatusReg = val;
break;
case MISCREG_HSTICK_CMPR:
hstick_cmpr = val;
break;
/** Floating Point Status Register */
case MISCREG_FSR:
fsr = val;
DPRINTF(MiscRegs, "FSR written with: %#x\n", fsr);
break;
case MISCREG_MMU_P_CONTEXT:
priContext = val;
break;
case MISCREG_MMU_S_CONTEXT:
secContext = val;
break;
case MISCREG_MMU_PART_ID:
partId = val;
break;
case MISCREG_MMU_LSU_CTRL:
lsuCtrlReg = val;
break;
case MISCREG_SCRATCHPAD_R0:
scratchPad[0] = val;
break;
case MISCREG_SCRATCHPAD_R1:
scratchPad[1] = val;
break;
case MISCREG_SCRATCHPAD_R2:
scratchPad[2] = val;
break;
case MISCREG_SCRATCHPAD_R3:
scratchPad[3] = val;
break;
case MISCREG_SCRATCHPAD_R4:
scratchPad[4] = val;
break;
case MISCREG_SCRATCHPAD_R5:
scratchPad[5] = val;
break;
case MISCREG_SCRATCHPAD_R6:
scratchPad[6] = val;
break;
case MISCREG_SCRATCHPAD_R7:
scratchPad[7] = val;
break;
case MISCREG_QUEUE_CPU_MONDO_HEAD:
cpu_mondo_head = val;
break;
case MISCREG_QUEUE_CPU_MONDO_TAIL:
cpu_mondo_tail = val;
break;
case MISCREG_QUEUE_DEV_MONDO_HEAD:
dev_mondo_head = val;
break;
case MISCREG_QUEUE_DEV_MONDO_TAIL:
dev_mondo_tail = val;
break;
case MISCREG_QUEUE_RES_ERROR_HEAD:
res_error_head = val;
break;
case MISCREG_QUEUE_RES_ERROR_TAIL:
res_error_tail = val;
break;
case MISCREG_QUEUE_NRES_ERROR_HEAD:
nres_error_head = val;
break;
case MISCREG_QUEUE_NRES_ERROR_TAIL:
nres_error_tail = val;
break;
default:
panic("Miscellaneous register %d not implemented\n", miscReg);
}
}
void
ISA::setMiscReg(int miscReg, MiscReg val, ThreadContext * tc)
{
MiscReg new_val = val;
switch (miscReg) {
case MISCREG_ASI:
tc->getDecoderPtr()->setContext(val);
break;
case MISCREG_STICK:
case MISCREG_TICK:
// stick and tick are same thing on niagra
// use stick for offset and tick for holding intrrupt bit
stick = mbits(val,62,0) - tc->getCpuPtr()->instCount();
tick = mbits(val,63,63);
DPRINTF(Timer, "Writing TICK=%#X\n", val);
break;
case MISCREG_FPRS:
// Configure the fpu based on the fprs
break;
case MISCREG_PCR:
// Set up performance counting based on pcr value
break;
case MISCREG_PSTATE:
pstate = val & PstateMask;
return;
case MISCREG_TL:
{
tl = val;
if (hpstate.tlz && tl == 0 && !hpstate.hpriv)
tc->getCpuPtr()->postInterrupt(0, IT_TRAP_LEVEL_ZERO, 0);
else
tc->getCpuPtr()->clearInterrupt(0, IT_TRAP_LEVEL_ZERO, 0);
return;
}
case MISCREG_CWP:
new_val = val >= NWindows ? NWindows - 1 : val;
if (val >= NWindows)
new_val = NWindows - 1;
installWindow(new_val, CurrentWindowOffset);
installWindow(new_val - 1, NextWindowOffset);
installWindow(new_val + 1, PreviousWindowOffset);
break;
case MISCREG_GL:
installGlobals(val, CurrentGlobalsOffset);
installGlobals(val, NextGlobalsOffset);
installGlobals(val, PreviousGlobalsOffset);
break;
case MISCREG_PIL:
case MISCREG_SOFTINT:
case MISCREG_SOFTINT_SET:
case MISCREG_SOFTINT_CLR:
case MISCREG_TICK_CMPR:
case MISCREG_STICK_CMPR:
case MISCREG_HINTP:
case MISCREG_HTSTATE:
case MISCREG_HTBA:
case MISCREG_HVER:
case MISCREG_STRAND_STS_REG:
case MISCREG_HSTICK_CMPR:
case MISCREG_QUEUE_CPU_MONDO_HEAD:
case MISCREG_QUEUE_CPU_MONDO_TAIL:
case MISCREG_QUEUE_DEV_MONDO_HEAD:
case MISCREG_QUEUE_DEV_MONDO_TAIL:
case MISCREG_QUEUE_RES_ERROR_HEAD:
case MISCREG_QUEUE_RES_ERROR_TAIL:
case MISCREG_QUEUE_NRES_ERROR_HEAD:
case MISCREG_QUEUE_NRES_ERROR_TAIL:
case MISCREG_HPSTATE:
setFSReg(miscReg, val, tc);
return;
}
setMiscRegNoEffect(miscReg, new_val);
}
void
sim: Refactor the serialization base class Objects that are can be serialized are supposed to inherit from the Serializable class. This class is meant to provide a unified API for such objects. However, so far it has mainly been used by SimObjects due to some fundamental design limitations. This changeset redesigns to the serialization interface to make it more generic and hide the underlying checkpoint storage. Specifically: * Add a set of APIs to serialize into a subsection of the current object. Previously, objects that needed this functionality would use ad-hoc solutions using nameOut() and section name generation. In the new world, an object that implements the interface has the methods serializeSection() and unserializeSection() that serialize into a named /subsection/ of the current object. Calling serialize() serializes an object into the current section. * Move the name() method from Serializable to SimObject as it is no longer needed for serialization. The fully qualified section name is generated by the main serialization code on the fly as objects serialize sub-objects. * Add a scoped ScopedCheckpointSection helper class. Some objects need to serialize data structures, that are not deriving from Serializable, into subsections. Previously, this was done using nameOut() and manual section name generation. To simplify this, this changeset introduces a ScopedCheckpointSection() helper class. When this class is instantiated, it adds a new /subsection/ and subsequent serialization calls during the lifetime of this helper class happen inside this section (or a subsection in case of nested sections). * The serialize() call is now const which prevents accidental state manipulation during serialization. Objects that rely on modifying state can use the serializeOld() call instead. The default implementation simply calls serialize(). Note: The old-style calls need to be explicitly called using the serializeOld()/serializeSectionOld() style APIs. These are used by default when serializing SimObjects. * Both the input and output checkpoints now use their own named types. This hides underlying checkpoint implementation from objects that need checkpointing and makes it easier to change the underlying checkpoint storage code.
2015-07-07 10:51:03 +02:00
ISA::serialize(CheckpointOut &cp) const
{
SERIALIZE_SCALAR(asi);
SERIALIZE_SCALAR(tick);
SERIALIZE_SCALAR(fprs);
SERIALIZE_SCALAR(gsr);
SERIALIZE_SCALAR(softint);
SERIALIZE_SCALAR(tick_cmpr);
SERIALIZE_SCALAR(stick);
SERIALIZE_SCALAR(stick_cmpr);
SERIALIZE_ARRAY(tpc,MaxTL);
SERIALIZE_ARRAY(tnpc,MaxTL);
SERIALIZE_ARRAY(tstate,MaxTL);
SERIALIZE_ARRAY(tt,MaxTL);
SERIALIZE_SCALAR(tba);
SERIALIZE_SCALAR((uint16_t)pstate);
SERIALIZE_SCALAR(tl);
SERIALIZE_SCALAR(pil);
SERIALIZE_SCALAR(cwp);
SERIALIZE_SCALAR(gl);
SERIALIZE_SCALAR((uint64_t)hpstate);
SERIALIZE_ARRAY(htstate,MaxTL);
SERIALIZE_SCALAR(hintp);
SERIALIZE_SCALAR(htba);
SERIALIZE_SCALAR(hstick_cmpr);
SERIALIZE_SCALAR(strandStatusReg);
SERIALIZE_SCALAR(fsr);
SERIALIZE_SCALAR(priContext);
SERIALIZE_SCALAR(secContext);
SERIALIZE_SCALAR(partId);
SERIALIZE_SCALAR(lsuCtrlReg);
SERIALIZE_ARRAY(scratchPad,8);
SERIALIZE_SCALAR(cpu_mondo_head);
SERIALIZE_SCALAR(cpu_mondo_tail);
SERIALIZE_SCALAR(dev_mondo_head);
SERIALIZE_SCALAR(dev_mondo_tail);
SERIALIZE_SCALAR(res_error_head);
SERIALIZE_SCALAR(res_error_tail);
SERIALIZE_SCALAR(nres_error_head);
SERIALIZE_SCALAR(nres_error_tail);
Tick tick_cmp = 0, stick_cmp = 0, hstick_cmp = 0;
ThreadContext *tc = NULL;
BaseCPU *cpu = NULL;
int tc_num = 0;
bool tick_intr_sched = true;
if (tickCompare)
tc = tickCompare->getTC();
else if (sTickCompare)
tc = sTickCompare->getTC();
else if (hSTickCompare)
tc = hSTickCompare->getTC();
else
tick_intr_sched = false;
SERIALIZE_SCALAR(tick_intr_sched);
if (tc) {
cpu = tc->getCpuPtr();
tc_num = cpu->findContext(tc);
if (tickCompare && tickCompare->scheduled())
tick_cmp = tickCompare->when();
if (sTickCompare && sTickCompare->scheduled())
stick_cmp = sTickCompare->when();
if (hSTickCompare && hSTickCompare->scheduled())
hstick_cmp = hSTickCompare->when();
SERIALIZE_OBJPTR(cpu);
SERIALIZE_SCALAR(tc_num);
SERIALIZE_SCALAR(tick_cmp);
SERIALIZE_SCALAR(stick_cmp);
SERIALIZE_SCALAR(hstick_cmp);
}
}
void
sim: Refactor the serialization base class Objects that are can be serialized are supposed to inherit from the Serializable class. This class is meant to provide a unified API for such objects. However, so far it has mainly been used by SimObjects due to some fundamental design limitations. This changeset redesigns to the serialization interface to make it more generic and hide the underlying checkpoint storage. Specifically: * Add a set of APIs to serialize into a subsection of the current object. Previously, objects that needed this functionality would use ad-hoc solutions using nameOut() and section name generation. In the new world, an object that implements the interface has the methods serializeSection() and unserializeSection() that serialize into a named /subsection/ of the current object. Calling serialize() serializes an object into the current section. * Move the name() method from Serializable to SimObject as it is no longer needed for serialization. The fully qualified section name is generated by the main serialization code on the fly as objects serialize sub-objects. * Add a scoped ScopedCheckpointSection helper class. Some objects need to serialize data structures, that are not deriving from Serializable, into subsections. Previously, this was done using nameOut() and manual section name generation. To simplify this, this changeset introduces a ScopedCheckpointSection() helper class. When this class is instantiated, it adds a new /subsection/ and subsequent serialization calls during the lifetime of this helper class happen inside this section (or a subsection in case of nested sections). * The serialize() call is now const which prevents accidental state manipulation during serialization. Objects that rely on modifying state can use the serializeOld() call instead. The default implementation simply calls serialize(). Note: The old-style calls need to be explicitly called using the serializeOld()/serializeSectionOld() style APIs. These are used by default when serializing SimObjects. * Both the input and output checkpoints now use their own named types. This hides underlying checkpoint implementation from objects that need checkpointing and makes it easier to change the underlying checkpoint storage code.
2015-07-07 10:51:03 +02:00
ISA::unserialize(CheckpointIn &cp)
{
UNSERIALIZE_SCALAR(asi);
UNSERIALIZE_SCALAR(tick);
UNSERIALIZE_SCALAR(fprs);
UNSERIALIZE_SCALAR(gsr);
UNSERIALIZE_SCALAR(softint);
UNSERIALIZE_SCALAR(tick_cmpr);
UNSERIALIZE_SCALAR(stick);
UNSERIALIZE_SCALAR(stick_cmpr);
UNSERIALIZE_ARRAY(tpc,MaxTL);
UNSERIALIZE_ARRAY(tnpc,MaxTL);
UNSERIALIZE_ARRAY(tstate,MaxTL);
UNSERIALIZE_ARRAY(tt,MaxTL);
UNSERIALIZE_SCALAR(tba);
{
uint16_t pstate;
UNSERIALIZE_SCALAR(pstate);
this->pstate = pstate;
}
UNSERIALIZE_SCALAR(tl);
UNSERIALIZE_SCALAR(pil);
UNSERIALIZE_SCALAR(cwp);
UNSERIALIZE_SCALAR(gl);
reloadRegMap();
{
uint64_t hpstate;
UNSERIALIZE_SCALAR(hpstate);
this->hpstate = hpstate;
}
UNSERIALIZE_ARRAY(htstate,MaxTL);
UNSERIALIZE_SCALAR(hintp);
UNSERIALIZE_SCALAR(htba);
UNSERIALIZE_SCALAR(hstick_cmpr);
UNSERIALIZE_SCALAR(strandStatusReg);
UNSERIALIZE_SCALAR(fsr);
UNSERIALIZE_SCALAR(priContext);
UNSERIALIZE_SCALAR(secContext);
UNSERIALIZE_SCALAR(partId);
UNSERIALIZE_SCALAR(lsuCtrlReg);
UNSERIALIZE_ARRAY(scratchPad,8);
UNSERIALIZE_SCALAR(cpu_mondo_head);
UNSERIALIZE_SCALAR(cpu_mondo_tail);
UNSERIALIZE_SCALAR(dev_mondo_head);
UNSERIALIZE_SCALAR(dev_mondo_tail);
UNSERIALIZE_SCALAR(res_error_head);
UNSERIALIZE_SCALAR(res_error_tail);
UNSERIALIZE_SCALAR(nres_error_head);
UNSERIALIZE_SCALAR(nres_error_tail);
Tick tick_cmp = 0, stick_cmp = 0, hstick_cmp = 0;
ThreadContext *tc = NULL;
BaseCPU *cpu = NULL;
int tc_num;
bool tick_intr_sched;
UNSERIALIZE_SCALAR(tick_intr_sched);
if (tick_intr_sched) {
UNSERIALIZE_OBJPTR(cpu);
if (cpu) {
UNSERIALIZE_SCALAR(tc_num);
UNSERIALIZE_SCALAR(tick_cmp);
UNSERIALIZE_SCALAR(stick_cmp);
UNSERIALIZE_SCALAR(hstick_cmp);
tc = cpu->getContext(tc_num);
if (tick_cmp) {
tickCompare = new TickCompareEvent(this, tc);
schedule(tickCompare, tick_cmp);
}
if (stick_cmp) {
sTickCompare = new STickCompareEvent(this, tc);
schedule(sTickCompare, stick_cmp);
}
if (hstick_cmp) {
hSTickCompare = new HSTickCompareEvent(this, tc);
schedule(hSTickCompare, hstick_cmp);
}
}
}
}
}
SparcISA::ISA *
SparcISAParams::create()
{
return new SparcISA::ISA(this);
}