mt.hh revision 6383
1/* 2 * Copyright (c) 2007 MIPS Technologies, Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Korey Sewell 29 */ 30 31#ifndef __ARCH_MIPS_MT_HH__ 32#define __ARCH_MIPS_MT_HH__ 33 34/** 35 * @file 36 * 37 * ISA-specific helper functions for multithreaded execution. 38 */ 39 40#include "arch/mips/faults.hh" 41#include "arch/mips/isa_traits.hh" 42#include "arch/mips/mt_constants.hh" 43#include "arch/mips/pra_constants.hh" 44#include "arch/mips/registers.hh" 45#include "base/bitfield.hh" 46#include "base/trace.hh" 47#include "base/misc.hh" 48 49#include <iostream> 50 51namespace MipsISA 52{ 53 54template <class TC> 55inline unsigned 56getVirtProcNum(TC *tc) 57{ 58 TCBindReg tcbind = tc->readMiscRegNoEffect(MISCREG_TC_BIND); 59 return tcbind.curVPE; 60} 61 62template <class TC> 63inline unsigned 64getTargetThread(TC *tc) 65{ 66 VPEControlReg vpeCtrl = tc->readMiscRegNoEffect(MISCREG_VPE_CONTROL); 67 return vpeCtrl.targTC; 68} 69 70template <class TC> 71inline void 72haltThread(TC *tc) 73{ 74 if (tc->status() == TC::Active) { 75 tc->halt(); 76 77 // Save last known PC in TCRestart 78 // @TODO: Needs to check if this is a branch and if so, 79 // take previous instruction 80 tc->setMiscReg(MISCREG_TC_RESTART, tc->readNextPC()); 81 82 warn("%i: Halting thread %i in %s @ PC %x, setting restart PC to %x", 83 curTick, tc->threadId(), tc->getCpuPtr()->name(), 84 tc->readPC(), tc->readNextPC()); 85 } 86} 87 88template <class TC> 89inline void 90restoreThread(TC *tc) 91{ 92 if (tc->status() != TC::Active) { 93 // Restore PC from TCRestart 94 IntReg pc = tc->readMiscRegNoEffect(MISCREG_TC_RESTART); 95 96 // TODO: SET PC WITH AN EVENT INSTEAD OF INSTANTANEOUSLY 97 tc->setPC(pc); 98 tc->setNextPC(pc + 4); 99 tc->setNextNPC(pc + 8); 100 tc->activate(0); 101 102 warn("%i: Restoring thread %i in %s @ PC %x", 103 curTick, tc->threadId(), tc->getCpuPtr()->name(), 104 tc->readPC()); 105 } 106} 107 108template <class TC> 109void 110forkThread(TC *tc, Fault &fault, int Rd_bits, int Rs, int Rt) 111{ 112 MVPConf0Reg mvpConf = tc->readMiscRegNoEffect(MISCREG_MVP_CONF0); 113 int num_threads = mvpConf.ptc + 1; 114 115 int success = 0; 116 for (ThreadID tid = 0; tid < num_threads && success == 0; tid++) { 117 TCBindReg tidTCBind = 118 tc->readRegOtherThread(MISCREG_TC_BIND + Ctrl_Base_DepTag, tid); 119 TCBindReg tcBind = tc->readMiscRegNoEffect(MISCREG_TC_BIND); 120 121 if (tidTCBind.curVPE = tcBind.curVPE) { 122 123 TCStatusReg tidTCStatus = 124 tc->readRegOtherThread(MISCREG_TC_STATUS + 125 Ctrl_Base_DepTag,tid); 126 127 TCHaltReg tidTCHalt = 128 tc->readRegOtherThread(MISCREG_TC_HALT + Ctrl_Base_DepTag,tid); 129 130 if (tidTCStatus.da == 1 && tidTCHalt.h == 0 && 131 tidTCStatus.a == 0 && success == 0) { 132 133 tc->setRegOtherThread(MISCREG_TC_RESTART + 134 Ctrl_Base_DepTag, Rs, tid); 135 tc->setRegOtherThread(Rd_bits, Rt, tid); 136 137 StatusReg status = tc->readMiscReg(MISCREG_STATUS); 138 TCStatusReg tcStatus = tc->readMiscReg(MISCREG_TC_STATUS); 139 140 // Set Run-State to Running 141 tidTCStatus.rnst = 0; 142 // Set Delay-Slot to 0 143 tidTCStatus.tds = 0; 144 // Set Dirty TC to 1 145 tidTCStatus.dt = 1; 146 // Set Activated to 1 147 tidTCStatus.a = 1; 148 // Set status to previous thread's status 149 tidTCStatus.tksu = status.ksu; 150 // Set ASID to previous thread's state 151 tidTCStatus.asid = tcStatus.asid; 152 153 // Write Status Register 154 tc->setRegOtherThread(MISCREG_TC_STATUS + Ctrl_Base_DepTag, 155 tidTCStatus, tid); 156 157 // Mark As Successful Fork 158 success = 1; 159 } 160 } else { 161 std::cerr << "Bad VPEs" << std::endl; 162 } 163 } 164 165 if (success == 0) { 166 VPEControlReg vpeControl = 167 tc->readMiscRegNoEffect(MISCREG_VPE_CONTROL); 168 vpeControl.excpt = 1; 169 tc->setMiscReg(MISCREG_VPE_CONTROL, vpeControl); 170 fault = new ThreadFault(); 171 } 172} 173 174 175template <class TC> 176int 177yieldThread(TC *tc, Fault &fault, int src_reg, uint32_t yield_mask) 178{ 179 if (src_reg == 0) { 180 MVPConf0Reg mvpConf0 = tc->readMiscRegNoEffect(MISCREG_MVP_CONF0); 181 ThreadID num_threads = mvpConf0.ptc + 1; 182 183 int ok = 0; 184 185 // Get Current VPE & TC numbers from calling thread 186 TCBindReg tcBind = tc->readMiscRegNoEffect(MISCREG_TC_BIND); 187 188 for (ThreadID tid = 0; tid < num_threads; tid++) { 189 TCStatusReg tidTCStatus = 190 tc->readRegOtherThread(MISCREG_TC_STATUS + Ctrl_Base_DepTag, 191 tid); 192 TCHaltReg tidTCHalt = 193 tc->readRegOtherThread(MISCREG_TC_HALT + Ctrl_Base_DepTag, 194 tid); 195 TCBindReg tidTCBind = 196 tc->readRegOtherThread(MISCREG_TC_BIND + Ctrl_Base_DepTag, 197 tid); 198 199 if (tidTCBind.curVPE == tcBind.curVPE && 200 tidTCBind.curTC == tcBind.curTC && 201 tidTCStatus.da == 1 && 202 tidTCHalt.h == 0 && 203 tidTCStatus.a == 1) { 204 ok = 1; 205 } 206 } 207 208 if (ok == 1) { 209 TCStatusReg tcStatus = tc->readMiscRegNoEffect(MISCREG_TC_STATUS); 210 tcStatus.a = 0; 211 tc->setMiscReg(MISCREG_TC_STATUS, tcStatus); 212 warn("%i: Deactivating Hardware Thread Context #%i", 213 curTick, tc->threadId()); 214 } 215 } else if (src_reg > 0) { 216 if (src_reg && !yield_mask != 0) { 217 VPEControlReg vpeControl = tc->readMiscReg(MISCREG_VPE_CONTROL); 218 vpeControl.excpt = 2; 219 tc->setMiscReg(MISCREG_VPE_CONTROL, vpeControl); 220 fault = new ThreadFault(); 221 } else { 222 } 223 } else if (src_reg != -2) { 224 TCStatusReg tcStatus = tc->readMiscRegNoEffect(MISCREG_TC_STATUS); 225 VPEControlReg vpeControl = 226 tc->readMiscRegNoEffect(MISCREG_VPE_CONTROL); 227 228 if (vpeControl.ysi == 1 && tcStatus.dt == 1 ) { 229 vpeControl.excpt = 4; 230 fault = new ThreadFault(); 231 } else { 232 } 233 } 234 235 return src_reg & yield_mask; 236} 237 238 239// TC will usually be a object derived from ThreadContext 240// (src/cpu/thread_context.hh) 241template <class TC> 242inline void 243updateStatusView(TC *tc) 244{ 245 // TCStatus' register view must be the same as 246 // Status register view for CU, MX, KSU bits 247 TCStatusReg tcStatus = tc->readMiscRegNoEffect(MISCREG_TC_STATUS); 248 StatusReg status = tc->readMiscRegNoEffect(MISCREG_STATUS); 249 250 status.cu = tcStatus.tcu; 251 status.mx = tcStatus.tmx; 252 status.ksu = tcStatus.tksu; 253 254 tc->setMiscRegNoEffect(MISCREG_STATUS, status); 255} 256 257// TC will usually be a object derived from ThreadContext 258// (src/cpu/thread_context.hh) 259template <class TC> 260inline void 261updateTCStatusView(TC *tc) 262{ 263 // TCStatus' register view must be the same as 264 // Status register view for CU, MX, KSU bits 265 TCStatusReg tcStatus = tc->readMiscRegNoEffect(MISCREG_TC_STATUS); 266 StatusReg status = tc->readMiscRegNoEffect(MISCREG_STATUS); 267 268 tcStatus.tcu = status.cu; 269 tcStatus.tmx = status.mx; 270 tcStatus.tksu = status.ksu; 271 272 tc->setMiscRegNoEffect(MISCREG_TC_STATUS, tcStatus); 273} 274 275} // namespace MipsISA 276 277 278#endif 279