* 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
*/
#include "arch/utility.hh"
BaseCPU::init();
#if FULL_SYSTEM
- for (int i = 0; i < execContexts.size(); ++i) {
- ExecContext *xc = execContexts[i];
+ for (int i = 0; i < threadContexts.size(); ++i) {
+ ThreadContext *tc = threadContexts[i];
// initialize CPU, including PC
- TheISA::initCPU(xc, xc->readCpuId());
+ TheISA::initCPU(tc, tc->readCpuId());
}
#endif
}
panic("AtomicSimpleCPU doesn't expect recvStatusChange callback!");
}
-Packet *
+void
AtomicSimpleCPU::CpuPort::recvRetry()
{
panic("AtomicSimpleCPU doesn't expect recvRetry callback!");
- return NULL;
}
{
_status = Idle;
- ifetch_req = new Request(true);
- ifetch_req->setAsid(0);
- // @todo fix me and get the real cpu iD!!!
- ifetch_req->setCpuNum(0);
- ifetch_req->setSize(sizeof(MachInst));
+ // @todo fix me and get the real cpu id & thread number!!!
+ ifetch_req = new Request();
+ ifetch_req->setThreadContext(0,0); //Need CPU/Thread IDS HERE
ifetch_pkt = new Packet(ifetch_req, Packet::ReadReq, Packet::Broadcast);
ifetch_pkt->dataStatic(&inst);
- data_read_req = new Request(true);
- // @todo fix me and get the real cpu iD!!!
- data_read_req->setCpuNum(0);
- data_read_req->setAsid(0);
+ data_read_req = new Request();
+ data_read_req->setThreadContext(0,0); //Need CPU/Thread IDS HERE
data_read_pkt = new Packet(data_read_req, Packet::ReadReq,
Packet::Broadcast);
data_read_pkt->dataStatic(&dataReg);
- data_write_req = new Request(true);
- // @todo fix me and get the real cpu iD!!!
- data_write_req->setCpuNum(0);
- data_write_req->setAsid(0);
+ data_write_req = new Request();
+ data_write_req->setThreadContext(0,0); //Need CPU/Thread IDS HERE
data_write_pkt = new Packet(data_write_req, Packet::WriteReq,
Packet::Broadcast);
}
void
AtomicSimpleCPU::serialize(ostream &os)
{
- BaseSimpleCPU::serialize(os);
SERIALIZE_ENUM(_status);
+ BaseSimpleCPU::serialize(os);
nameOut(os, csprintf("%s.tickEvent", name()));
tickEvent.serialize(os);
}
void
AtomicSimpleCPU::unserialize(Checkpoint *cp, const string §ion)
{
- BaseSimpleCPU::unserialize(cp, section);
UNSERIALIZE_ENUM(_status);
+ BaseSimpleCPU::unserialize(cp, section);
tickEvent.unserialize(cp, csprintf("%s.tickEvent", section));
}
void
-AtomicSimpleCPU::switchOut(Sampler *s)
+AtomicSimpleCPU::switchOut()
{
- sampler = s;
- if (status() == Running) {
- _status = SwitchedOut;
+ assert(status() == Running || status() == Idle);
+ _status = SwitchedOut;
- tickEvent.squash();
- }
- sampler->signalSwitched();
+ tickEvent.squash();
}
assert(!tickEvent.scheduled());
- // if any of this CPU's ExecContexts are active, mark the CPU as
+ // if any of this CPU's ThreadContexts are active, mark the CPU as
// running and schedule its tick event.
- for (int i = 0; i < execContexts.size(); ++i) {
- ExecContext *xc = execContexts[i];
- if (xc->status() == ExecContext::Active && _status != Running) {
+ for (int i = 0; i < threadContexts.size(); ++i) {
+ ThreadContext *tc = threadContexts[i];
+ if (tc->status() == ThreadContext::Active && _status != Running) {
_status = Running;
tickEvent.schedule(curTick);
break;
AtomicSimpleCPU::activateContext(int thread_num, int delay)
{
assert(thread_num == 0);
- assert(cpuXC);
+ assert(thread);
assert(_status == Idle);
assert(!tickEvent.scheduled());
AtomicSimpleCPU::suspendContext(int thread_num)
{
assert(thread_num == 0);
- assert(cpuXC);
+ assert(thread);
assert(_status == Running);
Fault
AtomicSimpleCPU::read(Addr addr, T &data, unsigned flags)
{
- data_read_req->setVaddr(addr);
- data_read_req->setSize(sizeof(T));
- data_read_req->setFlags(flags);
- data_read_req->setTime(curTick);
+ data_read_req->setVirt(0, addr, sizeof(T), flags, thread->readPC());
if (traceData) {
traceData->setAddr(addr);
}
// translate to physical address
- Fault fault = cpuXC->translateDataReadReq(data_read_req);
+ Fault fault = thread->translateDataReadReq(data_read_req);
// Now do the access.
if (fault == NoFault) {
- data_read_pkt->reset();
data_read_pkt->reinitFromRequest();
- dcache_complete = dcachePort.sendAtomic(data_read_pkt);
+ dcache_latency = dcachePort.sendAtomic(data_read_pkt);
dcache_access = true;
assert(data_read_pkt->result == Packet::Success);
Fault
AtomicSimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
{
- data_write_req->setVaddr(addr);
- data_write_req->setTime(curTick);
- data_write_req->setSize(sizeof(T));
- data_write_req->setFlags(flags);
+ data_write_req->setVirt(0, addr, sizeof(T), flags, thread->readPC());
if (traceData) {
traceData->setAddr(addr);
}
// translate to physical address
- Fault fault = cpuXC->translateDataWriteReq(data_write_req);
+ Fault fault = thread->translateDataWriteReq(data_write_req);
// Now do the access.
if (fault == NoFault) {
- data_write_pkt->reset();
data = htog(data);
- data_write_pkt->dataStatic(&data);
data_write_pkt->reinitFromRequest();
+ data_write_pkt->dataStatic(&data);
- dcache_complete = dcachePort.sendAtomic(data_write_pkt);
+ dcache_latency = dcachePort.sendAtomic(data_write_pkt);
dcache_access = true;
assert(data_write_pkt->result == Packet::Success);
checkForInterrupts();
- ifetch_req->resetMin();
- ifetch_pkt->reset();
- Fault fault = setupFetchPacket(ifetch_pkt);
+ Fault fault = setupFetchRequest(ifetch_req);
if (fault == NoFault) {
- Tick icache_complete = icachePort.sendAtomic(ifetch_pkt);
+ ifetch_pkt->reinitFromRequest();
+
+ Tick icache_latency = icachePort.sendAtomic(ifetch_pkt);
// ifetch_req is initialized to read the instruction directly
// into the CPU object's inst field.
fault = curStaticInst->execute(this, traceData);
postExecute();
- if (traceData) {
- traceData->finalize();
- }
-
if (simulate_stalls) {
- // This calculation assumes that the icache and dcache
- // access latencies are always a multiple of the CPU's
- // cycle time. If not, the next tick event may get
- // scheduled at a non-integer multiple of the CPU
- // cycle time.
- Tick icache_stall = icache_complete - curTick - cycles(1);
+ Tick icache_stall = icache_latency - cycles(1);
Tick dcache_stall =
- dcache_access ? dcache_complete - curTick - cycles(1) : 0;
- latency += icache_stall + dcache_stall;
+ dcache_access ? dcache_latency - cycles(1) : 0;
+ Tick stall_cycles = (icache_stall + dcache_stall) / cycles(1);
+ if (cycles(stall_cycles) < (icache_stall + dcache_stall))
+ latency += cycles(stall_cycles+1);
+ else
+ latency += cycles(stall_cycles);
}
}