Merge zizzer:/bk/newmem
into zizzer.eecs.umich.edu:/.automount/zooks/y/ksewell/research/m5-sim/newmem --HG-- extra : convert_revision : c48a8857f5a520ff8061eb3d8f08dcd43661e68c
This commit is contained in:
commit
de8eba6891
43 changed files with 1378 additions and 168 deletions
|
@ -88,12 +88,14 @@ base_sources = Split('''
|
|||
cpu/static_inst.cc
|
||||
cpu/sampler/sampler.cc
|
||||
|
||||
mem/request.cc
|
||||
mem/bridge.cc
|
||||
mem/bus.cc
|
||||
mem/connector.cc
|
||||
mem/mem_object.cc
|
||||
mem/packet.cc
|
||||
mem/physical.cc
|
||||
mem/port.cc
|
||||
mem/bus.cc
|
||||
mem/request.cc
|
||||
|
||||
python/pyconfig.cc
|
||||
python/embedded_py.cc
|
||||
|
|
|
@ -45,7 +45,6 @@ class AlphaSystem : public System
|
|||
{
|
||||
std::string console_path;
|
||||
std::string palcode;
|
||||
std::string boot_osflags;
|
||||
uint64_t system_type;
|
||||
uint64_t system_rev;
|
||||
};
|
||||
|
|
|
@ -57,6 +57,7 @@ full_system_sources = Split('''
|
|||
|
||||
# Syscall emulation (non-full-system) sources
|
||||
syscall_emulation_sources = Split('''
|
||||
linux/linux.cc
|
||||
linux/process.cc
|
||||
process.cc
|
||||
''')
|
||||
|
|
|
@ -16,44 +16,62 @@ decode OP default Unknown::unknown()
|
|||
0x0: bpcci({{
|
||||
if(passesCondition(CcrIcc, COND2))
|
||||
NNPC = xc->readPC() + disp;
|
||||
else
|
||||
handle_annul
|
||||
}});
|
||||
0x2: bpccx({{
|
||||
if(passesCondition(CcrXcc, COND2))
|
||||
NNPC = xc->readPC() + disp;
|
||||
else
|
||||
handle_annul
|
||||
}});
|
||||
}
|
||||
}
|
||||
0x2: Branch22::bicc({{
|
||||
if(passesCondition(CcrIcc, COND2))
|
||||
NNPC = xc->readPC() + disp;
|
||||
else
|
||||
handle_annul
|
||||
}});
|
||||
0x3: decode RCOND2
|
||||
{
|
||||
format BranchSplit
|
||||
{
|
||||
0x1: bpreq({{
|
||||
if(Rs1 == 0)
|
||||
if(Rs1.sdw == 0)
|
||||
NNPC = xc->readPC() + disp;
|
||||
else
|
||||
handle_annul
|
||||
}});
|
||||
0x2: bprle({{
|
||||
if(Rs1 <= 0)
|
||||
if(Rs1.sdw <= 0)
|
||||
NNPC = xc->readPC() + disp;
|
||||
else
|
||||
handle_annul
|
||||
}});
|
||||
0x3: bprl({{
|
||||
if(Rs1 < 0)
|
||||
if(Rs1.sdw < 0)
|
||||
NNPC = xc->readPC() + disp;
|
||||
else
|
||||
handle_annul
|
||||
}});
|
||||
0x5: bprne({{
|
||||
if(Rs1 != 0)
|
||||
if(Rs1.sdw != 0)
|
||||
NNPC = xc->readPC() + disp;
|
||||
else
|
||||
handle_annul
|
||||
}});
|
||||
0x6: bprg({{
|
||||
if(Rs1 > 0)
|
||||
if(Rs1.sdw > 0)
|
||||
NNPC = xc->readPC() + disp;
|
||||
else
|
||||
handle_annul
|
||||
}});
|
||||
0x7: bprge({{
|
||||
if(Rs1 >= 0)
|
||||
if(Rs1.sdw >= 0)
|
||||
NNPC = xc->readPC() + disp;
|
||||
else
|
||||
handle_annul
|
||||
}});
|
||||
}
|
||||
}
|
||||
|
@ -109,7 +127,7 @@ decode OP default Unknown::unknown()
|
|||
if(Rd.udw<63:31> != 0)
|
||||
Rd.udw = 0x7FFFFFFF;
|
||||
else if(Rd.udw<63:> && Rd.udw<62:31> != 0xFFFFFFFF)
|
||||
Rd.udw = 0xFFFFFFFF80000000;
|
||||
Rd.udw = 0xFFFFFFFF80000000ULL;
|
||||
}
|
||||
}});
|
||||
}
|
||||
|
@ -117,22 +135,22 @@ decode OP default Unknown::unknown()
|
|||
0x10: addcc({{
|
||||
int64_t resTemp, val2 = Rs2_or_imm13;
|
||||
Rd = resTemp = Rs1 + val2;}},
|
||||
{{((Rs1 & 0xFFFFFFFF + val2 & 0xFFFFFFFF) >> 31)}},
|
||||
{{(Rs1<31:0> + val2<31:0>)<32:>}},
|
||||
{{Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>}},
|
||||
{{((Rs1 >> 1) + (val2 >> 1) + (Rs1 & val2 & 0x1))<63:>}},
|
||||
{{(Rs1<63:1> + val2<63:1> + (Rs1 & val2)<0:>)<63:>}},
|
||||
{{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}}
|
||||
);
|
||||
0x11: IntOpCcRes::andcc({{Rd = Rs1 & Rs2_or_imm13;}});
|
||||
0x12: IntOpCcRes::orcc({{Rd = Rs1 | Rs2_or_imm13;}});
|
||||
0x13: IntOpCcRes::xorcc({{Rd = Rs1 ^ Rs2_or_imm13;}});
|
||||
0x14: subcc({{
|
||||
int64_t resTemp, val2 = Rs2_or_imm13;
|
||||
Rd = resTemp = Rs1 - val2;}},
|
||||
{{((Rs1 & 0xFFFFFFFF - val2 & 0xFFFFFFFF) >> 31)}},
|
||||
{{Rs1<31:> != val2<31:> && Rs1<31:> != resTemp<31:>}},
|
||||
{{(((Rs1 >> 1) + (~val2) >> 1) +
|
||||
((Rs1 | ~val2) & 0x1))<63:>}},
|
||||
{{Rs1<63:> != val2<63:> && Rs1<63:> != resTemp<63:>}}
|
||||
int64_t val2 = Rs2_or_imm13;
|
||||
Rd = Rs1 - val2;}},
|
||||
{{(~(Rs1<31:0> + (~val2)<31:0> + 1))<32:>}},
|
||||
{{(Rs1<31:> != val2<31:>) && (Rs1<31:> != Rd<31:>)}},
|
||||
{{(~(Rs1<63:1> + (~val2)<63:1> +
|
||||
(Rs1 | ~val2)<0:>))<63:>}},
|
||||
{{Rs1<63:> != val2<63:> && Rs1<63:> != Rd<63:>}}
|
||||
);
|
||||
0x15: IntOpCcRes::andncc({{Rd = Rs1 & ~Rs2_or_imm13;}});
|
||||
0x16: IntOpCcRes::orncc({{Rd = Rs1 | ~Rs2_or_imm13;}});
|
||||
|
@ -141,11 +159,10 @@ decode OP default Unknown::unknown()
|
|||
int64_t resTemp, val2 = Rs2_or_imm13;
|
||||
int64_t carryin = CcrIccC;
|
||||
Rd = resTemp = Rs1 + val2 + carryin;}},
|
||||
{{((Rs1 & 0xFFFFFFFF + val2 & 0xFFFFFFFF) >> 31
|
||||
+ carryin)}},
|
||||
{{(Rs1<31:0> + val2<31:0> + carryin)<32:>}},
|
||||
{{Rs1<31:> == val2<31:> && val2<31:> != resTemp<31:>}},
|
||||
{{((Rs1 >> 1) + (val2 >> 1) +
|
||||
((Rs1 & val2) | (carryin & (Rs1 | val2)) & 0x1))<63:>}},
|
||||
{{(Rs1<63:1> + val2<63:1> +
|
||||
((Rs1 & val2) | (carryin & (Rs1 | val2)))<0:>)<63:>}},
|
||||
{{Rs1<63:> == val2<63:> && val2<63:> != resTemp<63:>}}
|
||||
);
|
||||
0x1A: umulcc({{
|
||||
|
@ -162,9 +179,9 @@ decode OP default Unknown::unknown()
|
|||
int64_t resTemp, val2 = Rs2_or_imm13;
|
||||
int64_t carryin = CcrIccC;
|
||||
Rd = resTemp = Rs1 + ~(val2 + carryin) + 1;}},
|
||||
{{((Rs1 & 0xFFFFFFFF + (~(val2 + carryin)) & 0xFFFFFFFF + 1) >> 31)}},
|
||||
{{(~((Rs1<31:0> + (~(val2 + carryin))<31:0> + 1))<32:>)}},
|
||||
{{Rs1<31:> != val2<31:> && Rs1<31:> != resTemp<31:>}},
|
||||
{{(((Rs1 >> 1) + (~(val2 + carryin)) >> 1) + ((Rs1 | ~(val2+carryin)) & 0x1))<63:>}},
|
||||
{{(~((Rs1<63:1> + (~(val2 + carryin))<63:1>) + (Rs1<0:> + (~(val2+carryin))<0:> + 1)<63:1>))<63:>}},
|
||||
{{Rs1<63:> != val2<63:> && Rs1<63:> != resTemp<63:>}}
|
||||
);
|
||||
0x1D: udivxcc({{
|
||||
|
@ -197,7 +214,7 @@ decode OP default Unknown::unknown()
|
|||
overflow = (resTemp<63:31> != 0);
|
||||
underflow = (resTemp<63:> && resTemp<62:31> != 0xFFFFFFFF);
|
||||
if(overflow) Rd = resTemp = 0x7FFFFFFF;
|
||||
else if(underflow) Rd = resTemp = 0xFFFFFFFF80000000;
|
||||
else if(underflow) Rd = resTemp = 0xFFFFFFFF80000000ULL;
|
||||
else Rd = resTemp;
|
||||
} }},
|
||||
{{0}},
|
||||
|
@ -333,11 +350,15 @@ decode OP default Unknown::unknown()
|
|||
{
|
||||
0x0: movcci({{
|
||||
if(passesCondition(CcrIcc, COND4))
|
||||
Rd = (I ? SIMM11 : RS2);
|
||||
Rd = Rs2_or_imm11;
|
||||
else
|
||||
Rd = Rd;
|
||||
}});
|
||||
0x2: movccx({{
|
||||
if(passesCondition(CcrXcc, COND4))
|
||||
Rd = (I ? SIMM11 : RS2);
|
||||
Rd = Rs2_or_imm11;
|
||||
else
|
||||
Rd = Rd;
|
||||
}});
|
||||
}
|
||||
}
|
||||
|
@ -356,16 +377,17 @@ decode OP default Unknown::unknown()
|
|||
count += oneBits[temp & 0xF];
|
||||
temp = temp >> 4;
|
||||
}
|
||||
Rd = count;
|
||||
}});
|
||||
}
|
||||
0x2F: decode RCOND3
|
||||
{
|
||||
0x1: movreq({{if(Rs1 == 0) Rd = Rs2_or_imm10;}});
|
||||
0x2: movrle({{if(Rs1 <= 0) Rd = Rs2_or_imm10;}});
|
||||
0x3: movrl({{if(Rs1 < 0) Rd = Rs2_or_imm10;}});
|
||||
0x5: movrne({{if(Rs1 != 0) Rd = Rs2_or_imm10;}});
|
||||
0x6: movrg({{if(Rs1 > 0) Rd = Rs2_or_imm10;}});
|
||||
0x7: movrge({{if(Rs1 >= 0) Rd = Rs2_or_imm10;}});
|
||||
0x1: movreq({{Rd = (Rs1 == 0) ? Rs2_or_imm10 : Rd;}});
|
||||
0x2: movrle({{Rd = (Rs1 <= 0) ? Rs2_or_imm10 : Rd;}});
|
||||
0x3: movrl({{Rd = (Rs1 < 0) ? Rs2_or_imm10 : Rd;}});
|
||||
0x5: movrne({{Rd = (Rs1 != 0) ? Rs2_or_imm10 : Rd;}});
|
||||
0x6: movrg({{Rd = (Rs1 > 0) ? Rs2_or_imm10 : Rd;}});
|
||||
0x7: movrge({{Rd = (Rs1 >= 0) ? Rs2_or_imm10 : Rd;}});
|
||||
}
|
||||
0x30: decode RD {
|
||||
0x0: wry({{Y = Rs1 ^ Rs2_or_imm13;}});
|
||||
|
|
|
@ -194,7 +194,7 @@ output decoder {{
|
|||
{
|
||||
ccprintf(response, " <%s", symbol);
|
||||
if(symbolAddr != target)
|
||||
ccprintf(response, "+0x%x>", target - symbolAddr);
|
||||
ccprintf(response, "+%d>", target - symbolAddr);
|
||||
else
|
||||
ccprintf(response, ">");
|
||||
}
|
||||
|
@ -226,8 +226,25 @@ def template BranchExecute {{
|
|||
}
|
||||
}};
|
||||
|
||||
let {{
|
||||
handle_annul = '''
|
||||
{
|
||||
if(A)
|
||||
{
|
||||
NPC = xc->readNextNPC();
|
||||
NNPC = NPC + 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
NPC = xc->readNextPC();
|
||||
NNPC = xc->readNextNPC();
|
||||
}
|
||||
}'''
|
||||
}};
|
||||
|
||||
// Primary format for branch instructions:
|
||||
def format Branch(code, *opt_flags) {{
|
||||
code = re.sub(r'handle_annul', handle_annul, code)
|
||||
(usesImm, code, immCode,
|
||||
rString, iString) = splitOutImm(code)
|
||||
iop = InstObjParams(name, Name, 'Branch', code, opt_flags)
|
||||
|
@ -247,6 +264,7 @@ 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)
|
||||
|
@ -257,6 +275,7 @@ def format Branch19(code, *opt_flags) {{
|
|||
|
||||
// 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)
|
||||
|
@ -267,6 +286,7 @@ def format Branch22(code, *opt_flags) {{
|
|||
|
||||
// Primary format for branch instructions:
|
||||
def format Branch30(code, *opt_flags) {{
|
||||
code = re.sub(r'handle_annul', handle_annul, code)
|
||||
codeBlk = CodeBlock(code)
|
||||
iop = InstObjParams(name, Name, 'Branch30', codeBlk, opt_flags)
|
||||
header_output = BasicDeclare.subst(iop)
|
||||
|
@ -277,6 +297,7 @@ def format Branch30(code, *opt_flags) {{
|
|||
|
||||
// Primary format for branch instructions:
|
||||
def format BranchSplit(code, *opt_flags) {{
|
||||
code = re.sub(r'handle_annul', handle_annul, code)
|
||||
codeBlk = CodeBlock(code)
|
||||
iop = InstObjParams(name, Name, 'BranchSplit', codeBlk, opt_flags)
|
||||
header_output = BasicDeclare.subst(iop)
|
||||
|
|
|
@ -61,6 +61,21 @@ output header {{
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Base class for 11 bit immediate integer operations.
|
||||
*/
|
||||
class IntOpImm11 : public IntOpImm
|
||||
{
|
||||
protected:
|
||||
// Constructor
|
||||
IntOpImm11(const char *mnem, ExtMachInst _machInst,
|
||||
OpClass __opClass) :
|
||||
IntOpImm(mnem, _machInst, __opClass)
|
||||
{
|
||||
imm = sign_ext(SIMM11, 11);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Base class for 13 bit immediate integer operations.
|
||||
*/
|
||||
|
@ -271,14 +286,22 @@ let {{
|
|||
return (header_output, decoder_output, exec_output, decode_block)
|
||||
|
||||
calcCcCode = '''
|
||||
CcrIccN = (Rd >> 63) & 1;
|
||||
CcrIccZ = (Rd == 0);
|
||||
CcrXccN = (Rd >> 31) & 1;
|
||||
CcrXccZ = ((Rd & 0xFFFFFFFF) == 0);
|
||||
CcrIccN = (Rd >> 31) & 1;
|
||||
CcrIccZ = ((Rd & 0xFFFFFFFF) == 0);
|
||||
CcrXccN = (Rd >> 63) & 1;
|
||||
CcrXccZ = (Rd == 0);
|
||||
CcrIccV = %(ivValue)s;
|
||||
CcrIccC = %(icValue)s;
|
||||
CcrXccV = %(xvValue)s;
|
||||
CcrXccC = %(xcValue)s;
|
||||
DPRINTF(Sparc, "in = %%d\\n", CcrIccN);
|
||||
DPRINTF(Sparc, "iz = %%d\\n", CcrIccZ);
|
||||
DPRINTF(Sparc, "xn = %%d\\n", CcrXccN);
|
||||
DPRINTF(Sparc, "xz = %%d\\n", CcrXccZ);
|
||||
DPRINTF(Sparc, "iv = %%d\\n", CcrIccV);
|
||||
DPRINTF(Sparc, "ic = %%d\\n", CcrIccC);
|
||||
DPRINTF(Sparc, "xv = %%d\\n", CcrXccV);
|
||||
DPRINTF(Sparc, "xc = %%d\\n", CcrXccC);
|
||||
'''
|
||||
}};
|
||||
|
||||
|
|
|
@ -30,8 +30,9 @@ output header {{
|
|||
|
||||
// Constructor
|
||||
MemImm(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
|
||||
Mem(mnem, _machInst, __opClass), imm(SIMM13)
|
||||
Mem(mnem, _machInst, __opClass)
|
||||
{
|
||||
imm = sign_ext(SIMM13, 13);
|
||||
}
|
||||
|
||||
std::string generateDisassembly(Addr pc,
|
||||
|
@ -84,7 +85,10 @@ output decoder {{
|
|||
}
|
||||
ccprintf(response, "[ ");
|
||||
printReg(response, _srcRegIdx[!save ? 0 : 1]);
|
||||
if(imm >= 0)
|
||||
ccprintf(response, " + 0x%x ]", imm);
|
||||
else
|
||||
ccprintf(response, " + -0x%x ]", -imm);
|
||||
if(load)
|
||||
{
|
||||
ccprintf(response, ", ");
|
||||
|
@ -104,6 +108,7 @@ def template MemExecute {{
|
|||
%(op_decl)s;
|
||||
%(op_rd)s;
|
||||
%(ea_code)s;
|
||||
DPRINTF(Sparc, "The address is 0x%x\n", EA);
|
||||
%(load)s;
|
||||
%(code)s;
|
||||
%(store)s;
|
||||
|
@ -126,7 +131,7 @@ let {{
|
|||
|
||||
def doMemFormat(code, load, store, name, Name, opt_flags):
|
||||
addrCalcReg = 'EA = Rs1 + Rs2;'
|
||||
addrCalcImm = 'EA = Rs1 + SIMM13;'
|
||||
addrCalcImm = 'EA = Rs1 + imm;'
|
||||
iop = InstObjParams(name, Name, 'Mem', code,
|
||||
opt_flags, ("ea_code", addrCalcReg),
|
||||
("load", load), ("store", store))
|
||||
|
|
68
arch/sparc/linux/linux.cc
Normal file
68
arch/sparc/linux/linux.cc
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2005 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "arch/sparc/linux/linux.hh"
|
||||
|
||||
// open(2) flags translation table
|
||||
OpenFlagTransTable SparcLinux::openFlagTable[] = {
|
||||
#ifdef _MSC_VER
|
||||
{ SparcLinux::TGT_O_RDONLY, _O_RDONLY },
|
||||
{ SparcLinux::TGT_O_WRONLY, _O_WRONLY },
|
||||
{ SparcLinux::TGT_O_RDWR, _O_RDWR },
|
||||
{ SparcLinux::TGT_O_APPEND, _O_APPEND },
|
||||
{ SparcLinux::TGT_O_CREAT, _O_CREAT },
|
||||
{ SparcLinux::TGT_O_TRUNC, _O_TRUNC },
|
||||
{ SparcLinux::TGT_O_EXCL, _O_EXCL },
|
||||
#ifdef _O_NONBLOCK
|
||||
{ SparcLinux::TGT_O_NONBLOCK, _O_NONBLOCK },
|
||||
#endif
|
||||
#ifdef _O_NOCTTY
|
||||
{ SparcLinux::TGT_O_NOCTTY, _O_NOCTTY },
|
||||
#endif
|
||||
#ifdef _O_SYNC
|
||||
{ SparcLinux::TGT_O_SYNC, _O_SYNC },
|
||||
#endif
|
||||
#else /* !_MSC_VER */
|
||||
{ SparcLinux::TGT_O_RDONLY, O_RDONLY },
|
||||
{ SparcLinux::TGT_O_WRONLY, O_WRONLY },
|
||||
{ SparcLinux::TGT_O_RDWR, O_RDWR },
|
||||
{ SparcLinux::TGT_O_APPEND, O_APPEND },
|
||||
{ SparcLinux::TGT_O_CREAT, O_CREAT },
|
||||
{ SparcLinux::TGT_O_TRUNC, O_TRUNC },
|
||||
{ SparcLinux::TGT_O_EXCL, O_EXCL },
|
||||
{ SparcLinux::TGT_O_NONBLOCK, O_NONBLOCK },
|
||||
{ SparcLinux::TGT_O_NOCTTY, O_NOCTTY },
|
||||
#ifdef O_SYNC
|
||||
{ SparcLinux::TGT_O_SYNC, O_SYNC },
|
||||
#endif
|
||||
#endif /* _MSC_VER */
|
||||
};
|
||||
|
||||
const int SparcLinux::NUM_OPEN_FLAGS =
|
||||
(sizeof(SparcLinux::openFlagTable)/sizeof(SparcLinux::openFlagTable[0]));
|
||||
|
61
arch/sparc/linux/linux.hh
Normal file
61
arch/sparc/linux/linux.hh
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (c) 2003-2005 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __MIPS_MIPS_LINUX_HH
|
||||
#define __MIPS_MIPS_LINUX_HH
|
||||
|
||||
#include "kern/linux/linux.hh"
|
||||
|
||||
class SparcLinux : public Linux
|
||||
{
|
||||
public:
|
||||
|
||||
static OpenFlagTransTable openFlagTable[];
|
||||
|
||||
static const int TGT_O_RDONLY = 0x00000000; //!< O_RDONLY
|
||||
static const int TGT_O_WRONLY = 0x00000001; //!< O_WRONLY
|
||||
static const int TGT_O_RDWR = 0x00000002; //!< O_RDWR
|
||||
static const int TGT_O_NONBLOCK = 0x00004000; //!< O_NONBLOCK
|
||||
static const int TGT_O_APPEND = 0x00000008; //!< O_APPEND
|
||||
static const int TGT_O_CREAT = 0x00000200; //!< O_CREAT
|
||||
static const int TGT_O_TRUNC = 0x00000400; //!< O_TRUNC
|
||||
static const int TGT_O_EXCL = 0x00000800; //!< O_EXCL
|
||||
static const int TGT_O_NOCTTY = 0x00008000; //!< O_NOCTTY
|
||||
static const int TGT_O_SYNC = 0x00002000; //!< O_SYNC
|
||||
// static const int TGT_O_DRD = 0x00010000; //!< O_DRD
|
||||
// static const int TGT_O_DIRECTIO = 0x00020000; //!< O_DIRECTIO
|
||||
// static const int TGT_O_CACHE = 0x00002000; //!< O_CACHE
|
||||
// static const int TGT_O_DSYNC = 0x00008000; //!< O_DSYNC
|
||||
// static const int TGT_O_RSYNC = 0x00040000; //!< O_RSYNC
|
||||
|
||||
static const int NUM_OPEN_FLAGS;
|
||||
|
||||
static const unsigned TGT_MAP_ANONYMOUS = 0x20;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -98,7 +98,7 @@ SyscallDesc SparcLinuxProcess::syscallDescs[] = {
|
|||
/* 2 */ SyscallDesc("fork", unimplementedFunc),
|
||||
/* 3 */ SyscallDesc("read", readFunc),
|
||||
/* 4 */ SyscallDesc("write", writeFunc),
|
||||
/* 5 */ SyscallDesc("open", openFunc<Linux>),
|
||||
/* 5 */ SyscallDesc("open", openFunc<SparcLinux>),
|
||||
/* 6 */ SyscallDesc("close", closeFunc),
|
||||
/* 7 */ SyscallDesc("wait4", unimplementedFunc),
|
||||
/* 8 */ SyscallDesc("creat", unimplementedFunc),
|
||||
|
@ -155,7 +155,7 @@ SyscallDesc SparcLinuxProcess::syscallDescs[] = {
|
|||
/* 59 */ SyscallDesc("execve", unimplementedFunc),
|
||||
/* 60 */ SyscallDesc("umask", unimplementedFunc),
|
||||
/* 61 */ SyscallDesc("chroot", unimplementedFunc),
|
||||
/* 62 */ SyscallDesc("fstat", unimplementedFunc),
|
||||
/* 62 */ SyscallDesc("fstat", fstatFunc<SparcLinux>),
|
||||
/* 63 */ SyscallDesc("fstat64", unimplementedFunc),
|
||||
/* 64 */ SyscallDesc("getpagesize", unimplementedFunc),
|
||||
/* 65 */ SyscallDesc("msync", unimplementedFunc),
|
||||
|
@ -164,9 +164,9 @@ SyscallDesc SparcLinuxProcess::syscallDescs[] = {
|
|||
/* 68 */ SyscallDesc("pwrite64", unimplementedFunc),
|
||||
/* 69 */ SyscallDesc("geteuid32", unimplementedFunc),
|
||||
/* 70 */ SyscallDesc("getdgid32", unimplementedFunc),
|
||||
/* 71 */ SyscallDesc("mmap", unimplementedFunc),
|
||||
/* 71 */ SyscallDesc("mmap", mmapFunc<SparcLinux>),
|
||||
/* 72 */ SyscallDesc("setreuid32", unimplementedFunc),
|
||||
/* 73 */ SyscallDesc("munmap", unimplementedFunc),
|
||||
/* 73 */ SyscallDesc("munmap", munmapFunc),
|
||||
/* 74 */ SyscallDesc("mprotect", unimplementedFunc),
|
||||
/* 75 */ SyscallDesc("madvise", unimplementedFunc),
|
||||
/* 76 */ SyscallDesc("vhangup", unimplementedFunc),
|
||||
|
@ -281,7 +281,7 @@ SyscallDesc SparcLinuxProcess::syscallDescs[] = {
|
|||
/* 185 */ SyscallDesc("setpgid", unimplementedFunc),
|
||||
/* 186 */ SyscallDesc("fremovexattr", unimplementedFunc),
|
||||
/* 187 */ SyscallDesc("tkill", unimplementedFunc),
|
||||
/* 188 */ SyscallDesc("exit_group", unimplementedFunc),
|
||||
/* 188 */ SyscallDesc("exit_group", exitFunc),
|
||||
/* 189 */ SyscallDesc("uname", unameFunc),
|
||||
/* 190 */ SyscallDesc("init_module", unimplementedFunc),
|
||||
/* 191 */ SyscallDesc("personality", unimplementedFunc),
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#ifndef __SPARC_LINUX_PROCESS_HH__
|
||||
#define __SPARC_LINUX_PROCESS_HH__
|
||||
|
||||
#include "arch/sparc/linux/linux.hh"
|
||||
#include "arch/sparc/process.hh"
|
||||
#include "sim/process.hh"
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ SparcLiveProcess::create(const std::string &nm, System *system, int stdin_fd,
|
|||
|
||||
|
||||
if (objFile->getArch() != ObjectFile::SPARC)
|
||||
fatal("Object file does not match architecture.");
|
||||
fatal("Object file with arch %x does not match architecture %x.", objFile->getArch(), ObjectFile::SPARC);
|
||||
switch (objFile->getOpSys()) {
|
||||
case ObjectFile::Linux:
|
||||
process = new SparcLinuxProcess(nm, objFile, system,
|
||||
|
@ -85,11 +85,11 @@ SparcLiveProcess::SparcLiveProcess(const std::string &nm, ObjectFile *objFile,
|
|||
|
||||
// Set up stack. On SPARC Linux, stack goes from the top of memory
|
||||
// downward, less the hole for the kernel address space.
|
||||
stack_base = ((Addr)0x80000000000);
|
||||
stack_base = ((Addr)0x80000000000ULL);
|
||||
|
||||
// Set up region for mmaps. Tru64 seems to start just above 0 and
|
||||
// grow up from there.
|
||||
mmap_start = mmap_end = 0x10000;
|
||||
mmap_start = mmap_end = 0x800000;
|
||||
|
||||
// Set pointer for next thread stack. Reserve 8M for main stack.
|
||||
next_thread_stack_base = stack_base - (8 * 1024 * 1024);
|
||||
|
@ -135,6 +135,14 @@ SparcLiveProcess::startup()
|
|||
execContexts[0]->setMiscRegWithEffect(MISCREG_CWP, 0);
|
||||
}
|
||||
|
||||
m5_auxv_t buildAuxVect(int64_t type, int64_t val)
|
||||
{
|
||||
m5_auxv_t result;
|
||||
result.a_type = TheISA::htog(type);
|
||||
result.a_val = TheISA::htog(val);
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
SparcLiveProcess::argsInit(int intSize, int pageSize)
|
||||
{
|
||||
|
@ -145,10 +153,75 @@ SparcLiveProcess::argsInit(int intSize, int pageSize)
|
|||
// load object file into target memory
|
||||
objFile->loadSections(initVirtMem);
|
||||
|
||||
//These are the auxilliary vector types
|
||||
enum auxTypes
|
||||
{
|
||||
SPARC_AT_HWCAP = 16,
|
||||
SPARC_AT_PAGESZ = 6,
|
||||
SPARC_AT_CLKTCK = 17,
|
||||
SPARC_AT_PHDR = 3,
|
||||
SPARC_AT_PHENT = 4,
|
||||
SPARC_AT_PHNUM = 5,
|
||||
SPARC_AT_BASE = 7,
|
||||
SPARC_AT_FLAGS = 8,
|
||||
SPARC_AT_ENTRY = 9,
|
||||
SPARC_AT_UID = 11,
|
||||
SPARC_AT_EUID = 12,
|
||||
SPARC_AT_GID = 13,
|
||||
SPARC_AT_EGID = 14
|
||||
};
|
||||
|
||||
enum hardwareCaps
|
||||
{
|
||||
M5_HWCAP_SPARC_FLUSH = 1,
|
||||
M5_HWCAP_SPARC_STBAR = 2,
|
||||
M5_HWCAP_SPARC_SWAP = 4,
|
||||
M5_HWCAP_SPARC_MULDIV = 8,
|
||||
M5_HWCAP_SPARC_V9 = 16,
|
||||
//This one should technically only be set
|
||||
//if there is a cheetah or cheetah_plus tlb,
|
||||
//but we'll use it all the time
|
||||
M5_HWCAP_SPARC_ULTRA3 = 32
|
||||
};
|
||||
|
||||
const int64_t hwcap =
|
||||
M5_HWCAP_SPARC_FLUSH |
|
||||
M5_HWCAP_SPARC_STBAR |
|
||||
M5_HWCAP_SPARC_SWAP |
|
||||
M5_HWCAP_SPARC_MULDIV |
|
||||
M5_HWCAP_SPARC_V9 |
|
||||
M5_HWCAP_SPARC_ULTRA3;
|
||||
|
||||
//Setup the auxilliary vectors. These will already have
|
||||
//endian conversion.
|
||||
auxv.push_back(buildAuxVect(SPARC_AT_EGID, 100));
|
||||
auxv.push_back(buildAuxVect(SPARC_AT_GID, 100));
|
||||
auxv.push_back(buildAuxVect(SPARC_AT_EUID, 100));
|
||||
auxv.push_back(buildAuxVect(SPARC_AT_UID, 100));
|
||||
//This would work, but the entry point is a protected member
|
||||
//auxv.push_back(buildAuxVect(SPARC_AT_ENTRY, objFile->entry));
|
||||
auxv.push_back(buildAuxVect(SPARC_AT_FLAGS, 0));
|
||||
//This is the address of the elf "interpreter", which I don't
|
||||
//think we currently set up. It should be set to 0 (I think)
|
||||
//auxv.push_back(buildAuxVect(SPARC_AT_BASE, 0));
|
||||
//This is the number of headers which were in the original elf
|
||||
//file. This information isn't avaibale by this point.
|
||||
//auxv.push_back(buildAuxVect(SPARC_AT_PHNUM, 3));
|
||||
//This is the size of a program header entry. This isn't easy
|
||||
//to compute here.
|
||||
//auxv.push_back(buildAuxVect(SPARC_AT_PHENT, blah));
|
||||
//This is should be set to load_addr (whatever that is) +
|
||||
//e_phoff. I think it's a pointer to the program headers.
|
||||
//auxv.push_back(buildAuxVect(SPARC_AT_PHDR, blah));
|
||||
//This should be easy to get right, but I won't set it for now
|
||||
//auxv.push_back(buildAuxVect(SPARC_AT_CLKTCK, blah));
|
||||
auxv.push_back(buildAuxVect(SPARC_AT_PAGESZ, SparcISA::VMPageSize));
|
||||
auxv.push_back(buildAuxVect(SPARC_AT_HWCAP, hwcap));
|
||||
|
||||
//Figure out how big the initial stack needs to be
|
||||
|
||||
int aux_data_size = 0;
|
||||
//Figure out the aux_data_size?
|
||||
//Each auxilliary vector is two 8 byte words
|
||||
int aux_data_size = 2 * intSize * auxv.size();
|
||||
int env_data_size = 0;
|
||||
for (int i = 0; i < envp.size(); ++i) {
|
||||
env_data_size += envp[i].size() + 1;
|
||||
|
@ -198,8 +271,8 @@ SparcLiveProcess::argsInit(int intSize, int pageSize)
|
|||
Addr aux_data_base = stack_base - aux_data_size - info_block_padding;
|
||||
Addr env_data_base = aux_data_base - env_data_size;
|
||||
Addr arg_data_base = env_data_base - arg_data_size;
|
||||
Addr aux_array_base = arg_data_base - aux_array_size;
|
||||
Addr envp_array_base = aux_array_base - envp_array_size;
|
||||
Addr auxv_array_base = arg_data_base - aux_array_size;
|
||||
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;
|
||||
Addr window_save_base = argc_base - window_save_size;
|
||||
|
@ -208,24 +281,34 @@ SparcLiveProcess::argsInit(int intSize, int pageSize)
|
|||
DPRINTF(Sparc, "0x%x - aux data\n", aux_data_base);
|
||||
DPRINTF(Sparc, "0x%x - env data\n", env_data_base);
|
||||
DPRINTF(Sparc, "0x%x - arg data\n", arg_data_base);
|
||||
DPRINTF(Sparc, "0x%x - aux array\n", aux_array_base);
|
||||
DPRINTF(Sparc, "0x%x - env array\n", envp_array_base);
|
||||
DPRINTF(Sparc, "0x%x - arg array\n", argv_array_base);
|
||||
DPRINTF(Sparc, "0x%x - auxv array\n", auxv_array_base);
|
||||
DPRINTF(Sparc, "0x%x - envp array\n", envp_array_base);
|
||||
DPRINTF(Sparc, "0x%x - argv array\n", argv_array_base);
|
||||
DPRINTF(Sparc, "0x%x - argc \n", argc_base);
|
||||
DPRINTF(Sparc, "0x%x - window save\n", window_save_base);
|
||||
DPRINTF(Sparc, "0x%x - stack min\n", stack_min);
|
||||
|
||||
// write contents to stack
|
||||
uint64_t argc = argv.size();
|
||||
uint64_t guestArgc = TheISA::htog(argc);
|
||||
|
||||
//Copy the aux stuff? For now just put in the null vect
|
||||
//Copy the aux stuff
|
||||
for(int x = 0; x < auxv.size(); x++)
|
||||
{
|
||||
initVirtMem->writeBlob(auxv_array_base + x * 2 * intSize,
|
||||
(uint8_t*)&(auxv[x].a_type), intSize);
|
||||
initVirtMem->writeBlob(auxv_array_base + (x * 2 + 1) * intSize,
|
||||
(uint8_t*)&(auxv[x].a_val), intSize);
|
||||
}
|
||||
//Write out the terminating zeroed auxilliary vector
|
||||
const uint64_t zero = 0;
|
||||
initVirtMem->writeBlob(aux_array_base, (uint8_t*)&zero, 2 * intSize);
|
||||
initVirtMem->writeBlob(auxv_array_base + 2 * intSize * auxv.size(),
|
||||
(uint8_t*)&zero, 2 * 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*)&argc, intSize);
|
||||
initVirtMem->writeBlob(argc_base, (uint8_t*)&guestArgc, intSize);
|
||||
|
||||
execContexts[0]->setIntReg(ArgumentReg0, argc);
|
||||
execContexts[0]->setIntReg(ArgumentReg1, argv_array_base);
|
||||
|
|
|
@ -36,18 +36,19 @@
|
|||
class ObjectFile;
|
||||
class System;
|
||||
|
||||
class SparcLiveProcess : public LiveProcess
|
||||
typedef struct
|
||||
{
|
||||
protected:
|
||||
typedef struct
|
||||
{
|
||||
int64_t a_type;
|
||||
union {
|
||||
int64_t a_val;
|
||||
Addr a_ptr;
|
||||
Addr a_fcn;
|
||||
};
|
||||
} m5_auxv_t;
|
||||
} m5_auxv_t;
|
||||
|
||||
class SparcLiveProcess : public LiveProcess
|
||||
{
|
||||
protected:
|
||||
|
||||
static const Addr StackBias = 2047;
|
||||
|
||||
|
|
|
@ -140,7 +140,16 @@ namespace SparcISA
|
|||
DPRINTF(Sparc, "Now using %s globals",
|
||||
useAlt ? "alternate" : "regular");
|
||||
regView[Globals] = useAlt ? altGlobals : regGlobals;
|
||||
offset[Globals] = useAlt ? AltGlobalOffset : RegGlobalOffset;
|
||||
|
||||
// You have not included an out-of-class definition of your static
|
||||
// members. See [9.4.2]/4 and about a billion gcc bug reports. If
|
||||
// statements get around the problem through some magic, and than
|
||||
// seems nicer that putting a definition of them in a c file
|
||||
// somewhere.
|
||||
if (useAlt)
|
||||
offset[Globals] = AltGlobalOffset;
|
||||
else
|
||||
offset[Globals] = RegGlobalOffset;
|
||||
}
|
||||
|
||||
void serialize(std::ostream &os);
|
||||
|
|
200
arch/sparc/system.cc
Normal file
200
arch/sparc/system.cc
Normal file
|
@ -0,0 +1,200 @@
|
|||
/*
|
||||
* Copyright (c) 2002-2006 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "arch/sparc/system.hh"
|
||||
#include "arch/vtophys.hh"
|
||||
#include "base/remote_gdb.hh"
|
||||
#include "base/loader/object_file.hh"
|
||||
#include "base/loader/symtab.hh"
|
||||
#include "base/trace.hh"
|
||||
#include "mem/physical.hh"
|
||||
#include "sim/byteswap.hh"
|
||||
#include "sim/builder.hh"
|
||||
|
||||
|
||||
using namespace BigEndianGuest;
|
||||
|
||||
SparcSystem::SparcSystem(Params *p)
|
||||
: System(p)
|
||||
{
|
||||
resetSymtab = new SymbolTable;
|
||||
hypervisorSymtab = new SymbolTable;
|
||||
openbootSymtab = new SymbolTable;
|
||||
|
||||
|
||||
/**
|
||||
* Load the boot code, and hypervisor into memory.
|
||||
*/
|
||||
// Read the reset binary
|
||||
reset = createObjectFile(params()->reset_bin);
|
||||
if (reset == NULL)
|
||||
fatal("Could not load reset binary %s", params()->reset_bin);
|
||||
|
||||
// Read the openboot binary
|
||||
openboot = createObjectFile(params()->openboot_bin);
|
||||
if (openboot == NULL)
|
||||
fatal("Could not load openboot bianry %s", params()->openboot_bin);
|
||||
|
||||
// Read the hypervisor binary
|
||||
hypervisor = createObjectFile(params()->hypervisor_bin);
|
||||
if (hypervisor == NULL)
|
||||
fatal("Could not load hypervisor binary %s", params()->hypervisor_bin);
|
||||
|
||||
|
||||
// Load reset binary into memory
|
||||
reset->loadSections(&functionalPort, SparcISA::LoadAddrMask);
|
||||
// Load the openboot binary
|
||||
openboot->loadSections(&functionalPort, SparcISA::LoadAddrMask);
|
||||
// Load the hypervisor binary
|
||||
hypervisor->loadSections(&functionalPort, SparcISA::LoadAddrMask);
|
||||
|
||||
// load symbols
|
||||
if (!reset->loadGlobalSymbols(reset))
|
||||
panic("could not load reset symbols\n");
|
||||
|
||||
if (!openboot->loadGlobalSymbols(openbootSymtab))
|
||||
panic("could not load openboot symbols\n");
|
||||
|
||||
if (!hypervisor->loadLocalSymbols(hypervisorSymtab))
|
||||
panic("could not load hypervisor symbols\n");
|
||||
|
||||
// load symbols into debug table
|
||||
if (!reset->loadGlobalSymbols(debugSymbolTable))
|
||||
panic("could not load reset symbols\n");
|
||||
|
||||
if (!openboot->loadGlobalSymbols(debugSymbolTable))
|
||||
panic("could not load openboot symbols\n");
|
||||
|
||||
if (!hypervisor->loadLocalSymbols(debugSymbolTable))
|
||||
panic("could not load hypervisor symbols\n");
|
||||
|
||||
|
||||
// @todo any fixup code over writing data in binaries on setting break
|
||||
// events on functions should happen here.
|
||||
|
||||
}
|
||||
|
||||
SparcSystem::~SparcSystem()
|
||||
{
|
||||
delete resetSymtab;
|
||||
delete hypervisorSymtab;
|
||||
delete openbootSymtab;
|
||||
delete reset;
|
||||
delete openboot;
|
||||
delete hypervisor;
|
||||
}
|
||||
|
||||
bool
|
||||
SparcSystem::breakpoint()
|
||||
{
|
||||
panic("Need to implement");
|
||||
}
|
||||
|
||||
void
|
||||
SparcSystem::serialize(std::ostream &os)
|
||||
{
|
||||
System::serialize(os);
|
||||
resetSymtab->serialize("reset_symtab", os);
|
||||
hypervisorSymtab->serialize("hypervisor_symtab", os);
|
||||
openbootSymtab->serialize("openboot_symtab", os);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SparcSystem::unserialize(Checkpoint *cp, const std::string §ion)
|
||||
{
|
||||
System::unserialize(cp,section);
|
||||
resetSymtab->unserialize("reset_symtab", cp, section);
|
||||
hypervisorSymtab->unserialize("hypervisor_symtab", cp, section);
|
||||
openbootSymtab->unserialize("openboot_symtab", cp, section);
|
||||
}
|
||||
|
||||
|
||||
BEGIN_DECLARE_SIM_OBJECT_PARAMS(SparcSystem)
|
||||
|
||||
SimObjectParam<PhysicalMemory *> physmem;
|
||||
|
||||
Param<std::string> kernel;
|
||||
Param<std::string> reset_bin;
|
||||
Param<std::string> hypervisor_bin;
|
||||
Param<std::string> openboot_bin;
|
||||
|
||||
Param<std::string> boot_osflags;
|
||||
Param<std::string> readfile;
|
||||
Param<unsigned int> init_param;
|
||||
|
||||
Param<bool> bin;
|
||||
VectorParam<std::string> binned_fns;
|
||||
Param<bool> bin_int;
|
||||
|
||||
END_DECLARE_SIM_OBJECT_PARAMS(SparcSystem)
|
||||
|
||||
BEGIN_INIT_SIM_OBJECT_PARAMS(SparcSystem)
|
||||
|
||||
INIT_PARAM(boot_cpu_frequency, "Frequency of the boot CPU"),
|
||||
INIT_PARAM(physmem, "phsyical memory"),
|
||||
INIT_PARAM(kernel, "file that contains the kernel code"),
|
||||
INIT_PARAM(reset_bin, "file that contains the reset code"),
|
||||
INIT_PARAM(hypervisor_bin, "file that contains the hypervisor code"),
|
||||
INIT_PARAM(openboot_bin, "file that contains the openboot code"),
|
||||
INIT_PARAM_DFLT(boot_osflags, "flags to pass to the kernel during boot",
|
||||
"a"),
|
||||
INIT_PARAM_DFLT(readfile, "file to read startup script from", ""),
|
||||
INIT_PARAM_DFLT(init_param, "numerical value to pass into simulator", 0),
|
||||
INIT_PARAM_DFLT(system_type, "Type of system we are emulating", 34),
|
||||
INIT_PARAM_DFLT(system_rev, "Revision of system we are emulating", 1<<10),
|
||||
INIT_PARAM_DFLT(bin, "is this system to be binned", false),
|
||||
INIT_PARAM(binned_fns, "functions to be broken down and binned"),
|
||||
INIT_PARAM_DFLT(bin_int, "is interrupt code binned seperately?", true)
|
||||
|
||||
END_INIT_SIM_OBJECT_PARAMS(SparcSystem)
|
||||
|
||||
CREATE_SIM_OBJECT(SparcSystem)
|
||||
{
|
||||
SparcSystem::Params *p = new SparcSystem::Params;
|
||||
p->name = getInstanceName();
|
||||
p->boot_cpu_frequency = boot_cpu_frequency;
|
||||
p->physmem = physmem;
|
||||
p->kernel_path = kernel;
|
||||
p->reset_bin = reset_bin;
|
||||
p->hypervisor_bin = hypervisor_bin;
|
||||
p->openboot_bin = openboot_bin;
|
||||
p->boot_osflags = boot_osflags;
|
||||
p->init_param = init_param;
|
||||
p->readfile = readfile;
|
||||
p->system_type = system_type;
|
||||
p->system_rev = system_rev;
|
||||
p->bin = bin;
|
||||
p->binned_fns = binned_fns;
|
||||
p->bin_int = bin_int;
|
||||
return new SparcSystem(p);
|
||||
}
|
||||
|
||||
REGISTER_SIM_OBJECT("SparcSystem", SparcSystem)
|
||||
|
||||
|
114
arch/sparc/system.hh
Normal file
114
arch/sparc/system.hh
Normal file
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* Copyright (c) 2002-2005 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_SPARC_SYSTEM_HH__
|
||||
#define __ARCH_SPARC_SYSTEM_HH__
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/loader/symtab.hh"
|
||||
#include "cpu/pc_event.hh"
|
||||
#include "kern/system_events.hh"
|
||||
#include "sim/sim_object.hh"
|
||||
#include "sim/system.hh"
|
||||
|
||||
class SparcSystem : public System
|
||||
{
|
||||
public:
|
||||
struct Params : public System::Params
|
||||
{
|
||||
std::string reset_bin;
|
||||
std::string hypervison_bin;
|
||||
std::string openboot_bin;
|
||||
std::string boot_osflags;
|
||||
uint64_t system_type;
|
||||
uint64_t system_rev;
|
||||
};
|
||||
|
||||
SparcSystem(Params *p);
|
||||
|
||||
~SparcaSystem();
|
||||
|
||||
virtual bool breakpoint();
|
||||
|
||||
/**
|
||||
* Serialization stuff
|
||||
*/
|
||||
public:
|
||||
virtual void serialize(std::ostream &os);
|
||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
|
||||
/** reset binary symbol table */
|
||||
SymbolTable *resetSymtab;
|
||||
|
||||
/** hypervison binary symbol table */
|
||||
SymbolTable *hypervisorSymtab;
|
||||
|
||||
/** openboot symbol table */
|
||||
SymbolTable *openbootSymtab;
|
||||
|
||||
/** Object pointer for the reset binary */
|
||||
ObjectFile *reset;
|
||||
|
||||
/** Object pointer for the hypervisor code */
|
||||
ObjectFile *hypervisor;
|
||||
|
||||
/** Object pointer for the openboot code */
|
||||
ObjectFile *openboot;
|
||||
|
||||
protected:
|
||||
const Params *params() const { return (const Params *)_params; }
|
||||
|
||||
/** Add a function-based event to reset binary. */
|
||||
template <class T>
|
||||
T *SparcSystem::addResetFuncEvent(const char *lbl)
|
||||
{
|
||||
return addFuncEvent<T>(resetSymtab, lbl);
|
||||
}
|
||||
|
||||
/** Add a function-based event to the hypervisor. */
|
||||
template <class T>
|
||||
T *SparcSystem::addHypervisorFuncEvent(const char *lbl)
|
||||
{
|
||||
return addFuncEvent<T>(hypervisorSymtab, lbl);
|
||||
}
|
||||
|
||||
/** Add a function-based event to the openboot. */
|
||||
template <class T>
|
||||
T *SparcSystem::addOpenbootFuncEvent(const char *lbl)
|
||||
{
|
||||
return addFuncEvent<T>(openbootSymtab, lbl);
|
||||
}
|
||||
|
||||
virtual Addr fixFuncEventAddr(Addr addr);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -139,9 +139,13 @@ class LinuxTsunami(BaseTsunami):
|
|||
pci_func=0, pci_dev=0, pci_bus=0)
|
||||
|
||||
class LinuxAlphaSystem(LinuxAlphaSystem):
|
||||
magicbus = Bus()
|
||||
magicbus = Bus(bus_id=0)
|
||||
magicbus2 = Bus(bus_id=1)
|
||||
bridge = Bridge()
|
||||
physmem = PhysicalMemory(range = AddrRange('128MB'))
|
||||
c1 = Connector(side_a=Parent.physmem, side_b=Parent.magicbus)
|
||||
c0a = Connector(side_a=Parent.magicbus, side_b=Parent.bridge, side_b_name="side_a")
|
||||
c0b = Connector(side_a=Parent.magicbus2, side_b=Parent.bridge, side_b_name="side_b")
|
||||
c1 = Connector(side_a=Parent.physmem, side_b=Parent.magicbus2)
|
||||
tsunami = LinuxTsunami()
|
||||
c2 = Connector(side_a=Parent.tsunami.cchip, side_a_name='pio', side_b=Parent.magicbus)
|
||||
c3 = Connector(side_a=Parent.tsunami.pchip, side_a_name='pio', side_b=Parent.magicbus)
|
||||
|
@ -177,7 +181,7 @@ class LinuxAlphaSystem(LinuxAlphaSystem):
|
|||
read_only=True)
|
||||
simple_disk = SimpleDisk(disk=Parent.raw_image)
|
||||
intrctrl = IntrControl()
|
||||
cpu = SimpleCPU(mem=Parent.magicbus)
|
||||
cpu = SimpleCPU(mem=Parent.magicbus2)
|
||||
sim_console = SimConsole(listener=ConsoleListener(port=3456))
|
||||
kernel = '/z/saidi/work/m5.newmem/build/vmlinux'
|
||||
pal = binary('ts_osfpal')
|
||||
|
|
Binary file not shown.
|
@ -54,6 +54,7 @@
|
|||
#include "cpu/smt.hh"
|
||||
#include "cpu/static_inst.hh"
|
||||
#include "kern/kernel_stats.hh"
|
||||
#include "mem/packet_impl.hh"
|
||||
#include "sim/byteswap.hh"
|
||||
#include "sim/builder.hh"
|
||||
#include "sim/debug.hh"
|
||||
|
@ -631,6 +632,7 @@ SimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
|||
data_write_pkt->set(data);
|
||||
#else
|
||||
data_write_pkt->reset();
|
||||
data = htog(data);
|
||||
data_write_pkt->dataStatic(&data);
|
||||
#endif
|
||||
data_write_pkt->addr = data_write_req->getPaddr();
|
||||
|
|
|
@ -103,6 +103,10 @@ class SimpleCPU : public BaseCPU
|
|||
virtual void recvStatusChange(Status status);
|
||||
|
||||
virtual Packet *recvRetry();
|
||||
|
||||
virtual void getDeviceAddressRanges(AddrRangeList &resp,
|
||||
AddrRangeList &snoop)
|
||||
{ resp.clear(); snoop.clear(); }
|
||||
};
|
||||
|
||||
MemObject *mem;
|
||||
|
|
|
@ -99,7 +99,7 @@ AlphaConsole::read(Packet &pkt)
|
|||
assert(pkt.result == Unknown);
|
||||
assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize);
|
||||
|
||||
pkt.time = curTick + pioDelay;
|
||||
pkt.time += pioDelay;
|
||||
Addr daddr = pkt.addr - pioAddr;
|
||||
|
||||
pkt.allocate();
|
||||
|
@ -191,7 +191,7 @@ AlphaConsole::read(Packet &pkt)
|
|||
Tick
|
||||
AlphaConsole::write(Packet &pkt)
|
||||
{
|
||||
pkt.time = curTick + pioDelay;
|
||||
pkt.time += pioDelay;
|
||||
|
||||
assert(pkt.result == Unknown);
|
||||
assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize);
|
||||
|
|
|
@ -430,7 +430,7 @@ IdeController::read(Packet &pkt)
|
|||
IdeRegType reg_type;
|
||||
int disk;
|
||||
|
||||
pkt.time = curTick + pioDelay;
|
||||
pkt.time += pioDelay;
|
||||
pkt.allocate();
|
||||
if (pkt.size != 1 && pkt.size != 2 && pkt.size !=4)
|
||||
panic("Bad IDE read size: %d\n", pkt.size);
|
||||
|
@ -518,7 +518,7 @@ IdeController::write(Packet &pkt)
|
|||
int disk;
|
||||
uint8_t oldVal, newVal;
|
||||
|
||||
pkt.time = curTick + pioDelay;
|
||||
pkt.time += pioDelay;
|
||||
|
||||
parseAddr(pkt.addr, offset, channel, reg_type);
|
||||
|
||||
|
|
|
@ -116,7 +116,13 @@ DmaPort::recvTiming(Packet &pkt)
|
|||
DmaReqState *state;
|
||||
state = (DmaReqState*)pkt.senderState;
|
||||
state->completionEvent->schedule(pkt.time - pkt.req->getTime());
|
||||
delete pkt.req;
|
||||
delete &pkt;
|
||||
} else {
|
||||
delete pkt.req;
|
||||
delete &pkt;
|
||||
}
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
|
||||
#include "base/chunk_generator.hh"
|
||||
#include "mem/mem_object.hh"
|
||||
#include "mem/packet_impl.hh"
|
||||
#include "sim/eventq.hh"
|
||||
#include "sim/sim_object.hh"
|
||||
|
||||
|
@ -167,7 +168,7 @@ class DmaPort : public Port
|
|||
friend class DmaPort;
|
||||
};
|
||||
|
||||
void sendDma(Packet &pkt);
|
||||
void sendDma(Packet *pkt);
|
||||
|
||||
public:
|
||||
DmaPort(DmaDevice *dev, Platform *p);
|
||||
|
|
|
@ -54,7 +54,7 @@ IsaFake::read(Packet &pkt)
|
|||
assert(pkt.result == Unknown);
|
||||
assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize);
|
||||
|
||||
pkt.time = curTick + pioDelay;
|
||||
pkt.time += pioDelay;
|
||||
|
||||
DPRINTF(Tsunami, "read va=%#x size=%d\n", pkt.addr, pkt.size);
|
||||
|
||||
|
@ -80,7 +80,7 @@ IsaFake::read(Packet &pkt)
|
|||
Tick
|
||||
IsaFake::write(Packet &pkt)
|
||||
{
|
||||
pkt.time = curTick + pioDelay;
|
||||
pkt.time += pioDelay;
|
||||
DPRINTF(Tsunami, "write - va=%#x size=%d \n", pkt.addr, pkt.size);
|
||||
pkt.result = Success;
|
||||
return pioDelay;
|
||||
|
|
|
@ -493,7 +493,7 @@ NSGigE::read(Packet &pkt)
|
|||
{
|
||||
assert(ioEnable);
|
||||
|
||||
pkt.time = curTick + pioDelay;
|
||||
pkt.time += pioDelay;
|
||||
pkt.allocate();
|
||||
|
||||
//The mask is to give you only the offset into the device register file
|
||||
|
@ -729,7 +729,7 @@ NSGigE::write(Packet &pkt)
|
|||
DPRINTF(EthernetPIO, "write da=%#x pa=%#x size=%d\n",
|
||||
daddr, pkt.addr, pkt.size);
|
||||
|
||||
pkt.time = curTick + pioDelay;
|
||||
pkt.time += pioDelay;
|
||||
|
||||
if (daddr > LAST && daddr <= RESERVED) {
|
||||
panic("Accessing reserved register");
|
||||
|
|
|
@ -99,7 +99,7 @@ PciConfigAll::read(Packet &pkt)
|
|||
int func = (daddr >> 8) & 0x7;
|
||||
int reg = daddr & 0xFF;
|
||||
|
||||
pkt.time = curTick + pioDelay;
|
||||
pkt.time += pioDelay;
|
||||
pkt.allocate();
|
||||
|
||||
DPRINTF(PciConfigAll, "read va=%#x da=%#x size=%d\n", pkt.addr, daddr,
|
||||
|
@ -134,7 +134,7 @@ PciConfigAll::read(Packet &pkt)
|
|||
Tick
|
||||
PciConfigAll::write(Packet &pkt)
|
||||
{
|
||||
pkt.time = curTick + pioDelay;
|
||||
pkt.time += pioDelay;
|
||||
|
||||
assert(pkt.result == Unknown);
|
||||
assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize);
|
||||
|
|
|
@ -321,7 +321,7 @@ Device::read(Packet &pkt)
|
|||
Addr index = daddr >> Regs::VirtualShift;
|
||||
Addr raddr = daddr & Regs::VirtualMask;
|
||||
|
||||
pkt.time = curTick + pioDelay;
|
||||
pkt.time += pioDelay;
|
||||
pkt.allocate();
|
||||
|
||||
if (!regValid(raddr))
|
||||
|
@ -408,7 +408,7 @@ Device::write(Packet &pkt)
|
|||
Addr index = daddr >> Regs::VirtualShift;
|
||||
Addr raddr = daddr & Regs::VirtualMask;
|
||||
|
||||
pkt.time = curTick + pioDelay;
|
||||
pkt.time += pioDelay;
|
||||
|
||||
if (!regValid(raddr))
|
||||
panic("invalid register: cpu=%d, da=%#x pa=%#x size=%d",
|
||||
|
|
|
@ -76,7 +76,7 @@ TsunamiCChip::read(Packet &pkt)
|
|||
assert(pkt.result == Unknown);
|
||||
assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize);
|
||||
|
||||
pkt.time = curTick + pioDelay;
|
||||
pkt.time += pioDelay;
|
||||
Addr regnum = (pkt.addr - pioAddr) >> 6;
|
||||
Addr daddr = (pkt.addr - pioAddr);
|
||||
|
||||
|
@ -182,7 +182,7 @@ TsunamiCChip::read(Packet &pkt)
|
|||
Tick
|
||||
TsunamiCChip::write(Packet &pkt)
|
||||
{
|
||||
pkt.time = curTick + pioDelay;
|
||||
pkt.time += pioDelay;
|
||||
|
||||
|
||||
assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize);
|
||||
|
|
|
@ -441,7 +441,7 @@ TsunamiIO::read(Packet &pkt)
|
|||
assert(pkt.result == Unknown);
|
||||
assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize);
|
||||
|
||||
pkt.time = curTick + pioDelay;
|
||||
pkt.time += pioDelay;
|
||||
Addr daddr = pkt.addr - pioAddr;
|
||||
|
||||
DPRINTF(Tsunami, "io read va=%#x size=%d IOPorrt=%#x\n", pkt.addr,
|
||||
|
@ -505,7 +505,7 @@ TsunamiIO::read(Packet &pkt)
|
|||
Tick
|
||||
TsunamiIO::write(Packet &pkt)
|
||||
{
|
||||
pkt.time = curTick + pioDelay;
|
||||
pkt.time += pioDelay;
|
||||
|
||||
assert(pkt.result == Unknown);
|
||||
assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize);
|
||||
|
|
|
@ -71,7 +71,7 @@ TsunamiPChip::read(Packet &pkt)
|
|||
assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize);
|
||||
|
||||
|
||||
pkt.time = curTick + pioDelay;
|
||||
pkt.time += pioDelay;
|
||||
pkt.allocate();
|
||||
Addr daddr = (pkt.addr - pioAddr) >> 6;;
|
||||
assert(pkt.size == sizeof(uint64_t));
|
||||
|
@ -151,7 +151,7 @@ TsunamiPChip::read(Packet &pkt)
|
|||
Tick
|
||||
TsunamiPChip::write(Packet &pkt)
|
||||
{
|
||||
pkt.time = curTick + pioDelay;
|
||||
pkt.time += pioDelay;
|
||||
|
||||
assert(pkt.result == Unknown);
|
||||
assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize);
|
||||
|
|
|
@ -114,7 +114,7 @@ Uart8250::read(Packet &pkt)
|
|||
assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize);
|
||||
assert(pkt.size == 1);
|
||||
|
||||
pkt.time = curTick + pioDelay;
|
||||
pkt.time += pioDelay;
|
||||
Addr daddr = pkt.addr - pioAddr;
|
||||
pkt.allocate();
|
||||
|
||||
|
@ -198,7 +198,7 @@ Uart8250::write(Packet &pkt)
|
|||
assert(pkt.addr >= pioAddr && pkt.addr < pioAddr + pioSize);
|
||||
assert(pkt.size == 1);
|
||||
|
||||
pkt.time = curTick + pioDelay;
|
||||
pkt.time += pioDelay;
|
||||
Addr daddr = pkt.addr - pioAddr;
|
||||
|
||||
DPRINTF(Uart, " write register %#x value %#x\n", daddr, pkt.get<uint8_t>());
|
||||
|
|
263
mem/bridge.cc
Normal file
263
mem/bridge.cc
Normal file
|
@ -0,0 +1,263 @@
|
|||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file Definition of a simple bus bridge without buffering.
|
||||
*/
|
||||
|
||||
|
||||
#include "base/trace.hh"
|
||||
#include "mem/bridge.hh"
|
||||
#include "sim/builder.hh"
|
||||
|
||||
void
|
||||
Bridge::init()
|
||||
{
|
||||
// Make sure that both sides are connected to.
|
||||
if (sideA == NULL || sideB == NULL)
|
||||
panic("Both ports of bus bridge are not connected to a bus.\n");
|
||||
}
|
||||
|
||||
|
||||
/** Function called by the port when the bus is recieving a Timing
|
||||
* transaction.*/
|
||||
bool
|
||||
Bridge::recvTiming(Packet &pkt, Side id)
|
||||
{
|
||||
if (blockedA && id == SideA)
|
||||
return false;
|
||||
if (blockedB && id == SideB)
|
||||
return false;
|
||||
|
||||
if (delay) {
|
||||
if (!sendEvent.scheduled())
|
||||
sendEvent.schedule(curTick + delay);
|
||||
if (id == SideA) {
|
||||
inboundA.push_back(std::make_pair<Packet*, Tick>(&pkt, curTick));
|
||||
blockCheck(SideA);
|
||||
} else {
|
||||
inboundB.push_back(std::make_pair<Packet*, Tick>(&pkt, curTick));
|
||||
blockCheck(SideB);
|
||||
}
|
||||
} else {
|
||||
if (id == SideB) {
|
||||
sideA->sendPkt(pkt);
|
||||
blockCheck(SideB);
|
||||
} else {
|
||||
sideB->sendPkt(pkt);
|
||||
blockCheck(SideA);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
Bridge::blockCheck(Side id)
|
||||
{
|
||||
/* Check that we still have buffer space available. */
|
||||
if (id == SideB) {
|
||||
if (sideA->numQueued() + inboundB.size() >= queueSizeA && !blockedB) {
|
||||
sideB->sendStatusChange(Port::Blocked);
|
||||
blockedB = true;
|
||||
} else if (sideA->numQueued() + inboundB.size() < queueSizeA && blockedB) {
|
||||
sideB->sendStatusChange(Port::Unblocked);
|
||||
blockedB = false;
|
||||
}
|
||||
} else {
|
||||
if (sideB->numQueued() + inboundA.size() >= queueSizeB && !blockedA) {
|
||||
sideA->sendStatusChange(Port::Blocked);
|
||||
blockedA = true;
|
||||
} else if (sideB->numQueued() + inboundA.size() < queueSizeB && blockedA) {
|
||||
sideA->sendStatusChange(Port::Unblocked);
|
||||
blockedA = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Bridge::timerEvent()
|
||||
{
|
||||
Tick t = 0;
|
||||
|
||||
assert(inboundA.size() || inboundB.size());
|
||||
if (inboundA.size()) {
|
||||
while (inboundA.front().second <= curTick + delay){
|
||||
sideB->sendPkt(inboundA.front());
|
||||
inboundA.pop_front();
|
||||
}
|
||||
if (inboundA.size())
|
||||
t = inboundA.front().second + delay;
|
||||
}
|
||||
if (inboundB.size()) {
|
||||
while (inboundB.front().second <= curTick + delay){
|
||||
sideB->sendPkt(inboundA.front());
|
||||
inboundB.pop_front();
|
||||
}
|
||||
if (inboundB.size())
|
||||
if (t == 0)
|
||||
t = inboundB.front().second + delay;
|
||||
else
|
||||
t = std::min(t,inboundB.front().second + delay);
|
||||
} else {
|
||||
panic("timerEvent() called but nothing to do?");
|
||||
}
|
||||
|
||||
if (t != 0)
|
||||
sendEvent.schedule(t);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Bridge::BridgePort::sendPkt(Packet &pkt)
|
||||
{
|
||||
if (!sendTiming(pkt))
|
||||
outbound.push_back(std::make_pair<Packet*,Tick>(&pkt, curTick));
|
||||
}
|
||||
|
||||
void
|
||||
Bridge::BridgePort::sendPkt(std::pair<Packet*, Tick> p)
|
||||
{
|
||||
if (!sendTiming(*p.first))
|
||||
outbound.push_back(p);
|
||||
}
|
||||
|
||||
|
||||
Packet *
|
||||
Bridge::BridgePort::recvRetry()
|
||||
{
|
||||
Packet *pkt;
|
||||
assert(outbound.size() > 0);
|
||||
assert(outbound.front().second >= curTick + bridge->delay);
|
||||
pkt = outbound.front().first;
|
||||
outbound.pop_front();
|
||||
bridge->blockCheck(side);
|
||||
return pkt;
|
||||
}
|
||||
|
||||
/** Function called by the port when the bus is recieving a Atomic
|
||||
* transaction.*/
|
||||
Tick
|
||||
Bridge::recvAtomic(Packet &pkt, Side id)
|
||||
{
|
||||
pkt.time += delay;
|
||||
|
||||
if (id == SideA)
|
||||
return sideB->sendAtomic(pkt);
|
||||
else
|
||||
return sideA->sendAtomic(pkt);
|
||||
}
|
||||
|
||||
/** Function called by the port when the bus is recieving a Functional
|
||||
* transaction.*/
|
||||
void
|
||||
Bridge::recvFunctional(Packet &pkt, Side id)
|
||||
{
|
||||
pkt.time += delay;
|
||||
std::list<std::pair<Packet*, Tick> >::iterator i;
|
||||
bool pktContinue = true;
|
||||
|
||||
for(i = inboundA.begin(); i != inboundA.end(); ++i) {
|
||||
if (pkt.intersect(i->first)) {
|
||||
pktContinue &= fixPacket(pkt, *i->first);
|
||||
}
|
||||
}
|
||||
|
||||
for(i = inboundB.begin(); i != inboundB.end(); ++i) {
|
||||
if (pkt.intersect(i->first)) {
|
||||
pktContinue &= fixPacket(pkt, *i->first);
|
||||
}
|
||||
}
|
||||
|
||||
for(i = sideA->outbound.begin(); i != sideA->outbound.end(); ++i) {
|
||||
if (pkt.intersect(i->first)) {
|
||||
pktContinue &= fixPacket(pkt, *i->first);
|
||||
}
|
||||
}
|
||||
|
||||
for(i = sideB->outbound.begin(); i != sideB->outbound.end(); ++i) {
|
||||
if (pkt.intersect(i->first)) {
|
||||
pktContinue &= fixPacket(pkt, *i->first);
|
||||
}
|
||||
}
|
||||
|
||||
if (pktContinue) {
|
||||
if (id == SideA)
|
||||
sideB->sendFunctional(pkt);
|
||||
else
|
||||
sideA->sendFunctional(pkt);
|
||||
}
|
||||
}
|
||||
|
||||
/** Function called by the port when the bus is recieving a status change.*/
|
||||
void
|
||||
Bridge::recvStatusChange(Port::Status status, Side id)
|
||||
{
|
||||
if (status == Port::Blocked || status == Port::Unblocked)
|
||||
return ;
|
||||
|
||||
if (id == SideA)
|
||||
sideB->sendStatusChange(status);
|
||||
else
|
||||
sideA->sendStatusChange(status);
|
||||
}
|
||||
|
||||
void
|
||||
Bridge::addressRanges(AddrRangeList &resp, AddrRangeList &snoop, Side id)
|
||||
{
|
||||
if (id == SideA)
|
||||
sideB->getPeerAddressRanges(resp, snoop);
|
||||
else
|
||||
sideA->getPeerAddressRanges(resp, snoop);
|
||||
}
|
||||
|
||||
BEGIN_DECLARE_SIM_OBJECT_PARAMS(Bridge)
|
||||
|
||||
Param<int> queue_size_a;
|
||||
Param<int> queue_size_b;
|
||||
Param<Tick> delay;
|
||||
Param<bool> write_ack;
|
||||
|
||||
END_DECLARE_SIM_OBJECT_PARAMS(Bridge)
|
||||
|
||||
BEGIN_INIT_SIM_OBJECT_PARAMS(Bridge)
|
||||
|
||||
INIT_PARAM(queue_size_a, "The size of the queue for data coming into side a"),
|
||||
INIT_PARAM(queue_size_b, "The size of the queue for data coming into side b"),
|
||||
INIT_PARAM(delay, "The miminum delay to cross this bridge"),
|
||||
INIT_PARAM(write_ack, "Acknowledge any writes that are received.")
|
||||
|
||||
END_INIT_SIM_OBJECT_PARAMS(Bridge)
|
||||
|
||||
CREATE_SIM_OBJECT(Bridge)
|
||||
{
|
||||
return new Bridge(getInstanceName(), queue_size_a, queue_size_b, delay,
|
||||
write_ack);
|
||||
}
|
||||
|
||||
REGISTER_SIM_OBJECT("Bridge", Bridge)
|
214
mem/bridge.hh
Normal file
214
mem/bridge.hh
Normal file
|
@ -0,0 +1,214 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file Decleration of a simple bus bridge object with no buffering
|
||||
*/
|
||||
|
||||
#ifndef __MEM_BRIDGE_HH__
|
||||
#define __MEM_BRIDGE_HH__
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <inttypes.h>
|
||||
#include <queue>
|
||||
|
||||
|
||||
#include "mem/mem_object.hh"
|
||||
#include "mem/packet.hh"
|
||||
#include "mem/port.hh"
|
||||
#include "sim/eventq.hh"
|
||||
|
||||
class Bridge : public MemObject
|
||||
{
|
||||
public:
|
||||
enum Side
|
||||
{
|
||||
SideA,
|
||||
SideB
|
||||
};
|
||||
|
||||
protected:
|
||||
/** Function called by the port when the bus is recieving a Timing
|
||||
transaction.*/
|
||||
bool recvTiming(Packet &pkt, Side id);
|
||||
|
||||
/** Function called by the port when the bus is recieving a Atomic
|
||||
transaction.*/
|
||||
Tick recvAtomic(Packet &pkt, Side id);
|
||||
|
||||
/** Function called by the port when the bus is recieving a Functional
|
||||
transaction.*/
|
||||
void recvFunctional(Packet &pkt, Side id);
|
||||
|
||||
/** Function called by the port when the bus is recieving a status change.*/
|
||||
void recvStatusChange(Port::Status status, Side id);
|
||||
|
||||
/** Process address range request.
|
||||
* @param resp addresses that we can respond to
|
||||
* @param snoop addresses that we would like to snoop
|
||||
* @param id ide of the busport that made the request.
|
||||
*/
|
||||
void addressRanges(AddrRangeList &resp, AddrRangeList &snoop, Side id);
|
||||
|
||||
|
||||
/** Event that the SendEvent calls when it fires. This code must reschedule
|
||||
* the send event as required. */
|
||||
void timerEvent();
|
||||
|
||||
/** Decleration of the buses port type, one will be instantiated for each
|
||||
of the interfaces connecting to the bus. */
|
||||
class BridgePort : public Port
|
||||
{
|
||||
/** A pointer to the bus to which this port belongs. */
|
||||
Bridge *bridge;
|
||||
|
||||
/** A id to keep track of the intercafe ID this port is connected to. */
|
||||
Bridge::Side side;
|
||||
|
||||
public:
|
||||
|
||||
/** Constructor for the BusPort.*/
|
||||
BridgePort(Bridge *_bridge, Side _side)
|
||||
: bridge(_bridge), side(_side)
|
||||
{ }
|
||||
|
||||
int numQueued() { return outbound.size(); }
|
||||
|
||||
protected:
|
||||
/** Data this is waiting to be transmitted. */
|
||||
std::list<std::pair<Packet*, Tick> > outbound;
|
||||
|
||||
void sendPkt(Packet &pkt);
|
||||
void sendPkt(std::pair<Packet*, Tick> p);
|
||||
|
||||
/** When reciving a timing request from the peer port,
|
||||
pass it to the bridge. */
|
||||
virtual bool recvTiming(Packet &pkt)
|
||||
{ return bridge->recvTiming(pkt, side); }
|
||||
|
||||
/** When reciving a retry request from the peer port,
|
||||
pass it to the bridge. */
|
||||
virtual Packet* recvRetry();
|
||||
|
||||
/** When reciving a Atomic requestfrom the peer port,
|
||||
pass it to the bridge. */
|
||||
virtual Tick recvAtomic(Packet &pkt)
|
||||
{ return bridge->recvAtomic(pkt, side); }
|
||||
|
||||
/** When reciving a Functional request from the peer port,
|
||||
pass it to the bridge. */
|
||||
virtual void recvFunctional(Packet &pkt)
|
||||
{ bridge->recvFunctional(pkt, side); }
|
||||
|
||||
/** When reciving a status changefrom the peer port,
|
||||
pass it to the bridge. */
|
||||
virtual void recvStatusChange(Status status)
|
||||
{ bridge->recvStatusChange(status, side); }
|
||||
|
||||
/** When reciving a address range request the peer port,
|
||||
pass it to the bridge. */
|
||||
virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop)
|
||||
{ bridge->addressRanges(resp, snoop, side); }
|
||||
|
||||
friend class Bridge;
|
||||
};
|
||||
|
||||
class SendEvent : public Event
|
||||
{
|
||||
Bridge *bridge;
|
||||
|
||||
SendEvent(Bridge *b)
|
||||
: Event(&mainEventQueue), bridge(b) {}
|
||||
|
||||
virtual void process() { bridge->timerEvent(); }
|
||||
|
||||
virtual const char *description() { return "bridge delay event"; }
|
||||
friend class Bridge;
|
||||
};
|
||||
|
||||
SendEvent sendEvent;
|
||||
|
||||
/** Sides of the bus bridges. */
|
||||
BridgePort* sideA;
|
||||
BridgePort* sideB;
|
||||
|
||||
/** inbound queues on both sides. */
|
||||
std::list<std::pair<Packet*, Tick> > inboundA;
|
||||
std::list<std::pair<Packet*, Tick> > inboundB;
|
||||
|
||||
/** The size of the queue for data coming into side a */
|
||||
int queueSizeA;
|
||||
int queueSizeB;
|
||||
|
||||
/* if the side is blocked or not. */
|
||||
bool blockedA;
|
||||
bool blockedB;
|
||||
|
||||
/** Miminum delay though this bridge. */
|
||||
Tick delay;
|
||||
|
||||
/** If this bridge should acknowledge writes. */
|
||||
bool ackWrites;
|
||||
|
||||
public:
|
||||
|
||||
/** A function used to return the port associated with this bus object. */
|
||||
virtual Port *getPort(const std::string &if_name)
|
||||
{
|
||||
if (if_name == "side_a") {
|
||||
if (sideA != NULL)
|
||||
panic("bridge side a already connected to.");
|
||||
sideA = new BridgePort(this, SideA);
|
||||
return sideA;
|
||||
} else if (if_name == "side_b") {
|
||||
if (sideB != NULL)
|
||||
panic("bridge side b already connected to.");
|
||||
sideB = new BridgePort(this, SideB);
|
||||
return sideB;
|
||||
} else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
virtual void init();
|
||||
|
||||
Bridge(const std::string &n, int qsa, int qsb, Tick _delay, int write_ack)
|
||||
: MemObject(n), sendEvent(this), sideA(NULL), sideB(NULL),
|
||||
queueSizeA(qsa), queueSizeB(qsb), blockedA(false), blockedB(false),
|
||||
delay(_delay), ackWrites(write_ack)
|
||||
{}
|
||||
|
||||
/** Check if the port should block/unblock after recieving/sending a packet.
|
||||
* */
|
||||
void blockCheck(Side id);
|
||||
|
||||
friend class Bridge::SendEvent;
|
||||
|
||||
};
|
||||
|
||||
#endif //__MEM_BUS_HH__
|
45
mem/bus.cc
45
mem/bus.cc
|
@ -35,13 +35,22 @@
|
|||
#include "mem/bus.hh"
|
||||
#include "sim/builder.hh"
|
||||
|
||||
/** Get the ranges of anyone that we are connected to. */
|
||||
void
|
||||
Bus::init()
|
||||
{
|
||||
std::vector<Port*>::iterator intIter;
|
||||
for (intIter = interfaces.begin(); intIter != interfaces.end(); intIter++)
|
||||
(*intIter)->sendStatusChange(Port::RangeChange);
|
||||
}
|
||||
|
||||
|
||||
/** Function called by the port when the bus is recieving a Timing
|
||||
* transaction.*/
|
||||
bool
|
||||
Bus::recvTiming(Packet &pkt, int id)
|
||||
{
|
||||
|
||||
panic("I need to be implemented, but not right now.");
|
||||
return findPort(pkt.addr, id)->sendTiming(pkt);
|
||||
}
|
||||
|
||||
Port *
|
||||
|
@ -90,10 +99,13 @@ Bus::recvFunctional(Packet &pkt, int id)
|
|||
void
|
||||
Bus::recvStatusChange(Port::Status status, int id)
|
||||
{
|
||||
DPRINTF(Bus, "Bus %d recieved status change from device id %d\n",
|
||||
busId, id);
|
||||
assert(status == Port::RangeChange &&
|
||||
"The other statuses need to be implemented.");
|
||||
|
||||
assert(id < interfaces.size() && id >= 0);
|
||||
int x;
|
||||
Port *port = interfaces[id];
|
||||
AddrRangeList ranges;
|
||||
AddrRangeList snoops;
|
||||
|
@ -122,12 +134,31 @@ Bus::recvStatusChange(Port::Status status, int id)
|
|||
portList.push_back(dm);
|
||||
}
|
||||
DPRINTF(MMU, "port list has %d entries\n", portList.size());
|
||||
|
||||
// tell all our peers that our address range has changed.
|
||||
// Don't tell the device that caused this change, it already knows
|
||||
for (x = 0; x < interfaces.size(); x++)
|
||||
if (x != id)
|
||||
interfaces[x]->sendStatusChange(Port::RangeChange);
|
||||
}
|
||||
|
||||
void
|
||||
Bus::BusPort::addressRanges(AddrRangeList &resp, AddrRangeList &snoop)
|
||||
Bus::addressRanges(AddrRangeList &resp, AddrRangeList &snoop, int id)
|
||||
{
|
||||
panic("I'm not implemented.\n");
|
||||
std::vector<DevMap>::iterator portIter;
|
||||
|
||||
resp.clear();
|
||||
snoop.clear();
|
||||
|
||||
DPRINTF(Bus, "Bus id %d recieved address range request returning\n",
|
||||
busId);
|
||||
for (portIter = portList.begin(); portIter != portList.end(); portIter++) {
|
||||
if (portIter->portId != id) {
|
||||
resp.push_back(portIter->range);
|
||||
DPRINTF(Bus, "-- %#llX : %#llX\n", portIter->range.start,
|
||||
portIter->range.end);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BEGIN_DECLARE_SIM_OBJECT_PARAMS(Bus)
|
||||
|
@ -137,12 +168,12 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(Bus)
|
|||
END_DECLARE_SIM_OBJECT_PARAMS(Bus)
|
||||
|
||||
BEGIN_INIT_SIM_OBJECT_PARAMS(Bus)
|
||||
INIT_PARAM(bus_id, "junk bus id")
|
||||
END_INIT_SIM_OBJECT_PARAMS(PhysicalMemory)
|
||||
INIT_PARAM(bus_id, "a globally unique bus id")
|
||||
END_INIT_SIM_OBJECT_PARAMS(Bus)
|
||||
|
||||
CREATE_SIM_OBJECT(Bus)
|
||||
{
|
||||
return new Bus(getInstanceName());
|
||||
return new Bus(getInstanceName(), bus_id);
|
||||
}
|
||||
|
||||
REGISTER_SIM_OBJECT("Bus", Bus)
|
||||
|
|
21
mem/bus.hh
21
mem/bus.hh
|
@ -45,6 +45,9 @@
|
|||
|
||||
class Bus : public MemObject
|
||||
{
|
||||
/** a globally unique id for this bus. */
|
||||
int busId;
|
||||
|
||||
struct DevMap {
|
||||
int portId;
|
||||
Range<Addr> range;
|
||||
|
@ -77,6 +80,14 @@ class Bus : public MemObject
|
|||
Port *
|
||||
Bus::findPort(Addr addr, int id);
|
||||
|
||||
/** Process address range request.
|
||||
* @param resp addresses that we can respond to
|
||||
* @param snoop addresses that we would like to snoop
|
||||
* @param id ide of the busport that made the request.
|
||||
*/
|
||||
void addressRanges(AddrRangeList &resp, AddrRangeList &snoop, int id);
|
||||
|
||||
|
||||
/** Decleration of the buses port type, one will be instantiated for each
|
||||
of the interfaces connecting to the bus. */
|
||||
class BusPort : public Port
|
||||
|
@ -120,7 +131,8 @@ class Bus : public MemObject
|
|||
// downstream from this bus, yes? That is, the union of all
|
||||
// the 'owned' address ranges of all the other interfaces on
|
||||
// this bus...
|
||||
virtual void addressRanges(AddrRangeList &resp, AddrRangeList &snoop);
|
||||
virtual void getDeviceAddressRanges(AddrRangeList &resp, AddrRangeList &snoop)
|
||||
{ bus->addressRanges(resp, snoop, id); }
|
||||
|
||||
// Hack to make translating port work without changes
|
||||
virtual int deviceBlockSize() { return 32; }
|
||||
|
@ -141,8 +153,11 @@ class Bus : public MemObject
|
|||
interfaces.push_back(new BusPort(this, id));
|
||||
return interfaces.back();
|
||||
}
|
||||
Bus(const std::string &n)
|
||||
: MemObject(n) {}
|
||||
|
||||
virtual void init();
|
||||
|
||||
Bus(const std::string &n, int bus_id)
|
||||
: MemObject(n), busId(bus_id) {}
|
||||
|
||||
};
|
||||
|
||||
|
|
94
mem/packet.cc
Normal file
94
mem/packet.cc
Normal file
|
@ -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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Definition of the Packet Class, a packet is a transaction occuring
|
||||
* between a single level of the memory heirarchy (ie L1->L2).
|
||||
*/
|
||||
#include "base/misc.hh"
|
||||
#include "mem/packet.hh"
|
||||
|
||||
|
||||
/** delete the data pointed to in the data pointer. Ok to call to matter how
|
||||
* data was allocted. */
|
||||
void
|
||||
Packet::deleteData() {
|
||||
assert(staticData || dynamicData);
|
||||
if (staticData)
|
||||
return;
|
||||
|
||||
if (arrayData)
|
||||
delete [] data;
|
||||
else
|
||||
delete data;
|
||||
}
|
||||
|
||||
/** If there isn't data in the packet, allocate some. */
|
||||
void
|
||||
Packet::allocate() {
|
||||
if (data)
|
||||
return;
|
||||
assert(!staticData);
|
||||
dynamicData = true;
|
||||
arrayData = true;
|
||||
data = new uint8_t[size];
|
||||
}
|
||||
|
||||
/** Do the packet modify the same addresses. */
|
||||
bool
|
||||
Packet::intersect(Packet *p) {
|
||||
Addr s1 = addr;
|
||||
Addr e1 = addr + size;
|
||||
Addr s2 = p->addr;
|
||||
Addr e2 = p->addr + p->size;
|
||||
|
||||
if (s1 >= s2 && s1 < e2)
|
||||
return true;
|
||||
if (e1 >= s2 && e1 < e2)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Minimally reset a packet so something like simple cpu can reuse it. */
|
||||
void
|
||||
Packet::reset() {
|
||||
result = Unknown;
|
||||
if (dynamicData) {
|
||||
deleteData();
|
||||
dynamicData = false;
|
||||
arrayData = false;
|
||||
time = curTick;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool fixPacket(Packet &func, Packet &timing)
|
||||
{ panic("Need to implement!"); }
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2003 The Regents of The University of Michigan
|
||||
* Copyright (c) 2006 The Regents of The University of Michigan
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -142,7 +142,7 @@ struct Packet
|
|||
|
||||
Packet()
|
||||
: data(NULL), staticData(false), dynamicData(false), arrayData(false),
|
||||
result(Unknown)
|
||||
time(curTick), result(Unknown)
|
||||
{}
|
||||
|
||||
~Packet()
|
||||
|
@ -150,87 +150,43 @@ struct Packet
|
|||
|
||||
|
||||
/** Minimally reset a packet so something like simple cpu can reuse it. */
|
||||
void reset() {
|
||||
result = Unknown;
|
||||
if (dynamicData) {
|
||||
deleteData();
|
||||
dynamicData = false;
|
||||
arrayData = false;
|
||||
}
|
||||
}
|
||||
void reset();
|
||||
|
||||
/** Set the data pointer to the following value that should not be freed. */
|
||||
template <typename T>
|
||||
void dataStatic(T *p) {
|
||||
assert(!dynamicData);
|
||||
data = (PacketDataPtr)p;
|
||||
staticData = true;
|
||||
}
|
||||
void dataStatic(T *p);
|
||||
|
||||
/** Set the data pointer to a value that should have delete [] called on it.
|
||||
*/
|
||||
template <typename T>
|
||||
void dataDynamicArray(T *p) {
|
||||
assert(!staticData && !dynamicData);
|
||||
data = (PacketDataPtr)p;
|
||||
dynamicData = true;
|
||||
arrayData = true;
|
||||
}
|
||||
void dataDynamicArray(T *p);
|
||||
|
||||
/** set the data pointer to a value that should have delete called on it. */
|
||||
template <typename T>
|
||||
void dataDynamic(T *p) {
|
||||
assert(!staticData && !dynamicData);
|
||||
data = (PacketDataPtr)p;
|
||||
dynamicData = true;
|
||||
arrayData = false;
|
||||
}
|
||||
void dataDynamic(T *p);
|
||||
|
||||
/** return the value of what is pointed to in the packet. */
|
||||
template <typename T>
|
||||
T get() {
|
||||
assert(staticData || dynamicData);
|
||||
assert(sizeof(T) <= size);
|
||||
return *(T*)data;
|
||||
}
|
||||
T get();
|
||||
|
||||
/** get a pointer to the data ptr. */
|
||||
template <typename T>
|
||||
T* getPtr() {
|
||||
assert(staticData || dynamicData);
|
||||
return (T*)data;
|
||||
}
|
||||
|
||||
T* getPtr();
|
||||
|
||||
/** set the value in the data pointer to v. */
|
||||
template <typename T>
|
||||
void set(T v) {
|
||||
assert(sizeof(T) <= size);
|
||||
*(T*)data = v;
|
||||
}
|
||||
void set(T v);
|
||||
|
||||
/** delete the data pointed to in the data pointer. Ok to call to matter how
|
||||
* data was allocted. */
|
||||
void deleteData() {
|
||||
assert(staticData || dynamicData);
|
||||
if (staticData)
|
||||
return;
|
||||
|
||||
if (arrayData)
|
||||
delete [] data;
|
||||
else
|
||||
delete data;
|
||||
}
|
||||
void deleteData();
|
||||
|
||||
/** If there isn't data in the packet, allocate some. */
|
||||
void allocate() {
|
||||
if (data)
|
||||
return;
|
||||
assert(!staticData);
|
||||
dynamicData = true;
|
||||
arrayData = true;
|
||||
data = new uint8_t[size];
|
||||
}
|
||||
void allocate();
|
||||
|
||||
/** Do the packet modify the same addresses. */
|
||||
bool intersect(Packet *p);
|
||||
};
|
||||
|
||||
bool fixPacket(Packet &func, Packet &timing);
|
||||
#endif //__MEM_PACKET_HH
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
|
||||
#include "base/misc.hh"
|
||||
#include "config/full_system.hh"
|
||||
#include "mem/packet_impl.hh"
|
||||
#include "mem/physical.hh"
|
||||
#include "sim/host.hh"
|
||||
#include "sim/builder.hh"
|
||||
|
@ -181,7 +182,6 @@ PhysicalMemory::getPort(const std::string &if_name)
|
|||
void
|
||||
PhysicalMemory::recvStatusChange(Port::Status status)
|
||||
{
|
||||
panic("??");
|
||||
}
|
||||
|
||||
PhysicalMemory::MemoryPort::MemoryPort(PhysicalMemory *_memory)
|
||||
|
|
|
@ -227,7 +227,7 @@ class FunctionalPort : public Port
|
|||
virtual bool recvTiming(Packet &pkt) { panic("FuncPort is UniDir"); }
|
||||
virtual Tick recvAtomic(Packet &pkt) { panic("FuncPort is UniDir"); }
|
||||
virtual void recvFunctional(Packet &pkt) { panic("FuncPort is UniDir"); }
|
||||
virtual void recvStatusChange(Status status) {panic("FuncPort is UniDir");}
|
||||
virtual void recvStatusChange(Status status) {}
|
||||
|
||||
template <typename T>
|
||||
inline void write(Addr addr, T d)
|
||||
|
|
9
python/m5/objects/Bridge.py
Normal file
9
python/m5/objects/Bridge.py
Normal file
|
@ -0,0 +1,9 @@
|
|||
from m5 import *
|
||||
from MemObject import MemObject
|
||||
|
||||
class Bridge(MemObject):
|
||||
type = 'Bridge'
|
||||
queue_size_a = Param.Int(16, "The number of requests to buffer")
|
||||
queue_size_b = Param.Int(16, "The number of requests to buffer")
|
||||
delay = Param.Latency('0ns', "The latency of this bridge")
|
||||
write_ack = Param.Bool(False, "Should this bridge ack writes")
|
|
@ -9,6 +9,7 @@ class System(SimObject):
|
|||
init_param = Param.UInt64(0, "numerical value to pass into simulator")
|
||||
bin = Param.Bool(False, "is this system binned")
|
||||
binned_fns = VectorParam.String([], "functions broken down and binned")
|
||||
boot_osflags = Param.String("a", "boot flags to pass to the kernel")
|
||||
kernel = Param.String("file that contains the kernel code")
|
||||
readfile = Param.String("", "file to read startup script from")
|
||||
|
||||
|
@ -16,6 +17,5 @@ class AlphaSystem(System):
|
|||
type = 'AlphaSystem'
|
||||
console = Param.String("file that contains the console code")
|
||||
pal = Param.String("file that contains palcode")
|
||||
boot_osflags = Param.String("a", "boot flags to pass to the kernel")
|
||||
system_type = Param.UInt64("Type of system we are emulating")
|
||||
system_rev = Param.UInt64("Revision of system we are emulating")
|
||||
|
|
|
@ -155,6 +155,7 @@ class System : public SimObject
|
|||
|
||||
#if FULL_SYSTEM
|
||||
Tick boot_cpu_frequency;
|
||||
std::string boot_osflags;
|
||||
uint64_t init_param;
|
||||
bool bin;
|
||||
std::vector<std::string> binned_fns;
|
||||
|
|
Loading…
Reference in a new issue