summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configs/test/fs.py7
-rw-r--r--src/SConscript1
-rw-r--r--src/arch/sparc/isa/base.isa32
-rw-r--r--src/arch/sparc/isa/decoder.isa36
-rw-r--r--src/arch/sparc/isa/formats/basic.isa6
-rw-r--r--src/arch/sparc/isa/formats/branch.isa109
-rw-r--r--src/arch/sparc/isa/formats/integerop.isa145
-rw-r--r--src/arch/sparc/isa/formats/priv.isa20
-rw-r--r--src/arch/sparc/isa/includes.isa6
-rw-r--r--src/arch/sparc/regfile.hh6
-rw-r--r--src/cpu/simple/timing.cc43
-rw-r--r--src/cpu/simple/timing.hh48
-rw-r--r--src/dev/io_device.cc54
-rw-r--r--src/dev/io_device.hh59
-rw-r--r--src/mem/physical.cc63
-rw-r--r--src/mem/physical.hh21
-rw-r--r--src/mem/tport.cc82
-rw-r--r--src/mem/tport.hh134
-rw-r--r--src/python/m5/objects/Device.py2
-rw-r--r--src/python/m5/objects/Pci.py2
20 files changed, 475 insertions, 401 deletions
diff --git a/configs/test/fs.py b/configs/test/fs.py
index bb97d2c64..5468c5924 100644
--- a/configs/test/fs.py
+++ b/configs/test/fs.py
@@ -12,6 +12,7 @@ parser = optparse.OptionParser()
parser.add_option("-d", "--detailed", action="store_true")
parser.add_option("-t", "--timing", action="store_true")
parser.add_option("-m", "--maxtick", type="int")
+parser.add_option("--maxtime", type="float")
parser.add_option("--dual", help="Run full system using dual systems",
action="store_true")
@@ -41,7 +42,7 @@ if options.dual:
root.client.readfile = script('netperf-stream-nt-client.rcS')
root.server.readfile = script('netperf-server.rcS')
else:
- root = TsunamiRoot(clock = '2GHz', system = MyLinuxAlphaSystem(cpu, mem_mode, linux_image))
+ root = TsunamiRoot(clock = '1THz', system = MyLinuxAlphaSystem(cpu, mem_mode, linux_image))
m5.instantiate(root)
@@ -55,6 +56,10 @@ m5.instantiate(root)
if options.maxtick:
exit_event = m5.simulate(options.maxtick)
+elif options.maxtime:
+ simtime = int(options.maxtime * root.clock.value)
+ print "simulating for: ", simtime
+ exit_event = m5.simulate(simtime)
else:
exit_event = m5.simulate()
diff --git a/src/SConscript b/src/SConscript
index 10faf5aaf..812089a00 100644
--- a/src/SConscript
+++ b/src/SConscript
@@ -98,6 +98,7 @@ base_sources = Split('''
mem/packet.cc
mem/physical.cc
mem/port.cc
+ mem/tport.cc
mem/cache/base_cache.cc
mem/cache/cache.cc
diff --git a/src/arch/sparc/isa/base.isa b/src/arch/sparc/isa/base.isa
index 02f7cf61a..b518265aa 100644
--- a/src/arch/sparc/isa/base.isa
+++ b/src/arch/sparc/isa/base.isa
@@ -86,6 +86,11 @@ output header {{
const SymbolTable *symtab) const;
void printReg(std::ostream &os, int reg) const;
+ void printSrcReg(std::ostream &os, int reg) const;
+ void printDestReg(std::ostream &os, int reg) const;
+
+ void printRegArray(std::ostream &os,
+ const RegIndex indexArray[], int num) const;
};
bool passesCondition(uint32_t codes, uint32_t condition);
@@ -150,6 +155,33 @@ output decoder {{
ccprintf(os, "\t%s ", mnemonic);
}
+ void SparcStaticInst::printRegArray(std::ostream &os,
+ const RegIndex indexArray[], int num) const
+ {
+ if(num <= 0)
+ return;
+ printReg(os, indexArray[0]);
+ for(int x = 1; x < num; x++)
+ {
+ os << ", ";
+ printReg(os, indexArray[x]);
+ }
+ }
+
+ void
+ SparcStaticInst::printSrcReg(std::ostream &os, int reg) const
+ {
+ if(_numSrcRegs > reg)
+ printReg(os, _srcRegIdx[reg]);
+ }
+
+ void
+ SparcStaticInst::printDestReg(std::ostream &os, int reg) const
+ {
+ if(_numDestRegs > reg)
+ printReg(os, _destRegIdx[reg]);
+ }
+
void
SparcStaticInst::printReg(std::ostream &os, int reg) const
{
diff --git a/src/arch/sparc/isa/decoder.isa b/src/arch/sparc/isa/decoder.isa
index fa8832920..ca91f6755 100644
--- a/src/arch/sparc/isa/decoder.isa
+++ b/src/arch/sparc/isa/decoder.isa
@@ -39,30 +39,30 @@ decode OP default Unknown::unknown()
{
//Throw an illegal instruction acception
0x0: Trap::illtrap({{fault = new IllegalInstruction;}});
- 0x1: decode BPCC
+ format BranchN
{
- format Branch19
+ 0x1: decode BPCC
{
- 0x0: bpcci({{
+ 0x0: bpcci(19, {{
if(passesCondition(Ccr<3:0>, COND2))
NNPC = xc->readPC() + disp;
else
handle_annul
}});
- 0x2: bpccx({{
+ 0x2: bpccx(19, {{
if(passesCondition(Ccr<7:4>, COND2))
NNPC = xc->readPC() + disp;
else
handle_annul
}});
}
+ 0x2: bicc(22, {{
+ if(passesCondition(Ccr<3:0>, COND2))
+ NNPC = xc->readPC() + disp;
+ else
+ handle_annul
+ }});
}
- 0x2: Branch22::bicc({{
- if(passesCondition(Ccr<3:0>, COND2))
- NNPC = xc->readPC() + disp;
- else
- handle_annul
- }});
0x3: decode RCOND2
{
format BranchSplit
@@ -110,7 +110,7 @@ decode OP default Unknown::unknown()
0x5: Trap::fbpfcc({{fault = new FpDisabled;}});
0x6: Trap::fbfcc({{fault = new FpDisabled;}});
}
- 0x1: Branch30::call({{
+ 0x1: BranchN::call(30, {{
R15 = xc->readPC();
NNPC = R15 + disp;
}});
@@ -325,12 +325,12 @@ decode OP default Unknown::unknown()
0x28: rdasr({{
Rd = xc->readMiscRegWithEffect(RS1 + AsrStart, fault);
}});
- 0x29: rdhpr({{
+ 0x29: HPriv::rdhpr({{
// XXX Need to protect with format that traps non-priv/priv
// access
Rd = xc->readMiscRegWithEffect(RS1 + HprStart, fault);
}});
- 0x2A: rdpr({{
+ 0x2A: Priv::rdpr({{
// XXX Need to protect with format that traps non-priv
// access
Rd = xc->readMiscRegWithEffect(RS1 + PrStart, fault);
@@ -397,15 +397,15 @@ decode OP default Unknown::unknown()
0x0: BasicOperate::saved({{/*Boogy Boogy*/}});
0x1: BasicOperate::restored({{/*Boogy Boogy*/}});
}
- 0x32: wrpr({{
+ 0x32: Priv::wrpr({{
// XXX Need to protect with format that traps non-priv
// access
- xc->setMiscRegWithEffect(RD + PrStart, Rs1 ^ Rs2_or_imm13);
+ fault = xc->setMiscRegWithEffect(RD + PrStart, Rs1 ^ Rs2_or_imm13);
}});
- 0x33: wrhpr({{
+ 0x33: HPriv::wrhpr({{
// XXX Need to protect with format that traps non-priv/priv
// access
- xc->setMiscRegWithEffect(RD + HprStart, Rs1 ^ Rs2_or_imm13);
+ fault = xc->setMiscRegWithEffect(RD + HprStart, Rs1 ^ Rs2_or_imm13);
}});
0x34: Trap::fpop1({{fault = new FpDisabled;}});
0x35: Trap::fpop2({{fault = new FpDisabled;}});
@@ -549,7 +549,7 @@ decode OP default Unknown::unknown()
NNPC = Tnpc + 4;
Tl = Tl - 1;
}});
- 0x1: BasicOperate::retry({{
+ 0x1: Priv::retry({{
if(Tl == 0)
return new IllegalInstruction;
Cwp = Tstate<4:0>;
diff --git a/src/arch/sparc/isa/formats/basic.isa b/src/arch/sparc/isa/formats/basic.isa
index 60432cb6b..0a47a7ffe 100644
--- a/src/arch/sparc/isa/formats/basic.isa
+++ b/src/arch/sparc/isa/formats/basic.isa
@@ -63,7 +63,6 @@ def template BasicExecute {{
{
Fault fault = NoFault;
- %(fp_enable_check)s;
%(op_decl)s;
%(op_rd)s;
%(code)s;
@@ -81,11 +80,6 @@ def template BasicDecode {{
return new %(class_name)s(machInst);
}};
-// Basic decode template, passing mnemonic in as string arg to constructor.
-def template BasicDecodeWithMnemonic {{
- return new %(class_name)s("%(mnemonic)s", machInst);
-}};
-
// The most basic instruction format... used only for a few misc. insts
def format BasicOperate(code, *flags) {{
iop = InstObjParams(name, Name, 'SparcStaticInst',
diff --git a/src/arch/sparc/isa/formats/branch.isa b/src/arch/sparc/isa/formats/branch.isa
index 7d46ce739..8a3f05173 100644
--- a/src/arch/sparc/isa/formats/branch.isa
+++ b/src/arch/sparc/isa/formats/branch.isa
@@ -69,47 +69,18 @@ output header {{
};
/**
- * Base class for branches with 19 bit displacements.
+ * Base class for branches with n bit displacements.
*/
- class Branch19 : public BranchDisp
+ template<int bits>
+ class BranchNBits : public BranchDisp
{
protected:
// Constructor
- Branch19(const char *mnem, MachInst _machInst,
+ BranchNBits(const char *mnem, MachInst _machInst,
OpClass __opClass) :
BranchDisp(mnem, _machInst, __opClass)
{
- disp = sign_ext(DISP19 << 2, 21);
- }
- };
-
- /**
- * Base class for branches with 22 bit displacements.
- */
- class Branch22 : public BranchDisp
- {
- protected:
- // Constructor
- Branch22(const char *mnem, MachInst _machInst,
- OpClass __opClass) :
- BranchDisp(mnem, _machInst, __opClass)
- {
- disp = sign_ext(DISP22 << 2, 24);
- }
- };
-
- /**
- * Base class for branches with 30 bit displacements.
- */
- class Branch30 : public BranchDisp
- {
- protected:
- // Constructor
- Branch30(const char *mnem, MachInst _machInst,
- OpClass __opClass) :
- BranchDisp(mnem, _machInst, __opClass)
- {
- disp = sign_ext(DISP30 << 2, 32);
+ disp = sign_ext(_machInst << 2, bits + 2);
}
};
@@ -149,29 +120,23 @@ output header {{
}};
output decoder {{
+
+ template class BranchNBits<19>;
+
+ template class BranchNBits<22>;
+
+ template class BranchNBits<30>;
+
std::string Branch::generateDisassembly(Addr pc,
const SymbolTable *symtab) const
{
std::stringstream response;
printMnemonic(response, mnemonic);
-
- if (_numSrcRegs > 0)
- {
- printReg(response, _srcRegIdx[0]);
- for(int x = 1; x < _numSrcRegs; x++)
- {
+ printRegArray(response, _srcRegIdx, _numSrcRegs);
+ if(_numDestRegs && _numSrcRegs)
response << ", ";
- printReg(response, _srcRegIdx[x]);
- }
- }
-
- if (_numDestRegs > 0)
- {
- if(_numSrcRegs > 0)
- response << ", ";
- printReg(response, _destRegIdx[0]);
- }
+ printDestReg(response, 0);
return response.str();
}
@@ -182,27 +147,13 @@ output decoder {{
std::stringstream response;
printMnemonic(response, mnemonic);
-
- if (_numSrcRegs > 0)
- {
- printReg(response, _srcRegIdx[0]);
- for(int x = 1; x < _numSrcRegs; x++)
- {
- response << ", ";
- printReg(response, _srcRegIdx[x]);
- }
- }
-
+ printRegArray(response, _srcRegIdx, _numSrcRegs);
if(_numSrcRegs > 0)
response << ", ";
-
ccprintf(response, "0x%x", imm);
-
if (_numDestRegs > 0)
- {
response << ", ";
- printReg(response, _destRegIdx[0]);
- }
+ printDestReg(response, 0);
return response.str();
}
@@ -292,32 +243,10 @@ def format Branch(code, *opt_flags) {{
}};
// Primary format for branch instructions:
-def format Branch19(code, *opt_flags) {{
- code = re.sub(r'handle_annul', handle_annul, code)
- codeBlk = CodeBlock(code)
- iop = InstObjParams(name, Name, 'Branch19', codeBlk, opt_flags)
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- exec_output = BranchExecute.subst(iop)
- decode_block = BasicDecode.subst(iop)
-}};
-
-// Primary format for branch instructions:
-def format Branch22(code, *opt_flags) {{
- code = re.sub(r'handle_annul', handle_annul, code)
- codeBlk = CodeBlock(code)
- iop = InstObjParams(name, Name, 'Branch22', codeBlk, opt_flags)
- header_output = BasicDeclare.subst(iop)
- decoder_output = BasicConstructor.subst(iop)
- exec_output = BranchExecute.subst(iop)
- decode_block = BasicDecode.subst(iop)
-}};
-
-// Primary format for branch instructions:
-def format Branch30(code, *opt_flags) {{
+def format BranchN(bits, code, *opt_flags) {{
code = re.sub(r'handle_annul', handle_annul, code)
codeBlk = CodeBlock(code)
- iop = InstObjParams(name, Name, 'Branch30', codeBlk, opt_flags)
+ iop = InstObjParams(name, Name, "BranchNBits<%d>" % bits, codeBlk, opt_flags)
header_output = BasicDeclare.subst(iop)
decoder_output = BasicConstructor.subst(iop)
exec_output = BranchExecute.subst(iop)
diff --git a/src/arch/sparc/isa/formats/integerop.isa b/src/arch/sparc/isa/formats/integerop.isa
index 1894ce541..27616216e 100644
--- a/src/arch/sparc/isa/formats/integerop.isa
+++ b/src/arch/sparc/isa/formats/integerop.isa
@@ -132,7 +132,7 @@ output header {{
OpClass __opClass) :
IntOpImm(mnem, _machInst, __opClass)
{
- imm = (IMM22 << 10) & 0xFFFFFC00;
+ imm = (IMM22 & 0x3FFFFF) << 10;
}
std::string generateDisassembly(Addr pc,
@@ -157,12 +157,9 @@ output decoder {{
if(!strcmp(mnemonic, "or") && _srcRegIdx[0] == 0)
{
printMnemonic(os, "mov");
- if(_numSrcRegs > 0)
- printReg(os, _srcRegIdx[1]);
+ printSrcReg(os, 1);
ccprintf(os, ", ");
- if(_numDestRegs > 0)
- printReg(os, _destRegIdx[0]);
-
+ printDestReg(os, 0);
return true;
}
return false;
@@ -173,32 +170,24 @@ output decoder {{
{
if(!strcmp(mnemonic, "or"))
{
- if(_srcRegIdx[0] == 0)
+ if(_numSrcRegs > 0 && _srcRegIdx[0] == 0)
{
if(imm == 0)
- {
printMnemonic(os, "clr");
- if(_numDestRegs > 0)
- printReg(os, _destRegIdx[0]);
- return true;
- }
else
{
printMnemonic(os, "mov");
- ccprintf(os, ", 0x%x, ", imm);
- if(_numDestRegs > 0)
- printReg(os, _destRegIdx[0]);
- return true;
+ ccprintf(os, " 0x%x, ", imm);
}
+ printDestReg(os, 0);
+ return true;
}
else if(imm == 0)
{
printMnemonic(os, "mov");
- if(_numSrcRegs > 0)
- printReg(os, _srcRegIdx[0]);
+ printSrcReg(os, 0);
ccprintf(os, ", ");
- if(_numDestRegs > 0)
- printReg(os, _destRegIdx[0]);
+ printDestReg(os, 0);
return true;
}
}
@@ -210,25 +199,13 @@ output decoder {{
{
std::stringstream response;
- if(!printPseudoOps(response, pc, symtab))
- {
- printMnemonic(response, mnemonic);
- if (_numSrcRegs > 0)
- {
- printReg(response, _srcRegIdx[0]);
- for(int x = 1; x < _numSrcRegs; x++)
- {
- response << ", ";
- printReg(response, _srcRegIdx[x]);
- }
- }
- if (_numDestRegs > 0)
- {
- if(_numSrcRegs > 0)
- response << ", ";
- printReg(response, _destRegIdx[0]);
- }
- }
+ if(printPseudoOps(response, pc, symtab))
+ return response.str();
+ printMnemonic(response, mnemonic);
+ printRegArray(response, _srcRegIdx, _numSrcRegs);
+ if(_numDestRegs && _numSrcRegs)
+ response << ", ";
+ printDestReg(response, 0);
return response.str();
}
@@ -237,27 +214,16 @@ output decoder {{
{
std::stringstream response;
- if(!printPseudoOps(response, pc, symtab))
- {
- printMnemonic(response, mnemonic);
- if (_numSrcRegs > 0)
- {
- printReg(response, _srcRegIdx[0]);
- for(int x = 1; x < _numSrcRegs - 1; x++)
- {
- response << ", ";
- printReg(response, _srcRegIdx[x]);
- }
- }
- if(_numSrcRegs > 0)
- response << ", ";
- ccprintf(response, "0x%x", imm);
- if (_numDestRegs > 0)
- {
- response << ", ";
- printReg(response, _destRegIdx[0]);
- }
- }
+ if(printPseudoOps(response, pc, symtab))
+ return response.str();
+ printMnemonic(response, mnemonic);
+ printRegArray(response, _srcRegIdx, _numSrcRegs);
+ if(_numSrcRegs > 0)
+ response << ", ";
+ ccprintf(response, "0x%x", imm);
+ if(_numDestRegs > 0)
+ response << ", ";
+ printDestReg(response, 0);
return response.str();
}
@@ -267,10 +233,8 @@ output decoder {{
std::stringstream response;
printMnemonic(response, mnemonic);
- if(_numSrcRegs > 0)
- response << ", ";
ccprintf(response, "%%hi(0x%x), ", imm);
- printReg(response, _destRegIdx[0]);
+ printDestReg(response, 0);
return response.str();
}
}};
@@ -316,38 +280,29 @@ let {{
return (header_output, decoder_output, exec_output, decode_block)
calcCcCode = '''
- uint8_t tmp_ccriccc;
- uint8_t tmp_ccriccv;
- uint8_t tmp_ccriccz;
- uint8_t tmp_ccriccn;
- uint8_t tmp_ccrxccc;
- uint8_t tmp_ccrxccv;
- uint8_t tmp_ccrxccz;
- uint8_t tmp_ccrxccn;
-
- tmp_ccriccn = (Rd >> 31) & 1;
- tmp_ccriccz = ((Rd & 0xFFFFFFFF) == 0);
- tmp_ccrxccn = (Rd >> 63) & 1;
- tmp_ccrxccz = (Rd == 0);
- tmp_ccriccv = %(ivValue)s & 1;
- tmp_ccriccc = %(icValue)s & 1;
- tmp_ccrxccv = %(xvValue)s & 1;
- tmp_ccrxccc = %(xcValue)s & 1;
-
- Ccr = tmp_ccriccc | tmp_ccriccv << 1 |
- tmp_ccriccz << 2 | tmp_ccriccn << 3|
- tmp_ccrxccc << 4 | tmp_ccrxccv << 5|
- tmp_ccrxccz << 6| tmp_ccrxccn << 7;
-
-
- DPRINTF(Sparc, "in = %%d\\n", (uint16_t)tmp_ccriccn);
- DPRINTF(Sparc, "iz = %%d\\n", (uint16_t)tmp_ccriccz);
- DPRINTF(Sparc, "xn = %%d\\n", (uint16_t)tmp_ccrxccn);
- DPRINTF(Sparc, "xz = %%d\\n", (uint16_t)tmp_ccrxccz);
- DPRINTF(Sparc, "iv = %%d\\n", (uint16_t)tmp_ccriccv);
- DPRINTF(Sparc, "ic = %%d\\n", (uint16_t)tmp_ccriccc);
- DPRINTF(Sparc, "xv = %%d\\n", (uint16_t)tmp_ccrxccv);
- DPRINTF(Sparc, "xc = %%d\\n", (uint16_t)tmp_ccrxccc);
+ uint16_t _ic, _iv, _iz, _in, _xc, _xv, _xz, _xn;
+
+ _in = (Rd >> 31) & 1;
+ _iz = ((Rd & 0xFFFFFFFF) == 0);
+ _xn = (Rd >> 63) & 1;
+ _xz = (Rd == 0);
+ _iv = %(ivValue)s & 1;
+ _ic = %(icValue)s & 1;
+ _xv = %(xvValue)s & 1;
+ _xc = %(xcValue)s & 1;
+
+ Ccr = _ic << 0 | _iv << 1 | _iz << 2 | _in << 3 |
+ _xc << 4 | _xv << 5 | _xz << 6 | _xn << 7;
+
+
+ DPRINTF(Sparc, "in = %%d\\n", _in);
+ DPRINTF(Sparc, "iz = %%d\\n", _iz);
+ DPRINTF(Sparc, "xn = %%d\\n", _xn);
+ DPRINTF(Sparc, "xz = %%d\\n", _xz);
+ DPRINTF(Sparc, "iv = %%d\\n", _iv);
+ DPRINTF(Sparc, "ic = %%d\\n", _ic);
+ DPRINTF(Sparc, "xv = %%d\\n", _xv);
+ DPRINTF(Sparc, "xc = %%d\\n", _xc);
'''
}};
diff --git a/src/arch/sparc/isa/formats/priv.isa b/src/arch/sparc/isa/formats/priv.isa
index 7df59d736..d7ee01519 100644
--- a/src/arch/sparc/isa/formats/priv.isa
+++ b/src/arch/sparc/isa/formats/priv.isa
@@ -72,7 +72,11 @@ output decoder {{
std::string Priv::generateDisassembly(Addr pc,
const SymbolTable *symtab) const
{
- return "Privileged Instruction";
+ std::stringstream response;
+
+ printMnemonic(response, mnemonic);
+
+ return response.str();
}
}};
@@ -87,9 +91,10 @@ def template PrivExecute {{
if(%(check)s)
return new PrivilegedAction;
+ Fault fault = NoFault;
%(code)s;
%(op_wb)s;
- return NoFault;
+ return fault;
}
}};
@@ -116,10 +121,17 @@ let {{
// Primary format for integer operate instructions:
def format Priv(code, *opt_flags) {{
- checkCode = "((xc->readMiscReg(PrStart + MISCREG_PSTATE))<2:2>)"
+ checkCode = '''((xc->readMiscReg(PrStart + MISCREG_PSTATE))<2:2>) ||
+ ((xc->readMiscReg(HprStart + MISCREG_HPSTATE))<2:2>)'''
(header_output, decoder_output,
exec_output, decode_block) = doPrivFormat(code,
- checkCode, name, Name, opt_flags)
+ checkCode, name, Name, opt_flags + ('IprAccessOp',))
}};
+def format HPriv(code, *opt_flags) {{
+ checkCode = "((xc->readMiscReg(HprStart + MISCREG_HPSTATE))<2:2>)"
+ (header_output, decoder_output,
+ exec_output, decode_block) = doPrivFormat(code,
+ checkCode, name, Name, opt_flags + ('IprAccessOp',))
+}};
diff --git a/src/arch/sparc/isa/includes.isa b/src/arch/sparc/isa/includes.isa
index 40afb3722..3783051c4 100644
--- a/src/arch/sparc/isa/includes.isa
+++ b/src/arch/sparc/isa/includes.isa
@@ -36,7 +36,6 @@
output header {{
#include <sstream>
#include <iostream>
-#include <iomanip>
#include "cpu/static_inst.hh"
#include "arch/sparc/faults.hh"
@@ -50,7 +49,6 @@ output decoder {{
#include "base/loader/symtab.hh"
#include "cpu/thread_context.hh" // for Jump::branchTarget()
-#include <math.h>
#if defined(linux)
#include <fenv.h>
#endif
@@ -59,14 +57,10 @@ using namespace SparcISA;
}};
output exec {{
-#include <math.h>
#if defined(linux)
#include <fenv.h>
#endif
-#ifdef FULL_SYSTEM
-//#include "sim/pseudo_inst.hh"
-#endif
#include "cpu/base.hh"
#include "cpu/exetrace.hh"
#include "sim/sim_exit.hh"
diff --git a/src/arch/sparc/regfile.hh b/src/arch/sparc/regfile.hh
index cbeb3c7b9..e5192d684 100644
--- a/src/arch/sparc/regfile.hh
+++ b/src/arch/sparc/regfile.hh
@@ -55,14 +55,12 @@ namespace SparcISA
// NWINDOWS - number of register windows, can be 3 to 32
const int NWindows = 32;
-
const int AsrStart = 0;
const int PrStart = 32;
const int HprStart = 64;
const int MiscStart = 96;
const uint64_t Bit64 = (1ULL << 63);
-
class IntRegFile
{
protected:
@@ -625,11 +623,9 @@ namespace SparcISA
hpstateFields.red = 1;
hpstateFields.hpriv = 1;
hpstateFields.tlz = 0; // this is a guess
-
hintp = 0; // no interrupts pending
hstick_cmprFields.int_dis = 1; // disable timer compare interrupts
hstick_cmprFields.tick_cmpr = 0; // Reset to 0 for pretty printing
-
#else
/* //This sets up the initial state of the processor for usermode processes
pstateFields.priv = 0; //Process runs in user mode
@@ -687,6 +683,8 @@ namespace SparcISA
void copyMiscRegs(ThreadContext * tc);
+ protected:
+
bool isHyperPriv() { return hpstateFields.hpriv; }
bool isPriv() { return hpstateFields.hpriv || pstateFields.priv; }
bool isNonPriv() { return !isPriv(); }
diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc
index 246bcec05..5c1654f7e 100644
--- a/src/cpu/simple/timing.cc
+++ b/src/cpu/simple/timing.cc
@@ -85,8 +85,16 @@ TimingSimpleCPU::CpuPort::recvStatusChange(Status status)
panic("TimingSimpleCPU doesn't expect recvStatusChange callback!");
}
+
+void
+TimingSimpleCPU::CpuPort::TickEvent::schedule(Packet *_pkt, Tick t)
+{
+ pkt = _pkt;
+ Event::schedule(t);
+}
+
TimingSimpleCPU::TimingSimpleCPU(Params *p)
- : BaseSimpleCPU(p), icachePort(this), dcachePort(this)
+ : BaseSimpleCPU(p), icachePort(this, p->clock), dcachePort(this, p->clock)
{
_status = Idle;
ifetch_pkt = dcache_pkt = NULL;
@@ -462,11 +470,26 @@ TimingSimpleCPU::completeIfetch(Packet *pkt)
}
}
+void
+TimingSimpleCPU::IcachePort::ITickEvent::process()
+{
+ cpu->completeIfetch(pkt);
+}
bool
TimingSimpleCPU::IcachePort::recvTiming(Packet *pkt)
{
- cpu->completeIfetch(pkt);
+ // These next few lines could be replaced with something faster
+ // who knows what though
+ Tick time = pkt->req->getTime();
+ while (time < curTick)
+ time += lat;
+
+ if (time == curTick)
+ cpu->completeIfetch(pkt);
+ else
+ tickEvent.schedule(pkt, time);
+
return true;
}
@@ -523,11 +546,25 @@ TimingSimpleCPU::completeDrain()
bool
TimingSimpleCPU::DcachePort::recvTiming(Packet *pkt)
{
- cpu->completeDataAccess(pkt);
+ Tick time = pkt->req->getTime();
+ while (time < curTick)
+ time += lat;
+
+ if (time == curTick)
+ cpu->completeDataAccess(pkt);
+ else
+ tickEvent.schedule(pkt, time);
+
return true;
}
void
+TimingSimpleCPU::DcachePort::DTickEvent::process()
+{
+ cpu->completeDataAccess(pkt);
+}
+
+void
TimingSimpleCPU::DcachePort::recvRetry()
{
// we shouldn't get a retry unless we have a packet that we're
diff --git a/src/cpu/simple/timing.hh b/src/cpu/simple/timing.hh
index ac36e5c99..d03fa4bc0 100644
--- a/src/cpu/simple/timing.hh
+++ b/src/cpu/simple/timing.hh
@@ -74,11 +74,12 @@ class TimingSimpleCPU : public BaseSimpleCPU
{
protected:
TimingSimpleCPU *cpu;
+ Tick lat;
public:
- CpuPort(const std::string &_name, TimingSimpleCPU *_cpu)
- : Port(_name), cpu(_cpu)
+ CpuPort(const std::string &_name, TimingSimpleCPU *_cpu, Tick _lat)
+ : Port(_name), cpu(_cpu), lat(_lat)
{ }
protected:
@@ -92,14 +93,26 @@ class TimingSimpleCPU : public BaseSimpleCPU
virtual void getDeviceAddressRanges(AddrRangeList &resp,
AddrRangeList &snoop)
{ resp.clear(); snoop.clear(); }
+
+ struct TickEvent : public Event
+ {
+ Packet *pkt;
+ TimingSimpleCPU *cpu;
+
+ TickEvent(TimingSimpleCPU *_cpu)
+ :Event(&mainEventQueue), cpu(_cpu) {}
+ const char *description() { return "Timing CPU clock event"; }
+ void schedule(Packet *_pkt, Tick t);
+ };
+
};
class IcachePort : public CpuPort
{
public:
- IcachePort(TimingSimpleCPU *_cpu)
- : CpuPort(_cpu->name() + "-iport", _cpu)
+ IcachePort(TimingSimpleCPU *_cpu, Tick _lat)
+ : CpuPort(_cpu->name() + "-iport", _cpu, _lat), tickEvent(_cpu)
{ }
protected:
@@ -107,14 +120,26 @@ class TimingSimpleCPU : public BaseSimpleCPU
virtual bool recvTiming(Packet *pkt);
virtual void recvRetry();
+
+ struct ITickEvent : public TickEvent
+ {
+
+ ITickEvent(TimingSimpleCPU *_cpu)
+ : TickEvent(_cpu) {}
+ void process();
+ const char *description() { return "Timing CPU clock event"; }
+ };
+
+ ITickEvent tickEvent;
+
};
class DcachePort : public CpuPort
{
public:
- DcachePort(TimingSimpleCPU *_cpu)
- : CpuPort(_cpu->name() + "-dport", _cpu)
+ DcachePort(TimingSimpleCPU *_cpu, Tick _lat)
+ : CpuPort(_cpu->name() + "-dport", _cpu, _lat), tickEvent(_cpu)
{ }
protected:
@@ -122,6 +147,17 @@ class TimingSimpleCPU : public BaseSimpleCPU
virtual bool recvTiming(Packet *pkt);
virtual void recvRetry();
+
+ struct DTickEvent : public TickEvent
+ {
+ DTickEvent(TimingSimpleCPU *_cpu)
+ : TickEvent(_cpu) {}
+ void process();
+ const char *description() { return "Timing CPU clock event"; }
+ };
+
+ DTickEvent tickEvent;
+
};
IcachePort icachePort;
diff --git a/src/dev/io_device.cc b/src/dev/io_device.cc
index 660efabfd..b51a93190 100644
--- a/src/dev/io_device.cc
+++ b/src/dev/io_device.cc
@@ -36,8 +36,7 @@
PioPort::PioPort(PioDevice *dev, System *s, std::string pname)
- : Port(dev->name() + pname), device(dev), sys(s),
- outTiming(0), drainEvent(NULL)
+ : SimpleTimingPort(dev->name() + pname), device(dev), sys(s)
{ }
@@ -61,48 +60,6 @@ PioPort::getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop)
}
-void
-PioPort::recvRetry()
-{
- bool result = true;
- while (result && transmitList.size()) {
- result = Port::sendTiming(transmitList.front());
- if (result)
- transmitList.pop_front();
- }
- if (transmitList.size() == 0 && drainEvent) {
- drainEvent->process();
- drainEvent = NULL;
- }
-}
-
-void
-PioPort::SendEvent::process()
-{
- port->outTiming--;
- assert(port->outTiming >= 0);
- if (port->Port::sendTiming(packet))
- if (port->transmitList.size() == 0 && port->drainEvent) {
- port->drainEvent->process();
- port->drainEvent = NULL;
- }
- return;
-
- port->transmitList.push_back(packet);
-}
-
-void
-PioPort::resendNacked(Packet *pkt) {
- pkt->reinitNacked();
- if (transmitList.size()) {
- transmitList.push_front(pkt);
- } else {
- if (!Port::sendTiming(pkt))
- transmitList.push_front(pkt);
- }
-};
-
-
bool
PioPort::recvTiming(Packet *pkt)
{
@@ -117,15 +74,6 @@ PioPort::recvTiming(Packet *pkt)
return true;
}
-unsigned int
-PioPort::drain(Event *de)
-{
- if (outTiming == 0 && transmitList.size() == 0)
- return 0;
- drainEvent = de;
- return 1;
-}
-
PioDevice::~PioDevice()
{
if (pioPort)
diff --git a/src/dev/io_device.hh b/src/dev/io_device.hh
index fa3f98247..22a32e73a 100644
--- a/src/dev/io_device.hh
+++ b/src/dev/io_device.hh
@@ -37,6 +37,7 @@
#include "mem/packet_impl.hh"
#include "sim/eventq.hh"
#include "sim/sim_object.hh"
+#include "mem/tport.hh"
class Platform;
class PioDevice;
@@ -48,13 +49,9 @@ class System;
* sensitive to an address range use. The port takes all the memory
* access types and roles them into one read() and write() call that the device
* must respond to. The device must also provide the addressRanges() function
- * with which it returns the address ranges it is interested in. An extra
- * sendTiming() function is implemented which takes an delay. In this way the
- * device can immediatly call sendTiming(pkt, time) after processing a request
- * and the request will be handled by the port even if the port bus the device
- * connects to is blocked.
- */
-class PioPort : public Port
+ * with which it returns the address ranges it is interested in. */
+
+class PioPort : public SimpleTimingPort
{
protected:
/** The device that this port serves. */
@@ -64,10 +61,6 @@ class PioPort : public Port
* we are currently operating in. */
System *sys;
- /** A list of outgoing timing response packets that haven't been serviced
- * yet. */
- std::list<Packet*> transmitList;
-
/** The current status of the peer(bus) that we are connected to. */
Status peerStatus;
@@ -82,53 +75,9 @@ class PioPort : public Port
virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop);
- void resendNacked(Packet *pkt);
-
- /**
- * This class is used to implemented sendTiming() with a delay. When a delay
- * is requested a new event is created. When the event time expires it
- * attempts to send the packet. If it cannot, the packet is pushed onto the
- * transmit list to be sent when recvRetry() is called. */
- class SendEvent : public Event
- {
- PioPort *port;
- Packet *packet;
-
- SendEvent(PioPort *p, Packet *pkt, Tick t)
- : Event(&mainEventQueue), port(p), packet(pkt)
- { schedule(curTick + t); }
-
- virtual void process();
-
- virtual const char *description()
- { return "Future scheduled sendTiming event"; }
-
- friend class PioPort;
- };
-
- /** Number of timing requests that are emulating the device timing before
- * attempting to end up on the bus.
- */
- int outTiming;
-
- /** If we need to drain, keep the drain event around until we're done
- * here.*/
- Event *drainEvent;
-
- /** Schedule a sendTiming() event to be called in the future. */
- void sendTiming(Packet *pkt, Tick time)
- { outTiming++; new PioPort::SendEvent(this, pkt, time); }
-
- /** This function is notification that the device should attempt to send a
- * packet again. */
- virtual void recvRetry();
-
public:
PioPort(PioDevice *dev, System *s, std::string pname = "-pioport");
- unsigned int drain(Event *de);
-
- friend class PioPort::SendEvent;
};
diff --git a/src/mem/physical.cc b/src/mem/physical.cc
index 2d66602ab..291c70d8c 100644
--- a/src/mem/physical.cc
+++ b/src/mem/physical.cc
@@ -26,6 +26,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Ron Dreslinski
+ * Ali Saidi
*/
#include <sys/types.h>
@@ -52,24 +53,6 @@
using namespace std;
using namespace TheISA;
-PhysicalMemory::MemResponseEvent::MemResponseEvent(Packet *pkt, MemoryPort* _m)
- : Event(&mainEventQueue, CPU_Tick_Pri), pkt(pkt), memoryPort(_m)
-{
-
- this->setFlags(AutoDelete);
-}
-
-void
-PhysicalMemory::MemResponseEvent::process()
-{
- memoryPort->sendTiming(pkt);
-}
-
-const char *
-PhysicalMemory::MemResponseEvent::description()
-{
- return "Physical Memory Timing Access respnse event";
-}
PhysicalMemory::PhysicalMemory(const string &n, Tick latency)
: MemObject(n),base_addr(0), pmem_addr(NULL), port(NULL), lat(latency)
@@ -124,27 +107,8 @@ PhysicalMemory::deviceBlockSize()
return 0;
}
-bool
-PhysicalMemory::doTimingAccess (Packet *pkt, MemoryPort* memoryPort)
-{
- doFunctionalAccess(pkt);
-
- // turn packet around to go back to requester
- pkt->makeTimingResponse();
- MemResponseEvent* response = new MemResponseEvent(pkt, memoryPort);
- response->schedule(curTick + lat);
-
- return true;
-}
Tick
-PhysicalMemory::doAtomicAccess(Packet *pkt)
-{
- doFunctionalAccess(pkt);
- return lat;
-}
-
-void
PhysicalMemory::doFunctionalAccess(Packet *pkt)
{
assert(pkt->getAddr() + pkt->getSize() < pmem_size);
@@ -170,6 +134,7 @@ PhysicalMemory::doFunctionalAccess(Packet *pkt)
}
pkt->result = Packet::Success;
+ return lat;
}
Port *
@@ -195,7 +160,7 @@ PhysicalMemory::recvStatusChange(Port::Status status)
PhysicalMemory::MemoryPort::MemoryPort(const std::string &_name,
PhysicalMemory *_memory)
- : Port(_name), memory(_memory)
+ : SimpleTimingPort(_name), memory(_memory)
{ }
void
@@ -228,13 +193,20 @@ PhysicalMemory::MemoryPort::deviceBlockSize()
bool
PhysicalMemory::MemoryPort::recvTiming(Packet *pkt)
{
- return memory->doTimingAccess(pkt, this);
+ assert(pkt->result != Packet::Nacked);
+
+ Tick latency = memory->doFunctionalAccess(pkt);
+
+ pkt->makeTimingResponse();
+ sendTiming(pkt, latency);
+
+ return true;
}
Tick
PhysicalMemory::MemoryPort::recvAtomic(Packet *pkt)
{
- return memory->doAtomicAccess(pkt);
+ return memory->doFunctionalAccess(pkt);
}
void
@@ -243,7 +215,16 @@ PhysicalMemory::MemoryPort::recvFunctional(Packet *pkt)
memory->doFunctionalAccess(pkt);
}
-
+unsigned int
+PhysicalMemory::drain(Event *de)
+{
+ int count = port->drain(de);
+ if (count)
+ changeState(Draining);
+ else
+ changeState(Drained);
+ return count;
+}
void
PhysicalMemory::serialize(ostream &os)
diff --git a/src/mem/physical.hh b/src/mem/physical.hh
index 50fa75ed3..b549c1f8b 100644
--- a/src/mem/physical.hh
+++ b/src/mem/physical.hh
@@ -37,7 +37,7 @@
#include "base/range.hh"
#include "mem/mem_object.hh"
#include "mem/packet.hh"
-#include "mem/port.hh"
+#include "mem/tport.hh"
#include "sim/eventq.hh"
#include <map>
#include <string>
@@ -47,7 +47,7 @@
//
class PhysicalMemory : public MemObject
{
- class MemoryPort : public Port
+ class MemoryPort : public SimpleTimingPort
{
PhysicalMemory *memory;
@@ -74,16 +74,6 @@ class PhysicalMemory : public MemObject
int numPorts;
- struct MemResponseEvent : public Event
- {
- Packet *pkt;
- MemoryPort *memoryPort;
-
- MemResponseEvent(Packet *pkt, MemoryPort *memoryPort);
- void process();
- const char *description();
- };
-
private:
// prevent copying of a MainMemory object
PhysicalMemory(const PhysicalMemory &specmem);
@@ -110,13 +100,10 @@ class PhysicalMemory : public MemObject
void getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop);
virtual Port *getPort(const std::string &if_name, int idx = -1);
void virtual init();
+ unsigned int drain(Event *de);
- // fast back-door memory access for vtophys(), remote gdb, etc.
- // uint64_t phys_read_qword(Addr addr) const;
private:
- bool doTimingAccess(Packet *pkt, MemoryPort *memoryPort);
- Tick doAtomicAccess(Packet *pkt);
- void doFunctionalAccess(Packet *pkt);
+ Tick doFunctionalAccess(Packet *pkt);
void recvStatusChange(Port::Status status);
diff --git a/src/mem/tport.cc b/src/mem/tport.cc
new file mode 100644
index 000000000..90cf68f02
--- /dev/null
+++ b/src/mem/tport.cc
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Ali Saidi
+ */
+
+#include "mem/tport.hh"
+
+void
+SimpleTimingPort::recvRetry()
+{
+ bool result = true;
+ while (result && transmitList.size()) {
+ result = Port::sendTiming(transmitList.front());
+ if (result)
+ transmitList.pop_front();
+ }
+ if (transmitList.size() == 0 && drainEvent) {
+ drainEvent->process();
+ drainEvent = NULL;
+ }
+}
+
+void
+SimpleTimingPort::SendEvent::process()
+{
+ port->outTiming--;
+ assert(port->outTiming >= 0);
+ if (port->Port::sendTiming(packet))
+ if (port->transmitList.size() == 0 && port->drainEvent) {
+ port->drainEvent->process();
+ port->drainEvent = NULL;
+ }
+ return;
+
+ port->transmitList.push_back(packet);
+}
+
+void
+SimpleTimingPort::resendNacked(Packet *pkt) {
+ pkt->reinitNacked();
+ if (transmitList.size()) {
+ transmitList.push_front(pkt);
+ } else {
+ if (!Port::sendTiming(pkt))
+ transmitList.push_front(pkt);
+ }
+};
+
+
+unsigned int
+SimpleTimingPort::drain(Event *de)
+{
+ if (outTiming == 0 && transmitList.size() == 0)
+ return 0;
+ drainEvent = de;
+ return 1;
+}
diff --git a/src/mem/tport.hh b/src/mem/tport.hh
new file mode 100644
index 000000000..5473e945e
--- /dev/null
+++ b/src/mem/tport.hh
@@ -0,0 +1,134 @@
+/*
+ * 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
+ * Implement a port which adds simple support of a sendTiming() function that
+ * takes a delay. In this way the * device can immediatly call
+ * sendTiming(pkt, time) after processing a request and the request will be
+ * handled by the port even if the port bus the device connects to is blocked.
+ */
+
+/** recvTiming and drain should be implemented something like this when this
+ * class is used.
+
+bool
+PioPort::recvTiming(Packet *pkt)
+{
+ if (pkt->result == Packet::Nacked) {
+ resendNacked(pkt);
+ } else {
+ Tick latency = device->recvAtomic(pkt);
+ // turn packet around to go back to requester
+ pkt->makeTimingResponse();
+ sendTiming(pkt, latency);
+ }
+ return true;
+}
+
+PioDevice::drain(Event *de)
+{
+ unsigned int count;
+ count = SimpleTimingPort->drain(de);
+ if (count)
+ changeState(Draining);
+ else
+ changeState(Drained);
+ return count;
+}
+*/
+
+#ifndef __MEM_TPORT_HH__
+#define __MEM_TPORT_HH__
+
+#include "mem/port.hh"
+#include "sim/eventq.hh"
+#include <list>
+#include <string>
+
+class SimpleTimingPort : public Port
+{
+ protected:
+ /** A list of outgoing timing response packets that haven't been serviced
+ * yet. */
+ std::list<Packet*> transmitList;
+ /**
+ * This class is used to implemented sendTiming() with a delay. When a delay
+ * is requested a new event is created. When the event time expires it
+ * attempts to send the packet. If it cannot, the packet is pushed onto the
+ * transmit list to be sent when recvRetry() is called. */
+ class SendEvent : public Event
+ {
+ SimpleTimingPort *port;
+ Packet *packet;
+
+ SendEvent(SimpleTimingPort *p, Packet *pkt, Tick t)
+ : Event(&mainEventQueue), port(p), packet(pkt)
+ { setFlags(AutoDelete); schedule(curTick + t); }
+
+ virtual void process();
+
+ virtual const char *description()
+ { return "Future scheduled sendTiming event"; }
+
+ friend class SimpleTimingPort;
+ };
+
+
+ /** Number of timing requests that are emulating the device timing before
+ * attempting to end up on the bus.
+ */
+ int outTiming;
+
+ /** If we need to drain, keep the drain event around until we're done
+ * here.*/
+ Event *drainEvent;
+
+ /** Schedule a sendTiming() event to be called in the future. */
+ void sendTiming(Packet *pkt, Tick time)
+ { outTiming++; new SimpleTimingPort::SendEvent(this, pkt, time); }
+
+ /** This function is notification that the device should attempt to send a
+ * packet again. */
+ virtual void recvRetry();
+
+ void resendNacked(Packet *pkt);
+ public:
+
+ SimpleTimingPort(std::string pname)
+ : Port(pname), outTiming(0), drainEvent(NULL)
+ {}
+
+ unsigned int drain(Event *de);
+
+ friend class SimpleTimingPort::SendEvent;
+};
+
+#endif // __MEM_TPORT_HH__
diff --git a/src/python/m5/objects/Device.py b/src/python/m5/objects/Device.py
index 222f750da..f72c8e73f 100644
--- a/src/python/m5/objects/Device.py
+++ b/src/python/m5/objects/Device.py
@@ -12,7 +12,7 @@ class BasicPioDevice(PioDevice):
type = 'BasicPioDevice'
abstract = True
pio_addr = Param.Addr("Device Address")
- pio_latency = Param.Tick(1, "Programmed IO latency in simticks")
+ pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks")
class DmaDevice(PioDevice):
type = 'DmaDevice'
diff --git a/src/python/m5/objects/Pci.py b/src/python/m5/objects/Pci.py
index 29014bb37..cc0d1cf4a 100644
--- a/src/python/m5/objects/Pci.py
+++ b/src/python/m5/objects/Pci.py
@@ -52,7 +52,7 @@ class PciDevice(DmaDevice):
pci_bus = Param.Int("PCI bus")
pci_dev = Param.Int("PCI device number")
pci_func = Param.Int("PCI function code")
- pio_latency = Param.Tick(1, "Programmed IO latency in simticks")
+ pio_latency = Param.Latency('1ns', "Programmed IO latency in simticks")
configdata = Param.PciConfigData(Parent.any, "PCI Config data")
class PciFake(PciDevice):