mt.hh revision 6378
11689SN/A/*
22326SN/A * Copyright (c) 2007 MIPS Technologies, Inc.
31689SN/A * All rights reserved.
41689SN/A *
51689SN/A * Redistribution and use in source and binary forms, with or without
61689SN/A * modification, are permitted provided that the following conditions are
71689SN/A * met: redistributions of source code must retain the above copyright
81689SN/A * notice, this list of conditions and the following disclaimer;
91689SN/A * redistributions in binary form must reproduce the above copyright
101689SN/A * notice, this list of conditions and the following disclaimer in the
111689SN/A * documentation and/or other materials provided with the distribution;
121689SN/A * neither the name of the copyright holders nor the names of its
131689SN/A * contributors may be used to endorse or promote products derived from
141689SN/A * this software without specific prior written permission.
151689SN/A *
161689SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
171689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
181689SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
191689SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
201689SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
211689SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
221689SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
231689SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
241689SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
251689SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
261689SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665Ssaidi@eecs.umich.edu *
282665Ssaidi@eecs.umich.edu * Authors: Korey Sewell
291689SN/A */
301689SN/A
311060SN/A#ifndef __ARCH_MIPS_MT_HH__
321060SN/A#define __ARCH_MIPS_MT_HH__
331689SN/A
341060SN/A/**
351060SN/A * @file
361060SN/A *
371060SN/A * ISA-specific helper functions for multithreaded execution.
382292SN/A */
391717SN/A
401060SN/A#include "arch/mips/faults.hh"
412292SN/A#include "arch/mips/isa_traits.hh"
421681SN/A#include "arch/mips/mt_constants.hh"
431681SN/A#include "arch/mips/pra_constants.hh"
442292SN/A#include "arch/mips/registers.hh"
452326SN/A#include "base/bitfield.hh"
461061SN/A#include "base/trace.hh"
471060SN/A#include "base/misc.hh"
481061SN/A
492292SN/A#include <iostream>
502292SN/A
512292SN/Anamespace MipsISA
522292SN/A{
532292SN/A
542292SN/Atemplate <class TC>
552307SN/Ainline unsigned
562307SN/AgetVirtProcNum(TC *tc)
571060SN/A{
582292SN/A    TCBindReg tcbind = tc->readMiscRegNoEffect(TCBind);
592292SN/A    return tcbind.curVPE;
602292SN/A}
611060SN/A
621060SN/Atemplate <class TC>
631060SN/Ainline unsigned
641060SN/AgetTargetThread(TC *tc)
651060SN/A{
661060SN/A    VPEControlReg vpeCtrl = tc->readMiscRegNoEffect(VPEControl);
671681SN/A    return vpeCtrl.targTC;
682292SN/A}
691681SN/A
702292SN/Atemplate <class TC>
712292SN/Ainline void
722292SN/AhaltThread(TC *tc)
732292SN/A{
742292SN/A    if (tc->status() == TC::Active) {
752292SN/A        tc->halt();
762292SN/A
772292SN/A        // Save last known PC in TCRestart
782292SN/A        // @TODO: Needs to check if this is a branch and if so,
792292SN/A        // take previous instruction
802292SN/A        tc->setMiscReg(TCRestart, tc->readNextPC());
812292SN/A
822292SN/A        warn("%i: Halting thread %i in %s @ PC %x, setting restart PC to %x",
832292SN/A                curTick, tc->threadId(), tc->getCpuPtr()->name(),
842292SN/A                tc->readPC(), tc->readNextPC());
852292SN/A    }
862292SN/A}
871060SN/A
881060SN/Atemplate <class TC>
891681SN/Ainline void
901062SN/ArestoreThread(TC *tc)
912292SN/A{
921062SN/A    if (tc->status() != TC::Active) {
932301SN/A        // Restore PC from TCRestart
942301SN/A        IntReg pc = tc->readMiscRegNoEffect(TCRestart);
951062SN/A
962727Sktlim@umich.edu        // TODO: SET PC WITH AN EVENT INSTEAD OF INSTANTANEOUSLY
971062SN/A        tc->setPC(pc);
981062SN/A        tc->setNextPC(pc + 4);
991062SN/A        tc->setNextNPC(pc + 8);
1001062SN/A        tc->activate(0);
1011062SN/A
1021062SN/A        warn("%i: Restoring thread %i in %s @ PC %x",
1031062SN/A                curTick, tc->threadId(), tc->getCpuPtr()->name(),
1041062SN/A                tc->readPC());
1051062SN/A    }
1061062SN/A}
1071062SN/A
1081062SN/Atemplate <class TC>
1091062SN/Avoid
1101062SN/AforkThread(TC *tc, Fault &fault, int Rd_bits, int Rs, int Rt)
1111062SN/A{
1121062SN/A    MVPConf0Reg mvpConf = tc->readMiscRegNoEffect(MVPConf0);
1131062SN/A    int num_threads = mvpConf.ptc + 1;
1141062SN/A
1151062SN/A    int success = 0;
1161062SN/A    for (ThreadID tid = 0; tid < num_threads && success == 0; tid++) {
1171062SN/A        TCBindReg tidTCBind =
1181062SN/A            tc->readRegOtherThread(TCBind + Ctrl_Base_DepTag, tid);
1191062SN/A        TCBindReg tcBind = tc->readMiscRegNoEffect(TCBind);
1201062SN/A
1211062SN/A        if (tidTCBind.curVPE = tcBind.curVPE) {
1221062SN/A
1231062SN/A            TCStatusReg tidTCStatus =
1241062SN/A                tc->readRegOtherThread(TCStatus + Ctrl_Base_DepTag,tid);
1251062SN/A
1261062SN/A            TCHaltReg tidTCHalt =
1271062SN/A                tc->readRegOtherThread(TCHalt + Ctrl_Base_DepTag,tid);
1281062SN/A
1291062SN/A            if (tidTCStatus.da == 1 && tidTCHalt.h == 0 &&
1301062SN/A                tidTCStatus.a == 0 && success == 0) {
1311062SN/A
1321062SN/A                tc->setRegOtherThread(TCRestart + Ctrl_Base_DepTag, Rs, tid);
1331062SN/A                tc->setRegOtherThread(Rd_bits, Rt, tid);
1341062SN/A
1351062SN/A                StatusReg status = tc->readMiscReg(Status);
1361062SN/A                TCStatusReg tcStatus = tc->readMiscReg(TCStatus);
1371062SN/A
1382292SN/A                // Set Run-State to Running
1392292SN/A                tidTCStatus.rnst = 0;
1402292SN/A                // Set Delay-Slot to 0
1412292SN/A                tidTCStatus.tds = 0;
1421062SN/A                // Set Dirty TC to 1
1431062SN/A                tidTCStatus.dt = 1;
1441062SN/A                // Set Activated to 1
1451062SN/A                tidTCStatus.a = 1;
1461062SN/A                // Set status to previous thread's status
1471062SN/A                tidTCStatus.tksu = status.ksu;
1481062SN/A                // Set ASID to previous thread's state
1492292SN/A                tidTCStatus.asid = tcStatus.asid;
1502292SN/A
1512292SN/A                // Write Status Register
1522292SN/A                tc->setRegOtherThread(TCStatus + Ctrl_Base_DepTag,
1532292SN/A                                      tidTCStatus, tid);
1542292SN/A
1552292SN/A                // Mark As Successful Fork
1562292SN/A                success = 1;
1572292SN/A            }
1582292SN/A        } else {
1592301SN/A            std::cerr << "Bad VPEs" << std::endl;
1602727Sktlim@umich.edu        }
1612727Sktlim@umich.edu    }
1622727Sktlim@umich.edu
1632727Sktlim@umich.edu    if (success == 0) {
1642727Sktlim@umich.edu        VPEControlReg vpeControl = tc->readMiscRegNoEffect(VPEControl);
1652727Sktlim@umich.edu        vpeControl.excpt = 1;
1662727Sktlim@umich.edu        tc->setMiscReg(VPEControl, vpeControl);
1672727Sktlim@umich.edu        fault = new ThreadFault();
1682727Sktlim@umich.edu    }
1692727Sktlim@umich.edu}
1702727Sktlim@umich.edu
1712727Sktlim@umich.edu
1722727Sktlim@umich.edutemplate <class TC>
1732727Sktlim@umich.eduint
1742727Sktlim@umich.eduyieldThread(TC *tc, Fault &fault, int src_reg, uint32_t yield_mask)
1752301SN/A{
1762301SN/A    if (src_reg == 0) {
1772301SN/A        MVPConf0Reg mvpConf0 = tc->readMiscRegNoEffect(MVPConf0);
1782727Sktlim@umich.edu        ThreadID num_threads = mvpConf0.ptc + 1;
1792301SN/A
1802727Sktlim@umich.edu        int ok = 0;
1812301SN/A
1822301SN/A        // Get Current VPE & TC numbers from calling thread
1832301SN/A        TCBindReg tcBind = tc->readMiscRegNoEffect(TCBind);
1842727Sktlim@umich.edu
1852301SN/A        for (ThreadID tid = 0; tid < num_threads; tid++) {
1862727Sktlim@umich.edu            TCStatusReg tidTCStatus =
1872301SN/A                tc->readRegOtherThread(TCStatus + Ctrl_Base_DepTag, tid);
1882301SN/A            TCHaltReg tidTCHalt =
1892301SN/A                tc->readRegOtherThread(TCHalt + Ctrl_Base_DepTag, tid);
1902727Sktlim@umich.edu            TCBindReg tidTCBind =
1912301SN/A                tc->readRegOtherThread(TCBind + Ctrl_Base_DepTag, tid);
1922727Sktlim@umich.edu
1932301SN/A            if (tidTCBind.curVPE == tcBind.curVPE &&
1942301SN/A                tidTCBind.curTC == tcBind.curTC &&
1952301SN/A                tidTCStatus.da == 1 &&
1962727Sktlim@umich.edu                tidTCHalt.h == 0    &&
1972301SN/A                tidTCStatus.a == 1) {
1982301SN/A                ok = 1;
1992301SN/A            }
2002301SN/A        }
2012727Sktlim@umich.edu
2022727Sktlim@umich.edu        if (ok == 1) {
2032727Sktlim@umich.edu            TCStatusReg tcStatus = tc->readMiscRegNoEffect(TCStatus);
2042727Sktlim@umich.edu            tcStatus.a = 0;
2052727Sktlim@umich.edu            tc->setMiscReg(TCStatus, tcStatus);
2062727Sktlim@umich.edu            warn("%i: Deactivating Hardware Thread Context #%i",
2072727Sktlim@umich.edu                    curTick, tc->threadId());
2082727Sktlim@umich.edu        }
2092727Sktlim@umich.edu    } else if (src_reg > 0) {
2102301SN/A        if (src_reg && !yield_mask != 0) {
2112301SN/A            VPEControlReg vpeControl = tc->readMiscReg(VPEControl);
2122301SN/A            vpeControl.excpt = 2;
2132301SN/A            tc->setMiscReg(VPEControl, vpeControl);
2142301SN/A            fault = new ThreadFault();
2152727Sktlim@umich.edu        } else {
2162301SN/A        }
2172326SN/A    } else if (src_reg != -2) {
2182301SN/A        TCStatusReg tcStatus = tc->readMiscRegNoEffect(TCStatus);
2192301SN/A        VPEControlReg vpeControl = tc->readMiscRegNoEffect(VPEControl);
2202301SN/A
2212727Sktlim@umich.edu        if (vpeControl.ysi == 1 && tcStatus.dt == 1 ) {
2222301SN/A            vpeControl.excpt = 4;
2232326SN/A            fault = new ThreadFault();
2242301SN/A        } else {
2252301SN/A        }
2262301SN/A    }
2272727Sktlim@umich.edu
2282301SN/A    return src_reg & yield_mask;
2292326SN/A}
2302301SN/A
2312301SN/A
2322301SN/A// TC will usually be a object derived from ThreadContext
2332727Sktlim@umich.edu// (src/cpu/thread_context.hh)
2342301SN/Atemplate <class TC>
2352326SN/Ainline void
2362301SN/AupdateStatusView(TC *tc)
2372301SN/A{
2382301SN/A    // TCStatus' register view must be the same as
2392727Sktlim@umich.edu    // Status register view for CU, MX, KSU bits
2402301SN/A    TCStatusReg tcStatus = tc->readMiscRegNoEffect(TCStatus);
2412326SN/A    StatusReg status = tc->readMiscRegNoEffect(Status);
2422301SN/A
2432301SN/A    status.cu = tcStatus.tcu;
2442727Sktlim@umich.edu    status.mx = tcStatus.tmx;
2452301SN/A    status.ksu = tcStatus.tksu;
2462326SN/A
2472301SN/A    tc->setMiscRegNoEffect(Status, status);
2482326SN/A}
2492301SN/A
2502301SN/A// TC will usually be a object derived from ThreadContext
2512727Sktlim@umich.edu// (src/cpu/thread_context.hh)
2522301SN/Atemplate <class TC>
2532326SN/Ainline void
2542301SN/AupdateTCStatusView(TC *tc)
2552326SN/A{
2562301SN/A    // TCStatus' register view must be the same as
2572301SN/A    // Status register view for CU, MX, KSU bits
2582727Sktlim@umich.edu    TCStatusReg tcStatus = tc->readMiscRegNoEffect(TCStatus);
2592326SN/A    StatusReg status = tc->readMiscRegNoEffect(Status);
2601062SN/A
2611062SN/A    tcStatus.tcu = status.cu;
2621681SN/A    tcStatus.tmx = status.mx;
2631060SN/A    tcStatus.tksu = status.ksu;
2642292SN/A
2651060SN/A    tc->setMiscRegNoEffect(TCStatus, tcStatus);
2662292SN/A}
2672292SN/A
2682292SN/A} // namespace MipsISA
2692292SN/A
2702292SN/A
2712292SN/A#endif
2722292SN/A