mt.hh revision 5254
14661Sksewell@umich.edu/*
25254Sksewell@umich.edu * Copyright N) 2007 MIPS Technologies, Inc.  All Rights Reserved
34661Sksewell@umich.edu *
45222Sksewell@umich.edu * This software is part of the M5 simulator.
54661Sksewell@umich.edu *
65222Sksewell@umich.edu * THIS IS A LEGAL AGREEMENT.  BY DOWNLOADING, USING, COPYING, CREATING
75222Sksewell@umich.edu * DERIVATIVE WORKS, AND/OR DISTRIBUTING THIS SOFTWARE YOU ARE AGREEING
85222Sksewell@umich.edu * TO THESE TERMS AND CONDITIONS.
94661Sksewell@umich.edu *
105222Sksewell@umich.edu * Permission is granted to use, copy, create derivative works and
115222Sksewell@umich.edu * distribute this software and such derivative works for any purpose,
125222Sksewell@umich.edu * so long as (1) the copyright notice above, this grant of permission,
135222Sksewell@umich.edu * and the disclaimer below appear in all copies and derivative works
145222Sksewell@umich.edu * made, (2) the copyright notice above is augmented as appropriate to
155222Sksewell@umich.edu * reflect the addition of any new copyrightable work in a derivative
165254Sksewell@umich.edu * work (e.g., Copyright N) <Publication Year> Copyright Owner), and (3)
175254Sksewell@umich.edu * the name of MIPS Technologies, Inc. ($(B!H(BMIPS$(B!I(B) is not used in any
185222Sksewell@umich.edu * advertising or publicity pertaining to the use or distribution of
195222Sksewell@umich.edu * this software without specific, written prior authorization.
205222Sksewell@umich.edu *
215254Sksewell@umich.edu * THIS SOFTWARE IS PROVIDED $(B!H(BAS IS.$(B!I(B  MIPS MAKES NO WARRANTIES AND
225222Sksewell@umich.edu * DISCLAIMS ALL WARRANTIES, WHETHER EXPRESS, STATUTORY, IMPLIED OR
235222Sksewell@umich.edu * OTHERWISE, INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
245222Sksewell@umich.edu * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
255222Sksewell@umich.edu * NON-INFRINGEMENT OF THIRD PARTY RIGHTS, REGARDING THIS SOFTWARE.
265222Sksewell@umich.edu * IN NO EVENT SHALL MIPS BE LIABLE FOR ANY DAMAGES, INCLUDING DIRECT,
275222Sksewell@umich.edu * INDIRECT, INCIDENTAL, CONSEQUENTIAL, SPECIAL, OR PUNITIVE DAMAGES OF
285222Sksewell@umich.edu * ANY KIND OR NATURE, ARISING OUT OF OR IN CONNECTION WITH THIS AGREEMENT,
295222Sksewell@umich.edu * THIS SOFTWARE AND/OR THE USE OF THIS SOFTWARE, WHETHER SUCH LIABILITY
305222Sksewell@umich.edu * IS ASSERTED ON THE BASIS OF CONTRACT, TORT (INCLUDING NEGLIGENCE OR
315222Sksewell@umich.edu * STRICT LIABILITY), OR OTHERWISE, EVEN IF MIPS HAS BEEN WARNED OF THE
325222Sksewell@umich.edu * POSSIBILITY OF ANY SUCH LOSS OR DAMAGE IN ADVANCE.
335222Sksewell@umich.edu *
345254Sksewell@umich.edu * Authors: Korey Sewell
355254Sksewell@umich.edu *          Jaidev Patwardhan
365222Sksewell@umich.edu *
374661Sksewell@umich.edu */
384661Sksewell@umich.edu
394661Sksewell@umich.edu#ifndef __ARCH_MIPS_MT_HH__
404661Sksewell@umich.edu#define __ARCH_MIPS_MT_HH__
414661Sksewell@umich.edu
424661Sksewell@umich.edu/**
434661Sksewell@umich.edu * @file
444661Sksewell@umich.edu *
454661Sksewell@umich.edu * ISA-specific helper functions for multithreaded execution.
464661Sksewell@umich.edu */
474661Sksewell@umich.edu
484661Sksewell@umich.edu#include "arch/isa_traits.hh"
494661Sksewell@umich.edu#include "arch/mips/faults.hh"
504661Sksewell@umich.edu#include "arch/mips/mt_constants.hh"
514661Sksewell@umich.edu#include "base/bitfield.hh"
524661Sksewell@umich.edu#include "base/trace.hh"
534661Sksewell@umich.edu#include "base/misc.hh"
544661Sksewell@umich.edu
554661Sksewell@umich.edu#include <iostream>
564661Sksewell@umich.eduusing namespace std;
574661Sksewell@umich.edu
584661Sksewell@umich.edunamespace MipsISA
594661Sksewell@umich.edu{
604661Sksewell@umich.edu
614661Sksewell@umich.edu
624661Sksewell@umich.edutemplate <class TC>
634661Sksewell@umich.eduinline unsigned
644661Sksewell@umich.edugetVirtProcNum(TC *tc)
654661Sksewell@umich.edu{
664661Sksewell@umich.edu    MiscReg tcbind = tc->readMiscRegNoEffect(TCBind);
674661Sksewell@umich.edu    return bits(tcbind, TCB_CUR_VPE_HI, TCB_CUR_VPE_LO);
684661Sksewell@umich.edu}
694661Sksewell@umich.edu
704661Sksewell@umich.edutemplate <class TC>
714661Sksewell@umich.eduinline unsigned
724661Sksewell@umich.edugetTargetThread(TC *tc)
734661Sksewell@umich.edu{
744661Sksewell@umich.edu    MiscReg vpec_ctrl = tc->readMiscRegNoEffect(VPEControl);
754661Sksewell@umich.edu    return bits(vpec_ctrl, VPEC_TARG_TC_HI, VPEC_TARG_TC_LO);
764661Sksewell@umich.edu}
774661Sksewell@umich.edu
784661Sksewell@umich.edutemplate <class TC>
794661Sksewell@umich.eduinline void
804661Sksewell@umich.eduhaltThread(TC *tc)
814661Sksewell@umich.edu{
824661Sksewell@umich.edu    if (tc->status() == TC::Active) {
834661Sksewell@umich.edu        tc->halt();
844661Sksewell@umich.edu
854661Sksewell@umich.edu        // Save last known PC in TCRestart
864661Sksewell@umich.edu        // @TODO: Needs to check if this is a branch and if so, take previous instruction
874661Sksewell@umich.edu        tc->setMiscReg(TCRestart, tc->readNextPC());
884661Sksewell@umich.edu
894661Sksewell@umich.edu        warn("%i: Halting thread %i in %s @ PC %x, setting restart PC to %x", curTick, tc->getThreadNum(), tc->getCpuPtr()->name(),
904661Sksewell@umich.edu             tc->readPC(), tc->readNextPC());
914661Sksewell@umich.edu    }
924661Sksewell@umich.edu}
934661Sksewell@umich.edu
944661Sksewell@umich.edutemplate <class TC>
954661Sksewell@umich.eduinline void
964661Sksewell@umich.edurestoreThread(TC *tc)
974661Sksewell@umich.edu{
984661Sksewell@umich.edu    if (tc->status() != TC::Active) {
994661Sksewell@umich.edu        // Restore PC from TCRestart
1004661Sksewell@umich.edu        IntReg pc = tc->readMiscRegNoEffect(TCRestart);
1014661Sksewell@umich.edu
1024661Sksewell@umich.edu        // TODO: SET PC WITH AN EVENT INSTEAD OF INSTANTANEOUSLY
1034661Sksewell@umich.edu        // tc->setPCEvent(pc, pc + 4, pc + 8);
1044661Sksewell@umich.edu        tc->setPC(pc);
1054661Sksewell@umich.edu        tc->setNextPC(pc + 4);
1064661Sksewell@umich.edu        tc->setNextNPC(pc + 8);
1074661Sksewell@umich.edu        tc->activate(0);
1084661Sksewell@umich.edu
1094661Sksewell@umich.edu        warn("%i: Restoring thread %i in %s @ PC %x", curTick, tc->getThreadNum(), tc->getCpuPtr()->name(),
1104661Sksewell@umich.edu             tc->readPC());
1114661Sksewell@umich.edu    }
1124661Sksewell@umich.edu}
1134661Sksewell@umich.edu
1144661Sksewell@umich.edutemplate <class TC>
1154661Sksewell@umich.eduvoid
1164661Sksewell@umich.eduforkThread(TC *tc, Fault &fault, int Rd_bits, int Rs, int Rt)
1174661Sksewell@umich.edu{
1184661Sksewell@umich.edu    int num_threads = bits(tc->readMiscRegNoEffect(MVPConf0), MVPC0_PTC_HI, MVPC0_PTC_LO) + 1;
1194661Sksewell@umich.edu
1204661Sksewell@umich.edu    int success = 0;
1214661Sksewell@umich.edu    for (int tid = 0; tid < num_threads && success == 0; tid++) {
1224661Sksewell@umich.edu        unsigned tid_TCBind = tc->readRegOtherThread(MipsISA::TCBind + Ctrl_Base_DepTag,
1234661Sksewell@umich.edu                                                     tid);
1244661Sksewell@umich.edu        unsigned tc_bind = tc->readMiscRegNoEffect(MipsISA::TCBind);
1254661Sksewell@umich.edu
1264661Sksewell@umich.edu        if (bits(tid_TCBind, TCB_CUR_VPE_HI, TCB_CUR_VPE_LO) ==
1274661Sksewell@umich.edu            bits(tc_bind, TCB_CUR_VPE_HI, TCB_CUR_VPE_LO)) {
1284661Sksewell@umich.edu
1294661Sksewell@umich.edu            unsigned tid_TCStatus = tc->readRegOtherThread(MipsISA::TCStatus + Ctrl_Base_DepTag,
1304661Sksewell@umich.edu                                                           tid);
1314661Sksewell@umich.edu
1324661Sksewell@umich.edu            unsigned tid_TCHalt = tc->readRegOtherThread(MipsISA::TCHalt + Ctrl_Base_DepTag,
1334661Sksewell@umich.edu                                                         tid);
1344661Sksewell@umich.edu
1354661Sksewell@umich.edu            if (bits(tid_TCStatus, TCS_DA) == 1 &&
1364661Sksewell@umich.edu                bits(tid_TCHalt, TCH_H) == 0    &&
1374661Sksewell@umich.edu                bits(tid_TCStatus, TCS_A) == 0  &&
1384661Sksewell@umich.edu                success == 0) {
1394661Sksewell@umich.edu
1404661Sksewell@umich.edu                tc->setRegOtherThread(MipsISA::TCRestart + Ctrl_Base_DepTag, Rs, tid);
1414661Sksewell@umich.edu
1424661Sksewell@umich.edu                tc->setRegOtherThread(Rd_bits, Rt, tid);
1434661Sksewell@umich.edu
1444661Sksewell@umich.edu                unsigned status_ksu = bits(tc->readMiscReg(MipsISA::Status),
1454661Sksewell@umich.edu                                           S_KSU_HI, S_KSU_LO);
1464661Sksewell@umich.edu                unsigned tc_status_asid = bits(tc->readMiscReg(MipsISA::TCStatus),
1474661Sksewell@umich.edu                                          TCS_ASID_HI, TCS_ASID_LO);
1484661Sksewell@umich.edu
1494661Sksewell@umich.edu                // Set Run-State to Running
1504661Sksewell@umich.edu                replaceBits(tid_TCStatus, TCSTATUS_RNST_HI, TCSTATUS_RNST_LO, 0);
1514661Sksewell@umich.edu
1524661Sksewell@umich.edu                // Set Delay-Slot to 0
1534661Sksewell@umich.edu                replaceBits(tid_TCStatus, TCSTATUS_TDS, 0);
1544661Sksewell@umich.edu
1554661Sksewell@umich.edu                // Set Dirty TC to 1
1564661Sksewell@umich.edu                replaceBits(tid_TCStatus, TCSTATUS_DT, 1);
1574661Sksewell@umich.edu
1584661Sksewell@umich.edu                // Set Activated to 1
1594661Sksewell@umich.edu                replaceBits(tid_TCStatus, TCSTATUS_A, 1);
1604661Sksewell@umich.edu
1614661Sksewell@umich.edu                // Set status to previous thread's status
1624661Sksewell@umich.edu                replaceBits(tid_TCStatus, TCSTATUS_TKSU_HI, TCSTATUS_TKSU_LO, status_ksu);
1634661Sksewell@umich.edu
1644661Sksewell@umich.edu                // Set ASID to previous thread's state
1654661Sksewell@umich.edu                replaceBits(tid_TCStatus, TCSTATUS_ASID_HI, TCSTATUS_ASID_LO, tc_status_asid);
1664661Sksewell@umich.edu
1674661Sksewell@umich.edu                // Write Status Register
1684661Sksewell@umich.edu                tc->setRegOtherThread(MipsISA::TCStatus + Ctrl_Base_DepTag,
1694661Sksewell@umich.edu                                      tid_TCStatus, tid);
1704661Sksewell@umich.edu
1714661Sksewell@umich.edu                // Mark As Successful Fork
1724661Sksewell@umich.edu                success = 1;
1734661Sksewell@umich.edu            }
1744661Sksewell@umich.edu        } else {
1754661Sksewell@umich.edu            std::cerr << "Bad VPEs" << endl;
1764661Sksewell@umich.edu        }
1774661Sksewell@umich.edu    }
1784661Sksewell@umich.edu
1794661Sksewell@umich.edu    if (success == 0) {
1804661Sksewell@umich.edu        unsigned vpe_control = tc->readMiscRegNoEffect(MipsISA::VPEControl);
1814661Sksewell@umich.edu        tc->setMiscReg(VPEControl, insertBits(vpe_control, VPEC_EXCPT_HI, VPEC_EXCPT_LO, 1));
1824661Sksewell@umich.edu        fault = new ThreadFault();
1834661Sksewell@umich.edu    }
1844661Sksewell@umich.edu}
1854661Sksewell@umich.edu
1864661Sksewell@umich.edu
1874661Sksewell@umich.edutemplate <class TC>
1884661Sksewell@umich.eduint
1894661Sksewell@umich.eduyieldThread(TC *tc, Fault &fault, int src_reg, uint32_t yield_mask)
1904661Sksewell@umich.edu{
1914661Sksewell@umich.edu    if (src_reg == 0) {
1924661Sksewell@umich.edu        unsigned mvpconf0 = tc->readMiscRegNoEffect(MVPConf0);
1934661Sksewell@umich.edu        int num_threads = bits(mvpconf0, MVPC0_PTC_HI, MVPC0_PTC_LO) + 1;
1944661Sksewell@umich.edu
1954661Sksewell@umich.edu        int ok = 0;
1964661Sksewell@umich.edu
1974661Sksewell@umich.edu        // Get Current VPE & TC numbers from calling thread
1984661Sksewell@umich.edu        unsigned tcbind = tc->readMiscRegNoEffect(TCBind);
1994661Sksewell@umich.edu        unsigned cur_vpe = bits(tcbind, TCB_CUR_VPE_HI, TCB_CUR_VPE_LO);
2004661Sksewell@umich.edu        unsigned cur_tc = bits(tcbind, TCB_CUR_TC_HI, TCB_CUR_TC_LO);
2014661Sksewell@umich.edu
2024661Sksewell@umich.edu        for (int tid = 0; tid < num_threads; tid++) {
2034661Sksewell@umich.edu            unsigned tid_TCStatus = tc->readRegOtherThread(MipsISA::TCStatus + Ctrl_Base_DepTag,
2044661Sksewell@umich.edu                                                           tid);
2054661Sksewell@umich.edu            unsigned tid_TCHalt = tc->readRegOtherThread(MipsISA::TCHalt + Ctrl_Base_DepTag,
2064661Sksewell@umich.edu                                                         tid);
2074661Sksewell@umich.edu            unsigned tid_TCBind = tc->readRegOtherThread(MipsISA::TCBind + Ctrl_Base_DepTag,
2084661Sksewell@umich.edu                                                         tid);
2094661Sksewell@umich.edu
2104661Sksewell@umich.edu            unsigned tid_vpe = bits(tid_TCBind, TCB_CUR_VPE_HI, TCB_CUR_VPE_LO);
2114661Sksewell@umich.edu            unsigned tid_tc = bits(tid_TCBind, TCB_CUR_TC_HI, TCB_CUR_TC_LO);
2124661Sksewell@umich.edu            unsigned tid_tcstatus_da = bits(tid_TCStatus, TCS_DA);
2134661Sksewell@umich.edu            unsigned tid_tcstatus_a = bits(tid_TCStatus, TCS_A);
2144661Sksewell@umich.edu            unsigned tid_tchalt_h = bits(tid_TCHalt, TCH_H);
2154661Sksewell@umich.edu
2164661Sksewell@umich.edu            if (tid_vpe == cur_vpe &&
2174661Sksewell@umich.edu                tid_tc == cur_tc &&
2184661Sksewell@umich.edu                tid_tcstatus_da == 1 &&
2194661Sksewell@umich.edu                tid_tchalt_h == 0    &&
2204661Sksewell@umich.edu                tid_tcstatus_a == 1) {
2214661Sksewell@umich.edu                ok = 1;
2224661Sksewell@umich.edu            }
2234661Sksewell@umich.edu        }
2244661Sksewell@umich.edu
2254661Sksewell@umich.edu        if (ok == 1) {
2264661Sksewell@umich.edu            unsigned tcstatus = tc->readMiscRegNoEffect(TCStatus);
2274661Sksewell@umich.edu            tc->setMiscReg(TCStatus, insertBits(tcstatus, TCS_A, TCS_A, 0));
2284661Sksewell@umich.edu            warn("%i: Deactivating Hardware Thread Context #%i", curTick, tc->getThreadNum());
2294661Sksewell@umich.edu        }
2304661Sksewell@umich.edu    } else if (src_reg > 0) {
2314661Sksewell@umich.edu        if (src_reg & !yield_mask != 0) {
2324661Sksewell@umich.edu            unsigned vpe_control = tc->readMiscReg(VPEControl);
2334661Sksewell@umich.edu            tc->setMiscReg(VPEControl, insertBits(vpe_control, VPEC_EXCPT_HI, VPEC_EXCPT_LO, 2));
2344661Sksewell@umich.edu            fault = new ThreadFault();
2354661Sksewell@umich.edu        } else {
2364661Sksewell@umich.edu            //tc->setThreadRescheduleCondition(src_reg & yield_mask);
2374661Sksewell@umich.edu        }
2384661Sksewell@umich.edu    } else if (src_reg != -2) {
2394661Sksewell@umich.edu        unsigned tcstatus = tc->readMiscRegNoEffect(TCStatus);
2404661Sksewell@umich.edu        unsigned vpe_control = tc->readMiscRegNoEffect(VPEControl);
2414661Sksewell@umich.edu        unsigned tcstatus_dt = bits(tcstatus, TCS_DT);
2424661Sksewell@umich.edu        unsigned vpe_control_ysi = bits(vpe_control, VPEC_YSI);
2434661Sksewell@umich.edu
2444661Sksewell@umich.edu        if (vpe_control_ysi == 1 && tcstatus_dt == 1 ) {
2454661Sksewell@umich.edu            tc->setMiscReg(VPEControl, insertBits(vpe_control, VPEC_EXCPT_HI, VPEC_EXCPT_LO, 4));
2464661Sksewell@umich.edu            fault = new ThreadFault();
2474661Sksewell@umich.edu        } else {
2484661Sksewell@umich.edu            //tc->ScheduleOtherThreads();
2494661Sksewell@umich.edu            //std::cerr << "T" << tc->getThreadNum() << "YIELD: Schedule Other Threads.\n" << std::endl;
2504661Sksewell@umich.edu            //tc->suspend();
2514661Sksewell@umich.edu            // Save last known PC in TCRestart
2524661Sksewell@umich.edu            // @TODO: Needs to check if this is a branch and if so, take previous instruction
2534661Sksewell@umich.edu            //tc->setMiscRegWithEffect(TCRestart, tc->readNextPC());
2544661Sksewell@umich.edu        }
2554661Sksewell@umich.edu    }
2564661Sksewell@umich.edu
2574661Sksewell@umich.edu    return src_reg & yield_mask;
2584661Sksewell@umich.edu}
2594661Sksewell@umich.edu
2604661Sksewell@umich.edu
2614661Sksewell@umich.edu// TC will usually be a object derived from ThreadContext
2624661Sksewell@umich.edu// (src/cpu/thread_context.hh)
2634661Sksewell@umich.edutemplate <class TC>
2644661Sksewell@umich.eduinline void
2654661Sksewell@umich.eduupdateStatusView(TC *tc)
2664661Sksewell@umich.edu{
2674661Sksewell@umich.edu    // TCStatus' register view must be the same as
2684661Sksewell@umich.edu    // Status register view for CU, MX, KSU bits
2694661Sksewell@umich.edu    MiscReg tc_status = tc->readMiscRegNoEffect(TCStatus);
2704661Sksewell@umich.edu    MiscReg status = tc->readMiscRegNoEffect(Status);
2714661Sksewell@umich.edu
2724661Sksewell@umich.edu    unsigned cu_bits = bits(tc_status, TCS_TCU_HI, TCS_TCU_LO);
2734661Sksewell@umich.edu    replaceBits(status, S_CU_HI, S_CU_LO, cu_bits);
2744661Sksewell@umich.edu
2754661Sksewell@umich.edu    unsigned mx_bits = bits(tc_status, TCS_TMX);
2764661Sksewell@umich.edu    replaceBits(status, S_MX, S_MX, mx_bits);
2774661Sksewell@umich.edu
2784661Sksewell@umich.edu    unsigned ksu_bits = bits(tc_status, TCS_TKSU_HI, TCS_TKSU_LO);
2794661Sksewell@umich.edu    replaceBits(status, S_KSU_HI, S_KSU_LO, ksu_bits);
2804661Sksewell@umich.edu
2814661Sksewell@umich.edu    tc->setMiscRegNoEffect(Status, status);
2824661Sksewell@umich.edu}
2834661Sksewell@umich.edu
2844661Sksewell@umich.edu// TC will usually be a object derived from ThreadContext
2854661Sksewell@umich.edu// (src/cpu/thread_context.hh)
2864661Sksewell@umich.edutemplate <class TC>
2874661Sksewell@umich.eduinline void
2884661Sksewell@umich.eduupdateTCStatusView(TC *tc)
2894661Sksewell@umich.edu{
2904661Sksewell@umich.edu    // TCStatus' register view must be the same as
2914661Sksewell@umich.edu    // Status register view for CU, MX, KSU bits
2924661Sksewell@umich.edu    MiscReg tc_status = tc->readMiscRegNoEffect(TCStatus);
2934661Sksewell@umich.edu    MiscReg status = tc->readMiscRegNoEffect(Status);
2944661Sksewell@umich.edu
2954661Sksewell@umich.edu    unsigned cu_bits = bits(status, S_CU_HI, S_CU_LO);
2964661Sksewell@umich.edu    replaceBits(tc_status, TCS_TCU_HI, TCS_TCU_LO, cu_bits);
2974661Sksewell@umich.edu
2984661Sksewell@umich.edu    unsigned mx_bits = bits(status, S_MX, S_MX);
2994661Sksewell@umich.edu    replaceBits(tc_status, TCS_TMX, mx_bits);
3004661Sksewell@umich.edu
3014661Sksewell@umich.edu    unsigned ksu_bits = bits(status, S_KSU_HI, S_KSU_LO);
3024661Sksewell@umich.edu    replaceBits(tc_status, TCS_TKSU_HI, TCS_TKSU_LO, ksu_bits);
3034661Sksewell@umich.edu
3044661Sksewell@umich.edu    tc->setMiscRegNoEffect(TCStatus, tc_status);
3054661Sksewell@umich.edu}
3064661Sksewell@umich.edu
3074661Sksewell@umich.edu} // namespace MipsISA
3084661Sksewell@umich.edu
3094661Sksewell@umich.edu
3104661Sksewell@umich.edu#endif
311