mt.hh revision 6221
14604Sgblack@eecs.umich.edu/* 24604Sgblack@eecs.umich.edu * Copyright (c) 2007 MIPS Technologies, Inc. 34604Sgblack@eecs.umich.edu * All rights reserved. 44604Sgblack@eecs.umich.edu * 54604Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 64604Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 74604Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 84604Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 94604Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 104604Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 114604Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 124604Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 134604Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 144604Sgblack@eecs.umich.edu * this software without specific prior written permission. 154604Sgblack@eecs.umich.edu * 164604Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 174604Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 184604Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 194604Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 204604Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 214604Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 224604Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 234604Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 244604Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 254604Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 264604Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 274604Sgblack@eecs.umich.edu * 284604Sgblack@eecs.umich.edu * Authors: Korey Sewell 294604Sgblack@eecs.umich.edu */ 304604Sgblack@eecs.umich.edu 314604Sgblack@eecs.umich.edu#ifndef __ARCH_MIPS_MT_HH__ 324604Sgblack@eecs.umich.edu#define __ARCH_MIPS_MT_HH__ 334604Sgblack@eecs.umich.edu 344604Sgblack@eecs.umich.edu/** 354604Sgblack@eecs.umich.edu * @file 364604Sgblack@eecs.umich.edu * 374604Sgblack@eecs.umich.edu * ISA-specific helper functions for multithreaded execution. 384604Sgblack@eecs.umich.edu */ 394604Sgblack@eecs.umich.edu 404604Sgblack@eecs.umich.edu#include "arch/isa_traits.hh" 414604Sgblack@eecs.umich.edu#include "arch/mips/faults.hh" 424604Sgblack@eecs.umich.edu#include "arch/mips/mt_constants.hh" 434604Sgblack@eecs.umich.edu#include "base/bitfield.hh" 444604Sgblack@eecs.umich.edu#include "base/trace.hh" 454604Sgblack@eecs.umich.edu#include "base/misc.hh" 464604Sgblack@eecs.umich.edu 474604Sgblack@eecs.umich.edu#include <iostream> 484604Sgblack@eecs.umich.edu 494604Sgblack@eecs.umich.edunamespace MipsISA 504604Sgblack@eecs.umich.edu{ 514604Sgblack@eecs.umich.edu 524604Sgblack@eecs.umich.edu 534604Sgblack@eecs.umich.edutemplate <class TC> 544604Sgblack@eecs.umich.eduinline unsigned 554604Sgblack@eecs.umich.edugetVirtProcNum(TC *tc) 564604Sgblack@eecs.umich.edu{ 574604Sgblack@eecs.umich.edu MiscReg tcbind = tc->readMiscRegNoEffect(TCBind); 585616Snate@binkert.org return bits(tcbind, TCB_CUR_VPE_HI, TCB_CUR_VPE_LO); 595616Snate@binkert.org} 604604Sgblack@eecs.umich.edu 614604Sgblack@eecs.umich.edutemplate <class TC> 624604Sgblack@eecs.umich.eduinline unsigned 634604Sgblack@eecs.umich.edugetTargetThread(TC *tc) 644604Sgblack@eecs.umich.edu{ 654604Sgblack@eecs.umich.edu MiscReg vpec_ctrl = tc->readMiscRegNoEffect(VPEControl); 664604Sgblack@eecs.umich.edu return bits(vpec_ctrl, VPEC_TARG_TC_HI, VPEC_TARG_TC_LO); 674604Sgblack@eecs.umich.edu} 684604Sgblack@eecs.umich.edu 694604Sgblack@eecs.umich.edutemplate <class TC> 704604Sgblack@eecs.umich.eduinline void 714712Sgblack@eecs.umich.eduhaltThread(TC *tc) 724712Sgblack@eecs.umich.edu{ 734604Sgblack@eecs.umich.edu if (tc->status() == TC::Active) { 744604Sgblack@eecs.umich.edu tc->halt(); 754604Sgblack@eecs.umich.edu 764604Sgblack@eecs.umich.edu // Save last known PC in TCRestart 774604Sgblack@eecs.umich.edu // @TODO: Needs to check if this is a branch and if so, take previous instruction 784848Sgblack@eecs.umich.edu tc->setMiscReg(TCRestart, tc->readNextPC()); 794604Sgblack@eecs.umich.edu 804604Sgblack@eecs.umich.edu warn("%i: Halting thread %i in %s @ PC %x, setting restart PC to %x", curTick, tc->threadId(), tc->getCpuPtr()->name(), 814604Sgblack@eecs.umich.edu tc->readPC(), tc->readNextPC()); 826071Sgblack@eecs.umich.edu } 836071Sgblack@eecs.umich.edu} 846071Sgblack@eecs.umich.edu 856071Sgblack@eecs.umich.edutemplate <class TC> 866071Sgblack@eecs.umich.eduinline void 876071Sgblack@eecs.umich.edurestoreThread(TC *tc) 886071Sgblack@eecs.umich.edu{ 896071Sgblack@eecs.umich.edu if (tc->status() != TC::Active) { 906071Sgblack@eecs.umich.edu // Restore PC from TCRestart 916071Sgblack@eecs.umich.edu IntReg pc = tc->readMiscRegNoEffect(TCRestart); 926071Sgblack@eecs.umich.edu 936071Sgblack@eecs.umich.edu // TODO: SET PC WITH AN EVENT INSTEAD OF INSTANTANEOUSLY 946071Sgblack@eecs.umich.edu // tc->setPCEvent(pc, pc + 4, pc + 8); 956071Sgblack@eecs.umich.edu tc->setPC(pc); 966071Sgblack@eecs.umich.edu tc->setNextPC(pc + 4); 976071Sgblack@eecs.umich.edu tc->setNextNPC(pc + 8); 986071Sgblack@eecs.umich.edu tc->activate(0); 996071Sgblack@eecs.umich.edu 1006071Sgblack@eecs.umich.edu warn("%i: Restoring thread %i in %s @ PC %x", curTick, tc->threadId(), tc->getCpuPtr()->name(), 1016071Sgblack@eecs.umich.edu tc->readPC()); 1026071Sgblack@eecs.umich.edu } 1036071Sgblack@eecs.umich.edu} 1046071Sgblack@eecs.umich.edu 1056071Sgblack@eecs.umich.edutemplate <class TC> 1066071Sgblack@eecs.umich.eduvoid 1076071Sgblack@eecs.umich.eduforkThread(TC *tc, Fault &fault, int Rd_bits, int Rs, int Rt) 1084604Sgblack@eecs.umich.edu{ 1094604Sgblack@eecs.umich.edu int num_threads = bits(tc->readMiscRegNoEffect(MVPConf0), MVPC0_PTC_HI, MVPC0_PTC_LO) + 1; 1104712Sgblack@eecs.umich.edu 1114604Sgblack@eecs.umich.edu int success = 0; 1124712Sgblack@eecs.umich.edu for (ThreadID tid = 0; tid < num_threads && success == 0; tid++) { 1134712Sgblack@eecs.umich.edu unsigned tid_TCBind = tc->readRegOtherThread(MipsISA::TCBind + Ctrl_Base_DepTag, 1144848Sgblack@eecs.umich.edu tid); 1154604Sgblack@eecs.umich.edu unsigned tc_bind = tc->readMiscRegNoEffect(MipsISA::TCBind); 1164604Sgblack@eecs.umich.edu 1174604Sgblack@eecs.umich.edu if (bits(tid_TCBind, TCB_CUR_VPE_HI, TCB_CUR_VPE_LO) == 1184863Sgblack@eecs.umich.edu bits(tc_bind, TCB_CUR_VPE_HI, TCB_CUR_VPE_LO)) { 1194863Sgblack@eecs.umich.edu 1204863Sgblack@eecs.umich.edu unsigned tid_TCStatus = tc->readRegOtherThread(MipsISA::TCStatus + Ctrl_Base_DepTag, 1215570Snate@binkert.org tid); 1224863Sgblack@eecs.umich.edu 1234863Sgblack@eecs.umich.edu unsigned tid_TCHalt = tc->readRegOtherThread(MipsISA::TCHalt + Ctrl_Base_DepTag, 1244863Sgblack@eecs.umich.edu tid); 1254863Sgblack@eecs.umich.edu 1264863Sgblack@eecs.umich.edu if (bits(tid_TCStatus, TCS_DA) == 1 && 1274863Sgblack@eecs.umich.edu bits(tid_TCHalt, TCH_H) == 0 && 1284863Sgblack@eecs.umich.edu bits(tid_TCStatus, TCS_A) == 0 && 1294863Sgblack@eecs.umich.edu success == 0) { 1304863Sgblack@eecs.umich.edu 1314604Sgblack@eecs.umich.edu tc->setRegOtherThread(MipsISA::TCRestart + Ctrl_Base_DepTag, Rs, tid); 1324604Sgblack@eecs.umich.edu 1335966Sgblack@eecs.umich.edu tc->setRegOtherThread(Rd_bits, Rt, tid); 1345966Sgblack@eecs.umich.edu 1355966Sgblack@eecs.umich.edu unsigned status_ksu = bits(tc->readMiscReg(MipsISA::Status), 1365966Sgblack@eecs.umich.edu S_KSU_HI, S_KSU_LO); 1375966Sgblack@eecs.umich.edu unsigned tc_status_asid = bits(tc->readMiscReg(MipsISA::TCStatus), 1385966Sgblack@eecs.umich.edu TCS_ASID_HI, TCS_ASID_LO); 1395966Sgblack@eecs.umich.edu 1405966Sgblack@eecs.umich.edu // Set Run-State to Running 141 replaceBits(tid_TCStatus, TCSTATUS_RNST_HI, TCSTATUS_RNST_LO, 0); 142 143 // Set Delay-Slot to 0 144 replaceBits(tid_TCStatus, TCSTATUS_TDS, 0); 145 146 // Set Dirty TC to 1 147 replaceBits(tid_TCStatus, TCSTATUS_DT, 1); 148 149 // Set Activated to 1 150 replaceBits(tid_TCStatus, TCSTATUS_A, 1); 151 152 // Set status to previous thread's status 153 replaceBits(tid_TCStatus, TCSTATUS_TKSU_HI, TCSTATUS_TKSU_LO, status_ksu); 154 155 // Set ASID to previous thread's state 156 replaceBits(tid_TCStatus, TCSTATUS_ASID_HI, TCSTATUS_ASID_LO, tc_status_asid); 157 158 // Write Status Register 159 tc->setRegOtherThread(MipsISA::TCStatus + Ctrl_Base_DepTag, 160 tid_TCStatus, tid); 161 162 // Mark As Successful Fork 163 success = 1; 164 } 165 } else { 166 std::cerr << "Bad VPEs" << std::endl; 167 } 168 } 169 170 if (success == 0) { 171 unsigned vpe_control = tc->readMiscRegNoEffect(MipsISA::VPEControl); 172 tc->setMiscReg(VPEControl, insertBits(vpe_control, VPEC_EXCPT_HI, VPEC_EXCPT_LO, 1)); 173 fault = new ThreadFault(); 174 } 175} 176 177 178template <class TC> 179int 180yieldThread(TC *tc, Fault &fault, int src_reg, uint32_t yield_mask) 181{ 182 if (src_reg == 0) { 183 unsigned mvpconf0 = tc->readMiscRegNoEffect(MVPConf0); 184 ThreadID num_threads = bits(mvpconf0, MVPC0_PTC_HI, MVPC0_PTC_LO) + 1; 185 186 int ok = 0; 187 188 // Get Current VPE & TC numbers from calling thread 189 unsigned tcbind = tc->readMiscRegNoEffect(TCBind); 190 unsigned cur_vpe = bits(tcbind, TCB_CUR_VPE_HI, TCB_CUR_VPE_LO); 191 unsigned cur_tc = bits(tcbind, TCB_CUR_TC_HI, TCB_CUR_TC_LO); 192 193 for (ThreadID tid = 0; tid < num_threads; tid++) { 194 unsigned tid_TCStatus = tc->readRegOtherThread(MipsISA::TCStatus + Ctrl_Base_DepTag, 195 tid); 196 unsigned tid_TCHalt = tc->readRegOtherThread(MipsISA::TCHalt + Ctrl_Base_DepTag, 197 tid); 198 unsigned tid_TCBind = tc->readRegOtherThread(MipsISA::TCBind + Ctrl_Base_DepTag, 199 tid); 200 201 unsigned tid_vpe = bits(tid_TCBind, TCB_CUR_VPE_HI, TCB_CUR_VPE_LO); 202 unsigned tid_tc = bits(tid_TCBind, TCB_CUR_TC_HI, TCB_CUR_TC_LO); 203 unsigned tid_tcstatus_da = bits(tid_TCStatus, TCS_DA); 204 unsigned tid_tcstatus_a = bits(tid_TCStatus, TCS_A); 205 unsigned tid_tchalt_h = bits(tid_TCHalt, TCH_H); 206 207 if (tid_vpe == cur_vpe && 208 tid_tc == cur_tc && 209 tid_tcstatus_da == 1 && 210 tid_tchalt_h == 0 && 211 tid_tcstatus_a == 1) { 212 ok = 1; 213 } 214 } 215 216 if (ok == 1) { 217 unsigned tcstatus = tc->readMiscRegNoEffect(TCStatus); 218 tc->setMiscReg(TCStatus, insertBits(tcstatus, TCS_A, TCS_A, 0)); 219 warn("%i: Deactivating Hardware Thread Context #%i", curTick, tc->threadId()); 220 } 221 } else if (src_reg > 0) { 222 if (src_reg && !yield_mask != 0) { 223 unsigned vpe_control = tc->readMiscReg(VPEControl); 224 tc->setMiscReg(VPEControl, insertBits(vpe_control, VPEC_EXCPT_HI, VPEC_EXCPT_LO, 2)); 225 fault = new ThreadFault(); 226 } else { 227 //tc->setThreadRescheduleCondition(src_reg & yield_mask); 228 } 229 } else if (src_reg != -2) { 230 unsigned tcstatus = tc->readMiscRegNoEffect(TCStatus); 231 unsigned vpe_control = tc->readMiscRegNoEffect(VPEControl); 232 unsigned tcstatus_dt = bits(tcstatus, TCS_DT); 233 unsigned vpe_control_ysi = bits(vpe_control, VPEC_YSI); 234 235 if (vpe_control_ysi == 1 && tcstatus_dt == 1 ) { 236 tc->setMiscReg(VPEControl, insertBits(vpe_control, VPEC_EXCPT_HI, VPEC_EXCPT_LO, 4)); 237 fault = new ThreadFault(); 238 } else { 239 //tc->ScheduleOtherThreads(); 240 //std::cerr << "T" << tc->threadId() << "YIELD: Schedule Other Threads.\n" << std::endl; 241 //tc->suspend(); 242 // Save last known PC in TCRestart 243 // @TODO: Needs to check if this is a branch and if so, take previous instruction 244 //tc->setMiscRegWithEffect(TCRestart, tc->readNextPC()); 245 } 246 } 247 248 return src_reg & yield_mask; 249} 250 251 252// TC will usually be a object derived from ThreadContext 253// (src/cpu/thread_context.hh) 254template <class TC> 255inline void 256updateStatusView(TC *tc) 257{ 258 // TCStatus' register view must be the same as 259 // Status register view for CU, MX, KSU bits 260 MiscReg tc_status = tc->readMiscRegNoEffect(TCStatus); 261 MiscReg status = tc->readMiscRegNoEffect(Status); 262 263 unsigned cu_bits = bits(tc_status, TCS_TCU_HI, TCS_TCU_LO); 264 replaceBits(status, S_CU_HI, S_CU_LO, cu_bits); 265 266 unsigned mx_bits = bits(tc_status, TCS_TMX); 267 replaceBits(status, S_MX, S_MX, mx_bits); 268 269 unsigned ksu_bits = bits(tc_status, TCS_TKSU_HI, TCS_TKSU_LO); 270 replaceBits(status, S_KSU_HI, S_KSU_LO, ksu_bits); 271 272 tc->setMiscRegNoEffect(Status, status); 273} 274 275// TC will usually be a object derived from ThreadContext 276// (src/cpu/thread_context.hh) 277template <class TC> 278inline void 279updateTCStatusView(TC *tc) 280{ 281 // TCStatus' register view must be the same as 282 // Status register view for CU, MX, KSU bits 283 MiscReg tc_status = tc->readMiscRegNoEffect(TCStatus); 284 MiscReg status = tc->readMiscRegNoEffect(Status); 285 286 unsigned cu_bits = bits(status, S_CU_HI, S_CU_LO); 287 replaceBits(tc_status, TCS_TCU_HI, TCS_TCU_LO, cu_bits); 288 289 unsigned mx_bits = bits(status, S_MX, S_MX); 290 replaceBits(tc_status, TCS_TMX, mx_bits); 291 292 unsigned ksu_bits = bits(status, S_KSU_HI, S_KSU_LO); 293 replaceBits(tc_status, TCS_TKSU_HI, TCS_TKSU_LO, ksu_bits); 294 295 tc->setMiscRegNoEffect(TCStatus, tc_status); 296} 297 298} // namespace MipsISA 299 300 301#endif 302