mt.hh revision 6378
112854Sgabeblack@google.com/*
212854Sgabeblack@google.com * Copyright (c) 2007 MIPS Technologies, Inc.
312854Sgabeblack@google.com * All rights reserved.
412854Sgabeblack@google.com *
512854Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without
612854Sgabeblack@google.com * modification, are permitted provided that the following conditions are
712854Sgabeblack@google.com * met: redistributions of source code must retain the above copyright
812854Sgabeblack@google.com * notice, this list of conditions and the following disclaimer;
912854Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright
1012854Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the
1112854Sgabeblack@google.com * documentation and/or other materials provided with the distribution;
1212854Sgabeblack@google.com * neither the name of the copyright holders nor the names of its
1312854Sgabeblack@google.com * contributors may be used to endorse or promote products derived from
1412854Sgabeblack@google.com * this software without specific prior written permission.
1512854Sgabeblack@google.com *
1612854Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1712854Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1812854Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1912854Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2012854Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2112854Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2212854Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2312854Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2412854Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2512854Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2612854Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2712854Sgabeblack@google.com *
2812854Sgabeblack@google.com * Authors: Korey Sewell
2912854Sgabeblack@google.com */
3012854Sgabeblack@google.com
3112854Sgabeblack@google.com#ifndef __ARCH_MIPS_MT_HH__
3212854Sgabeblack@google.com#define __ARCH_MIPS_MT_HH__
3312854Sgabeblack@google.com
3412854Sgabeblack@google.com/**
3512854Sgabeblack@google.com * @file
3612854Sgabeblack@google.com *
3712854Sgabeblack@google.com * ISA-specific helper functions for multithreaded execution.
3812854Sgabeblack@google.com */
3912854Sgabeblack@google.com
4012854Sgabeblack@google.com#include "arch/mips/faults.hh"
4112854Sgabeblack@google.com#include "arch/mips/isa_traits.hh"
4212854Sgabeblack@google.com#include "arch/mips/mt_constants.hh"
4312854Sgabeblack@google.com#include "arch/mips/pra_constants.hh"
4412854Sgabeblack@google.com#include "arch/mips/registers.hh"
4512854Sgabeblack@google.com#include "base/bitfield.hh"
4612854Sgabeblack@google.com#include "base/trace.hh"
4712854Sgabeblack@google.com#include "base/misc.hh"
4812854Sgabeblack@google.com
4912854Sgabeblack@google.com#include <iostream>
5012854Sgabeblack@google.com
5112854Sgabeblack@google.comnamespace MipsISA
5212854Sgabeblack@google.com{
5312854Sgabeblack@google.com
5412854Sgabeblack@google.comtemplate <class TC>
5512854Sgabeblack@google.cominline unsigned
5612854Sgabeblack@google.comgetVirtProcNum(TC *tc)
5712854Sgabeblack@google.com{
5812854Sgabeblack@google.com    TCBindReg tcbind = tc->readMiscRegNoEffect(TCBind);
5912854Sgabeblack@google.com    return tcbind.curVPE;
6012854Sgabeblack@google.com}
6112854Sgabeblack@google.com
6212854Sgabeblack@google.comtemplate <class TC>
6312854Sgabeblack@google.cominline unsigned
6412854Sgabeblack@google.comgetTargetThread(TC *tc)
6512854Sgabeblack@google.com{
6612854Sgabeblack@google.com    VPEControlReg vpeCtrl = tc->readMiscRegNoEffect(VPEControl);
6712854Sgabeblack@google.com    return vpeCtrl.targTC;
6812854Sgabeblack@google.com}
6912854Sgabeblack@google.com
7012854Sgabeblack@google.comtemplate <class TC>
7112854Sgabeblack@google.cominline void
7212854Sgabeblack@google.comhaltThread(TC *tc)
7312854Sgabeblack@google.com{
7412854Sgabeblack@google.com    if (tc->status() == TC::Active) {
7512854Sgabeblack@google.com        tc->halt();
7612854Sgabeblack@google.com
7712854Sgabeblack@google.com        // Save last known PC in TCRestart
7812854Sgabeblack@google.com        // @TODO: Needs to check if this is a branch and if so,
7912854Sgabeblack@google.com        // take previous instruction
8012854Sgabeblack@google.com        tc->setMiscReg(TCRestart, tc->readNextPC());
8112854Sgabeblack@google.com
8212854Sgabeblack@google.com        warn("%i: Halting thread %i in %s @ PC %x, setting restart PC to %x",
8312854Sgabeblack@google.com                curTick, tc->threadId(), tc->getCpuPtr()->name(),
8412854Sgabeblack@google.com                tc->readPC(), tc->readNextPC());
8512854Sgabeblack@google.com    }
8612854Sgabeblack@google.com}
8712854Sgabeblack@google.com
8812854Sgabeblack@google.comtemplate <class TC>
8912854Sgabeblack@google.cominline void
9012854Sgabeblack@google.comrestoreThread(TC *tc)
9112854Sgabeblack@google.com{
9212854Sgabeblack@google.com    if (tc->status() != TC::Active) {
9312854Sgabeblack@google.com        // Restore PC from TCRestart
9412854Sgabeblack@google.com        IntReg pc = tc->readMiscRegNoEffect(TCRestart);
9512854Sgabeblack@google.com
9612854Sgabeblack@google.com        // TODO: SET PC WITH AN EVENT INSTEAD OF INSTANTANEOUSLY
9712854Sgabeblack@google.com        tc->setPC(pc);
9812854Sgabeblack@google.com        tc->setNextPC(pc + 4);
9912854Sgabeblack@google.com        tc->setNextNPC(pc + 8);
10012854Sgabeblack@google.com        tc->activate(0);
10112854Sgabeblack@google.com
10212854Sgabeblack@google.com        warn("%i: Restoring thread %i in %s @ PC %x",
10312854Sgabeblack@google.com                curTick, tc->threadId(), tc->getCpuPtr()->name(),
10412854Sgabeblack@google.com                tc->readPC());
10512854Sgabeblack@google.com    }
10612854Sgabeblack@google.com}
10712854Sgabeblack@google.com
10812854Sgabeblack@google.comtemplate <class TC>
10912854Sgabeblack@google.comvoid
11012854Sgabeblack@google.comforkThread(TC *tc, Fault &fault, int Rd_bits, int Rs, int Rt)
11112854Sgabeblack@google.com{
11212854Sgabeblack@google.com    MVPConf0Reg mvpConf = tc->readMiscRegNoEffect(MVPConf0);
11312854Sgabeblack@google.com    int num_threads = mvpConf.ptc + 1;
11412854Sgabeblack@google.com
11512854Sgabeblack@google.com    int success = 0;
11612854Sgabeblack@google.com    for (ThreadID tid = 0; tid < num_threads && success == 0; tid++) {
11712854Sgabeblack@google.com        TCBindReg tidTCBind =
11812854Sgabeblack@google.com            tc->readRegOtherThread(TCBind + Ctrl_Base_DepTag, tid);
11912854Sgabeblack@google.com        TCBindReg tcBind = tc->readMiscRegNoEffect(TCBind);
12012854Sgabeblack@google.com
12112854Sgabeblack@google.com        if (tidTCBind.curVPE = tcBind.curVPE) {
12212854Sgabeblack@google.com
12312854Sgabeblack@google.com            TCStatusReg tidTCStatus =
12412854Sgabeblack@google.com                tc->readRegOtherThread(TCStatus + Ctrl_Base_DepTag,tid);
12512854Sgabeblack@google.com
12612854Sgabeblack@google.com            TCHaltReg tidTCHalt =
12712854Sgabeblack@google.com                tc->readRegOtherThread(TCHalt + Ctrl_Base_DepTag,tid);
12812854Sgabeblack@google.com
12912854Sgabeblack@google.com            if (tidTCStatus.da == 1 && tidTCHalt.h == 0 &&
13012854Sgabeblack@google.com                tidTCStatus.a == 0 && success == 0) {
13112854Sgabeblack@google.com
13212854Sgabeblack@google.com                tc->setRegOtherThread(TCRestart + Ctrl_Base_DepTag, Rs, tid);
13312854Sgabeblack@google.com                tc->setRegOtherThread(Rd_bits, Rt, tid);
13412854Sgabeblack@google.com
13512854Sgabeblack@google.com                StatusReg status = tc->readMiscReg(Status);
13612854Sgabeblack@google.com                TCStatusReg tcStatus = tc->readMiscReg(TCStatus);
13712854Sgabeblack@google.com
13812854Sgabeblack@google.com                // Set Run-State to Running
13912854Sgabeblack@google.com                tidTCStatus.rnst = 0;
14012854Sgabeblack@google.com                // Set Delay-Slot to 0
14112854Sgabeblack@google.com                tidTCStatus.tds = 0;
14212854Sgabeblack@google.com                // Set Dirty TC to 1
14312854Sgabeblack@google.com                tidTCStatus.dt = 1;
14412854Sgabeblack@google.com                // Set Activated to 1
14512854Sgabeblack@google.com                tidTCStatus.a = 1;
14612854Sgabeblack@google.com                // Set status to previous thread's status
14712854Sgabeblack@google.com                tidTCStatus.tksu = status.ksu;
14812854Sgabeblack@google.com                // Set ASID to previous thread's state
14912854Sgabeblack@google.com                tidTCStatus.asid = tcStatus.asid;
15012854Sgabeblack@google.com
15112854Sgabeblack@google.com                // Write Status Register
15212854Sgabeblack@google.com                tc->setRegOtherThread(TCStatus + Ctrl_Base_DepTag,
15312854Sgabeblack@google.com                                      tidTCStatus, tid);
15412854Sgabeblack@google.com
15512854Sgabeblack@google.com                // Mark As Successful Fork
15612854Sgabeblack@google.com                success = 1;
15712854Sgabeblack@google.com            }
15812854Sgabeblack@google.com        } else {
15912854Sgabeblack@google.com            std::cerr << "Bad VPEs" << std::endl;
16012854Sgabeblack@google.com        }
16112854Sgabeblack@google.com    }
16212854Sgabeblack@google.com
16312854Sgabeblack@google.com    if (success == 0) {
16412854Sgabeblack@google.com        VPEControlReg vpeControl = tc->readMiscRegNoEffect(VPEControl);
16512854Sgabeblack@google.com        vpeControl.excpt = 1;
16612854Sgabeblack@google.com        tc->setMiscReg(VPEControl, vpeControl);
16712854Sgabeblack@google.com        fault = new ThreadFault();
16812854Sgabeblack@google.com    }
16912854Sgabeblack@google.com}
17012854Sgabeblack@google.com
17112854Sgabeblack@google.com
17212854Sgabeblack@google.comtemplate <class TC>
17312854Sgabeblack@google.comint
17412854Sgabeblack@google.comyieldThread(TC *tc, Fault &fault, int src_reg, uint32_t yield_mask)
17512854Sgabeblack@google.com{
17612854Sgabeblack@google.com    if (src_reg == 0) {
17712854Sgabeblack@google.com        MVPConf0Reg mvpConf0 = tc->readMiscRegNoEffect(MVPConf0);
17812854Sgabeblack@google.com        ThreadID num_threads = mvpConf0.ptc + 1;
17912854Sgabeblack@google.com
18012854Sgabeblack@google.com        int ok = 0;
18112854Sgabeblack@google.com
18212854Sgabeblack@google.com        // Get Current VPE & TC numbers from calling thread
18312854Sgabeblack@google.com        TCBindReg tcBind = tc->readMiscRegNoEffect(TCBind);
18412854Sgabeblack@google.com
18512854Sgabeblack@google.com        for (ThreadID tid = 0; tid < num_threads; tid++) {
18612854Sgabeblack@google.com            TCStatusReg tidTCStatus =
18712854Sgabeblack@google.com                tc->readRegOtherThread(TCStatus + Ctrl_Base_DepTag, tid);
18812854Sgabeblack@google.com            TCHaltReg tidTCHalt =
18912854Sgabeblack@google.com                tc->readRegOtherThread(TCHalt + Ctrl_Base_DepTag, tid);
19012854Sgabeblack@google.com            TCBindReg tidTCBind =
19112854Sgabeblack@google.com                tc->readRegOtherThread(TCBind + Ctrl_Base_DepTag, tid);
19212854Sgabeblack@google.com
19312854Sgabeblack@google.com            if (tidTCBind.curVPE == tcBind.curVPE &&
19412854Sgabeblack@google.com                tidTCBind.curTC == tcBind.curTC &&
19512854Sgabeblack@google.com                tidTCStatus.da == 1 &&
19612854Sgabeblack@google.com                tidTCHalt.h == 0    &&
19712854Sgabeblack@google.com                tidTCStatus.a == 1) {
19812854Sgabeblack@google.com                ok = 1;
19912854Sgabeblack@google.com            }
20012854Sgabeblack@google.com        }
20112854Sgabeblack@google.com
20212854Sgabeblack@google.com        if (ok == 1) {
20312854Sgabeblack@google.com            TCStatusReg tcStatus = tc->readMiscRegNoEffect(TCStatus);
20412854Sgabeblack@google.com            tcStatus.a = 0;
20512854Sgabeblack@google.com            tc->setMiscReg(TCStatus, tcStatus);
20612854Sgabeblack@google.com            warn("%i: Deactivating Hardware Thread Context #%i",
20712854Sgabeblack@google.com                    curTick, tc->threadId());
20812854Sgabeblack@google.com        }
20912854Sgabeblack@google.com    } else if (src_reg > 0) {
21012854Sgabeblack@google.com        if (src_reg && !yield_mask != 0) {
21112854Sgabeblack@google.com            VPEControlReg vpeControl = tc->readMiscReg(VPEControl);
21212854Sgabeblack@google.com            vpeControl.excpt = 2;
21312854Sgabeblack@google.com            tc->setMiscReg(VPEControl, vpeControl);
21412854Sgabeblack@google.com            fault = new ThreadFault();
21512854Sgabeblack@google.com        } else {
21612854Sgabeblack@google.com        }
21712854Sgabeblack@google.com    } else if (src_reg != -2) {
21812854Sgabeblack@google.com        TCStatusReg tcStatus = tc->readMiscRegNoEffect(TCStatus);
21912854Sgabeblack@google.com        VPEControlReg vpeControl = tc->readMiscRegNoEffect(VPEControl);
22012854Sgabeblack@google.com
22112854Sgabeblack@google.com        if (vpeControl.ysi == 1 && tcStatus.dt == 1 ) {
22212854Sgabeblack@google.com            vpeControl.excpt = 4;
22312854Sgabeblack@google.com            fault = new ThreadFault();
22412854Sgabeblack@google.com        } else {
22512854Sgabeblack@google.com        }
22612854Sgabeblack@google.com    }
22712854Sgabeblack@google.com
22812854Sgabeblack@google.com    return src_reg & yield_mask;
22912854Sgabeblack@google.com}
23012854Sgabeblack@google.com
23112854Sgabeblack@google.com
23212854Sgabeblack@google.com// TC will usually be a object derived from ThreadContext
23312854Sgabeblack@google.com// (src/cpu/thread_context.hh)
23412854Sgabeblack@google.comtemplate <class TC>
23512854Sgabeblack@google.cominline void
23612854Sgabeblack@google.comupdateStatusView(TC *tc)
23712854Sgabeblack@google.com{
23812854Sgabeblack@google.com    // TCStatus' register view must be the same as
23912854Sgabeblack@google.com    // Status register view for CU, MX, KSU bits
24012854Sgabeblack@google.com    TCStatusReg tcStatus = tc->readMiscRegNoEffect(TCStatus);
24112854Sgabeblack@google.com    StatusReg status = tc->readMiscRegNoEffect(Status);
24212854Sgabeblack@google.com
24312854Sgabeblack@google.com    status.cu = tcStatus.tcu;
24412854Sgabeblack@google.com    status.mx = tcStatus.tmx;
24512854Sgabeblack@google.com    status.ksu = tcStatus.tksu;
24612854Sgabeblack@google.com
24712854Sgabeblack@google.com    tc->setMiscRegNoEffect(Status, status);
24812854Sgabeblack@google.com}
24912854Sgabeblack@google.com
25012854Sgabeblack@google.com// TC will usually be a object derived from ThreadContext
25112854Sgabeblack@google.com// (src/cpu/thread_context.hh)
25212854Sgabeblack@google.comtemplate <class TC>
25312854Sgabeblack@google.cominline void
25412854Sgabeblack@google.comupdateTCStatusView(TC *tc)
25512854Sgabeblack@google.com{
25612854Sgabeblack@google.com    // TCStatus' register view must be the same as
25712854Sgabeblack@google.com    // Status register view for CU, MX, KSU bits
25812854Sgabeblack@google.com    TCStatusReg tcStatus = tc->readMiscRegNoEffect(TCStatus);
25912854Sgabeblack@google.com    StatusReg status = tc->readMiscRegNoEffect(Status);
26012854Sgabeblack@google.com
26112854Sgabeblack@google.com    tcStatus.tcu = status.cu;
26212854Sgabeblack@google.com    tcStatus.tmx = status.mx;
26312854Sgabeblack@google.com    tcStatus.tksu = status.ksu;
26412854Sgabeblack@google.com
26512854Sgabeblack@google.com    tc->setMiscRegNoEffect(TCStatus, tcStatus);
26612854Sgabeblack@google.com}
26712854Sgabeblack@google.com
26812854Sgabeblack@google.com} // namespace MipsISA
26912854Sgabeblack@google.com
27012854Sgabeblack@google.com
27112854Sgabeblack@google.com#endif
27212854Sgabeblack@google.com