mt.hh revision 5254
1/* 2 * Copyright N) 2007 MIPS Technologies, Inc. All Rights Reserved 3 * 4 * This software is part of the M5 simulator. 5 * 6 * THIS IS A LEGAL AGREEMENT. BY DOWNLOADING, USING, COPYING, CREATING 7 * DERIVATIVE WORKS, AND/OR DISTRIBUTING THIS SOFTWARE YOU ARE AGREEING 8 * TO THESE TERMS AND CONDITIONS. 9 * 10 * Permission is granted to use, copy, create derivative works and 11 * distribute this software and such derivative works for any purpose, 12 * so long as (1) the copyright notice above, this grant of permission, 13 * and the disclaimer below appear in all copies and derivative works 14 * made, (2) the copyright notice above is augmented as appropriate to 15 * reflect the addition of any new copyrightable work in a derivative 16 * work (e.g., Copyright N) <Publication Year> Copyright Owner), and (3) 17 * the name of MIPS Technologies, Inc. ($(B!H(BMIPS$(B!I(B) is not used in any 18 * advertising or publicity pertaining to the use or distribution of 19 * this software without specific, written prior authorization. 20 * 21 * THIS SOFTWARE IS PROVIDED $(B!H(BAS IS.$(B!I(B MIPS MAKES NO WARRANTIES AND 22 * DISCLAIMS ALL WARRANTIES, WHETHER EXPRESS, STATUTORY, IMPLIED OR 23 * OTHERWISE, INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 24 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND 25 * NON-INFRINGEMENT OF THIRD PARTY RIGHTS, REGARDING THIS SOFTWARE. 26 * IN NO EVENT SHALL MIPS BE LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, 27 * INDIRECT, INCIDENTAL, CONSEQUENTIAL, SPECIAL, OR PUNITIVE DAMAGES OF 28 * ANY KIND OR NATURE, ARISING OUT OF OR IN CONNECTION WITH THIS AGREEMENT, 29 * THIS SOFTWARE AND/OR THE USE OF THIS SOFTWARE, WHETHER SUCH LIABILITY 30 * IS ASSERTED ON THE BASIS OF CONTRACT, TORT (INCLUDING NEGLIGENCE OR 31 * STRICT LIABILITY), OR OTHERWISE, EVEN IF MIPS HAS BEEN WARNED OF THE 32 * POSSIBILITY OF ANY SUCH LOSS OR DAMAGE IN ADVANCE. 33 * 34 * Authors: Korey Sewell 35 * Jaidev Patwardhan 36 * 37 */ 38 39#ifndef __ARCH_MIPS_MT_HH__ 40#define __ARCH_MIPS_MT_HH__ 41 42/** 43 * @file 44 * 45 * ISA-specific helper functions for multithreaded execution. 46 */ 47 48#include "arch/isa_traits.hh" 49#include "arch/mips/faults.hh" 50#include "arch/mips/mt_constants.hh" 51#include "base/bitfield.hh" 52#include "base/trace.hh" 53#include "base/misc.hh" 54 55#include <iostream> 56using namespace std; 57 58namespace MipsISA 59{ 60 61 62template <class TC> 63inline unsigned 64getVirtProcNum(TC *tc) 65{ 66 MiscReg tcbind = tc->readMiscRegNoEffect(TCBind); 67 return bits(tcbind, TCB_CUR_VPE_HI, TCB_CUR_VPE_LO); 68} 69 70template <class TC> 71inline unsigned 72getTargetThread(TC *tc) 73{ 74 MiscReg vpec_ctrl = tc->readMiscRegNoEffect(VPEControl); 75 return bits(vpec_ctrl, VPEC_TARG_TC_HI, VPEC_TARG_TC_LO); 76} 77 78template <class TC> 79inline void 80haltThread(TC *tc) 81{ 82 if (tc->status() == TC::Active) { 83 tc->halt(); 84 85 // Save last known PC in TCRestart 86 // @TODO: Needs to check if this is a branch and if so, take previous instruction 87 tc->setMiscReg(TCRestart, tc->readNextPC()); 88 89 warn("%i: Halting thread %i in %s @ PC %x, setting restart PC to %x", curTick, tc->getThreadNum(), tc->getCpuPtr()->name(), 90 tc->readPC(), tc->readNextPC()); 91 } 92} 93 94template <class TC> 95inline void 96restoreThread(TC *tc) 97{ 98 if (tc->status() != TC::Active) { 99 // Restore PC from TCRestart 100 IntReg pc = tc->readMiscRegNoEffect(TCRestart); 101 102 // TODO: SET PC WITH AN EVENT INSTEAD OF INSTANTANEOUSLY 103 // tc->setPCEvent(pc, pc + 4, pc + 8); 104 tc->setPC(pc); 105 tc->setNextPC(pc + 4); 106 tc->setNextNPC(pc + 8); 107 tc->activate(0); 108 109 warn("%i: Restoring thread %i in %s @ PC %x", curTick, tc->getThreadNum(), tc->getCpuPtr()->name(), 110 tc->readPC()); 111 } 112} 113 114template <class TC> 115void 116forkThread(TC *tc, Fault &fault, int Rd_bits, int Rs, int Rt) 117{ 118 int num_threads = bits(tc->readMiscRegNoEffect(MVPConf0), MVPC0_PTC_HI, MVPC0_PTC_LO) + 1; 119 120 int success = 0; 121 for (int tid = 0; tid < num_threads && success == 0; tid++) { 122 unsigned tid_TCBind = tc->readRegOtherThread(MipsISA::TCBind + Ctrl_Base_DepTag, 123 tid); 124 unsigned tc_bind = tc->readMiscRegNoEffect(MipsISA::TCBind); 125 126 if (bits(tid_TCBind, TCB_CUR_VPE_HI, TCB_CUR_VPE_LO) == 127 bits(tc_bind, TCB_CUR_VPE_HI, TCB_CUR_VPE_LO)) { 128 129 unsigned tid_TCStatus = tc->readRegOtherThread(MipsISA::TCStatus + Ctrl_Base_DepTag, 130 tid); 131 132 unsigned tid_TCHalt = tc->readRegOtherThread(MipsISA::TCHalt + Ctrl_Base_DepTag, 133 tid); 134 135 if (bits(tid_TCStatus, TCS_DA) == 1 && 136 bits(tid_TCHalt, TCH_H) == 0 && 137 bits(tid_TCStatus, TCS_A) == 0 && 138 success == 0) { 139 140 tc->setRegOtherThread(MipsISA::TCRestart + Ctrl_Base_DepTag, Rs, tid); 141 142 tc->setRegOtherThread(Rd_bits, Rt, tid); 143 144 unsigned status_ksu = bits(tc->readMiscReg(MipsISA::Status), 145 S_KSU_HI, S_KSU_LO); 146 unsigned tc_status_asid = bits(tc->readMiscReg(MipsISA::TCStatus), 147 TCS_ASID_HI, TCS_ASID_LO); 148 149 // Set Run-State to Running 150 replaceBits(tid_TCStatus, TCSTATUS_RNST_HI, TCSTATUS_RNST_LO, 0); 151 152 // Set Delay-Slot to 0 153 replaceBits(tid_TCStatus, TCSTATUS_TDS, 0); 154 155 // Set Dirty TC to 1 156 replaceBits(tid_TCStatus, TCSTATUS_DT, 1); 157 158 // Set Activated to 1 159 replaceBits(tid_TCStatus, TCSTATUS_A, 1); 160 161 // Set status to previous thread's status 162 replaceBits(tid_TCStatus, TCSTATUS_TKSU_HI, TCSTATUS_TKSU_LO, status_ksu); 163 164 // Set ASID to previous thread's state 165 replaceBits(tid_TCStatus, TCSTATUS_ASID_HI, TCSTATUS_ASID_LO, tc_status_asid); 166 167 // Write Status Register 168 tc->setRegOtherThread(MipsISA::TCStatus + Ctrl_Base_DepTag, 169 tid_TCStatus, tid); 170 171 // Mark As Successful Fork 172 success = 1; 173 } 174 } else { 175 std::cerr << "Bad VPEs" << endl; 176 } 177 } 178 179 if (success == 0) { 180 unsigned vpe_control = tc->readMiscRegNoEffect(MipsISA::VPEControl); 181 tc->setMiscReg(VPEControl, insertBits(vpe_control, VPEC_EXCPT_HI, VPEC_EXCPT_LO, 1)); 182 fault = new ThreadFault(); 183 } 184} 185 186 187template <class TC> 188int 189yieldThread(TC *tc, Fault &fault, int src_reg, uint32_t yield_mask) 190{ 191 if (src_reg == 0) { 192 unsigned mvpconf0 = tc->readMiscRegNoEffect(MVPConf0); 193 int num_threads = bits(mvpconf0, MVPC0_PTC_HI, MVPC0_PTC_LO) + 1; 194 195 int ok = 0; 196 197 // Get Current VPE & TC numbers from calling thread 198 unsigned tcbind = tc->readMiscRegNoEffect(TCBind); 199 unsigned cur_vpe = bits(tcbind, TCB_CUR_VPE_HI, TCB_CUR_VPE_LO); 200 unsigned cur_tc = bits(tcbind, TCB_CUR_TC_HI, TCB_CUR_TC_LO); 201 202 for (int tid = 0; tid < num_threads; tid++) { 203 unsigned tid_TCStatus = tc->readRegOtherThread(MipsISA::TCStatus + Ctrl_Base_DepTag, 204 tid); 205 unsigned tid_TCHalt = tc->readRegOtherThread(MipsISA::TCHalt + Ctrl_Base_DepTag, 206 tid); 207 unsigned tid_TCBind = tc->readRegOtherThread(MipsISA::TCBind + Ctrl_Base_DepTag, 208 tid); 209 210 unsigned tid_vpe = bits(tid_TCBind, TCB_CUR_VPE_HI, TCB_CUR_VPE_LO); 211 unsigned tid_tc = bits(tid_TCBind, TCB_CUR_TC_HI, TCB_CUR_TC_LO); 212 unsigned tid_tcstatus_da = bits(tid_TCStatus, TCS_DA); 213 unsigned tid_tcstatus_a = bits(tid_TCStatus, TCS_A); 214 unsigned tid_tchalt_h = bits(tid_TCHalt, TCH_H); 215 216 if (tid_vpe == cur_vpe && 217 tid_tc == cur_tc && 218 tid_tcstatus_da == 1 && 219 tid_tchalt_h == 0 && 220 tid_tcstatus_a == 1) { 221 ok = 1; 222 } 223 } 224 225 if (ok == 1) { 226 unsigned tcstatus = tc->readMiscRegNoEffect(TCStatus); 227 tc->setMiscReg(TCStatus, insertBits(tcstatus, TCS_A, TCS_A, 0)); 228 warn("%i: Deactivating Hardware Thread Context #%i", curTick, tc->getThreadNum()); 229 } 230 } else if (src_reg > 0) { 231 if (src_reg & !yield_mask != 0) { 232 unsigned vpe_control = tc->readMiscReg(VPEControl); 233 tc->setMiscReg(VPEControl, insertBits(vpe_control, VPEC_EXCPT_HI, VPEC_EXCPT_LO, 2)); 234 fault = new ThreadFault(); 235 } else { 236 //tc->setThreadRescheduleCondition(src_reg & yield_mask); 237 } 238 } else if (src_reg != -2) { 239 unsigned tcstatus = tc->readMiscRegNoEffect(TCStatus); 240 unsigned vpe_control = tc->readMiscRegNoEffect(VPEControl); 241 unsigned tcstatus_dt = bits(tcstatus, TCS_DT); 242 unsigned vpe_control_ysi = bits(vpe_control, VPEC_YSI); 243 244 if (vpe_control_ysi == 1 && tcstatus_dt == 1 ) { 245 tc->setMiscReg(VPEControl, insertBits(vpe_control, VPEC_EXCPT_HI, VPEC_EXCPT_LO, 4)); 246 fault = new ThreadFault(); 247 } else { 248 //tc->ScheduleOtherThreads(); 249 //std::cerr << "T" << tc->getThreadNum() << "YIELD: Schedule Other Threads.\n" << std::endl; 250 //tc->suspend(); 251 // Save last known PC in TCRestart 252 // @TODO: Needs to check if this is a branch and if so, take previous instruction 253 //tc->setMiscRegWithEffect(TCRestart, tc->readNextPC()); 254 } 255 } 256 257 return src_reg & yield_mask; 258} 259 260 261// TC will usually be a object derived from ThreadContext 262// (src/cpu/thread_context.hh) 263template <class TC> 264inline void 265updateStatusView(TC *tc) 266{ 267 // TCStatus' register view must be the same as 268 // Status register view for CU, MX, KSU bits 269 MiscReg tc_status = tc->readMiscRegNoEffect(TCStatus); 270 MiscReg status = tc->readMiscRegNoEffect(Status); 271 272 unsigned cu_bits = bits(tc_status, TCS_TCU_HI, TCS_TCU_LO); 273 replaceBits(status, S_CU_HI, S_CU_LO, cu_bits); 274 275 unsigned mx_bits = bits(tc_status, TCS_TMX); 276 replaceBits(status, S_MX, S_MX, mx_bits); 277 278 unsigned ksu_bits = bits(tc_status, TCS_TKSU_HI, TCS_TKSU_LO); 279 replaceBits(status, S_KSU_HI, S_KSU_LO, ksu_bits); 280 281 tc->setMiscRegNoEffect(Status, status); 282} 283 284// TC will usually be a object derived from ThreadContext 285// (src/cpu/thread_context.hh) 286template <class TC> 287inline void 288updateTCStatusView(TC *tc) 289{ 290 // TCStatus' register view must be the same as 291 // Status register view for CU, MX, KSU bits 292 MiscReg tc_status = tc->readMiscRegNoEffect(TCStatus); 293 MiscReg status = tc->readMiscRegNoEffect(Status); 294 295 unsigned cu_bits = bits(status, S_CU_HI, S_CU_LO); 296 replaceBits(tc_status, TCS_TCU_HI, TCS_TCU_LO, cu_bits); 297 298 unsigned mx_bits = bits(status, S_MX, S_MX); 299 replaceBits(tc_status, TCS_TMX, mx_bits); 300 301 unsigned ksu_bits = bits(status, S_KSU_HI, S_KSU_LO); 302 replaceBits(tc_status, TCS_TKSU_HI, TCS_TKSU_LO, ksu_bits); 303 304 tc->setMiscRegNoEffect(TCStatus, tc_status); 305} 306 307} // namespace MipsISA 308 309 310#endif 311