mt.hh revision 6383
14661Sksewell@umich.edu/*
25268Sksewell@umich.edu * Copyright (c) 2007 MIPS Technologies, Inc.
35268Sksewell@umich.edu * All rights reserved.
44661Sksewell@umich.edu *
55268Sksewell@umich.edu * Redistribution and use in source and binary forms, with or without
65268Sksewell@umich.edu * modification, are permitted provided that the following conditions are
75268Sksewell@umich.edu * met: redistributions of source code must retain the above copyright
85268Sksewell@umich.edu * notice, this list of conditions and the following disclaimer;
95268Sksewell@umich.edu * redistributions in binary form must reproduce the above copyright
105268Sksewell@umich.edu * notice, this list of conditions and the following disclaimer in the
115268Sksewell@umich.edu * documentation and/or other materials provided with the distribution;
125268Sksewell@umich.edu * neither the name of the copyright holders nor the names of its
135268Sksewell@umich.edu * contributors may be used to endorse or promote products derived from
145268Sksewell@umich.edu * this software without specific prior written permission.
154661Sksewell@umich.edu *
165268Sksewell@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
175268Sksewell@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
185268Sksewell@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
195268Sksewell@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
205268Sksewell@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
215268Sksewell@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
225268Sksewell@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
235268Sksewell@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
245268Sksewell@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
255268Sksewell@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
265268Sksewell@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
275222Sksewell@umich.edu *
285254Sksewell@umich.edu * Authors: Korey Sewell
294661Sksewell@umich.edu */
304661Sksewell@umich.edu
314661Sksewell@umich.edu#ifndef __ARCH_MIPS_MT_HH__
324661Sksewell@umich.edu#define __ARCH_MIPS_MT_HH__
334661Sksewell@umich.edu
344661Sksewell@umich.edu/**
354661Sksewell@umich.edu * @file
364661Sksewell@umich.edu *
374661Sksewell@umich.edu * ISA-specific helper functions for multithreaded execution.
384661Sksewell@umich.edu */
394661Sksewell@umich.edu
404661Sksewell@umich.edu#include "arch/mips/faults.hh"
416329Sgblack@eecs.umich.edu#include "arch/mips/isa_traits.hh"
424661Sksewell@umich.edu#include "arch/mips/mt_constants.hh"
436376Sgblack@eecs.umich.edu#include "arch/mips/pra_constants.hh"
446329Sgblack@eecs.umich.edu#include "arch/mips/registers.hh"
454661Sksewell@umich.edu#include "base/bitfield.hh"
464661Sksewell@umich.edu#include "base/trace.hh"
474661Sksewell@umich.edu#include "base/misc.hh"
484661Sksewell@umich.edu
494661Sksewell@umich.edu#include <iostream>
504661Sksewell@umich.edu
514661Sksewell@umich.edunamespace MipsISA
524661Sksewell@umich.edu{
534661Sksewell@umich.edu
544661Sksewell@umich.edutemplate <class TC>
554661Sksewell@umich.eduinline unsigned
564661Sksewell@umich.edugetVirtProcNum(TC *tc)
574661Sksewell@umich.edu{
586383Sgblack@eecs.umich.edu    TCBindReg tcbind = tc->readMiscRegNoEffect(MISCREG_TC_BIND);
596376Sgblack@eecs.umich.edu    return tcbind.curVPE;
604661Sksewell@umich.edu}
614661Sksewell@umich.edu
624661Sksewell@umich.edutemplate <class TC>
634661Sksewell@umich.eduinline unsigned
644661Sksewell@umich.edugetTargetThread(TC *tc)
654661Sksewell@umich.edu{
666383Sgblack@eecs.umich.edu    VPEControlReg vpeCtrl = tc->readMiscRegNoEffect(MISCREG_VPE_CONTROL);
676376Sgblack@eecs.umich.edu    return vpeCtrl.targTC;
684661Sksewell@umich.edu}
694661Sksewell@umich.edu
704661Sksewell@umich.edutemplate <class TC>
714661Sksewell@umich.eduinline void
724661Sksewell@umich.eduhaltThread(TC *tc)
734661Sksewell@umich.edu{
744661Sksewell@umich.edu    if (tc->status() == TC::Active) {
754661Sksewell@umich.edu        tc->halt();
764661Sksewell@umich.edu
774661Sksewell@umich.edu        // Save last known PC in TCRestart
786378Sgblack@eecs.umich.edu        // @TODO: Needs to check if this is a branch and if so,
796378Sgblack@eecs.umich.edu        // take previous instruction
806383Sgblack@eecs.umich.edu        tc->setMiscReg(MISCREG_TC_RESTART, tc->readNextPC());
814661Sksewell@umich.edu
826378Sgblack@eecs.umich.edu        warn("%i: Halting thread %i in %s @ PC %x, setting restart PC to %x",
836378Sgblack@eecs.umich.edu                curTick, tc->threadId(), tc->getCpuPtr()->name(),
846378Sgblack@eecs.umich.edu                tc->readPC(), tc->readNextPC());
854661Sksewell@umich.edu    }
864661Sksewell@umich.edu}
874661Sksewell@umich.edu
884661Sksewell@umich.edutemplate <class TC>
894661Sksewell@umich.eduinline void
904661Sksewell@umich.edurestoreThread(TC *tc)
914661Sksewell@umich.edu{
924661Sksewell@umich.edu    if (tc->status() != TC::Active) {
934661Sksewell@umich.edu        // Restore PC from TCRestart
946383Sgblack@eecs.umich.edu        IntReg pc = tc->readMiscRegNoEffect(MISCREG_TC_RESTART);
954661Sksewell@umich.edu
964661Sksewell@umich.edu        // TODO: SET PC WITH AN EVENT INSTEAD OF INSTANTANEOUSLY
974661Sksewell@umich.edu        tc->setPC(pc);
984661Sksewell@umich.edu        tc->setNextPC(pc + 4);
994661Sksewell@umich.edu        tc->setNextNPC(pc + 8);
1004661Sksewell@umich.edu        tc->activate(0);
1014661Sksewell@umich.edu
1026378Sgblack@eecs.umich.edu        warn("%i: Restoring thread %i in %s @ PC %x",
1036378Sgblack@eecs.umich.edu                curTick, tc->threadId(), tc->getCpuPtr()->name(),
1046378Sgblack@eecs.umich.edu                tc->readPC());
1054661Sksewell@umich.edu    }
1064661Sksewell@umich.edu}
1074661Sksewell@umich.edu
1084661Sksewell@umich.edutemplate <class TC>
1094661Sksewell@umich.eduvoid
1104661Sksewell@umich.eduforkThread(TC *tc, Fault &fault, int Rd_bits, int Rs, int Rt)
1114661Sksewell@umich.edu{
1126383Sgblack@eecs.umich.edu    MVPConf0Reg mvpConf = tc->readMiscRegNoEffect(MISCREG_MVP_CONF0);
1136376Sgblack@eecs.umich.edu    int num_threads = mvpConf.ptc + 1;
1144661Sksewell@umich.edu
1154661Sksewell@umich.edu    int success = 0;
1166221Snate@binkert.org    for (ThreadID tid = 0; tid < num_threads && success == 0; tid++) {
1176376Sgblack@eecs.umich.edu        TCBindReg tidTCBind =
1186383Sgblack@eecs.umich.edu            tc->readRegOtherThread(MISCREG_TC_BIND + Ctrl_Base_DepTag, tid);
1196383Sgblack@eecs.umich.edu        TCBindReg tcBind = tc->readMiscRegNoEffect(MISCREG_TC_BIND);
1204661Sksewell@umich.edu
1216376Sgblack@eecs.umich.edu        if (tidTCBind.curVPE = tcBind.curVPE) {
1224661Sksewell@umich.edu
1236376Sgblack@eecs.umich.edu            TCStatusReg tidTCStatus =
1246383Sgblack@eecs.umich.edu                tc->readRegOtherThread(MISCREG_TC_STATUS +
1256383Sgblack@eecs.umich.edu                                       Ctrl_Base_DepTag,tid);
1264661Sksewell@umich.edu
1276376Sgblack@eecs.umich.edu            TCHaltReg tidTCHalt =
1286383Sgblack@eecs.umich.edu                tc->readRegOtherThread(MISCREG_TC_HALT + Ctrl_Base_DepTag,tid);
1294661Sksewell@umich.edu
1306376Sgblack@eecs.umich.edu            if (tidTCStatus.da == 1 && tidTCHalt.h == 0 &&
1316376Sgblack@eecs.umich.edu                tidTCStatus.a == 0 && success == 0) {
1324661Sksewell@umich.edu
1336383Sgblack@eecs.umich.edu                tc->setRegOtherThread(MISCREG_TC_RESTART +
1346383Sgblack@eecs.umich.edu                                      Ctrl_Base_DepTag, Rs, tid);
1354661Sksewell@umich.edu                tc->setRegOtherThread(Rd_bits, Rt, tid);
1364661Sksewell@umich.edu
1376383Sgblack@eecs.umich.edu                StatusReg status = tc->readMiscReg(MISCREG_STATUS);
1386383Sgblack@eecs.umich.edu                TCStatusReg tcStatus = tc->readMiscReg(MISCREG_TC_STATUS);
1394661Sksewell@umich.edu
1404661Sksewell@umich.edu                // Set Run-State to Running
1416376Sgblack@eecs.umich.edu                tidTCStatus.rnst = 0;
1424661Sksewell@umich.edu                // Set Delay-Slot to 0
1436376Sgblack@eecs.umich.edu                tidTCStatus.tds = 0;
1444661Sksewell@umich.edu                // Set Dirty TC to 1
1456376Sgblack@eecs.umich.edu                tidTCStatus.dt = 1;
1464661Sksewell@umich.edu                // Set Activated to 1
1476376Sgblack@eecs.umich.edu                tidTCStatus.a = 1;
1484661Sksewell@umich.edu                // Set status to previous thread's status
1496376Sgblack@eecs.umich.edu                tidTCStatus.tksu = status.ksu;
1504661Sksewell@umich.edu                // Set ASID to previous thread's state
1516376Sgblack@eecs.umich.edu                tidTCStatus.asid = tcStatus.asid;
1524661Sksewell@umich.edu
1534661Sksewell@umich.edu                // Write Status Register
1546383Sgblack@eecs.umich.edu                tc->setRegOtherThread(MISCREG_TC_STATUS + Ctrl_Base_DepTag,
1556376Sgblack@eecs.umich.edu                                      tidTCStatus, tid);
1564661Sksewell@umich.edu
1574661Sksewell@umich.edu                // Mark As Successful Fork
1584661Sksewell@umich.edu                success = 1;
1594661Sksewell@umich.edu            }
1604661Sksewell@umich.edu        } else {
1615991Ssteve.reinhardt@amd.com            std::cerr << "Bad VPEs" << std::endl;
1624661Sksewell@umich.edu        }
1634661Sksewell@umich.edu    }
1644661Sksewell@umich.edu
1654661Sksewell@umich.edu    if (success == 0) {
1666383Sgblack@eecs.umich.edu        VPEControlReg vpeControl =
1676383Sgblack@eecs.umich.edu            tc->readMiscRegNoEffect(MISCREG_VPE_CONTROL);
1686376Sgblack@eecs.umich.edu        vpeControl.excpt = 1;
1696383Sgblack@eecs.umich.edu        tc->setMiscReg(MISCREG_VPE_CONTROL, vpeControl);
1704661Sksewell@umich.edu        fault = new ThreadFault();
1714661Sksewell@umich.edu    }
1724661Sksewell@umich.edu}
1734661Sksewell@umich.edu
1744661Sksewell@umich.edu
1754661Sksewell@umich.edutemplate <class TC>
1764661Sksewell@umich.eduint
1774661Sksewell@umich.eduyieldThread(TC *tc, Fault &fault, int src_reg, uint32_t yield_mask)
1784661Sksewell@umich.edu{
1794661Sksewell@umich.edu    if (src_reg == 0) {
1806383Sgblack@eecs.umich.edu        MVPConf0Reg mvpConf0 = tc->readMiscRegNoEffect(MISCREG_MVP_CONF0);
1816376Sgblack@eecs.umich.edu        ThreadID num_threads = mvpConf0.ptc + 1;
1824661Sksewell@umich.edu
1834661Sksewell@umich.edu        int ok = 0;
1844661Sksewell@umich.edu
1854661Sksewell@umich.edu        // Get Current VPE & TC numbers from calling thread
1866383Sgblack@eecs.umich.edu        TCBindReg tcBind = tc->readMiscRegNoEffect(MISCREG_TC_BIND);
1874661Sksewell@umich.edu
1886221Snate@binkert.org        for (ThreadID tid = 0; tid < num_threads; tid++) {
1896376Sgblack@eecs.umich.edu            TCStatusReg tidTCStatus =
1906383Sgblack@eecs.umich.edu                tc->readRegOtherThread(MISCREG_TC_STATUS + Ctrl_Base_DepTag,
1916383Sgblack@eecs.umich.edu                                       tid);
1926376Sgblack@eecs.umich.edu            TCHaltReg tidTCHalt =
1936383Sgblack@eecs.umich.edu                tc->readRegOtherThread(MISCREG_TC_HALT + Ctrl_Base_DepTag,
1946383Sgblack@eecs.umich.edu                                       tid);
1956376Sgblack@eecs.umich.edu            TCBindReg tidTCBind =
1966383Sgblack@eecs.umich.edu                tc->readRegOtherThread(MISCREG_TC_BIND + Ctrl_Base_DepTag,
1976383Sgblack@eecs.umich.edu                                       tid);
1984661Sksewell@umich.edu
1996376Sgblack@eecs.umich.edu            if (tidTCBind.curVPE == tcBind.curVPE &&
2006376Sgblack@eecs.umich.edu                tidTCBind.curTC == tcBind.curTC &&
2016376Sgblack@eecs.umich.edu                tidTCStatus.da == 1 &&
2026376Sgblack@eecs.umich.edu                tidTCHalt.h == 0    &&
2036376Sgblack@eecs.umich.edu                tidTCStatus.a == 1) {
2044661Sksewell@umich.edu                ok = 1;
2054661Sksewell@umich.edu            }
2064661Sksewell@umich.edu        }
2074661Sksewell@umich.edu
2084661Sksewell@umich.edu        if (ok == 1) {
2096383Sgblack@eecs.umich.edu            TCStatusReg tcStatus = tc->readMiscRegNoEffect(MISCREG_TC_STATUS);
2106376Sgblack@eecs.umich.edu            tcStatus.a = 0;
2116383Sgblack@eecs.umich.edu            tc->setMiscReg(MISCREG_TC_STATUS, tcStatus);
2126376Sgblack@eecs.umich.edu            warn("%i: Deactivating Hardware Thread Context #%i",
2136376Sgblack@eecs.umich.edu                    curTick, tc->threadId());
2144661Sksewell@umich.edu        }
2154661Sksewell@umich.edu    } else if (src_reg > 0) {
2165561Snate@binkert.org        if (src_reg && !yield_mask != 0) {
2176383Sgblack@eecs.umich.edu            VPEControlReg vpeControl = tc->readMiscReg(MISCREG_VPE_CONTROL);
2186376Sgblack@eecs.umich.edu            vpeControl.excpt = 2;
2196383Sgblack@eecs.umich.edu            tc->setMiscReg(MISCREG_VPE_CONTROL, vpeControl);
2204661Sksewell@umich.edu            fault = new ThreadFault();
2214661Sksewell@umich.edu        } else {
2224661Sksewell@umich.edu        }
2234661Sksewell@umich.edu    } else if (src_reg != -2) {
2246383Sgblack@eecs.umich.edu        TCStatusReg tcStatus = tc->readMiscRegNoEffect(MISCREG_TC_STATUS);
2256383Sgblack@eecs.umich.edu        VPEControlReg vpeControl =
2266383Sgblack@eecs.umich.edu            tc->readMiscRegNoEffect(MISCREG_VPE_CONTROL);
2274661Sksewell@umich.edu
2286376Sgblack@eecs.umich.edu        if (vpeControl.ysi == 1 && tcStatus.dt == 1 ) {
2296376Sgblack@eecs.umich.edu            vpeControl.excpt = 4;
2304661Sksewell@umich.edu            fault = new ThreadFault();
2314661Sksewell@umich.edu        } else {
2324661Sksewell@umich.edu        }
2334661Sksewell@umich.edu    }
2344661Sksewell@umich.edu
2354661Sksewell@umich.edu    return src_reg & yield_mask;
2364661Sksewell@umich.edu}
2374661Sksewell@umich.edu
2384661Sksewell@umich.edu
2394661Sksewell@umich.edu// TC will usually be a object derived from ThreadContext
2404661Sksewell@umich.edu// (src/cpu/thread_context.hh)
2414661Sksewell@umich.edutemplate <class TC>
2424661Sksewell@umich.eduinline void
2434661Sksewell@umich.eduupdateStatusView(TC *tc)
2444661Sksewell@umich.edu{
2454661Sksewell@umich.edu    // TCStatus' register view must be the same as
2464661Sksewell@umich.edu    // Status register view for CU, MX, KSU bits
2476383Sgblack@eecs.umich.edu    TCStatusReg tcStatus = tc->readMiscRegNoEffect(MISCREG_TC_STATUS);
2486383Sgblack@eecs.umich.edu    StatusReg status = tc->readMiscRegNoEffect(MISCREG_STATUS);
2494661Sksewell@umich.edu
2506376Sgblack@eecs.umich.edu    status.cu = tcStatus.tcu;
2516376Sgblack@eecs.umich.edu    status.mx = tcStatus.tmx;
2526376Sgblack@eecs.umich.edu    status.ksu = tcStatus.tksu;
2534661Sksewell@umich.edu
2546383Sgblack@eecs.umich.edu    tc->setMiscRegNoEffect(MISCREG_STATUS, status);
2554661Sksewell@umich.edu}
2564661Sksewell@umich.edu
2574661Sksewell@umich.edu// TC will usually be a object derived from ThreadContext
2584661Sksewell@umich.edu// (src/cpu/thread_context.hh)
2594661Sksewell@umich.edutemplate <class TC>
2604661Sksewell@umich.eduinline void
2614661Sksewell@umich.eduupdateTCStatusView(TC *tc)
2624661Sksewell@umich.edu{
2634661Sksewell@umich.edu    // TCStatus' register view must be the same as
2644661Sksewell@umich.edu    // Status register view for CU, MX, KSU bits
2656383Sgblack@eecs.umich.edu    TCStatusReg tcStatus = tc->readMiscRegNoEffect(MISCREG_TC_STATUS);
2666383Sgblack@eecs.umich.edu    StatusReg status = tc->readMiscRegNoEffect(MISCREG_STATUS);
2674661Sksewell@umich.edu
2686376Sgblack@eecs.umich.edu    tcStatus.tcu = status.cu;
2696376Sgblack@eecs.umich.edu    tcStatus.tmx = status.mx;
2706376Sgblack@eecs.umich.edu    tcStatus.tksu = status.ksu;
2714661Sksewell@umich.edu
2726383Sgblack@eecs.umich.edu    tc->setMiscRegNoEffect(MISCREG_TC_STATUS, tcStatus);
2734661Sksewell@umich.edu}
2744661Sksewell@umich.edu
2754661Sksewell@umich.edu} // namespace MipsISA
2764661Sksewell@umich.edu
2774661Sksewell@umich.edu
2784661Sksewell@umich.edu#endif
279