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 <iostream> 41 42#include "arch/mips/faults.hh" 43#include "arch/mips/isa_traits.hh" 44#include "arch/mips/mt_constants.hh" 45#include "arch/mips/pra_constants.hh" 46#include "arch/mips/registers.hh" 47#include "base/bitfield.hh" 48#include "base/misc.hh" 49#include "base/trace.hh" 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 PCState pc = tc->pcState(); 81 tc->setMiscReg(MISCREG_TC_RESTART, pc.npc()); 82 83 warn("%i: Halting thread %i in %s @ PC %x, setting restart PC to %x", 84 curTick(), tc->threadId(), tc->getCpuPtr()->name(), 85 pc.pc(), pc.npc()); 86 } 87} 88 89template <class TC> 90inline void 91restoreThread(TC *tc) 92{ 93 if (tc->status() != TC::Active) { 94 // Restore PC from TCRestart 95 Addr restartPC = tc->readMiscRegNoEffect(MISCREG_TC_RESTART); 96 97 // TODO: SET PC WITH AN EVENT INSTEAD OF INSTANTANEOUSLY 98 tc->pcState(restartPC); 99 tc->activate(); 100 101 warn("%i: Restoring thread %i in %s @ PC %x", 102 curTick(), tc->threadId(), tc->getCpuPtr()->name(), restartPC); 103 } 104} 105 106template <class TC> 107void 108forkThread(TC *tc, Fault &fault, int Rd_bits, int Rs, int Rt) 109{ 110 MVPConf0Reg mvpConf = tc->readMiscRegNoEffect(MISCREG_MVP_CONF0); 111 int num_threads = mvpConf.ptc + 1; 112 113 int success = 0; 114 for (ThreadID tid = 0; tid < num_threads && success == 0; tid++) { 115 TCBindReg tidTCBind =
| 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 <iostream> 41 42#include "arch/mips/faults.hh" 43#include "arch/mips/isa_traits.hh" 44#include "arch/mips/mt_constants.hh" 45#include "arch/mips/pra_constants.hh" 46#include "arch/mips/registers.hh" 47#include "base/bitfield.hh" 48#include "base/misc.hh" 49#include "base/trace.hh" 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 PCState pc = tc->pcState(); 81 tc->setMiscReg(MISCREG_TC_RESTART, pc.npc()); 82 83 warn("%i: Halting thread %i in %s @ PC %x, setting restart PC to %x", 84 curTick(), tc->threadId(), tc->getCpuPtr()->name(), 85 pc.pc(), pc.npc()); 86 } 87} 88 89template <class TC> 90inline void 91restoreThread(TC *tc) 92{ 93 if (tc->status() != TC::Active) { 94 // Restore PC from TCRestart 95 Addr restartPC = tc->readMiscRegNoEffect(MISCREG_TC_RESTART); 96 97 // TODO: SET PC WITH AN EVENT INSTEAD OF INSTANTANEOUSLY 98 tc->pcState(restartPC); 99 tc->activate(); 100 101 warn("%i: Restoring thread %i in %s @ PC %x", 102 curTick(), tc->threadId(), tc->getCpuPtr()->name(), restartPC); 103 } 104} 105 106template <class TC> 107void 108forkThread(TC *tc, Fault &fault, int Rd_bits, int Rs, int Rt) 109{ 110 MVPConf0Reg mvpConf = tc->readMiscRegNoEffect(MISCREG_MVP_CONF0); 111 int num_threads = mvpConf.ptc + 1; 112 113 int success = 0; 114 for (ThreadID tid = 0; tid < num_threads && success == 0; tid++) { 115 TCBindReg tidTCBind =
|
116 tc->readRegOtherThread(MISCREG_TC_BIND + Misc_Reg_Base, tid);
| 116 tc->readRegOtherThread(RegId(MiscRegClass, MISCREG_TC_BIND), tid);
|
117 TCBindReg tcBind = tc->readMiscRegNoEffect(MISCREG_TC_BIND); 118 119 if (tidTCBind.curVPE == tcBind.curVPE) { 120 121 TCStatusReg tidTCStatus =
| 117 TCBindReg tcBind = tc->readMiscRegNoEffect(MISCREG_TC_BIND); 118 119 if (tidTCBind.curVPE == tcBind.curVPE) { 120 121 TCStatusReg tidTCStatus =
|
122 tc->readRegOtherThread(MISCREG_TC_STATUS + 123 Misc_Reg_Base,tid);
| 122 tc->readRegOtherThread(RegId(MiscRegClass, MISCREG_TC_STATUS), 123 tid);
|
124 125 TCHaltReg tidTCHalt =
| 124 125 TCHaltReg tidTCHalt =
|
126 tc->readRegOtherThread(MISCREG_TC_HALT + Misc_Reg_Base,tid);
| 126 tc->readRegOtherThread(RegId(MiscRegClass, MISCREG_TC_HALT), 127 tid);
|
127 128 if (tidTCStatus.da == 1 && tidTCHalt.h == 0 && 129 tidTCStatus.a == 0 && success == 0) { 130
| 128 129 if (tidTCStatus.da == 1 && tidTCHalt.h == 0 && 130 tidTCStatus.a == 0 && success == 0) { 131
|
131 tc->setRegOtherThread(MISCREG_TC_RESTART + 132 Misc_Reg_Base, Rs, tid); 133 tc->setRegOtherThread(Rd_bits, Rt, tid);
| 132 tc->setRegOtherThread(RegId(MiscRegClass, MISCREG_TC_RESTART), 133 Rs, tid); 134 tc->setRegOtherThread(RegId(IntRegClass, Rd_bits), Rt, tid);
|
134 135 StatusReg status = tc->readMiscReg(MISCREG_STATUS); 136 TCStatusReg tcStatus = tc->readMiscReg(MISCREG_TC_STATUS); 137 138 // Set Run-State to Running 139 tidTCStatus.rnst = 0; 140 // Set Delay-Slot to 0 141 tidTCStatus.tds = 0; 142 // Set Dirty TC to 1 143 tidTCStatus.dt = 1; 144 // Set Activated to 1 145 tidTCStatus.a = 1; 146 // Set status to previous thread's status 147 tidTCStatus.tksu = status.ksu; 148 // Set ASID to previous thread's state 149 tidTCStatus.asid = tcStatus.asid; 150 151 // Write Status Register
| 135 136 StatusReg status = tc->readMiscReg(MISCREG_STATUS); 137 TCStatusReg tcStatus = tc->readMiscReg(MISCREG_TC_STATUS); 138 139 // Set Run-State to Running 140 tidTCStatus.rnst = 0; 141 // Set Delay-Slot to 0 142 tidTCStatus.tds = 0; 143 // Set Dirty TC to 1 144 tidTCStatus.dt = 1; 145 // Set Activated to 1 146 tidTCStatus.a = 1; 147 // Set status to previous thread's status 148 tidTCStatus.tksu = status.ksu; 149 // Set ASID to previous thread's state 150 tidTCStatus.asid = tcStatus.asid; 151 152 // Write Status Register
|
152 tc->setRegOtherThread(MISCREG_TC_STATUS + Misc_Reg_Base,
| 153 tc->setRegOtherThread(RegId(MiscRegClass, MISCREG_TC_STATUS),
|
153 tidTCStatus, tid); 154 155 // Mark As Successful Fork 156 success = 1; 157 } 158 } else { 159 std::cerr << "Bad VPEs" << std::endl; 160 } 161 } 162 163 if (success == 0) { 164 VPEControlReg vpeControl = 165 tc->readMiscRegNoEffect(MISCREG_VPE_CONTROL); 166 vpeControl.excpt = 1; 167 tc->setMiscReg(MISCREG_VPE_CONTROL, vpeControl); 168 fault = std::make_shared<ThreadFault>(); 169 } 170} 171 172 173template <class TC> 174int 175yieldThread(TC *tc, Fault &fault, int src_reg, uint32_t yield_mask) 176{ 177 if (src_reg == 0) { 178 MVPConf0Reg mvpConf0 = tc->readMiscRegNoEffect(MISCREG_MVP_CONF0); 179 ThreadID num_threads = mvpConf0.ptc + 1; 180 181 int ok = 0; 182 183 // Get Current VPE & TC numbers from calling thread 184 TCBindReg tcBind = tc->readMiscRegNoEffect(MISCREG_TC_BIND); 185 186 for (ThreadID tid = 0; tid < num_threads; tid++) { 187 TCStatusReg tidTCStatus =
| 154 tidTCStatus, tid); 155 156 // Mark As Successful Fork 157 success = 1; 158 } 159 } else { 160 std::cerr << "Bad VPEs" << std::endl; 161 } 162 } 163 164 if (success == 0) { 165 VPEControlReg vpeControl = 166 tc->readMiscRegNoEffect(MISCREG_VPE_CONTROL); 167 vpeControl.excpt = 1; 168 tc->setMiscReg(MISCREG_VPE_CONTROL, vpeControl); 169 fault = std::make_shared<ThreadFault>(); 170 } 171} 172 173 174template <class TC> 175int 176yieldThread(TC *tc, Fault &fault, int src_reg, uint32_t yield_mask) 177{ 178 if (src_reg == 0) { 179 MVPConf0Reg mvpConf0 = tc->readMiscRegNoEffect(MISCREG_MVP_CONF0); 180 ThreadID num_threads = mvpConf0.ptc + 1; 181 182 int ok = 0; 183 184 // Get Current VPE & TC numbers from calling thread 185 TCBindReg tcBind = tc->readMiscRegNoEffect(MISCREG_TC_BIND); 186 187 for (ThreadID tid = 0; tid < num_threads; tid++) { 188 TCStatusReg tidTCStatus =
|
188 tc->readRegOtherThread(MISCREG_TC_STATUS + Misc_Reg_Base,
| 189 tc->readRegOtherThread(RegId(MiscRegClass, MISCREG_TC_STATUS),
|
189 tid); 190 TCHaltReg tidTCHalt =
| 190 tid); 191 TCHaltReg tidTCHalt =
|
191 tc->readRegOtherThread(MISCREG_TC_HALT + Misc_Reg_Base,
| 192 tc->readRegOtherThread(RegId(MiscRegClass, MISCREG_TC_HALT),
|
192 tid); 193 TCBindReg tidTCBind =
| 193 tid); 194 TCBindReg tidTCBind =
|
194 tc->readRegOtherThread(MISCREG_TC_BIND + Misc_Reg_Base,
| 195 tc->readRegOtherThread(RegId(MiscRegClass, MISCREG_TC_BIND),
|
195 tid); 196 197 if (tidTCBind.curVPE == tcBind.curVPE && 198 tidTCBind.curTC == tcBind.curTC && 199 tidTCStatus.da == 1 && 200 tidTCHalt.h == 0 && 201 tidTCStatus.a == 1) { 202 ok = 1; 203 } 204 } 205 206 if (ok == 1) { 207 TCStatusReg tcStatus = tc->readMiscRegNoEffect(MISCREG_TC_STATUS); 208 tcStatus.a = 0; 209 tc->setMiscReg(MISCREG_TC_STATUS, tcStatus); 210 warn("%i: Deactivating Hardware Thread Context #%i", 211 curTick(), tc->threadId()); 212 } 213 } else if (src_reg > 0) { 214 if (src_reg && !yield_mask != 0) { 215 VPEControlReg vpeControl = tc->readMiscReg(MISCREG_VPE_CONTROL); 216 vpeControl.excpt = 2; 217 tc->setMiscReg(MISCREG_VPE_CONTROL, vpeControl); 218 fault = std::make_shared<ThreadFault>(); 219 } else { 220 } 221 } else if (src_reg != -2) { 222 TCStatusReg tcStatus = tc->readMiscRegNoEffect(MISCREG_TC_STATUS); 223 VPEControlReg vpeControl = 224 tc->readMiscRegNoEffect(MISCREG_VPE_CONTROL); 225 226 if (vpeControl.ysi == 1 && tcStatus.dt == 1 ) { 227 vpeControl.excpt = 4; 228 fault = std::make_shared<ThreadFault>(); 229 } else { 230 } 231 } 232 233 return src_reg & yield_mask; 234} 235 236 237// TC will usually be a object derived from ThreadContext 238// (src/cpu/thread_context.hh) 239template <class TC> 240inline void 241updateStatusView(TC *tc) 242{ 243 // TCStatus' register view must be the same as 244 // Status register view for CU, MX, KSU bits 245 TCStatusReg tcStatus = tc->readMiscRegNoEffect(MISCREG_TC_STATUS); 246 StatusReg status = tc->readMiscRegNoEffect(MISCREG_STATUS); 247 248 status.cu = tcStatus.tcu; 249 status.mx = tcStatus.tmx; 250 status.ksu = tcStatus.tksu; 251 252 tc->setMiscRegNoEffect(MISCREG_STATUS, status); 253} 254 255// TC will usually be a object derived from ThreadContext 256// (src/cpu/thread_context.hh) 257template <class TC> 258inline void 259updateTCStatusView(TC *tc) 260{ 261 // TCStatus' register view must be the same as 262 // Status register view for CU, MX, KSU bits 263 TCStatusReg tcStatus = tc->readMiscRegNoEffect(MISCREG_TC_STATUS); 264 StatusReg status = tc->readMiscRegNoEffect(MISCREG_STATUS); 265 266 tcStatus.tcu = status.cu; 267 tcStatus.tmx = status.mx; 268 tcStatus.tksu = status.ksu; 269 270 tc->setMiscRegNoEffect(MISCREG_TC_STATUS, tcStatus); 271} 272 273} // namespace MipsISA 274 275 276#endif
| 196 tid); 197 198 if (tidTCBind.curVPE == tcBind.curVPE && 199 tidTCBind.curTC == tcBind.curTC && 200 tidTCStatus.da == 1 && 201 tidTCHalt.h == 0 && 202 tidTCStatus.a == 1) { 203 ok = 1; 204 } 205 } 206 207 if (ok == 1) { 208 TCStatusReg tcStatus = tc->readMiscRegNoEffect(MISCREG_TC_STATUS); 209 tcStatus.a = 0; 210 tc->setMiscReg(MISCREG_TC_STATUS, tcStatus); 211 warn("%i: Deactivating Hardware Thread Context #%i", 212 curTick(), tc->threadId()); 213 } 214 } else if (src_reg > 0) { 215 if (src_reg && !yield_mask != 0) { 216 VPEControlReg vpeControl = tc->readMiscReg(MISCREG_VPE_CONTROL); 217 vpeControl.excpt = 2; 218 tc->setMiscReg(MISCREG_VPE_CONTROL, vpeControl); 219 fault = std::make_shared<ThreadFault>(); 220 } else { 221 } 222 } else if (src_reg != -2) { 223 TCStatusReg tcStatus = tc->readMiscRegNoEffect(MISCREG_TC_STATUS); 224 VPEControlReg vpeControl = 225 tc->readMiscRegNoEffect(MISCREG_VPE_CONTROL); 226 227 if (vpeControl.ysi == 1 && tcStatus.dt == 1 ) { 228 vpeControl.excpt = 4; 229 fault = std::make_shared<ThreadFault>(); 230 } else { 231 } 232 } 233 234 return src_reg & yield_mask; 235} 236 237 238// TC will usually be a object derived from ThreadContext 239// (src/cpu/thread_context.hh) 240template <class TC> 241inline void 242updateStatusView(TC *tc) 243{ 244 // TCStatus' register view must be the same as 245 // Status register view for CU, MX, KSU bits 246 TCStatusReg tcStatus = tc->readMiscRegNoEffect(MISCREG_TC_STATUS); 247 StatusReg status = tc->readMiscRegNoEffect(MISCREG_STATUS); 248 249 status.cu = tcStatus.tcu; 250 status.mx = tcStatus.tmx; 251 status.ksu = tcStatus.tksu; 252 253 tc->setMiscRegNoEffect(MISCREG_STATUS, status); 254} 255 256// TC will usually be a object derived from ThreadContext 257// (src/cpu/thread_context.hh) 258template <class TC> 259inline void 260updateTCStatusView(TC *tc) 261{ 262 // TCStatus' register view must be the same as 263 // Status register view for CU, MX, KSU bits 264 TCStatusReg tcStatus = tc->readMiscRegNoEffect(MISCREG_TC_STATUS); 265 StatusReg status = tc->readMiscRegNoEffect(MISCREG_STATUS); 266 267 tcStatus.tcu = status.cu; 268 tcStatus.tmx = status.mx; 269 tcStatus.tksu = status.ksu; 270 271 tc->setMiscRegNoEffect(MISCREG_TC_STATUS, tcStatus); 272} 273 274} // namespace MipsISA 275 276 277#endif
|