Merge zizzer:/bk/newmem
into zeep.pool:/z/saidi/work/m5.newmem src/cpu/simple/atomic.cc: merge steve's changes in. --HG-- extra : convert_revision : a17eda37cd63c9380af6fe68b0aef4b1e1974231
This commit is contained in:
commit
b9005f3562
28 changed files with 530 additions and 314 deletions
|
@ -544,7 +544,7 @@ def template StoreCondCompleteAcc {{
|
||||||
%(fp_enable_check)s;
|
%(fp_enable_check)s;
|
||||||
%(op_dest_decl)s;
|
%(op_dest_decl)s;
|
||||||
|
|
||||||
uint64_t write_result = pkt->req->getScResult();
|
uint64_t write_result = pkt->req->getExtraData();
|
||||||
|
|
||||||
if (fault == NoFault) {
|
if (fault == NoFault) {
|
||||||
%(postacc_code)s;
|
%(postacc_code)s;
|
||||||
|
|
|
@ -68,7 +68,7 @@ handleLockedWrite(XC *xc, Request *req)
|
||||||
if (req->isUncacheable()) {
|
if (req->isUncacheable()) {
|
||||||
// Funky Turbolaser mailbox access...don't update
|
// Funky Turbolaser mailbox access...don't update
|
||||||
// result register (see stq_c in decoder.isa)
|
// result register (see stq_c in decoder.isa)
|
||||||
req->setScResult(2);
|
req->setExtraData(2);
|
||||||
} else {
|
} else {
|
||||||
// standard store conditional
|
// standard store conditional
|
||||||
bool lock_flag = xc->readMiscReg(MISCREG_LOCKFLAG);
|
bool lock_flag = xc->readMiscReg(MISCREG_LOCKFLAG);
|
||||||
|
@ -76,7 +76,7 @@ handleLockedWrite(XC *xc, Request *req)
|
||||||
if (!lock_flag || (req->getPaddr() & ~0xf) != lock_addr) {
|
if (!lock_flag || (req->getPaddr() & ~0xf) != lock_addr) {
|
||||||
// Lock flag not set or addr mismatch in CPU;
|
// Lock flag not set or addr mismatch in CPU;
|
||||||
// don't even bother sending to memory system
|
// don't even bother sending to memory system
|
||||||
req->setScResult(0);
|
req->setExtraData(0);
|
||||||
xc->setMiscReg(MISCREG_LOCKFLAG, false);
|
xc->setMiscReg(MISCREG_LOCKFLAG, false);
|
||||||
// the rest of this code is not architectural;
|
// the rest of this code is not architectural;
|
||||||
// it's just a debugging aid to help detect
|
// it's just a debugging aid to help detect
|
||||||
|
|
|
@ -42,6 +42,7 @@ namespace AlphaISA
|
||||||
typedef uint8_t RegIndex;
|
typedef uint8_t RegIndex;
|
||||||
|
|
||||||
typedef uint64_t IntReg;
|
typedef uint64_t IntReg;
|
||||||
|
typedef uint64_t LargestRead;
|
||||||
|
|
||||||
// floating point register file entry type
|
// floating point register file entry type
|
||||||
typedef double FloatReg;
|
typedef double FloatReg;
|
||||||
|
|
|
@ -1124,6 +1124,9 @@ def buildOperandTypeMap(userDict, lineno):
|
||||||
ctype = 'float'
|
ctype = 'float'
|
||||||
elif size == 64:
|
elif size == 64:
|
||||||
ctype = 'double'
|
ctype = 'double'
|
||||||
|
elif desc == 'twin int':
|
||||||
|
is_signed = 0
|
||||||
|
ctype = 'Twin64_t'
|
||||||
if ctype == '':
|
if ctype == '':
|
||||||
error(lineno, 'Unrecognized type description "%s" in userDict')
|
error(lineno, 'Unrecognized type description "%s" in userDict')
|
||||||
operandTypeMap[ext] = (size, ctype, is_signed)
|
operandTypeMap[ext] = (size, ctype, is_signed)
|
||||||
|
@ -1156,7 +1159,10 @@ class Operand(object):
|
||||||
# template must be careful not to use it if it doesn't apply.
|
# template must be careful not to use it if it doesn't apply.
|
||||||
if self.isMem():
|
if self.isMem():
|
||||||
self.mem_acc_size = self.makeAccSize()
|
self.mem_acc_size = self.makeAccSize()
|
||||||
self.mem_acc_type = self.ctype
|
if self.ctype == 'Twin64_t':
|
||||||
|
self.mem_acc_type = 'Twin'
|
||||||
|
else:
|
||||||
|
self.mem_acc_type = 'uint'
|
||||||
|
|
||||||
# Finalize additional fields (primarily code fields). This step
|
# Finalize additional fields (primarily code fields). This step
|
||||||
# is done separately since some of these fields may depend on the
|
# is done separately since some of these fields may depend on the
|
||||||
|
@ -1386,6 +1392,9 @@ class MemOperand(Operand):
|
||||||
# Note that initializations in the declarations are solely
|
# Note that initializations in the declarations are solely
|
||||||
# to avoid 'uninitialized variable' errors from the compiler.
|
# to avoid 'uninitialized variable' errors from the compiler.
|
||||||
# Declare memory data variable.
|
# Declare memory data variable.
|
||||||
|
if self.ctype == 'Twin64_t':
|
||||||
|
return "%s %s; %s.a = 0; %s.b = 0;\n" % (self.ctype, self.base_name,
|
||||||
|
self.base_name, self.base_name)
|
||||||
c = '%s %s = 0;\n' % (self.ctype, self.base_name)
|
c = '%s %s = 0;\n' % (self.ctype, self.base_name)
|
||||||
return c
|
return c
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,8 @@ namespace MipsISA
|
||||||
typedef uint8_t RegIndex;
|
typedef uint8_t RegIndex;
|
||||||
|
|
||||||
typedef uint32_t IntReg;
|
typedef uint32_t IntReg;
|
||||||
|
typedef uint64_t LargestRead;
|
||||||
|
|
||||||
|
|
||||||
// floating point register file entry type
|
// floating point register file entry type
|
||||||
typedef uint32_t FloatReg32;
|
typedef uint32_t FloatReg32;
|
||||||
|
|
|
@ -472,8 +472,8 @@ decode OP default Unknown::unknown()
|
||||||
}});
|
}});
|
||||||
//7-14 should cause an illegal instruction exception
|
//7-14 should cause an illegal instruction exception
|
||||||
0x0F: decode I {
|
0x0F: decode I {
|
||||||
0x0: Nop::stbar({{/*stuff*/}});
|
0x0: Nop::stbar({{/*stuff*/}}, IsWriteBarrier, MemWriteOp);
|
||||||
0x1: Nop::membar({{/*stuff*/}});
|
0x1: Nop::membar({{/*stuff*/}}, IsMemBarrier, MemReadOp);
|
||||||
}
|
}
|
||||||
0x10: Priv::rdpcr({{Rd = Pcr;}});
|
0x10: Priv::rdpcr({{Rd = Pcr;}});
|
||||||
0x11: PrivCheck::rdpic({{Rd = Pic;}}, {{Pcr<0:>}});
|
0x11: PrivCheck::rdpic({{Rd = Pic;}}, {{Pcr<0:>}});
|
||||||
|
@ -1168,15 +1168,17 @@ decode OP default Unknown::unknown()
|
||||||
0x0A: ldsh({{Rd = (int16_t)Mem.shw;}});
|
0x0A: ldsh({{Rd = (int16_t)Mem.shw;}});
|
||||||
0x0B: ldx({{Rd = (int64_t)Mem.sdw;}});
|
0x0B: ldx({{Rd = (int64_t)Mem.sdw;}});
|
||||||
}
|
}
|
||||||
0x0D: LoadStore::ldstub(
|
0x0D: Swap::ldstub({{Mem.ub = 0xFF;}},
|
||||||
{{uReg0 = Mem.ub;}},
|
{{
|
||||||
{{Rd.ub = uReg0;
|
uint8_t tmp = mem_data;
|
||||||
Mem.ub = 0xFF;}});
|
Rd.ub = tmp;
|
||||||
|
}}, MEM_SWAP);
|
||||||
0x0E: Store::stx({{Mem.udw = Rd}});
|
0x0E: Store::stx({{Mem.udw = Rd}});
|
||||||
0x0F: LoadStore::swap(
|
0x0F: Swap::swap({{Mem.uw = Rd.uw}},
|
||||||
{{ uReg0 = Mem.uw}},
|
{{
|
||||||
{{ Mem.uw = Rd.uw;
|
uint32_t tmp = mem_data;
|
||||||
Rd.uw = uReg0;}});
|
Rd.uw = tmp;
|
||||||
|
}}, MEM_SWAP);
|
||||||
format LoadAlt {
|
format LoadAlt {
|
||||||
0x10: lduwa({{Rd = Mem.uw;}}, {{EXT_ASI}});
|
0x10: lduwa({{Rd = Mem.uw;}}, {{EXT_ASI}});
|
||||||
0x11: lduba({{Rd = Mem.ub;}}, {{EXT_ASI}});
|
0x11: lduba({{Rd = Mem.ub;}}, {{EXT_ASI}});
|
||||||
|
@ -1184,34 +1186,60 @@ decode OP default Unknown::unknown()
|
||||||
0x13: decode EXT_ASI {
|
0x13: decode EXT_ASI {
|
||||||
//ASI_LDTD_AIUP
|
//ASI_LDTD_AIUP
|
||||||
0x22: TwinLoad::ldtx_aiup(
|
0x22: TwinLoad::ldtx_aiup(
|
||||||
{{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}});
|
{{RdLow.udw = (Mem.tudw).a;
|
||||||
|
RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
|
||||||
//ASI_LDTD_AIUS
|
//ASI_LDTD_AIUS
|
||||||
0x23: TwinLoad::ldtx_aius(
|
0x23: TwinLoad::ldtx_aius(
|
||||||
{{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}});
|
{{RdLow.udw = (Mem.tudw).a;
|
||||||
|
RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
|
||||||
//ASI_QUAD_LDD
|
//ASI_QUAD_LDD
|
||||||
0x24: TwinLoad::ldtx_quad_ldd(
|
0x24: TwinLoad::ldtx_quad_ldd(
|
||||||
{{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}});
|
{{RdLow.udw = (Mem.tudw).a;
|
||||||
|
RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
|
||||||
//ASI_LDTX_REAL
|
//ASI_LDTX_REAL
|
||||||
0x26: TwinLoad::ldtx_real(
|
0x26: TwinLoad::ldtx_real(
|
||||||
{{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}});
|
{{RdLow.udw = (Mem.tudw).a;
|
||||||
|
RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
|
||||||
//ASI_LDTX_N
|
//ASI_LDTX_N
|
||||||
0x27: TwinLoad::ldtx_n(
|
0x27: TwinLoad::ldtx_n(
|
||||||
{{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}});
|
{{RdLow.udw = (Mem.tudw).a;
|
||||||
|
RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
|
||||||
|
//ASI_LDTX_AIUP_L
|
||||||
|
0x2A: TwinLoad::ldtx_aiup_l(
|
||||||
|
{{RdLow.udw = (Mem.tudw).a;
|
||||||
|
RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
|
||||||
|
//ASI_LDTX_AIUS_L
|
||||||
|
0x2B: TwinLoad::ldtx_aius_l(
|
||||||
|
{{RdLow.udw = (Mem.tudw).a;
|
||||||
|
RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
|
||||||
//ASI_LDTX_L
|
//ASI_LDTX_L
|
||||||
0x2C: TwinLoad::ldtx_l(
|
0x2C: TwinLoad::ldtx_l(
|
||||||
{{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}});
|
{{RdLow.udw = (Mem.tudw).a;
|
||||||
|
RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
|
||||||
//ASI_LDTX_REAL_L
|
//ASI_LDTX_REAL_L
|
||||||
0x2E: TwinLoad::ldtx_real_l(
|
0x2E: TwinLoad::ldtx_real_l(
|
||||||
{{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}});
|
{{RdLow.udw = (Mem.tudw).a;
|
||||||
|
RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
|
||||||
//ASI_LDTX_N_L
|
//ASI_LDTX_N_L
|
||||||
0x2F: TwinLoad::ldtx_n_l(
|
0x2F: TwinLoad::ldtx_n_l(
|
||||||
{{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}});
|
{{RdLow.udw = (Mem.tudw).a;
|
||||||
|
RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
|
||||||
//ASI_LDTX_P
|
//ASI_LDTX_P
|
||||||
0xE2: TwinLoad::ldtx_p(
|
0xE2: TwinLoad::ldtx_p(
|
||||||
{{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}});
|
{{RdLow.udw = (Mem.tudw).a;
|
||||||
|
RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
|
||||||
//ASI_LDTX_S
|
//ASI_LDTX_S
|
||||||
0xE3: TwinLoad::ldtx_s(
|
0xE3: TwinLoad::ldtx_s(
|
||||||
{{RdTwin.udw = Mem.udw;}}, {{EXT_ASI}});
|
{{RdLow.udw = (Mem.tudw).a;
|
||||||
|
RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
|
||||||
|
//ASI_LDTX_PL
|
||||||
|
0xEA: TwinLoad::ldtx_pl(
|
||||||
|
{{RdLow.udw = (Mem.tudw).a;
|
||||||
|
RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
|
||||||
|
//ASI_LDTX_SL
|
||||||
|
0xEB: TwinLoad::ldtx_sl(
|
||||||
|
{{RdLow.udw = (Mem.tudw).a;
|
||||||
|
RdHigh.udw = (Mem.tudw).b;}}, {{EXT_ASI}});
|
||||||
default: ldtwa({{
|
default: ldtwa({{
|
||||||
uint64_t val = Mem.udw;
|
uint64_t val = Mem.udw;
|
||||||
RdLow = val<31:0>;
|
RdLow = val<31:0>;
|
||||||
|
@ -1231,15 +1259,18 @@ decode OP default Unknown::unknown()
|
||||||
0x1A: ldsha({{Rd = (int16_t)Mem.shw;}}, {{EXT_ASI}});
|
0x1A: ldsha({{Rd = (int16_t)Mem.shw;}}, {{EXT_ASI}});
|
||||||
0x1B: ldxa({{Rd = (int64_t)Mem.sdw;}}, {{EXT_ASI}});
|
0x1B: ldxa({{Rd = (int64_t)Mem.sdw;}}, {{EXT_ASI}});
|
||||||
}
|
}
|
||||||
0x1D: LoadStoreAlt::ldstuba(
|
0x1D: SwapAlt::ldstuba({{Mem.ub = 0xFF;}},
|
||||||
{{uReg0 = Mem.ub;}},
|
{{
|
||||||
{{Rd.ub = uReg0;
|
uint8_t tmp = mem_data;
|
||||||
Mem.ub = 0xFF;}}, {{EXT_ASI}});
|
Rd.ub = tmp;
|
||||||
|
}}, {{EXT_ASI}}, MEM_SWAP);
|
||||||
0x1E: StoreAlt::stxa({{Mem.udw = Rd}}, {{EXT_ASI}});
|
0x1E: StoreAlt::stxa({{Mem.udw = Rd}}, {{EXT_ASI}});
|
||||||
0x1F: LoadStoreAlt::swapa(
|
0x1F: SwapAlt::swapa({{Mem.uw = Rd.uw}},
|
||||||
{{ uReg0 = Mem.uw}},
|
{{
|
||||||
{{ Mem.uw = Rd.uw;
|
uint32_t tmp = mem_data;
|
||||||
Rd.uw = uReg0;}}, {{EXT_ASI}});
|
Rd.uw = tmp;
|
||||||
|
}}, {{EXT_ASI}}, MEM_SWAP);
|
||||||
|
|
||||||
format Trap {
|
format Trap {
|
||||||
0x20: Load::ldf({{Frds.uw = Mem.uw;}});
|
0x20: Load::ldf({{Frds.uw = Mem.uw;}});
|
||||||
0x21: decode RD {
|
0x21: decode RD {
|
||||||
|
@ -1438,21 +1469,17 @@ decode OP default Unknown::unknown()
|
||||||
{{fault = new DataAccessException;}});
|
{{fault = new DataAccessException;}});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
0x3C: Cas::casa(
|
0x3C: CasAlt::casa({{
|
||||||
{{uReg0 = Mem.uw;}},
|
mem_data = htog(Rs2.uw);
|
||||||
{{if(Rs2.uw == uReg0)
|
Mem.uw = Rd.uw;}},
|
||||||
Mem.uw = Rd.uw;
|
{{
|
||||||
else
|
uint32_t tmp = mem_data;
|
||||||
storeCond = false;
|
Rd.uw = tmp;
|
||||||
Rd.uw = uReg0;}}, {{EXT_ASI}});
|
}}, {{EXT_ASI}}, MEM_SWAP_COND);
|
||||||
0x3D: Nop::prefetcha({{ }});
|
0x3D: Nop::prefetcha({{ }});
|
||||||
0x3E: Cas::casxa(
|
0x3E: CasAlt::casxa({{mem_data = gtoh(Rs2);
|
||||||
{{uReg0 = Mem.udw;}},
|
Mem.udw = Rd.udw; }},
|
||||||
{{if(Rs2 == uReg0)
|
{{ Rd.udw = mem_data; }}, {{EXT_ASI}}, MEM_SWAP_COND);
|
||||||
Mem.udw = Rd;
|
|
||||||
else
|
|
||||||
storeCond = false;
|
|
||||||
Rd = uReg0;}}, {{EXT_ASI}});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2006 The Regents of The University of Michigan
|
// Copyright (c) 2006-2007 The Regents of The University of Michigan
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -52,22 +52,20 @@ def template MemDeclare {{
|
||||||
}};
|
}};
|
||||||
|
|
||||||
let {{
|
let {{
|
||||||
def doMemFormat(code, execute, faultCode, name, Name, asi, opt_flags):
|
def doMemFormat(code, execute, faultCode, name, Name, asi, opt_flags, postacc_code = ''):
|
||||||
addrCalcReg = 'EA = Rs1 + Rs2;'
|
addrCalcReg = 'EA = Rs1 + Rs2;'
|
||||||
addrCalcImm = 'EA = Rs1 + imm;'
|
addrCalcImm = 'EA = Rs1 + imm;'
|
||||||
iop = InstObjParams(name, Name, 'Mem',
|
iop = InstObjParams(name, Name, 'Mem',
|
||||||
{"code": code, "fault_check": faultCode,
|
{"code": code, "postacc_code" : postacc_code,
|
||||||
"ea_code": addrCalcReg},
|
"fault_check": faultCode, "ea_code": addrCalcReg}, opt_flags)
|
||||||
opt_flags)
|
|
||||||
iop_imm = InstObjParams(name, Name + "Imm", 'MemImm',
|
iop_imm = InstObjParams(name, Name + "Imm", 'MemImm',
|
||||||
{"code": code, "fault_check": faultCode,
|
{"code": code, "postacc_code" : postacc_code,
|
||||||
"ea_code": addrCalcImm},
|
"fault_check": faultCode, "ea_code": addrCalcImm}, opt_flags)
|
||||||
opt_flags)
|
|
||||||
header_output = MemDeclare.subst(iop) + MemDeclare.subst(iop_imm)
|
header_output = MemDeclare.subst(iop) + MemDeclare.subst(iop_imm)
|
||||||
decoder_output = BasicConstructor.subst(iop) + BasicConstructor.subst(iop_imm)
|
decoder_output = BasicConstructor.subst(iop) + BasicConstructor.subst(iop_imm)
|
||||||
decode_block = ROrImmDecode.subst(iop)
|
decode_block = ROrImmDecode.subst(iop)
|
||||||
exec_output = doDualSplitExecute(code, addrCalcReg, addrCalcImm,
|
exec_output = doDualSplitExecute(code, postacc_code, addrCalcReg,
|
||||||
execute, faultCode, name, name + "Imm",
|
addrCalcImm, execute, faultCode, name, name + "Imm",
|
||||||
Name, Name + "Imm", asi, opt_flags)
|
Name, Name + "Imm", asi, opt_flags)
|
||||||
return (header_output, decoder_output, exec_output, decode_block)
|
return (header_output, decoder_output, exec_output, decode_block)
|
||||||
}};
|
}};
|
||||||
|
@ -103,3 +101,13 @@ def format Store(code, *opt_flags) {{
|
||||||
decode_block) = doMemFormat(code,
|
decode_block) = doMemFormat(code,
|
||||||
StoreFuncs, '', name, Name, 0, opt_flags)
|
StoreFuncs, '', name, Name, 0, opt_flags)
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
def format TwinLoad(code, asi, *opt_flags) {{
|
||||||
|
(header_output,
|
||||||
|
decoder_output,
|
||||||
|
exec_output,
|
||||||
|
decode_block) = doMemFormat(code, LoadFuncs,
|
||||||
|
AlternateASIPrivFaultCheck + TwinAlignmentFaultCheck,
|
||||||
|
name, Name, asi, opt_flags)
|
||||||
|
}};
|
||||||
|
|
||||||
|
|
|
@ -91,65 +91,6 @@ output header {{
|
||||||
};
|
};
|
||||||
}};
|
}};
|
||||||
|
|
||||||
output header {{
|
|
||||||
|
|
||||||
class TwinMem : public SparcMacroInst
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
// We make the assumption that all block memory operations
|
|
||||||
// Will take 8 instructions to execute
|
|
||||||
TwinMem(const char *mnem, ExtMachInst _machInst) :
|
|
||||||
SparcMacroInst(mnem, _machInst, No_OpClass, 2)
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
|
|
||||||
class TwinMemImm : public BlockMem
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
TwinMemImm(const char *mnem, ExtMachInst _machInst) :
|
|
||||||
BlockMem(mnem, _machInst)
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
|
|
||||||
class TwinMemMicro : public SparcMicroInst
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
TwinMemMicro(const char *mnem, ExtMachInst _machInst,
|
|
||||||
OpClass __opClass, int8_t _offset) :
|
|
||||||
SparcMicroInst(mnem, _machInst, __opClass),
|
|
||||||
offset(_offset)
|
|
||||||
{}
|
|
||||||
|
|
||||||
std::string generateDisassembly(Addr pc,
|
|
||||||
const SymbolTable *symtab) const;
|
|
||||||
|
|
||||||
const int8_t offset;
|
|
||||||
};
|
|
||||||
|
|
||||||
class TwinMemImmMicro : public BlockMemMicro
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
TwinMemImmMicro(const char *mnem, ExtMachInst _machInst,
|
|
||||||
OpClass __opClass, int8_t _offset) :
|
|
||||||
BlockMemMicro(mnem, _machInst, __opClass, _offset),
|
|
||||||
imm(sext<13>(SIMM13))
|
|
||||||
{}
|
|
||||||
|
|
||||||
std::string generateDisassembly(Addr pc,
|
|
||||||
const SymbolTable *symtab) const;
|
|
||||||
|
|
||||||
const int32_t imm;
|
|
||||||
};
|
|
||||||
}};
|
|
||||||
|
|
||||||
output decoder {{
|
output decoder {{
|
||||||
std::string BlockMemMicro::generateDisassembly(Addr pc,
|
std::string BlockMemMicro::generateDisassembly(Addr pc,
|
||||||
const SymbolTable *symtab) const
|
const SymbolTable *symtab) const
|
||||||
|
@ -208,64 +149,6 @@ output decoder {{
|
||||||
|
|
||||||
}};
|
}};
|
||||||
|
|
||||||
output decoder {{
|
|
||||||
std::string TwinMemMicro::generateDisassembly(Addr pc,
|
|
||||||
const SymbolTable *symtab) const
|
|
||||||
{
|
|
||||||
std::stringstream response;
|
|
||||||
bool load = flags[IsLoad];
|
|
||||||
bool save = flags[IsStore];
|
|
||||||
|
|
||||||
printMnemonic(response, mnemonic);
|
|
||||||
if(save)
|
|
||||||
{
|
|
||||||
printReg(response, _srcRegIdx[0]);
|
|
||||||
ccprintf(response, ", ");
|
|
||||||
}
|
|
||||||
ccprintf(response, "[ ");
|
|
||||||
printReg(response, _srcRegIdx[!save ? 0 : 1]);
|
|
||||||
ccprintf(response, " + ");
|
|
||||||
printReg(response, _srcRegIdx[!save ? 1 : 2]);
|
|
||||||
ccprintf(response, " ]");
|
|
||||||
if(load)
|
|
||||||
{
|
|
||||||
ccprintf(response, ", ");
|
|
||||||
printReg(response, _destRegIdx[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return response.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string TwinMemImmMicro::generateDisassembly(Addr pc,
|
|
||||||
const SymbolTable *symtab) const
|
|
||||||
{
|
|
||||||
std::stringstream response;
|
|
||||||
bool load = flags[IsLoad];
|
|
||||||
bool save = flags[IsStore];
|
|
||||||
|
|
||||||
printMnemonic(response, mnemonic);
|
|
||||||
if(save)
|
|
||||||
{
|
|
||||||
printReg(response, _srcRegIdx[1]);
|
|
||||||
ccprintf(response, ", ");
|
|
||||||
}
|
|
||||||
ccprintf(response, "[ ");
|
|
||||||
printReg(response, _srcRegIdx[0]);
|
|
||||||
if(imm >= 0)
|
|
||||||
ccprintf(response, " + 0x%x ]", imm);
|
|
||||||
else
|
|
||||||
ccprintf(response, " + -0x%x ]", -imm);
|
|
||||||
if(load)
|
|
||||||
{
|
|
||||||
ccprintf(response, ", ");
|
|
||||||
printReg(response, _destRegIdx[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return response.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
}};
|
|
||||||
|
|
||||||
def template BlockMemDeclare {{
|
def template BlockMemDeclare {{
|
||||||
/**
|
/**
|
||||||
* Static instruction class for a block memory operation
|
* Static instruction class for a block memory operation
|
||||||
|
@ -359,39 +242,6 @@ def template BlockMemDeclare {{
|
||||||
};
|
};
|
||||||
}};
|
}};
|
||||||
|
|
||||||
def template TwinMemDeclare {{
|
|
||||||
/**
|
|
||||||
* Static instruction class for a block memory operation
|
|
||||||
*/
|
|
||||||
class %(class_name)s : public %(base_class)s
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//Constructor
|
|
||||||
%(class_name)s(ExtMachInst machInst);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
class %(class_name)s_0 : public %(base_class)sMicro
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//Constructor
|
|
||||||
%(class_name)s_0(ExtMachInst machInst);
|
|
||||||
%(BasicExecDeclare)s
|
|
||||||
%(InitiateAccDeclare)s
|
|
||||||
%(CompleteAccDeclare)s
|
|
||||||
};
|
|
||||||
|
|
||||||
class %(class_name)s_1 : public %(base_class)sMicro
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//Constructor
|
|
||||||
%(class_name)s_1(ExtMachInst machInst);
|
|
||||||
%(BasicExecDeclare)s
|
|
||||||
%(InitiateAccDeclare)s
|
|
||||||
%(CompleteAccDeclare)s
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}};
|
|
||||||
|
|
||||||
// Basic instruction class constructor template.
|
// Basic instruction class constructor template.
|
||||||
def template BlockMemConstructor {{
|
def template BlockMemConstructor {{
|
||||||
inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
|
inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
|
||||||
|
@ -409,17 +259,6 @@ def template BlockMemConstructor {{
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
|
|
||||||
// Basic instruction class constructor template.
|
|
||||||
def template TwinMemConstructor {{
|
|
||||||
inline %(class_name)s::%(class_name)s(ExtMachInst machInst)
|
|
||||||
: %(base_class)s("%(mnemonic)s", machInst)
|
|
||||||
{
|
|
||||||
%(constructor)s;
|
|
||||||
microOps[0] = new %(class_name)s_0(machInst);
|
|
||||||
microOps[1] = new %(class_name)s_1(machInst);
|
|
||||||
}
|
|
||||||
}};
|
|
||||||
|
|
||||||
def template BlockMemMicroConstructor {{
|
def template BlockMemMicroConstructor {{
|
||||||
inline %(class_name)s::
|
inline %(class_name)s::
|
||||||
%(class_name)s_%(micro_pc)s::
|
%(class_name)s_%(micro_pc)s::
|
||||||
|
@ -467,7 +306,7 @@ let {{
|
||||||
decoder_output += BlockMemMicroConstructor.subst(iop)
|
decoder_output += BlockMemMicroConstructor.subst(iop)
|
||||||
decoder_output += BlockMemMicroConstructor.subst(iop_imm)
|
decoder_output += BlockMemMicroConstructor.subst(iop_imm)
|
||||||
exec_output += doDualSplitExecute(
|
exec_output += doDualSplitExecute(
|
||||||
pcedCode, addrCalcReg, addrCalcImm, execute, faultCode,
|
pcedCode, '', addrCalcReg, addrCalcImm, execute, faultCode,
|
||||||
makeMicroName(name, microPc),
|
makeMicroName(name, microPc),
|
||||||
makeMicroName(name + "Imm", microPc),
|
makeMicroName(name + "Imm", microPc),
|
||||||
makeMicroName(Name, microPc),
|
makeMicroName(Name, microPc),
|
||||||
|
@ -475,47 +314,6 @@ let {{
|
||||||
asi, opt_flags);
|
asi, opt_flags);
|
||||||
faultCode = ''
|
faultCode = ''
|
||||||
return (header_output, decoder_output, exec_output, decode_block)
|
return (header_output, decoder_output, exec_output, decode_block)
|
||||||
|
|
||||||
def doTwinLoadFormat(code, faultCode, name, Name, asi, opt_flags):
|
|
||||||
addrCalcReg = 'EA = Rs1 + Rs2 + offset;'
|
|
||||||
addrCalcImm = 'EA = Rs1 + imm + offset;'
|
|
||||||
iop = InstObjParams(name, Name, 'TwinMem', code, opt_flags)
|
|
||||||
iop_imm = InstObjParams(name, Name + 'Imm', 'TwinMemImm', code, opt_flags)
|
|
||||||
header_output = TwinMemDeclare.subst(iop) + TwinMemDeclare.subst(iop_imm)
|
|
||||||
decoder_output = TwinMemConstructor.subst(iop) + TwinMemConstructor.subst(iop_imm)
|
|
||||||
decode_block = ROrImmDecode.subst(iop)
|
|
||||||
matcher = re.compile(r'RdTwin')
|
|
||||||
exec_output = ''
|
|
||||||
for microPc in range(2):
|
|
||||||
flag_code = ''
|
|
||||||
pcedCode = ''
|
|
||||||
if (microPc == 1):
|
|
||||||
flag_code = "flags[IsLastMicroOp] = true;"
|
|
||||||
pcedCode = "RdLow = uReg0;\n"
|
|
||||||
pcedCode += matcher.sub("RdHigh", code)
|
|
||||||
else:
|
|
||||||
flag_code = "flags[IsDelayedCommit] = true; flags[IsFirstMicroOp] = true;"
|
|
||||||
pcedCode = matcher.sub("uReg0", code)
|
|
||||||
iop = InstObjParams(name, Name, 'TwinMem',
|
|
||||||
{"code": pcedCode, "ea_code": addrCalcReg,
|
|
||||||
"fault_check": faultCode, "micro_pc": microPc,
|
|
||||||
"set_flags": flag_code}, opt_flags)
|
|
||||||
iop_imm = InstObjParams(name, Name + 'Imm', 'TwinMemImm',
|
|
||||||
{"code": pcedCode, "ea_code": addrCalcImm,
|
|
||||||
"fault_check": faultCode, "micro_pc": microPc,
|
|
||||||
"set_flags": flag_code}, opt_flags)
|
|
||||||
decoder_output += BlockMemMicroConstructor.subst(iop)
|
|
||||||
decoder_output += BlockMemMicroConstructor.subst(iop_imm)
|
|
||||||
exec_output += doDualSplitExecute(
|
|
||||||
pcedCode, addrCalcReg, addrCalcImm, LoadFuncs, faultCode,
|
|
||||||
makeMicroName(name, microPc),
|
|
||||||
makeMicroName(name + "Imm", microPc),
|
|
||||||
makeMicroName(Name, microPc),
|
|
||||||
makeMicroName(Name + "Imm", microPc),
|
|
||||||
asi, opt_flags);
|
|
||||||
faultCode = ''
|
|
||||||
return (header_output, decoder_output, exec_output, decode_block)
|
|
||||||
|
|
||||||
}};
|
}};
|
||||||
|
|
||||||
def format BlockLoad(code, asi, *opt_flags) {{
|
def format BlockLoad(code, asi, *opt_flags) {{
|
||||||
|
@ -541,11 +339,3 @@ def format BlockStore(code, asi, *opt_flags) {{
|
||||||
decode_block) = doBlockMemFormat(code, faultCode,
|
decode_block) = doBlockMemFormat(code, faultCode,
|
||||||
StoreFuncs, name, Name, asi, opt_flags)
|
StoreFuncs, name, Name, asi, opt_flags)
|
||||||
}};
|
}};
|
||||||
|
|
||||||
def format TwinLoad(code, asi, *opt_flags) {{
|
|
||||||
faultCode = AlternateASIPrivFaultCheck + TwinAlignmentFaultCheck
|
|
||||||
(header_output,
|
|
||||||
decoder_output,
|
|
||||||
exec_output,
|
|
||||||
decode_block) = doTwinLoadFormat(code, faultCode, name, Name, asi, opt_flags)
|
|
||||||
}};
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2006 The Regents of The University of Michigan
|
// Copyright (c) 2006-2007 The Regents of The University of Michigan
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -42,4 +42,4 @@
|
||||||
##include "blockmem.isa"
|
##include "blockmem.isa"
|
||||||
|
|
||||||
//Include the load/store and cas memory format
|
//Include the load/store and cas memory format
|
||||||
##include "loadstore.isa"
|
##include "swap.isa"
|
||||||
|
|
183
src/arch/sparc/isa/formats/mem/swap.isa
Normal file
183
src/arch/sparc/isa/formats/mem/swap.isa
Normal file
|
@ -0,0 +1,183 @@
|
||||||
|
// Copyright (c) 2007 The Regents of The University of Michigan
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met: redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer;
|
||||||
|
// redistributions in binary form must reproduce the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer in the
|
||||||
|
// documentation and/or other materials provided with the distribution;
|
||||||
|
// neither the name of the copyright holders nor the names of its
|
||||||
|
// contributors may be used to endorse or promote products derived from
|
||||||
|
// this software without specific prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// Authors: Gabe Black
|
||||||
|
// Ali Saidi
|
||||||
|
|
||||||
|
//This template provides the execute functions for a swap
|
||||||
|
def template SwapExecute {{
|
||||||
|
Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
|
||||||
|
Trace::InstRecord *traceData) const
|
||||||
|
{
|
||||||
|
Fault fault = NoFault;
|
||||||
|
//This is to support the conditional store in cas instructions.
|
||||||
|
//It should be optomized out in all the others
|
||||||
|
bool storeCond = true;
|
||||||
|
Addr EA;
|
||||||
|
%(fp_enable_check)s;
|
||||||
|
%(op_decl)s;
|
||||||
|
uint64_t mem_data;
|
||||||
|
|
||||||
|
%(op_rd)s;
|
||||||
|
%(ea_code)s;
|
||||||
|
DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA);
|
||||||
|
%(fault_check)s;
|
||||||
|
if(fault == NoFault)
|
||||||
|
{
|
||||||
|
%(code)s;
|
||||||
|
}
|
||||||
|
if(storeCond && fault == NoFault)
|
||||||
|
{
|
||||||
|
fault = xc->write((uint%(mem_acc_size)s_t)Mem,
|
||||||
|
EA, %(asi_val)s, &mem_data);
|
||||||
|
}
|
||||||
|
if(fault == NoFault)
|
||||||
|
{
|
||||||
|
//Handle the swapping
|
||||||
|
%(postacc_code)s;
|
||||||
|
}
|
||||||
|
if(fault == NoFault)
|
||||||
|
{
|
||||||
|
//Write the resulting state to the execution context
|
||||||
|
%(op_wb)s;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fault;
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
|
||||||
|
|
||||||
|
def template SwapInitiateAcc {{
|
||||||
|
Fault %(class_name)s::initiateAcc(%(CPU_exec_context)s * xc,
|
||||||
|
Trace::InstRecord * traceData) const
|
||||||
|
{
|
||||||
|
Fault fault = NoFault;
|
||||||
|
Addr EA;
|
||||||
|
%(fp_enable_check)s;
|
||||||
|
uint64_t mem_data = 0;
|
||||||
|
%(op_decl)s;
|
||||||
|
%(op_rd)s;
|
||||||
|
%(ea_code)s;
|
||||||
|
|
||||||
|
DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA);
|
||||||
|
%(fault_check)s;
|
||||||
|
|
||||||
|
if(fault == NoFault)
|
||||||
|
{
|
||||||
|
%(code)s;
|
||||||
|
}
|
||||||
|
if(fault == NoFault)
|
||||||
|
{
|
||||||
|
fault = xc->write((uint%(mem_acc_size)s_t)Mem,
|
||||||
|
EA, %(asi_val)s, &mem_data);
|
||||||
|
}
|
||||||
|
return fault;
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def template SwapCompleteAcc {{
|
||||||
|
Fault %(class_name)s::completeAcc(PacketPtr pkt, %(CPU_exec_context)s * xc,
|
||||||
|
Trace::InstRecord * traceData) const
|
||||||
|
{
|
||||||
|
Fault fault = NoFault;
|
||||||
|
%(op_decl)s;
|
||||||
|
|
||||||
|
uint64_t mem_data = pkt->get<uint%(mem_acc_size)s_t>();
|
||||||
|
|
||||||
|
if(fault == NoFault)
|
||||||
|
{
|
||||||
|
//Handle the swapping
|
||||||
|
%(postacc_code)s;
|
||||||
|
}
|
||||||
|
if(fault == NoFault)
|
||||||
|
{
|
||||||
|
//Write the resulting state to the execution context
|
||||||
|
%(op_wb)s;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fault;
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
|
||||||
|
let {{
|
||||||
|
SwapFuncs = [SwapExecute, SwapInitiateAcc, SwapCompleteAcc]
|
||||||
|
}};
|
||||||
|
|
||||||
|
|
||||||
|
def format Swap(code, postacc_code, mem_flags, *opt_flags) {{
|
||||||
|
mem_flags = makeList(mem_flags)
|
||||||
|
flags = string.join(mem_flags, '|')
|
||||||
|
|
||||||
|
(header_output,
|
||||||
|
decoder_output,
|
||||||
|
exec_output,
|
||||||
|
decode_block) = doMemFormat(code, SwapFuncs, '', name, Name, flags,
|
||||||
|
opt_flags, postacc_code)
|
||||||
|
}};
|
||||||
|
|
||||||
|
def format SwapAlt(code, postacc_code, asi, mem_flags, *opt_flags) {{
|
||||||
|
mem_flags = makeList(mem_flags)
|
||||||
|
mem_flags.append(asi)
|
||||||
|
flags = string.join(mem_flags, '|')
|
||||||
|
(header_output,
|
||||||
|
decoder_output,
|
||||||
|
exec_output,
|
||||||
|
decode_block) = doMemFormat(code, SwapFuncs, AlternateASIPrivFaultCheck,
|
||||||
|
name, Name, flags, opt_flags, postacc_code)
|
||||||
|
}};
|
||||||
|
|
||||||
|
|
||||||
|
let {{
|
||||||
|
def doCasFormat(code, execute, faultCode, name, Name, asi, opt_flags, postacc_code = ''):
|
||||||
|
addrCalcReg = 'EA = Rs1;'
|
||||||
|
iop = InstObjParams(name, Name, 'Mem',
|
||||||
|
{"code": code, "postacc_code" : postacc_code,
|
||||||
|
"fault_check": faultCode, "ea_code": addrCalcReg}, opt_flags)
|
||||||
|
header_output = MemDeclare.subst(iop)
|
||||||
|
decoder_output = BasicConstructor.subst(iop)
|
||||||
|
decode_block = BasicDecode.subst(iop)
|
||||||
|
microParams = {"code": code, "postacc_code" : postacc_code,
|
||||||
|
"ea_code" : addrCalcReg, "fault_check" : faultCode}
|
||||||
|
exec_output = doSplitExecute(execute, name, Name, asi, opt_flags,
|
||||||
|
microParams);
|
||||||
|
return (header_output, decoder_output, exec_output, decode_block)
|
||||||
|
}};
|
||||||
|
|
||||||
|
|
||||||
|
def format CasAlt(code, postacc_code, asi, mem_flags, *opt_flags) {{
|
||||||
|
mem_flags = makeList(mem_flags)
|
||||||
|
mem_flags.append(asi)
|
||||||
|
flags = string.join(mem_flags, '|')
|
||||||
|
(header_output,
|
||||||
|
decoder_output,
|
||||||
|
exec_output,
|
||||||
|
decode_block) = doCasFormat(code, SwapFuncs, AlternateASIPrivFaultCheck,
|
||||||
|
name, Name, flags, opt_flags, postacc_code)
|
||||||
|
}};
|
||||||
|
|
||||||
|
|
|
@ -149,7 +149,7 @@ def template LoadExecute {{
|
||||||
%(fault_check)s;
|
%(fault_check)s;
|
||||||
if(fault == NoFault)
|
if(fault == NoFault)
|
||||||
{
|
{
|
||||||
fault = xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, %(asi_val)s);
|
fault = xc->read(EA, (%(mem_acc_type)s%(mem_acc_size)s_t&)Mem, %(asi_val)s);
|
||||||
}
|
}
|
||||||
if(fault == NoFault)
|
if(fault == NoFault)
|
||||||
{
|
{
|
||||||
|
@ -179,7 +179,7 @@ def template LoadInitiateAcc {{
|
||||||
%(fault_check)s;
|
%(fault_check)s;
|
||||||
if(fault == NoFault)
|
if(fault == NoFault)
|
||||||
{
|
{
|
||||||
fault = xc->read(EA, (uint%(mem_acc_size)s_t&)Mem, %(asi_val)s);
|
fault = xc->read(EA, (%(mem_acc_type)s%(mem_acc_size)s_t&)Mem, %(asi_val)s);
|
||||||
}
|
}
|
||||||
return fault;
|
return fault;
|
||||||
}
|
}
|
||||||
|
@ -246,6 +246,7 @@ def template StoreInitiateAcc {{
|
||||||
Addr EA;
|
Addr EA;
|
||||||
%(fp_enable_check)s;
|
%(fp_enable_check)s;
|
||||||
%(op_decl)s;
|
%(op_decl)s;
|
||||||
|
|
||||||
%(op_rd)s;
|
%(op_rd)s;
|
||||||
%(ea_code)s;
|
%(ea_code)s;
|
||||||
DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA);
|
DPRINTF(Sparc, "%s: The address is 0x%x\n", mnemonic, EA);
|
||||||
|
@ -290,6 +291,7 @@ def template CompleteAccDeclare {{
|
||||||
let {{
|
let {{
|
||||||
LoadFuncs = [LoadExecute, LoadInitiateAcc, LoadCompleteAcc]
|
LoadFuncs = [LoadExecute, LoadInitiateAcc, LoadCompleteAcc]
|
||||||
StoreFuncs = [StoreExecute, StoreInitiateAcc, StoreCompleteAcc]
|
StoreFuncs = [StoreExecute, StoreInitiateAcc, StoreCompleteAcc]
|
||||||
|
|
||||||
# The LSB can be zero, since it's really the MSB in doubles and quads
|
# The LSB can be zero, since it's really the MSB in doubles and quads
|
||||||
# and we're dealing with doubles
|
# and we're dealing with doubles
|
||||||
BlockAlignmentFaultCheck = '''
|
BlockAlignmentFaultCheck = '''
|
||||||
|
@ -337,14 +339,14 @@ let {{
|
||||||
return execf.subst(iop) + initf.subst(iop) + compf.subst(iop)
|
return execf.subst(iop) + initf.subst(iop) + compf.subst(iop)
|
||||||
|
|
||||||
|
|
||||||
def doDualSplitExecute(code, eaRegCode, eaImmCode, execute,
|
def doDualSplitExecute(code, postacc_code, eaRegCode, eaImmCode, execute,
|
||||||
faultCode, nameReg, nameImm, NameReg, NameImm, asi, opt_flags):
|
faultCode, nameReg, nameImm, NameReg, NameImm, asi, opt_flags):
|
||||||
executeCode = ''
|
executeCode = ''
|
||||||
for (eaCode, name, Name) in (
|
for (eaCode, name, Name) in (
|
||||||
(eaRegCode, nameReg, NameReg),
|
(eaRegCode, nameReg, NameReg),
|
||||||
(eaImmCode, nameImm, NameImm)):
|
(eaImmCode, nameImm, NameImm)):
|
||||||
microParams = {"code": code, "ea_code": eaCode,
|
microParams = {"code": code, "postacc_code" : postacc_code,
|
||||||
"fault_check": faultCode}
|
"ea_code": eaCode, "fault_check": faultCode}
|
||||||
executeCode += doSplitExecute(execute, name, Name,
|
executeCode += doSplitExecute(execute, name, Name,
|
||||||
asi, opt_flags, microParams)
|
asi, opt_flags, microParams)
|
||||||
return executeCode
|
return executeCode
|
||||||
|
|
|
@ -74,6 +74,7 @@ output exec {{
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include "arch/sparc/asi.hh"
|
#include "arch/sparc/asi.hh"
|
||||||
|
#include "base/bigint.hh"
|
||||||
#include "cpu/base.hh"
|
#include "cpu/base.hh"
|
||||||
#include "cpu/exetrace.hh"
|
#include "cpu/exetrace.hh"
|
||||||
#include "sim/sim_exit.hh"
|
#include "sim/sim_exit.hh"
|
||||||
|
|
|
@ -37,6 +37,7 @@ def operand_types {{
|
||||||
'uw' : ('unsigned int', 32),
|
'uw' : ('unsigned int', 32),
|
||||||
'sdw' : ('signed int', 64),
|
'sdw' : ('signed int', 64),
|
||||||
'udw' : ('unsigned int', 64),
|
'udw' : ('unsigned int', 64),
|
||||||
|
'tudw' : ('twin int', 64),
|
||||||
'sf' : ('float', 32),
|
'sf' : ('float', 32),
|
||||||
'df' : ('float', 64),
|
'df' : ('float', 64),
|
||||||
'qf' : ('float', 128)
|
'qf' : ('float', 128)
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#define __ARCH_SPARC_TYPES_HH__
|
#define __ARCH_SPARC_TYPES_HH__
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include "base/bigint.hh"
|
||||||
|
|
||||||
namespace SparcISA
|
namespace SparcISA
|
||||||
{
|
{
|
||||||
|
@ -39,6 +40,7 @@ namespace SparcISA
|
||||||
typedef uint64_t ExtMachInst;
|
typedef uint64_t ExtMachInst;
|
||||||
|
|
||||||
typedef uint64_t IntReg;
|
typedef uint64_t IntReg;
|
||||||
|
typedef Twin64_t LargestRead;
|
||||||
typedef uint64_t MiscReg;
|
typedef uint64_t MiscReg;
|
||||||
typedef double FloatReg;
|
typedef double FloatReg;
|
||||||
typedef uint64_t FloatRegBits;
|
typedef uint64_t FloatRegBits;
|
||||||
|
|
51
src/base/bigint.hh
Normal file
51
src/base/bigint.hh
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __BASE_BIGINT_HH__
|
||||||
|
#define __BASE_BIGINT_HH__
|
||||||
|
// Create a couple of large int types for atomic reads
|
||||||
|
struct m5_twin64_t {
|
||||||
|
uint64_t a;
|
||||||
|
uint64_t b;
|
||||||
|
inline m5_twin64_t& operator=(const uint64_t x)
|
||||||
|
{
|
||||||
|
a = x;
|
||||||
|
b = x;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is for twin loads (two 64 bit values), not 1 128 bit value (as far as
|
||||||
|
// endian conversion is concerned!
|
||||||
|
typedef m5_twin64_t Twin64_t;
|
||||||
|
|
||||||
|
|
||||||
|
#endif // __BASE_BIGINT_HH__
|
||||||
|
|
|
@ -868,7 +868,7 @@ BaseDynInst<Impl>::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
||||||
if (res) {
|
if (res) {
|
||||||
// always return some result to keep misspeculated paths
|
// always return some result to keep misspeculated paths
|
||||||
// (which will ignore faults) deterministic
|
// (which will ignore faults) deterministic
|
||||||
*res = (fault == NoFault) ? req->getScResult() : 0;
|
*res = (fault == NoFault) ? req->getExtraData() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return fault;
|
return fault;
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "arch/locked_mem.hh"
|
#include "arch/locked_mem.hh"
|
||||||
#include "arch/mmaped_ipr.hh"
|
#include "arch/mmaped_ipr.hh"
|
||||||
#include "arch/utility.hh"
|
#include "arch/utility.hh"
|
||||||
|
#include "base/bigint.hh"
|
||||||
#include "cpu/exetrace.hh"
|
#include "cpu/exetrace.hh"
|
||||||
#include "cpu/simple/atomic.hh"
|
#include "cpu/simple/atomic.hh"
|
||||||
#include "mem/packet.hh"
|
#include "mem/packet.hh"
|
||||||
|
@ -151,6 +152,8 @@ AtomicSimpleCPU::AtomicSimpleCPU(Params *p)
|
||||||
data_write_req->setThreadContext(p->cpu_id, 0); // Add thread ID here too
|
data_write_req->setThreadContext(p->cpu_id, 0); // Add thread ID here too
|
||||||
data_write_pkt = new Packet(data_write_req, MemCmd::WriteReq,
|
data_write_pkt = new Packet(data_write_req, MemCmd::WriteReq,
|
||||||
Packet::Broadcast);
|
Packet::Broadcast);
|
||||||
|
data_swap_pkt = new Packet(data_write_req, MemCmd::SwapReq,
|
||||||
|
Packet::Broadcast);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -316,6 +319,10 @@ AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags)
|
||||||
|
|
||||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||||
|
|
||||||
|
template
|
||||||
|
Fault
|
||||||
|
AtomicSimpleCPU::read(Addr addr, Twin64_t &data, unsigned flags);
|
||||||
|
|
||||||
template
|
template
|
||||||
Fault
|
Fault
|
||||||
AtomicSimpleCPU::read(Addr addr, uint64_t &data, unsigned flags);
|
AtomicSimpleCPU::read(Addr addr, uint64_t &data, unsigned flags);
|
||||||
|
@ -363,10 +370,15 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
||||||
{
|
{
|
||||||
// use the CPU's statically allocated write request and packet objects
|
// use the CPU's statically allocated write request and packet objects
|
||||||
Request *req = data_write_req;
|
Request *req = data_write_req;
|
||||||
PacketPtr pkt = data_write_pkt;
|
PacketPtr pkt;
|
||||||
|
|
||||||
req->setVirt(0, addr, sizeof(T), flags, thread->readPC());
|
req->setVirt(0, addr, sizeof(T), flags, thread->readPC());
|
||||||
|
|
||||||
|
if (req->isSwap())
|
||||||
|
pkt = data_swap_pkt;
|
||||||
|
else
|
||||||
|
pkt = data_write_pkt;
|
||||||
|
|
||||||
if (traceData) {
|
if (traceData) {
|
||||||
traceData->setAddr(addr);
|
traceData->setAddr(addr);
|
||||||
}
|
}
|
||||||
|
@ -381,6 +393,11 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
||||||
if (req->isLocked()) {
|
if (req->isLocked()) {
|
||||||
do_access = TheISA::handleLockedWrite(thread, req);
|
do_access = TheISA::handleLockedWrite(thread, req);
|
||||||
}
|
}
|
||||||
|
if (req->isCondSwap()) {
|
||||||
|
assert(res);
|
||||||
|
req->setExtraData(*res);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (do_access) {
|
if (do_access) {
|
||||||
pkt->reinitFromRequest();
|
pkt->reinitFromRequest();
|
||||||
|
@ -401,7 +418,10 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res) {
|
if (req->isSwap()) {
|
||||||
|
assert(res);
|
||||||
|
*res = pkt->get<T>();
|
||||||
|
} else if (res) {
|
||||||
*res = req->getScResult();
|
*res = req->getScResult();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,6 +118,7 @@ class AtomicSimpleCPU : public BaseSimpleCPU
|
||||||
PacketPtr data_read_pkt;
|
PacketPtr data_read_pkt;
|
||||||
Request *data_write_req;
|
Request *data_write_req;
|
||||||
PacketPtr data_write_pkt;
|
PacketPtr data_write_pkt;
|
||||||
|
PacketPtr data_swap_pkt;
|
||||||
|
|
||||||
bool dcache_access;
|
bool dcache_access;
|
||||||
Tick dcache_latency;
|
Tick dcache_latency;
|
||||||
|
|
|
@ -125,7 +125,7 @@ class BaseSimpleCPU : public BaseCPU
|
||||||
MachInst inst;
|
MachInst inst;
|
||||||
|
|
||||||
// Static data storage
|
// Static data storage
|
||||||
TheISA::IntReg dataReg;
|
TheISA::LargestRead dataReg;
|
||||||
|
|
||||||
StaticInstPtr curStaticInst;
|
StaticInstPtr curStaticInst;
|
||||||
StaticInstPtr curMacroStaticInst;
|
StaticInstPtr curMacroStaticInst;
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
#include "arch/locked_mem.hh"
|
#include "arch/locked_mem.hh"
|
||||||
#include "arch/utility.hh"
|
#include "arch/utility.hh"
|
||||||
|
#include "base/bigint.hh"
|
||||||
#include "cpu/exetrace.hh"
|
#include "cpu/exetrace.hh"
|
||||||
#include "cpu/simple/timing.hh"
|
#include "cpu/simple/timing.hh"
|
||||||
#include "mem/packet.hh"
|
#include "mem/packet.hh"
|
||||||
|
@ -310,6 +311,10 @@ TimingSimpleCPU::read(Addr addr, T &data, unsigned flags)
|
||||||
|
|
||||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||||
|
|
||||||
|
template
|
||||||
|
Fault
|
||||||
|
TimingSimpleCPU::read(Addr addr, Twin64_t &data, unsigned flags);
|
||||||
|
|
||||||
template
|
template
|
||||||
Fault
|
Fault
|
||||||
TimingSimpleCPU::read(Addr addr, uint64_t &data, unsigned flags);
|
TimingSimpleCPU::read(Addr addr, uint64_t &data, unsigned flags);
|
||||||
|
@ -359,12 +364,19 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
||||||
new Request(/* asid */ 0, addr, sizeof(T), flags, thread->readPC(),
|
new Request(/* asid */ 0, addr, sizeof(T), flags, thread->readPC(),
|
||||||
cpu_id, /* thread ID */ 0);
|
cpu_id, /* thread ID */ 0);
|
||||||
|
|
||||||
|
if (traceData) {
|
||||||
|
traceData->setAddr(req->getVaddr());
|
||||||
|
}
|
||||||
|
|
||||||
// translate to physical address
|
// translate to physical address
|
||||||
Fault fault = thread->translateDataWriteReq(req);
|
Fault fault = thread->translateDataWriteReq(req);
|
||||||
|
|
||||||
// Now do the access.
|
// Now do the access.
|
||||||
if (fault == NoFault) {
|
if (fault == NoFault) {
|
||||||
assert(dcache_pkt == NULL);
|
assert(dcache_pkt == NULL);
|
||||||
|
if (req->isSwap())
|
||||||
|
dcache_pkt = new Packet(req, MemCmd::SwapReq, Packet::Broadcast);
|
||||||
|
else
|
||||||
dcache_pkt = new Packet(req, MemCmd::WriteReq, Packet::Broadcast);
|
dcache_pkt = new Packet(req, MemCmd::WriteReq, Packet::Broadcast);
|
||||||
dcache_pkt->allocate();
|
dcache_pkt->allocate();
|
||||||
dcache_pkt->set(data);
|
dcache_pkt->set(data);
|
||||||
|
@ -374,6 +386,10 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
||||||
if (req->isLocked()) {
|
if (req->isLocked()) {
|
||||||
do_access = TheISA::handleLockedWrite(thread, req);
|
do_access = TheISA::handleLockedWrite(thread, req);
|
||||||
}
|
}
|
||||||
|
if (req->isCondSwap()) {
|
||||||
|
assert(res);
|
||||||
|
req->setExtraData(*res);
|
||||||
|
}
|
||||||
|
|
||||||
if (do_access) {
|
if (do_access) {
|
||||||
if (!dcachePort.sendTiming(dcache_pkt)) {
|
if (!dcachePort.sendTiming(dcache_pkt)) {
|
||||||
|
|
2
src/mem/cache/cache_blk.hh
vendored
2
src/mem/cache/cache_blk.hh
vendored
|
@ -249,7 +249,7 @@ class CacheBlk
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
req->setScResult(success ? 1 : 0);
|
req->setExtraData(success ? 1 : 0);
|
||||||
clearLoadLocks();
|
clearLoadLocks();
|
||||||
return success;
|
return success;
|
||||||
} else {
|
} else {
|
||||||
|
|
4
src/mem/cache/cache_impl.hh
vendored
4
src/mem/cache/cache_impl.hh
vendored
|
@ -206,7 +206,7 @@ Cache<TagStore,Coherence>::handleAccess(PacketPtr &pkt, int & lat,
|
||||||
// complete miss (no matching block)
|
// complete miss (no matching block)
|
||||||
if (pkt->req->isLocked() && pkt->isWrite()) {
|
if (pkt->req->isLocked() && pkt->isWrite()) {
|
||||||
// miss on store conditional... just give up now
|
// miss on store conditional... just give up now
|
||||||
pkt->req->setScResult(0);
|
pkt->req->setExtraData(0);
|
||||||
pkt->flags |= SATISFIED;
|
pkt->flags |= SATISFIED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1147,7 +1147,7 @@ Cache<TagStore,Coherence>::CpuSidePort::recvTiming(PacketPtr pkt)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pkt->isWrite() && (pkt->req->isLocked())) {
|
if (pkt->isWrite() && (pkt->req->isLocked())) {
|
||||||
pkt->req->setScResult(1);
|
pkt->req->setExtraData(1);
|
||||||
}
|
}
|
||||||
myCache()->access(pkt);
|
myCache()->access(pkt);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -94,7 +94,13 @@ MemCmd::commandInfo[] =
|
||||||
ReadExResp, "ReadExReq" },
|
ReadExResp, "ReadExReq" },
|
||||||
/* ReadExResp */
|
/* ReadExResp */
|
||||||
{ SET4(IsRead, IsInvalidate, IsResponse, HasData),
|
{ SET4(IsRead, IsInvalidate, IsResponse, HasData),
|
||||||
InvalidCmd, "ReadExResp" }
|
InvalidCmd, "ReadExResp" },
|
||||||
|
/* SwapReq -- for Swap ldstub type operations */
|
||||||
|
{ SET4(IsReadWrite, IsRequest, HasData, NeedsResponse),
|
||||||
|
SwapResp, "SwapReq" },
|
||||||
|
/* SwapResp -- for Swap ldstub type operations */
|
||||||
|
{ SET3(IsReadWrite, IsResponse, HasData),
|
||||||
|
InvalidCmd, "SwapResp" }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -238,9 +244,11 @@ operator<<(std::ostream &o, const Packet &p)
|
||||||
if (p.isRead())
|
if (p.isRead())
|
||||||
o << "Read ";
|
o << "Read ";
|
||||||
if (p.isWrite())
|
if (p.isWrite())
|
||||||
o << "Read ";
|
o << "Write ";
|
||||||
|
if (p.isReadWrite())
|
||||||
|
o << "Read/Write ";
|
||||||
if (p.isInvalidate())
|
if (p.isInvalidate())
|
||||||
o << "Read ";
|
o << "Invalidate ";
|
||||||
if (p.isRequest())
|
if (p.isRequest())
|
||||||
o << "Request ";
|
o << "Request ";
|
||||||
if (p.isResponse())
|
if (p.isResponse())
|
||||||
|
|
|
@ -88,6 +88,8 @@ class MemCmd
|
||||||
UpgradeReq,
|
UpgradeReq,
|
||||||
ReadExReq,
|
ReadExReq,
|
||||||
ReadExResp,
|
ReadExResp,
|
||||||
|
SwapReq,
|
||||||
|
SwapResp,
|
||||||
NUM_MEM_CMDS
|
NUM_MEM_CMDS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -106,6 +108,7 @@ class MemCmd
|
||||||
IsHWPrefetch,
|
IsHWPrefetch,
|
||||||
IsUpgrade,
|
IsUpgrade,
|
||||||
HasData,
|
HasData,
|
||||||
|
IsReadWrite,
|
||||||
NUM_COMMAND_ATTRIBUTES
|
NUM_COMMAND_ATTRIBUTES
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -141,6 +144,7 @@ class MemCmd
|
||||||
bool needsResponse() const { return testCmdAttrib(NeedsResponse); }
|
bool needsResponse() const { return testCmdAttrib(NeedsResponse); }
|
||||||
bool isInvalidate() const { return testCmdAttrib(IsInvalidate); }
|
bool isInvalidate() const { return testCmdAttrib(IsInvalidate); }
|
||||||
bool hasData() const { return testCmdAttrib(HasData); }
|
bool hasData() const { return testCmdAttrib(HasData); }
|
||||||
|
bool isReadWrite() const { return testCmdAttrib(IsReadWrite); }
|
||||||
|
|
||||||
const Command responseCommand() const {
|
const Command responseCommand() const {
|
||||||
return commandInfo[cmd].response;
|
return commandInfo[cmd].response;
|
||||||
|
@ -300,6 +304,7 @@ class Packet
|
||||||
bool needsResponse() const { return cmd.needsResponse(); }
|
bool needsResponse() const { return cmd.needsResponse(); }
|
||||||
bool isInvalidate() const { return cmd.isInvalidate(); }
|
bool isInvalidate() const { return cmd.isInvalidate(); }
|
||||||
bool hasData() const { return cmd.hasData(); }
|
bool hasData() const { return cmd.hasData(); }
|
||||||
|
bool isReadWrite() const { return cmd.isReadWrite(); }
|
||||||
|
|
||||||
bool isCacheFill() const { return (flags & CACHE_LINE_FILL) != 0; }
|
bool isCacheFill() const { return (flags & CACHE_LINE_FILL) != 0; }
|
||||||
bool isNoAllocate() const { return (flags & NO_ALLOCATE) != 0; }
|
bool isNoAllocate() const { return (flags & NO_ALLOCATE) != 0; }
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "arch/isa_traits.hh"
|
#include "arch/isa_traits.hh"
|
||||||
|
#include "base/bigint.hh"
|
||||||
#include "mem/packet.hh"
|
#include "mem/packet.hh"
|
||||||
#include "sim/byteswap.hh"
|
#include "sim/byteswap.hh"
|
||||||
|
|
||||||
|
@ -40,6 +41,19 @@
|
||||||
// these functions and make the users do their own byte swapping since
|
// these functions and make the users do their own byte swapping since
|
||||||
// the memory system does not in fact have an endianness.
|
// the memory system does not in fact have an endianness.
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline Twin64_t
|
||||||
|
Packet::get()
|
||||||
|
{
|
||||||
|
Twin64_t d;
|
||||||
|
assert(staticData || dynamicData);
|
||||||
|
assert(sizeof(Twin64_t) <= size);
|
||||||
|
d.a = TheISA::gtoh(*(uint64_t*)data);
|
||||||
|
d.b = TheISA::gtoh(*((uint64_t*)data + 1));
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** return the value of what is pointed to in the packet. */
|
/** return the value of what is pointed to in the packet. */
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline T
|
inline T
|
||||||
|
|
|
@ -92,7 +92,7 @@ Addr
|
||||||
PhysicalMemory::new_page()
|
PhysicalMemory::new_page()
|
||||||
{
|
{
|
||||||
Addr return_addr = pagePtr << LogVMPageSize;
|
Addr return_addr = pagePtr << LogVMPageSize;
|
||||||
return_addr += params()->addrRange.start;
|
return_addr += start();
|
||||||
|
|
||||||
++pagePtr;
|
++pagePtr;
|
||||||
return return_addr;
|
return return_addr;
|
||||||
|
@ -187,7 +187,7 @@ PhysicalMemory::checkLockedAddrList(Request *req)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isLocked) {
|
if (isLocked) {
|
||||||
req->setScResult(success ? 1 : 0);
|
req->setExtraData(success ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
|
@ -196,16 +196,14 @@ PhysicalMemory::checkLockedAddrList(Request *req)
|
||||||
void
|
void
|
||||||
PhysicalMemory::doFunctionalAccess(PacketPtr pkt)
|
PhysicalMemory::doFunctionalAccess(PacketPtr pkt)
|
||||||
{
|
{
|
||||||
assert(pkt->getAddr() >= params()->addrRange.start &&
|
assert(pkt->getAddr() >= start() &&
|
||||||
pkt->getAddr() + pkt->getSize() <= params()->addrRange.start +
|
pkt->getAddr() + pkt->getSize() <= start() + size());
|
||||||
params()->addrRange.size());
|
|
||||||
|
|
||||||
if (pkt->isRead()) {
|
if (pkt->isRead()) {
|
||||||
if (pkt->req->isLocked()) {
|
if (pkt->req->isLocked()) {
|
||||||
trackLoadLocked(pkt->req);
|
trackLoadLocked(pkt->req);
|
||||||
}
|
}
|
||||||
memcpy(pkt->getPtr<uint8_t>(),
|
memcpy(pkt->getPtr<uint8_t>(), pmemAddr + pkt->getAddr() - start(),
|
||||||
pmemAddr + pkt->getAddr() - params()->addrRange.start,
|
|
||||||
pkt->getSize());
|
pkt->getSize());
|
||||||
#if TRACING_ON
|
#if TRACING_ON
|
||||||
switch (pkt->getSize()) {
|
switch (pkt->getSize()) {
|
||||||
|
@ -233,8 +231,8 @@ PhysicalMemory::doFunctionalAccess(PacketPtr pkt)
|
||||||
}
|
}
|
||||||
else if (pkt->isWrite()) {
|
else if (pkt->isWrite()) {
|
||||||
if (writeOK(pkt->req)) {
|
if (writeOK(pkt->req)) {
|
||||||
memcpy(pmemAddr + pkt->getAddr() - params()->addrRange.start,
|
memcpy(pmemAddr + pkt->getAddr() - start(), pkt->getPtr<uint8_t>(),
|
||||||
pkt->getPtr<uint8_t>(), pkt->getSize());
|
pkt->getSize());
|
||||||
#if TRACING_ON
|
#if TRACING_ON
|
||||||
switch (pkt->getSize()) {
|
switch (pkt->getSize()) {
|
||||||
case sizeof(uint64_t):
|
case sizeof(uint64_t):
|
||||||
|
@ -259,12 +257,77 @@ PhysicalMemory::doFunctionalAccess(PacketPtr pkt)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
} else if (pkt->isInvalidate()) {
|
||||||
else if (pkt->isInvalidate()) {
|
|
||||||
//upgrade or invalidate
|
//upgrade or invalidate
|
||||||
pkt->flags |= SATISFIED;
|
pkt->flags |= SATISFIED;
|
||||||
|
} else if (pkt->isReadWrite()) {
|
||||||
|
IntReg overwrite_val;
|
||||||
|
bool overwrite_mem;
|
||||||
|
uint64_t condition_val64;
|
||||||
|
uint32_t condition_val32;
|
||||||
|
uint64_t test_val64;
|
||||||
|
uint32_t test_val32;
|
||||||
|
|
||||||
|
assert(sizeof(IntReg) >= pkt->getSize());
|
||||||
|
|
||||||
|
overwrite_mem = true;
|
||||||
|
// keep a copy of our possible write value, and copy what is at the
|
||||||
|
// memory address into the packet
|
||||||
|
memcpy(&overwrite_val, pkt->getPtr<uint8_t>(), pkt->getSize());
|
||||||
|
memcpy(pkt->getPtr<uint8_t>(), pmemAddr + pkt->getAddr() - start(),
|
||||||
|
pkt->getSize());
|
||||||
|
|
||||||
|
if (pkt->req->isCondSwap()) {
|
||||||
|
if (pkt->getSize() == sizeof(uint64_t)) {
|
||||||
|
condition_val64 = htog(pkt->req->getExtraData());
|
||||||
|
memcpy(&test_val64, pmemAddr + pkt->getAddr() - start(), sizeof(uint64_t));
|
||||||
|
overwrite_mem = test_val64 == condition_val64;
|
||||||
|
} else if (pkt->getSize() == sizeof(uint32_t)) {
|
||||||
|
condition_val32 = htog((uint32_t)pkt->req->getExtraData());
|
||||||
|
memcpy(&test_val32, pmemAddr + pkt->getAddr() - start(), sizeof(uint32_t));
|
||||||
|
overwrite_mem = test_val32 == condition_val32;
|
||||||
|
} else
|
||||||
|
panic("Invalid size for conditional read/write\n");
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
|
if (overwrite_mem)
|
||||||
|
memcpy(pmemAddr + pkt->getAddr() - start(),
|
||||||
|
&overwrite_val, pkt->getSize());
|
||||||
|
|
||||||
|
#if TRACING_ON
|
||||||
|
switch (pkt->getSize()) {
|
||||||
|
case sizeof(uint64_t):
|
||||||
|
DPRINTF(MemoryAccess, "Read/Write of size %i on address 0x%x old data 0x%x\n",
|
||||||
|
pkt->getSize(), pkt->getAddr(),pkt->get<uint64_t>());
|
||||||
|
DPRINTF(MemoryAccess, "New Data 0x%x %s conditional (0x%x) and %s \n",
|
||||||
|
overwrite_mem, pkt->req->isCondSwap() ? "was" : "wasn't",
|
||||||
|
condition_val64, overwrite_mem ? "happened" : "didn't happen");
|
||||||
|
break;
|
||||||
|
case sizeof(uint32_t):
|
||||||
|
DPRINTF(MemoryAccess, "Read/Write of size %i on address 0x%x old data 0x%x\n",
|
||||||
|
pkt->getSize(), pkt->getAddr(),pkt->get<uint32_t>());
|
||||||
|
DPRINTF(MemoryAccess, "New Data 0x%x %s conditional (0x%x) and %s \n",
|
||||||
|
overwrite_mem, pkt->req->isCondSwap() ? "was" : "wasn't",
|
||||||
|
condition_val32, overwrite_mem ? "happened" : "didn't happen");
|
||||||
|
break;
|
||||||
|
case sizeof(uint16_t):
|
||||||
|
DPRINTF(MemoryAccess, "Read/Write of size %i on address 0x%x old data 0x%x\n",
|
||||||
|
pkt->getSize(), pkt->getAddr(),pkt->get<uint16_t>());
|
||||||
|
DPRINTF(MemoryAccess, "New Data 0x%x wasn't conditional and happned\n",
|
||||||
|
overwrite_mem);
|
||||||
|
break;
|
||||||
|
case sizeof(uint8_t):
|
||||||
|
DPRINTF(MemoryAccess, "Read/Write of size %i on address 0x%x old data 0x%x\n",
|
||||||
|
pkt->getSize(), pkt->getAddr(),pkt->get<uint8_t>());
|
||||||
|
DPRINTF(MemoryAccess, "New Data 0x%x wasn't conditional and happned\n",
|
||||||
|
overwrite_mem);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DPRINTF(MemoryAccess, "Read/Write of size %i on address 0x%x\n",
|
||||||
|
pkt->getSize(), pkt->getAddr());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
panic("unimplemented");
|
panic("unimplemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,7 +378,7 @@ PhysicalMemory::getAddressRanges(AddrRangeList &resp, AddrRangeList &snoop)
|
||||||
{
|
{
|
||||||
snoop.clear();
|
snoop.clear();
|
||||||
resp.clear();
|
resp.clear();
|
||||||
resp.push_back(RangeSize(params()->addrRange.start,
|
resp.push_back(RangeSize(start(),
|
||||||
params()->addrRange.size()));
|
params()->addrRange.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -131,7 +131,7 @@ class PhysicalMemory : public MemObject
|
||||||
// no locked addrs: nothing to check, store_conditional fails
|
// no locked addrs: nothing to check, store_conditional fails
|
||||||
bool isLocked = req->isLocked();
|
bool isLocked = req->isLocked();
|
||||||
if (isLocked) {
|
if (isLocked) {
|
||||||
req->setScResult(0);
|
req->setExtraData(0);
|
||||||
}
|
}
|
||||||
return !isLocked; // only do write if not an sc
|
return !isLocked; // only do write if not an sc
|
||||||
} else {
|
} else {
|
||||||
|
@ -148,6 +148,7 @@ class PhysicalMemory : public MemObject
|
||||||
public:
|
public:
|
||||||
Addr new_page();
|
Addr new_page();
|
||||||
uint64_t size() { return params()->addrRange.size(); }
|
uint64_t size() { return params()->addrRange.size(); }
|
||||||
|
uint64_t start() { return params()->addrRange.start; }
|
||||||
|
|
||||||
struct Params
|
struct Params
|
||||||
{
|
{
|
||||||
|
|
|
@ -71,6 +71,10 @@ const uint32_t EVICT_NEXT = 0x20000;
|
||||||
const uint32_t NO_ALIGN_FAULT = 0x40000;
|
const uint32_t NO_ALIGN_FAULT = 0x40000;
|
||||||
/** The request was an instruction read. */
|
/** The request was an instruction read. */
|
||||||
const uint32_t INST_READ = 0x80000;
|
const uint32_t INST_READ = 0x80000;
|
||||||
|
/** This request is for a memory swap. */
|
||||||
|
const uint32_t MEM_SWAP = 0x100000;
|
||||||
|
const uint32_t MEM_SWAP_COND = 0x200000;
|
||||||
|
|
||||||
|
|
||||||
class Request
|
class Request
|
||||||
{
|
{
|
||||||
|
@ -104,8 +108,9 @@ class Request
|
||||||
/** The virtual address of the request. */
|
/** The virtual address of the request. */
|
||||||
Addr vaddr;
|
Addr vaddr;
|
||||||
|
|
||||||
/** The return value of store conditional. */
|
/** Extra data for the request, such as the return value of
|
||||||
uint64_t scResult;
|
* store conditional or the compare value for a CAS. */
|
||||||
|
uint64_t extraData;
|
||||||
|
|
||||||
/** The cpu number (for statistics, typically). */
|
/** The cpu number (for statistics, typically). */
|
||||||
int cpuNum;
|
int cpuNum;
|
||||||
|
@ -120,7 +125,7 @@ class Request
|
||||||
/** Whether or not the asid & vaddr are valid. */
|
/** Whether or not the asid & vaddr are valid. */
|
||||||
bool validAsidVaddr;
|
bool validAsidVaddr;
|
||||||
/** Whether or not the sc result is valid. */
|
/** Whether or not the sc result is valid. */
|
||||||
bool validScResult;
|
bool validExData;
|
||||||
/** Whether or not the cpu number & thread ID are valid. */
|
/** Whether or not the cpu number & thread ID are valid. */
|
||||||
bool validCpuAndThreadNums;
|
bool validCpuAndThreadNums;
|
||||||
/** Whether or not the pc is valid. */
|
/** Whether or not the pc is valid. */
|
||||||
|
@ -130,7 +135,7 @@ class Request
|
||||||
/** Minimal constructor. No fields are initialized. */
|
/** Minimal constructor. No fields are initialized. */
|
||||||
Request()
|
Request()
|
||||||
: validPaddr(false), validAsidVaddr(false),
|
: validPaddr(false), validAsidVaddr(false),
|
||||||
validScResult(false), validCpuAndThreadNums(false), validPC(false)
|
validExData(false), validCpuAndThreadNums(false), validPC(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -169,7 +174,7 @@ class Request
|
||||||
validPaddr = true;
|
validPaddr = true;
|
||||||
validAsidVaddr = false;
|
validAsidVaddr = false;
|
||||||
validPC = false;
|
validPC = false;
|
||||||
validScResult = false;
|
validExData = false;
|
||||||
mmapedIpr = false;
|
mmapedIpr = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,7 +192,7 @@ class Request
|
||||||
validPaddr = false;
|
validPaddr = false;
|
||||||
validAsidVaddr = true;
|
validAsidVaddr = true;
|
||||||
validPC = true;
|
validPC = true;
|
||||||
validScResult = false;
|
validExData = false;
|
||||||
mmapedIpr = false;
|
mmapedIpr = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,12 +242,12 @@ class Request
|
||||||
void setMmapedIpr(bool r) { assert(validAsidVaddr); mmapedIpr = r; }
|
void setMmapedIpr(bool r) { assert(validAsidVaddr); mmapedIpr = r; }
|
||||||
|
|
||||||
/** Accessor function to check if sc result is valid. */
|
/** Accessor function to check if sc result is valid. */
|
||||||
bool scResultValid() { return validScResult; }
|
bool extraDataValid() { return validExData; }
|
||||||
/** Accessor function for store conditional return value.*/
|
/** Accessor function for store conditional return value.*/
|
||||||
uint64_t getScResult() { assert(validScResult); return scResult; }
|
uint64_t getExtraData() { assert(validExData); return extraData; }
|
||||||
/** Accessor function for store conditional return value.*/
|
/** Accessor function for store conditional return value.*/
|
||||||
void setScResult(uint64_t _scResult)
|
void setExtraData(uint64_t _extraData)
|
||||||
{ scResult = _scResult; validScResult = true; }
|
{ extraData = _extraData; validExData = true; }
|
||||||
|
|
||||||
/** Accessor function for cpu number.*/
|
/** Accessor function for cpu number.*/
|
||||||
int getCpuNum() { assert(validCpuAndThreadNums); return cpuNum; }
|
int getCpuNum() { assert(validCpuAndThreadNums); return cpuNum; }
|
||||||
|
@ -259,6 +264,12 @@ class Request
|
||||||
|
|
||||||
bool isLocked() { return (getFlags() & LOCKED) != 0; }
|
bool isLocked() { return (getFlags() & LOCKED) != 0; }
|
||||||
|
|
||||||
|
bool isSwap() { return (getFlags() & MEM_SWAP ||
|
||||||
|
getFlags() & MEM_SWAP_COND); }
|
||||||
|
|
||||||
|
bool isCondSwap() { return (getFlags() & MEM_SWAP_COND) != 0; }
|
||||||
|
|
||||||
|
|
||||||
friend class Packet;
|
friend class Packet;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue