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