Implement Alpha LL/SC support for SimpleCPU (Atomic & Timing)
and PhysicalMemory. *No* support for caches or O3CPU. Note that properly setting cpu_id on all CPUs is now required for correct operation. src/arch/SConscript: src/base/traceflags.py: src/cpu/base.hh: src/cpu/simple/atomic.cc: src/cpu/simple/timing.cc: src/cpu/simple/timing.hh: src/mem/physical.cc: src/mem/physical.hh: src/mem/request.hh: src/python/m5/objects/BaseCPU.py: tests/configs/simple-atomic.py: tests/configs/simple-timing.py: tests/configs/tsunami-simple-atomic-dual.py: tests/configs/tsunami-simple-atomic.py: tests/configs/tsunami-simple-timing-dual.py: tests/configs/tsunami-simple-timing.py: Implement Alpha LL/SC support for SimpleCPU (Atomic & Timing) and PhysicalMemory. *No* support for caches or O3CPU. --HG-- extra : convert_revision : 6ce982d44924cc477e049b9adf359818908e72be
This commit is contained in:
parent
be36c808f7
commit
d3fba5aa30
19 changed files with 465 additions and 53 deletions
|
@ -50,6 +50,7 @@ isa_switch_hdrs = Split('''
|
||||||
arguments.hh
|
arguments.hh
|
||||||
faults.hh
|
faults.hh
|
||||||
isa_traits.hh
|
isa_traits.hh
|
||||||
|
locked_mem.hh
|
||||||
process.hh
|
process.hh
|
||||||
regfile.hh
|
regfile.hh
|
||||||
stacktrace.hh
|
stacktrace.hh
|
||||||
|
|
97
src/arch/alpha/locked_mem.hh
Normal file
97
src/arch/alpha/locked_mem.hh
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
/*
|
||||||
|
* 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: Steve Reinhardt
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ARCH_ALPHA_LOCKED_MEM_HH__
|
||||||
|
#define __ARCH_ALPHA_LOCKED_MEM_HH__
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* ISA-specific helper functions for locked memory accesses.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "arch/isa_traits.hh"
|
||||||
|
#include "base/misc.hh"
|
||||||
|
#include "mem/request.hh"
|
||||||
|
|
||||||
|
|
||||||
|
namespace AlphaISA
|
||||||
|
{
|
||||||
|
template <class XC>
|
||||||
|
inline void
|
||||||
|
handleLockedRead(XC *xc, Request *req)
|
||||||
|
{
|
||||||
|
xc->setMiscReg(Lock_Addr_DepTag, req->getPaddr() & ~0xf);
|
||||||
|
xc->setMiscReg(Lock_Flag_DepTag, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <class XC>
|
||||||
|
inline bool
|
||||||
|
handleLockedWrite(XC *xc, Request *req)
|
||||||
|
{
|
||||||
|
if (req->isUncacheable()) {
|
||||||
|
// Funky Turbolaser mailbox access...don't update
|
||||||
|
// result register (see stq_c in decoder.isa)
|
||||||
|
req->setScResult(2);
|
||||||
|
} else {
|
||||||
|
// standard store conditional
|
||||||
|
bool lock_flag = xc->readMiscReg(Lock_Flag_DepTag);
|
||||||
|
Addr lock_addr = xc->readMiscReg(Lock_Addr_DepTag);
|
||||||
|
if (!lock_flag || (req->getPaddr() & ~0xf) != lock_addr) {
|
||||||
|
// Lock flag not set or addr mismatch in CPU;
|
||||||
|
// don't even bother sending to memory system
|
||||||
|
req->setScResult(0);
|
||||||
|
xc->setMiscReg(Lock_Flag_DepTag, false);
|
||||||
|
// the rest of this code is not architectural;
|
||||||
|
// it's just a debugging aid to help detect
|
||||||
|
// livelock by warning on long sequences of failed
|
||||||
|
// store conditionals
|
||||||
|
int stCondFailures = xc->readStCondFailures();
|
||||||
|
stCondFailures++;
|
||||||
|
xc->setStCondFailures(stCondFailures);
|
||||||
|
if (stCondFailures % 100000 == 0) {
|
||||||
|
warn("cpu %d: %d consecutive "
|
||||||
|
"store conditional failures\n",
|
||||||
|
xc->readCpuId(), stCondFailures);
|
||||||
|
}
|
||||||
|
|
||||||
|
// store conditional failed already, so don't issue it to mem
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace AlphaISA
|
||||||
|
|
||||||
|
#endif
|
62
src/arch/mips/locked_mem.hh
Normal file
62
src/arch/mips/locked_mem.hh
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* 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: Steve Reinhardt
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ARCH_MIPS_LOCKED_MEM_HH__
|
||||||
|
#define __ARCH_MIPS_LOCKED_MEM_HH__
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* ISA-specific helper functions for locked memory accesses.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "mem/request.hh"
|
||||||
|
|
||||||
|
|
||||||
|
namespace MipsISA
|
||||||
|
{
|
||||||
|
template <class XC>
|
||||||
|
inline void
|
||||||
|
handleLockedRead(XC *xc, Request *req)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <class XC>
|
||||||
|
inline bool
|
||||||
|
handleLockedWrite(XC *xc, Request *req)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace MipsISA
|
||||||
|
|
||||||
|
#endif
|
62
src/arch/sparc/locked_mem.hh
Normal file
62
src/arch/sparc/locked_mem.hh
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* 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: Steve Reinhardt
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ARCH_SPARC_LOCKED_MEM_HH__
|
||||||
|
#define __ARCH_SPARC_LOCKED_MEM_HH__
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* ISA-specific helper functions for locked memory accesses.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "mem/request.hh"
|
||||||
|
|
||||||
|
|
||||||
|
namespace SparcISA
|
||||||
|
{
|
||||||
|
template <class XC>
|
||||||
|
inline void
|
||||||
|
handleLockedRead(XC *xc, Request *req)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <class XC>
|
||||||
|
inline bool
|
||||||
|
handleLockedWrite(XC *xc, Request *req)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace SparcISA
|
||||||
|
|
||||||
|
#endif
|
|
@ -112,6 +112,7 @@ baseFlags = [
|
||||||
'IdeDisk',
|
'IdeDisk',
|
||||||
'InstExec',
|
'InstExec',
|
||||||
'Interrupt',
|
'Interrupt',
|
||||||
|
'LLSC',
|
||||||
'LSQ',
|
'LSQ',
|
||||||
'LSQUnit',
|
'LSQUnit',
|
||||||
'Loader',
|
'Loader',
|
||||||
|
|
|
@ -140,8 +140,8 @@ class BaseCPU : public MemObject
|
||||||
bool functionTrace;
|
bool functionTrace;
|
||||||
Tick functionTraceStart;
|
Tick functionTraceStart;
|
||||||
System *system;
|
System *system;
|
||||||
#if FULL_SYSTEM
|
|
||||||
int cpu_id;
|
int cpu_id;
|
||||||
|
#if FULL_SYSTEM
|
||||||
Tick profile;
|
Tick profile;
|
||||||
#endif
|
#endif
|
||||||
Tick progress_interval;
|
Tick progress_interval;
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
* Authors: Steve Reinhardt
|
* Authors: Steve Reinhardt
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "arch/locked_mem.hh"
|
||||||
#include "arch/utility.hh"
|
#include "arch/utility.hh"
|
||||||
#include "cpu/exetrace.hh"
|
#include "cpu/exetrace.hh"
|
||||||
#include "cpu/simple/atomic.hh"
|
#include "cpu/simple/atomic.hh"
|
||||||
|
@ -133,20 +134,19 @@ AtomicSimpleCPU::AtomicSimpleCPU(Params *p)
|
||||||
{
|
{
|
||||||
_status = Idle;
|
_status = Idle;
|
||||||
|
|
||||||
// @todo fix me and get the real cpu id & thread number!!!
|
|
||||||
ifetch_req = new Request();
|
ifetch_req = new Request();
|
||||||
ifetch_req->setThreadContext(0,0); //Need CPU/Thread IDS HERE
|
ifetch_req->setThreadContext(p->cpu_id, 0); // Add thread ID if we add MT
|
||||||
ifetch_pkt = new Packet(ifetch_req, Packet::ReadReq, Packet::Broadcast);
|
ifetch_pkt = new Packet(ifetch_req, Packet::ReadReq, Packet::Broadcast);
|
||||||
ifetch_pkt->dataStatic(&inst);
|
ifetch_pkt->dataStatic(&inst);
|
||||||
|
|
||||||
data_read_req = new Request();
|
data_read_req = new Request();
|
||||||
data_read_req->setThreadContext(0,0); //Need CPU/Thread IDS HERE
|
data_read_req->setThreadContext(p->cpu_id, 0); // Add thread ID here too
|
||||||
data_read_pkt = new Packet(data_read_req, Packet::ReadReq,
|
data_read_pkt = new Packet(data_read_req, Packet::ReadReq,
|
||||||
Packet::Broadcast);
|
Packet::Broadcast);
|
||||||
data_read_pkt->dataStatic(&dataReg);
|
data_read_pkt->dataStatic(&dataReg);
|
||||||
|
|
||||||
data_write_req = new Request();
|
data_write_req = new Request();
|
||||||
data_write_req->setThreadContext(0,0); //Need CPU/Thread IDS HERE
|
data_write_req->setThreadContext(p->cpu_id, 0); // Add thread ID here too
|
||||||
data_write_pkt = new Packet(data_write_req, Packet::WriteReq,
|
data_write_pkt = new Packet(data_write_req, Packet::WriteReq,
|
||||||
Packet::Broadcast);
|
Packet::Broadcast);
|
||||||
}
|
}
|
||||||
|
@ -275,6 +275,10 @@ AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags)
|
||||||
|
|
||||||
assert(pkt->result == Packet::Success);
|
assert(pkt->result == Packet::Success);
|
||||||
data = pkt->get<T>();
|
data = pkt->get<T>();
|
||||||
|
|
||||||
|
if (req->isLocked()) {
|
||||||
|
TheISA::handleLockedRead(thread, req);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This will need a new way to tell if it has a dcache attached.
|
// This will need a new way to tell if it has a dcache attached.
|
||||||
|
@ -346,6 +350,13 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
||||||
|
|
||||||
// Now do the access.
|
// Now do the access.
|
||||||
if (fault == NoFault) {
|
if (fault == NoFault) {
|
||||||
|
bool do_access = true; // flag to suppress cache access
|
||||||
|
|
||||||
|
if (req->isLocked()) {
|
||||||
|
do_access = TheISA::handleLockedWrite(thread, req);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (do_access) {
|
||||||
data = htog(data);
|
data = htog(data);
|
||||||
pkt->reinitFromRequest();
|
pkt->reinitFromRequest();
|
||||||
pkt->dataStatic(&data);
|
pkt->dataStatic(&data);
|
||||||
|
@ -354,11 +365,19 @@ AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
||||||
dcache_access = true;
|
dcache_access = true;
|
||||||
|
|
||||||
assert(pkt->result == Packet::Success);
|
assert(pkt->result == Packet::Success);
|
||||||
|
}
|
||||||
|
|
||||||
if (res && req->getFlags() & LOCKED) {
|
if (req->isLocked()) {
|
||||||
|
uint64_t scResult = req->getScResult();
|
||||||
|
if (scResult != 0) {
|
||||||
|
// clear failure counter
|
||||||
|
thread->setStCondFailures(0);
|
||||||
|
}
|
||||||
|
if (res) {
|
||||||
*res = req->getScResult();
|
*res = req->getScResult();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// This will need a new way to tell if it's hooked up to a cache or not.
|
// This will need a new way to tell if it's hooked up to a cache or not.
|
||||||
if (req->getFlags() & UNCACHEABLE)
|
if (req->getFlags() & UNCACHEABLE)
|
||||||
|
@ -474,11 +493,11 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(AtomicSimpleCPU)
|
||||||
Param<Tick> progress_interval;
|
Param<Tick> progress_interval;
|
||||||
SimObjectParam<MemObject *> mem;
|
SimObjectParam<MemObject *> mem;
|
||||||
SimObjectParam<System *> system;
|
SimObjectParam<System *> system;
|
||||||
|
Param<int> cpu_id;
|
||||||
|
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
SimObjectParam<AlphaITB *> itb;
|
SimObjectParam<AlphaITB *> itb;
|
||||||
SimObjectParam<AlphaDTB *> dtb;
|
SimObjectParam<AlphaDTB *> dtb;
|
||||||
Param<int> cpu_id;
|
|
||||||
Param<Tick> profile;
|
Param<Tick> profile;
|
||||||
#else
|
#else
|
||||||
SimObjectParam<Process *> workload;
|
SimObjectParam<Process *> workload;
|
||||||
|
@ -507,11 +526,11 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(AtomicSimpleCPU)
|
||||||
INIT_PARAM(progress_interval, "Progress interval"),
|
INIT_PARAM(progress_interval, "Progress interval"),
|
||||||
INIT_PARAM(mem, "memory"),
|
INIT_PARAM(mem, "memory"),
|
||||||
INIT_PARAM(system, "system object"),
|
INIT_PARAM(system, "system object"),
|
||||||
|
INIT_PARAM(cpu_id, "processor ID"),
|
||||||
|
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
INIT_PARAM(itb, "Instruction TLB"),
|
INIT_PARAM(itb, "Instruction TLB"),
|
||||||
INIT_PARAM(dtb, "Data TLB"),
|
INIT_PARAM(dtb, "Data TLB"),
|
||||||
INIT_PARAM(cpu_id, "processor ID"),
|
|
||||||
INIT_PARAM(profile, ""),
|
INIT_PARAM(profile, ""),
|
||||||
#else
|
#else
|
||||||
INIT_PARAM(workload, "processes to run"),
|
INIT_PARAM(workload, "processes to run"),
|
||||||
|
@ -545,11 +564,11 @@ CREATE_SIM_OBJECT(AtomicSimpleCPU)
|
||||||
params->simulate_stalls = simulate_stalls;
|
params->simulate_stalls = simulate_stalls;
|
||||||
params->mem = mem;
|
params->mem = mem;
|
||||||
params->system = system;
|
params->system = system;
|
||||||
|
params->cpu_id = cpu_id;
|
||||||
|
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
params->itb = itb;
|
params->itb = itb;
|
||||||
params->dtb = dtb;
|
params->dtb = dtb;
|
||||||
params->cpu_id = cpu_id;
|
|
||||||
params->profile = profile;
|
params->profile = profile;
|
||||||
#else
|
#else
|
||||||
params->process = workload;
|
params->process = workload;
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
* Authors: Steve Reinhardt
|
* Authors: Steve Reinhardt
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "arch/locked_mem.hh"
|
||||||
#include "arch/utility.hh"
|
#include "arch/utility.hh"
|
||||||
#include "cpu/exetrace.hh"
|
#include "cpu/exetrace.hh"
|
||||||
#include "cpu/simple/timing.hh"
|
#include "cpu/simple/timing.hh"
|
||||||
|
@ -94,7 +95,8 @@ TimingSimpleCPU::CpuPort::TickEvent::schedule(Packet *_pkt, Tick t)
|
||||||
}
|
}
|
||||||
|
|
||||||
TimingSimpleCPU::TimingSimpleCPU(Params *p)
|
TimingSimpleCPU::TimingSimpleCPU(Params *p)
|
||||||
: BaseSimpleCPU(p), icachePort(this, p->clock), dcachePort(this, p->clock)
|
: BaseSimpleCPU(p), icachePort(this, p->clock), dcachePort(this, p->clock),
|
||||||
|
cpu_id(p->cpu_id)
|
||||||
{
|
{
|
||||||
_status = Idle;
|
_status = Idle;
|
||||||
ifetch_pkt = dcache_pkt = NULL;
|
ifetch_pkt = dcache_pkt = NULL;
|
||||||
|
@ -229,7 +231,7 @@ TimingSimpleCPU::read(Addr addr, T &data, unsigned flags)
|
||||||
{
|
{
|
||||||
Request *req =
|
Request *req =
|
||||||
new Request(/* asid */ 0, addr, sizeof(T), flags, thread->readPC(),
|
new Request(/* asid */ 0, addr, sizeof(T), flags, thread->readPC(),
|
||||||
/* CPU ID */ 0, /* thread ID */ 0);
|
cpu_id, /* thread ID */ 0);
|
||||||
|
|
||||||
if (traceData) {
|
if (traceData) {
|
||||||
traceData->setAddr(req->getVaddr());
|
traceData->setAddr(req->getVaddr());
|
||||||
|
@ -310,7 +312,7 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
||||||
{
|
{
|
||||||
Request *req =
|
Request *req =
|
||||||
new Request(/* asid */ 0, addr, sizeof(T), flags, thread->readPC(),
|
new Request(/* asid */ 0, addr, sizeof(T), flags, thread->readPC(),
|
||||||
/* CPU ID */ 0, /* thread ID */ 0);
|
cpu_id, /* thread ID */ 0);
|
||||||
|
|
||||||
// translate to physical address
|
// translate to physical address
|
||||||
Fault fault = thread->translateDataWriteReq(req);
|
Fault fault = thread->translateDataWriteReq(req);
|
||||||
|
@ -322,6 +324,13 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
||||||
dcache_pkt->allocate();
|
dcache_pkt->allocate();
|
||||||
dcache_pkt->set(data);
|
dcache_pkt->set(data);
|
||||||
|
|
||||||
|
bool do_access = true; // flag to suppress cache access
|
||||||
|
|
||||||
|
if (req->isLocked()) {
|
||||||
|
do_access = TheISA::handleLockedWrite(thread, req);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (do_access) {
|
||||||
if (!dcachePort.sendTiming(dcache_pkt)) {
|
if (!dcachePort.sendTiming(dcache_pkt)) {
|
||||||
_status = DcacheRetry;
|
_status = DcacheRetry;
|
||||||
} else {
|
} else {
|
||||||
|
@ -330,6 +339,7 @@ TimingSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
|
||||||
dcache_pkt = NULL;
|
dcache_pkt = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// This will need a new way to tell if it's hooked up to a cache or not.
|
// This will need a new way to tell if it's hooked up to a cache or not.
|
||||||
if (req->getFlags() & UNCACHEABLE)
|
if (req->getFlags() & UNCACHEABLE)
|
||||||
|
@ -392,9 +402,8 @@ TimingSimpleCPU::fetch()
|
||||||
{
|
{
|
||||||
checkForInterrupts();
|
checkForInterrupts();
|
||||||
|
|
||||||
// need to fill in CPU & thread IDs here
|
|
||||||
Request *ifetch_req = new Request();
|
Request *ifetch_req = new Request();
|
||||||
ifetch_req->setThreadContext(0,0); //Need CPU/Thread IDS HERE
|
ifetch_req->setThreadContext(cpu_id, /* thread ID */ 0);
|
||||||
Fault fault = setupFetchRequest(ifetch_req);
|
Fault fault = setupFetchRequest(ifetch_req);
|
||||||
|
|
||||||
ifetch_pkt = new Packet(ifetch_req, Packet::ReadReq, Packet::Broadcast);
|
ifetch_pkt = new Packet(ifetch_req, Packet::ReadReq, Packet::Broadcast);
|
||||||
|
@ -453,12 +462,20 @@ TimingSimpleCPU::completeIfetch(Packet *pkt)
|
||||||
if (curStaticInst->isMemRef() && !curStaticInst->isDataPrefetch()) {
|
if (curStaticInst->isMemRef() && !curStaticInst->isDataPrefetch()) {
|
||||||
// load or store: just send to dcache
|
// load or store: just send to dcache
|
||||||
Fault fault = curStaticInst->initiateAcc(this, traceData);
|
Fault fault = curStaticInst->initiateAcc(this, traceData);
|
||||||
if (fault == NoFault) {
|
if (_status != Running) {
|
||||||
// successfully initiated access: instruction will
|
// instruction will complete in dcache response callback
|
||||||
// complete in dcache response callback
|
assert(_status == DcacheWaitResponse || _status == DcacheRetry);
|
||||||
assert(_status == DcacheWaitResponse);
|
assert(fault == NoFault);
|
||||||
} else {
|
} else {
|
||||||
// fault: complete now to invoke fault handler
|
if (fault == NoFault) {
|
||||||
|
// early fail on store conditional: complete now
|
||||||
|
assert(dcache_pkt != NULL);
|
||||||
|
fault = curStaticInst->completeAcc(dcache_pkt, this,
|
||||||
|
traceData);
|
||||||
|
delete dcache_pkt->req;
|
||||||
|
delete dcache_pkt;
|
||||||
|
dcache_pkt = NULL;
|
||||||
|
}
|
||||||
postExecute();
|
postExecute();
|
||||||
advanceInst(fault);
|
advanceInst(fault);
|
||||||
}
|
}
|
||||||
|
@ -479,8 +496,7 @@ TimingSimpleCPU::IcachePort::ITickEvent::process()
|
||||||
bool
|
bool
|
||||||
TimingSimpleCPU::IcachePort::recvTiming(Packet *pkt)
|
TimingSimpleCPU::IcachePort::recvTiming(Packet *pkt)
|
||||||
{
|
{
|
||||||
// These next few lines could be replaced with something faster
|
// delay processing of returned data until next CPU clock edge
|
||||||
// who knows what though
|
|
||||||
Tick time = pkt->req->getTime();
|
Tick time = pkt->req->getTime();
|
||||||
while (time < curTick)
|
while (time < curTick)
|
||||||
time += lat;
|
time += lat;
|
||||||
|
@ -527,6 +543,10 @@ TimingSimpleCPU::completeDataAccess(Packet *pkt)
|
||||||
|
|
||||||
Fault fault = curStaticInst->completeAcc(pkt, this, traceData);
|
Fault fault = curStaticInst->completeAcc(pkt, this, traceData);
|
||||||
|
|
||||||
|
if (pkt->isRead() && pkt->req->isLocked()) {
|
||||||
|
TheISA::handleLockedRead(thread, pkt->req);
|
||||||
|
}
|
||||||
|
|
||||||
delete pkt->req;
|
delete pkt->req;
|
||||||
delete pkt;
|
delete pkt;
|
||||||
|
|
||||||
|
@ -546,6 +566,7 @@ TimingSimpleCPU::completeDrain()
|
||||||
bool
|
bool
|
||||||
TimingSimpleCPU::DcachePort::recvTiming(Packet *pkt)
|
TimingSimpleCPU::DcachePort::recvTiming(Packet *pkt)
|
||||||
{
|
{
|
||||||
|
// delay processing of returned data until next CPU clock edge
|
||||||
Tick time = pkt->req->getTime();
|
Tick time = pkt->req->getTime();
|
||||||
while (time < curTick)
|
while (time < curTick)
|
||||||
time += lat;
|
time += lat;
|
||||||
|
@ -574,6 +595,7 @@ TimingSimpleCPU::DcachePort::recvRetry()
|
||||||
Packet *tmp = cpu->dcache_pkt;
|
Packet *tmp = cpu->dcache_pkt;
|
||||||
if (sendTiming(tmp)) {
|
if (sendTiming(tmp)) {
|
||||||
cpu->_status = DcacheWaitResponse;
|
cpu->_status = DcacheWaitResponse;
|
||||||
|
// memory system takes ownership of packet
|
||||||
cpu->dcache_pkt = NULL;
|
cpu->dcache_pkt = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -592,11 +614,11 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(TimingSimpleCPU)
|
||||||
Param<Tick> progress_interval;
|
Param<Tick> progress_interval;
|
||||||
SimObjectParam<MemObject *> mem;
|
SimObjectParam<MemObject *> mem;
|
||||||
SimObjectParam<System *> system;
|
SimObjectParam<System *> system;
|
||||||
|
Param<int> cpu_id;
|
||||||
|
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
SimObjectParam<AlphaITB *> itb;
|
SimObjectParam<AlphaITB *> itb;
|
||||||
SimObjectParam<AlphaDTB *> dtb;
|
SimObjectParam<AlphaDTB *> dtb;
|
||||||
Param<int> cpu_id;
|
|
||||||
Param<Tick> profile;
|
Param<Tick> profile;
|
||||||
#else
|
#else
|
||||||
SimObjectParam<Process *> workload;
|
SimObjectParam<Process *> workload;
|
||||||
|
@ -625,11 +647,11 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(TimingSimpleCPU)
|
||||||
INIT_PARAM(progress_interval, "Progress interval"),
|
INIT_PARAM(progress_interval, "Progress interval"),
|
||||||
INIT_PARAM(mem, "memory"),
|
INIT_PARAM(mem, "memory"),
|
||||||
INIT_PARAM(system, "system object"),
|
INIT_PARAM(system, "system object"),
|
||||||
|
INIT_PARAM(cpu_id, "processor ID"),
|
||||||
|
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
INIT_PARAM(itb, "Instruction TLB"),
|
INIT_PARAM(itb, "Instruction TLB"),
|
||||||
INIT_PARAM(dtb, "Data TLB"),
|
INIT_PARAM(dtb, "Data TLB"),
|
||||||
INIT_PARAM(cpu_id, "processor ID"),
|
|
||||||
INIT_PARAM(profile, ""),
|
INIT_PARAM(profile, ""),
|
||||||
#else
|
#else
|
||||||
INIT_PARAM(workload, "processes to run"),
|
INIT_PARAM(workload, "processes to run"),
|
||||||
|
@ -661,11 +683,11 @@ CREATE_SIM_OBJECT(TimingSimpleCPU)
|
||||||
params->functionTraceStart = function_trace_start;
|
params->functionTraceStart = function_trace_start;
|
||||||
params->mem = mem;
|
params->mem = mem;
|
||||||
params->system = system;
|
params->system = system;
|
||||||
|
params->cpu_id = cpu_id;
|
||||||
|
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
params->itb = itb;
|
params->itb = itb;
|
||||||
params->dtb = dtb;
|
params->dtb = dtb;
|
||||||
params->cpu_id = cpu_id;
|
|
||||||
params->profile = profile;
|
params->profile = profile;
|
||||||
#else
|
#else
|
||||||
params->process = workload;
|
params->process = workload;
|
||||||
|
|
|
@ -166,6 +166,8 @@ class TimingSimpleCPU : public BaseSimpleCPU
|
||||||
Packet *ifetch_pkt;
|
Packet *ifetch_pkt;
|
||||||
Packet *dcache_pkt;
|
Packet *dcache_pkt;
|
||||||
|
|
||||||
|
int cpu_id;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual Port *getPort(const std::string &if_name, int idx = -1);
|
virtual Port *getPort(const std::string &if_name, int idx = -1);
|
||||||
|
|
|
@ -110,6 +110,88 @@ PhysicalMemory::calculateLatency(Packet *pkt)
|
||||||
return lat;
|
return lat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Add load-locked to tracking list. Should only be called if the
|
||||||
|
// operation is a load and the LOCKED flag is set.
|
||||||
|
void
|
||||||
|
PhysicalMemory::trackLoadLocked(Request *req)
|
||||||
|
{
|
||||||
|
Addr paddr = LockedAddr::mask(req->getPaddr());
|
||||||
|
|
||||||
|
// first we check if we already have a locked addr for this
|
||||||
|
// xc. Since each xc only gets one, we just update the
|
||||||
|
// existing record with the new address.
|
||||||
|
list<LockedAddr>::iterator i;
|
||||||
|
|
||||||
|
for (i = lockedAddrList.begin(); i != lockedAddrList.end(); ++i) {
|
||||||
|
if (i->matchesContext(req)) {
|
||||||
|
DPRINTF(LLSC, "Modifying lock record: cpu %d thread %d addr %#x\n",
|
||||||
|
req->getCpuNum(), req->getThreadNum(), paddr);
|
||||||
|
i->addr = paddr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// no record for this xc: need to allocate a new one
|
||||||
|
DPRINTF(LLSC, "Adding lock record: cpu %d thread %d addr %#x\n",
|
||||||
|
req->getCpuNum(), req->getThreadNum(), paddr);
|
||||||
|
lockedAddrList.push_front(LockedAddr(req));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Called on *writes* only... both regular stores and
|
||||||
|
// store-conditional operations. Check for conventional stores which
|
||||||
|
// conflict with locked addresses, and for success/failure of store
|
||||||
|
// conditionals.
|
||||||
|
bool
|
||||||
|
PhysicalMemory::checkLockedAddrList(Request *req)
|
||||||
|
{
|
||||||
|
Addr paddr = LockedAddr::mask(req->getPaddr());
|
||||||
|
bool isLocked = req->isLocked();
|
||||||
|
|
||||||
|
// Initialize return value. Non-conditional stores always
|
||||||
|
// succeed. Assume conditional stores will fail until proven
|
||||||
|
// otherwise.
|
||||||
|
bool success = !isLocked;
|
||||||
|
|
||||||
|
// Iterate over list. Note that there could be multiple matching
|
||||||
|
// records, as more than one context could have done a load locked
|
||||||
|
// to this location.
|
||||||
|
list<LockedAddr>::iterator i = lockedAddrList.begin();
|
||||||
|
|
||||||
|
while (i != lockedAddrList.end()) {
|
||||||
|
|
||||||
|
if (i->addr == paddr) {
|
||||||
|
// we have a matching address
|
||||||
|
|
||||||
|
if (isLocked && i->matchesContext(req)) {
|
||||||
|
// it's a store conditional, and as far as the memory
|
||||||
|
// system can tell, the requesting context's lock is
|
||||||
|
// still valid.
|
||||||
|
DPRINTF(LLSC, "StCond success: cpu %d thread %d addr %#x\n",
|
||||||
|
req->getCpuNum(), req->getThreadNum(), paddr);
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get rid of our record of this lock and advance to next
|
||||||
|
DPRINTF(LLSC, "Erasing lock record: cpu %d thread %d addr %#x\n",
|
||||||
|
i->cpuNum, i->threadNum, paddr);
|
||||||
|
i = lockedAddrList.erase(i);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// no match: advance to next record
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLocked) {
|
||||||
|
req->setScResult(success ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PhysicalMemory::doFunctionalAccess(Packet *pkt)
|
PhysicalMemory::doFunctionalAccess(Packet *pkt)
|
||||||
{
|
{
|
||||||
|
@ -117,18 +199,17 @@ PhysicalMemory::doFunctionalAccess(Packet *pkt)
|
||||||
|
|
||||||
switch (pkt->cmd) {
|
switch (pkt->cmd) {
|
||||||
case Packet::ReadReq:
|
case Packet::ReadReq:
|
||||||
|
if (pkt->req->isLocked()) {
|
||||||
|
trackLoadLocked(pkt->req);
|
||||||
|
}
|
||||||
memcpy(pkt->getPtr<uint8_t>(),
|
memcpy(pkt->getPtr<uint8_t>(),
|
||||||
pmemAddr + pkt->getAddr() - params()->addrRange.start,
|
pmemAddr + pkt->getAddr() - params()->addrRange.start,
|
||||||
pkt->getSize());
|
pkt->getSize());
|
||||||
break;
|
break;
|
||||||
case Packet::WriteReq:
|
case Packet::WriteReq:
|
||||||
|
if (writeOK(pkt->req)) {
|
||||||
memcpy(pmemAddr + pkt->getAddr() - params()->addrRange.start,
|
memcpy(pmemAddr + pkt->getAddr() - params()->addrRange.start,
|
||||||
pkt->getPtr<uint8_t>(),
|
pkt->getPtr<uint8_t>(), pkt->getSize());
|
||||||
pkt->getSize());
|
|
||||||
// temporary hack: will need to add real LL/SC implementation
|
|
||||||
// for cacheless systems later.
|
|
||||||
if (pkt->req->getFlags() & LOCKED) {
|
|
||||||
pkt->req->setScResult(1);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -78,6 +78,68 @@ class PhysicalMemory : public MemObject
|
||||||
const PhysicalMemory &operator=(const PhysicalMemory &specmem);
|
const PhysicalMemory &operator=(const PhysicalMemory &specmem);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
class LockedAddr {
|
||||||
|
public:
|
||||||
|
// on alpha, minimum LL/SC granularity is 16 bytes, so lower
|
||||||
|
// bits need to masked off.
|
||||||
|
static const Addr Addr_Mask = 0xf;
|
||||||
|
|
||||||
|
static Addr mask(Addr paddr) { return (paddr & ~Addr_Mask); }
|
||||||
|
|
||||||
|
Addr addr; // locked address
|
||||||
|
int cpuNum; // locking CPU
|
||||||
|
int threadNum; // locking thread ID within CPU
|
||||||
|
|
||||||
|
// check for matching execution context
|
||||||
|
bool matchesContext(Request *req)
|
||||||
|
{
|
||||||
|
return (cpuNum == req->getCpuNum() &&
|
||||||
|
threadNum == req->getThreadNum());
|
||||||
|
}
|
||||||
|
|
||||||
|
LockedAddr(Request *req)
|
||||||
|
: addr(mask(req->getPaddr())),
|
||||||
|
cpuNum(req->getCpuNum()),
|
||||||
|
threadNum(req->getThreadNum())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::list<LockedAddr> lockedAddrList;
|
||||||
|
|
||||||
|
// helper function for checkLockedAddrs(): we really want to
|
||||||
|
// inline a quick check for an empty locked addr list (hopefully
|
||||||
|
// the common case), and do the full list search (if necessary) in
|
||||||
|
// this out-of-line function
|
||||||
|
bool checkLockedAddrList(Request *req);
|
||||||
|
|
||||||
|
// Record the address of a load-locked operation so that we can
|
||||||
|
// clear the execution context's lock flag if a matching store is
|
||||||
|
// performed
|
||||||
|
void trackLoadLocked(Request *req);
|
||||||
|
|
||||||
|
// Compare a store address with any locked addresses so we can
|
||||||
|
// clear the lock flag appropriately. Return value set to 'false'
|
||||||
|
// if store operation should be suppressed (because it was a
|
||||||
|
// conditional store and the address was no longer locked by the
|
||||||
|
// requesting execution context), 'true' otherwise. Note that
|
||||||
|
// this method must be called on *all* stores since even
|
||||||
|
// non-conditional stores must clear any matching lock addresses.
|
||||||
|
bool writeOK(Request *req) {
|
||||||
|
if (lockedAddrList.empty()) {
|
||||||
|
// no locked addrs: nothing to check, store_conditional fails
|
||||||
|
bool isLocked = req->isLocked();
|
||||||
|
if (isLocked) {
|
||||||
|
req->setScResult(0);
|
||||||
|
}
|
||||||
|
return !isLocked; // only do write if not an sc
|
||||||
|
} else {
|
||||||
|
// iterate over list...
|
||||||
|
return checkLockedAddrList(req);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t *pmemAddr;
|
uint8_t *pmemAddr;
|
||||||
MemoryPort *port;
|
MemoryPort *port;
|
||||||
int pagePtr;
|
int pagePtr;
|
||||||
|
|
|
@ -232,9 +232,11 @@ class Request
|
||||||
Addr getPC() { assert(validPC); return pc; }
|
Addr getPC() { assert(validPC); return pc; }
|
||||||
|
|
||||||
/** Accessor Function to Check Cacheability. */
|
/** Accessor Function to Check Cacheability. */
|
||||||
bool isUncacheable() { return getFlags() & UNCACHEABLE; }
|
bool isUncacheable() { return (getFlags() & UNCACHEABLE) != 0; }
|
||||||
|
|
||||||
bool isInstRead() { return getFlags() & INST_READ; }
|
bool isInstRead() { return (getFlags() & INST_READ) != 0; }
|
||||||
|
|
||||||
|
bool isLocked() { return (getFlags() & LOCKED) != 0; }
|
||||||
|
|
||||||
friend class Packet;
|
friend class Packet;
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,10 +11,11 @@ class BaseCPU(SimObject):
|
||||||
mem = Param.MemObject("memory")
|
mem = Param.MemObject("memory")
|
||||||
|
|
||||||
system = Param.System(Parent.any, "system object")
|
system = Param.System(Parent.any, "system object")
|
||||||
|
cpu_id = Param.Int("CPU identifier")
|
||||||
|
|
||||||
if build_env['FULL_SYSTEM']:
|
if build_env['FULL_SYSTEM']:
|
||||||
dtb = Param.AlphaDTB(AlphaDTB(), "Data TLB")
|
dtb = Param.AlphaDTB(AlphaDTB(), "Data TLB")
|
||||||
itb = Param.AlphaITB(AlphaITB(), "Instruction TLB")
|
itb = Param.AlphaITB(AlphaITB(), "Instruction TLB")
|
||||||
cpu_id = Param.Int(-1, "CPU identifier")
|
|
||||||
else:
|
else:
|
||||||
workload = VectorParam.Process("processes to run")
|
workload = VectorParam.Process("processes to run")
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
import m5
|
import m5
|
||||||
from m5.objects import *
|
from m5.objects import *
|
||||||
|
|
||||||
system = System(cpu = AtomicSimpleCPU(),
|
system = System(cpu = AtomicSimpleCPU(cpu_id=0),
|
||||||
physmem = PhysicalMemory(),
|
physmem = PhysicalMemory(),
|
||||||
membus = Bus())
|
membus = Bus())
|
||||||
system.physmem.port = system.membus.port
|
system.physmem.port = system.membus.port
|
||||||
|
|
|
@ -36,7 +36,7 @@ class MyCache(BaseCache):
|
||||||
mshrs = 10
|
mshrs = 10
|
||||||
tgts_per_mshr = 5
|
tgts_per_mshr = 5
|
||||||
|
|
||||||
cpu = TimingSimpleCPU()
|
cpu = TimingSimpleCPU(cpu_id=0)
|
||||||
cpu.addTwoLevelCacheHierarchy(MyCache(size = '128kB'), MyCache(size = '256kB'),
|
cpu.addTwoLevelCacheHierarchy(MyCache(size = '128kB'), MyCache(size = '256kB'),
|
||||||
MyCache(size = '2MB'))
|
MyCache(size = '2MB'))
|
||||||
cpu.mem = cpu.dcache
|
cpu.mem = cpu.dcache
|
||||||
|
|
|
@ -34,7 +34,7 @@ import FSConfig
|
||||||
AlphaConsole.cpu = Parent.cpu[0]
|
AlphaConsole.cpu = Parent.cpu[0]
|
||||||
IntrControl.cpu = Parent.cpu[0]
|
IntrControl.cpu = Parent.cpu[0]
|
||||||
|
|
||||||
cpus = [ AtomicSimpleCPU() for i in xrange(2) ]
|
cpus = [ AtomicSimpleCPU(cpu_id=i) for i in xrange(2) ]
|
||||||
system = FSConfig.makeLinuxAlphaSystem('atomic')
|
system = FSConfig.makeLinuxAlphaSystem('atomic')
|
||||||
system.cpu = cpus
|
system.cpu = cpus
|
||||||
for c in cpus:
|
for c in cpus:
|
||||||
|
|
|
@ -31,7 +31,7 @@ from m5.objects import *
|
||||||
m5.AddToPath('../configs/common')
|
m5.AddToPath('../configs/common')
|
||||||
import FSConfig
|
import FSConfig
|
||||||
|
|
||||||
cpu = AtomicSimpleCPU()
|
cpu = AtomicSimpleCPU(cpu_id=0)
|
||||||
system = FSConfig.makeLinuxAlphaSystem('atomic')
|
system = FSConfig.makeLinuxAlphaSystem('atomic')
|
||||||
system.cpu = cpu
|
system.cpu = cpu
|
||||||
cpu.connectMemPorts(system.membus)
|
cpu.connectMemPorts(system.membus)
|
||||||
|
|
|
@ -34,7 +34,7 @@ import FSConfig
|
||||||
AlphaConsole.cpu = Parent.cpu[0]
|
AlphaConsole.cpu = Parent.cpu[0]
|
||||||
IntrControl.cpu = Parent.cpu[0]
|
IntrControl.cpu = Parent.cpu[0]
|
||||||
|
|
||||||
cpus = [ TimingSimpleCPU() for i in xrange(2) ]
|
cpus = [ TimingSimpleCPU(cpu_id=i) for i in xrange(2) ]
|
||||||
system = FSConfig.makeLinuxAlphaSystem('timing')
|
system = FSConfig.makeLinuxAlphaSystem('timing')
|
||||||
system.cpu = cpus
|
system.cpu = cpus
|
||||||
for c in cpus:
|
for c in cpus:
|
||||||
|
|
|
@ -31,7 +31,7 @@ from m5.objects import *
|
||||||
m5.AddToPath('../configs/common')
|
m5.AddToPath('../configs/common')
|
||||||
import FSConfig
|
import FSConfig
|
||||||
|
|
||||||
cpu = TimingSimpleCPU()
|
cpu = TimingSimpleCPU(cpu_id=0)
|
||||||
system = FSConfig.makeLinuxAlphaSystem('timing')
|
system = FSConfig.makeLinuxAlphaSystem('timing')
|
||||||
system.cpu = cpu
|
system.cpu = cpu
|
||||||
cpu.connectMemPorts(system.membus)
|
cpu.connectMemPorts(system.membus)
|
||||||
|
|
Loading…
Reference in a new issue