mt.hh revision 6376
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 54 55template <class TC> 56inline unsigned 57getVirtProcNum(TC *tc) 58{ 59 TCBindReg tcbind = tc->readMiscRegNoEffect(TCBind); 60 return tcbind.curVPE; 61} 62 63template <class TC> 64inline unsigned 65getTargetThread(TC *tc) 66{ 67 VPEControlReg vpeCtrl = tc->readMiscRegNoEffect(VPEControl); 68 return vpeCtrl.targTC; 69} 70 71template <class TC> 72inline void 73haltThread(TC *tc) 74{ 75 if (tc->status() == TC::Active) { 76 tc->halt(); 77 78 // Save last known PC in TCRestart 79 // @TODO: Needs to check if this is a branch and if so, take previous instruction 80 tc->setMiscReg(TCRestart, tc->readNextPC()); 81 82 warn("%i: Halting thread %i in %s @ PC %x, setting restart PC to %x", curTick, tc->threadId(), tc->getCpuPtr()->name(), 83 tc->readPC(), tc->readNextPC()); 84 } 85} 86 87template <class TC> 88inline void 89restoreThread(TC *tc) 90{ 91 if (tc->status() != TC::Active) { 92 // Restore PC from TCRestart 93 IntReg pc = tc->readMiscRegNoEffect(TCRestart); 94 95 // TODO: SET PC WITH AN EVENT INSTEAD OF INSTANTANEOUSLY 96 // tc->setPCEvent(pc, pc + 4, pc + 8); 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", curTick, tc->threadId(), tc->getCpuPtr()->name(), 103 tc->readPC()); 104 } 105} 106 107template <class TC> 108void 109forkThread(TC *tc, Fault &fault, int Rd_bits, int Rs, int Rt) 110{ 111 MVPConf0Reg mvpConf = tc->readMiscRegNoEffect(MVPConf0); 112 int num_threads = mvpConf.ptc + 1; 113 114 int success = 0; 115 for (ThreadID tid = 0; tid < num_threads && success == 0; tid++) { 116 TCBindReg tidTCBind = 117 tc->readRegOtherThread(TCBind + Ctrl_Base_DepTag, tid); 118 TCBindReg tcBind = tc->readMiscRegNoEffect(TCBind); 119 120 if (tidTCBind.curVPE = tcBind.curVPE) { 121 122 TCStatusReg tidTCStatus = 123 tc->readRegOtherThread(TCStatus + Ctrl_Base_DepTag,tid); 124 125 TCHaltReg tidTCHalt = 126 tc->readRegOtherThread(TCHalt + Ctrl_Base_DepTag,tid); 127 128 if (tidTCStatus.da == 1 && tidTCHalt.h == 0 && 129 tidTCStatus.a == 0 && success == 0) { 130 131 tc->setRegOtherThread(TCRestart + Ctrl_Base_DepTag, Rs, tid); 132 tc->setRegOtherThread(Rd_bits, Rt, tid); 133 134 StatusReg status = tc->readMiscReg(Status); 135 TCStatusReg tcStatus = tc->readMiscReg(TCStatus); 136 137 // Set Run-State to Running 138 tidTCStatus.rnst = 0; 139 // Set Delay-Slot to 0 140 tidTCStatus.tds = 0; 141 // Set Dirty TC to 1 142 tidTCStatus.dt = 1; 143 // Set Activated to 1 144 tidTCStatus.a = 1; 145 // Set status to previous thread's status 146 tidTCStatus.tksu = status.ksu; 147 // Set ASID to previous thread's state 148 tidTCStatus.asid = tcStatus.asid; 149 150 // Write Status Register 151 tc->setRegOtherThread(TCStatus + Ctrl_Base_DepTag, 152 tidTCStatus, tid); 153 154 // Mark As Successful Fork 155 success = 1; 156 } 157 } else { 158 std::cerr << "Bad VPEs" << std::endl; 159 } 160 } 161 162 if (success == 0) { 163 VPEControlReg vpeControl = tc->readMiscRegNoEffect(VPEControl); 164 vpeControl.excpt = 1; 165 tc->setMiscReg(VPEControl, vpeControl); 166 fault = new ThreadFault(); 167 } 168} 169 170 171template <class TC> 172int 173yieldThread(TC *tc, Fault &fault, int src_reg, uint32_t yield_mask) 174{ 175 if (src_reg == 0) { 176 MVPConf0Reg mvpConf0 = tc->readMiscRegNoEffect(MVPConf0); 177 ThreadID num_threads = mvpConf0.ptc + 1; 178 179 int ok = 0; 180 181 // Get Current VPE & TC numbers from calling thread 182 TCBindReg tcBind = tc->readMiscRegNoEffect(TCBind); 183 184 for (ThreadID tid = 0; tid < num_threads; tid++) { 185 TCStatusReg tidTCStatus = 186 tc->readRegOtherThread(TCStatus + Ctrl_Base_DepTag, tid); 187 TCHaltReg tidTCHalt = 188 tc->readRegOtherThread(TCHalt + Ctrl_Base_DepTag, tid); 189 TCBindReg tidTCBind = 190 tc->readRegOtherThread(TCBind + Ctrl_Base_DepTag, tid); 191 192 if (tidTCBind.curVPE == tcBind.curVPE && 193 tidTCBind.curTC == tcBind.curTC && 194 tidTCStatus.da == 1 && 195 tidTCHalt.h == 0 && 196 tidTCStatus.a == 1) { 197 ok = 1; 198 } 199 } 200 201 if (ok == 1) { 202 TCStatusReg tcStatus = tc->readMiscRegNoEffect(TCStatus); 203 tcStatus.a = 0; 204 tc->setMiscReg(TCStatus, tcStatus); 205 warn("%i: Deactivating Hardware Thread Context #%i", 206 curTick, tc->threadId()); 207 } 208 } else if (src_reg > 0) { 209 if (src_reg && !yield_mask != 0) { 210 VPEControlReg vpeControl = tc->readMiscReg(VPEControl); 211 vpeControl.excpt = 2; 212 tc->setMiscReg(VPEControl, vpeControl); 213 fault = new ThreadFault(); 214 } else { 215 } 216 } else if (src_reg != -2) { 217 TCStatusReg tcStatus = tc->readMiscRegNoEffect(TCStatus); 218 VPEControlReg vpeControl = tc->readMiscRegNoEffect(VPEControl); 219 220 if (vpeControl.ysi == 1 && tcStatus.dt == 1 ) { 221 vpeControl.excpt = 4; 222 fault = new ThreadFault(); 223 } else { 224 } 225 } 226 227 return src_reg & yield_mask; 228} 229 230 231// TC will usually be a object derived from ThreadContext 232// (src/cpu/thread_context.hh) 233template <class TC> 234inline void 235updateStatusView(TC *tc) 236{ 237 // TCStatus' register view must be the same as 238 // Status register view for CU, MX, KSU bits 239 TCStatusReg tcStatus = tc->readMiscRegNoEffect(TCStatus); 240 StatusReg status = tc->readMiscRegNoEffect(Status); 241 242 status.cu = tcStatus.tcu; 243 status.mx = tcStatus.tmx; 244 status.ksu = tcStatus.tksu; 245 246 tc->setMiscRegNoEffect(Status, status); 247} 248 249// TC will usually be a object derived from ThreadContext 250// (src/cpu/thread_context.hh) 251template <class TC> 252inline void 253updateTCStatusView(TC *tc) 254{ 255 // TCStatus' register view must be the same as 256 // Status register view for CU, MX, KSU bits 257 TCStatusReg tcStatus = tc->readMiscRegNoEffect(TCStatus); 258 StatusReg status = tc->readMiscRegNoEffect(Status); 259 260 tcStatus.tcu = status.cu; 261 tcStatus.tmx = status.mx; 262 tcStatus.tksu = status.ksu; 263 264 tc->setMiscRegNoEffect(TCStatus, tcStatus); 265} 266 267} // namespace MipsISA 268 269 270#endif 271