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/isa_traits.hh" 41#include "arch/mips/faults.hh" 42#include "arch/mips/mt_constants.hh" 43#include "base/bitfield.hh" 44#include "base/trace.hh" 45#include "base/misc.hh" 46 47#include <iostream> 48using namespace std; 49 50namespace MipsISA 51{ 52 53 54template <class TC> 55inline unsigned 56getVirtProcNum(TC *tc) 57{ 58 MiscReg tcbind = tc->readMiscRegNoEffect(TCBind); 59 return bits(tcbind, TCB_CUR_VPE_HI, TCB_CUR_VPE_LO); 60} 61 62template <class TC> 63inline unsigned 64getTargetThread(TC *tc) 65{ 66 MiscReg vpec_ctrl = tc->readMiscRegNoEffect(VPEControl); 67 return bits(vpec_ctrl, VPEC_TARG_TC_HI, VPEC_TARG_TC_LO); 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, take previous instruction 79 tc->setMiscReg(TCRestart, tc->readNextPC()); 80 81 warn("%i: Halting thread %i in %s @ PC %x, setting restart PC to %x", curTick, tc->getThreadNum(), tc->getCpuPtr()->name(), 82 tc->readPC(), tc->readNextPC()); 83 } 84} 85 86template <class TC> 87inline void 88restoreThread(TC *tc) 89{ 90 if (tc->status() != TC::Active) { 91 // Restore PC from TCRestart 92 IntReg pc = tc->readMiscRegNoEffect(TCRestart); 93 94 // TODO: SET PC WITH AN EVENT INSTEAD OF INSTANTANEOUSLY 95 // tc->setPCEvent(pc, pc + 4, pc + 8); 96 tc->setPC(pc); 97 tc->setNextPC(pc + 4); 98 tc->setNextNPC(pc + 8); 99 tc->activate(0); 100 101 warn("%i: Restoring thread %i in %s @ PC %x", curTick, tc->getThreadNum(), tc->getCpuPtr()->name(), 102 tc->readPC()); 103 } 104} 105 106template <class TC> 107void 108forkThread(TC *tc, Fault &fault, int Rd_bits, int Rs, int Rt) 109{ 110 int num_threads = bits(tc->readMiscRegNoEffect(MVPConf0), MVPC0_PTC_HI, MVPC0_PTC_LO) + 1; 111 112 int success = 0; 113 for (int tid = 0; tid < num_threads && success == 0; tid++) { 114 unsigned tid_TCBind = tc->readRegOtherThread(MipsISA::TCBind + Ctrl_Base_DepTag, 115 tid); 116 unsigned tc_bind = tc->readMiscRegNoEffect(MipsISA::TCBind); 117 118 if (bits(tid_TCBind, TCB_CUR_VPE_HI, TCB_CUR_VPE_LO) == 119 bits(tc_bind, TCB_CUR_VPE_HI, TCB_CUR_VPE_LO)) { 120 121 unsigned tid_TCStatus = tc->readRegOtherThread(MipsISA::TCStatus + Ctrl_Base_DepTag, 122 tid); 123 124 unsigned tid_TCHalt = tc->readRegOtherThread(MipsISA::TCHalt + Ctrl_Base_DepTag, 125 tid); 126 127 if (bits(tid_TCStatus, TCS_DA) == 1 && 128 bits(tid_TCHalt, TCH_H) == 0 && 129 bits(tid_TCStatus, TCS_A) == 0 && 130 success == 0) { 131 132 tc->setRegOtherThread(MipsISA::TCRestart + Ctrl_Base_DepTag, Rs, tid); 133 134 tc->setRegOtherThread(Rd_bits, Rt, tid); 135 136 unsigned status_ksu = bits(tc->readMiscReg(MipsISA::Status), 137 S_KSU_HI, S_KSU_LO); 138 unsigned tc_status_asid = bits(tc->readMiscReg(MipsISA::TCStatus), 139 TCS_ASID_HI, TCS_ASID_LO); 140 141 // Set Run-State to Running 142 replaceBits(tid_TCStatus, TCSTATUS_RNST_HI, TCSTATUS_RNST_LO, 0); 143 144 // Set Delay-Slot to 0 145 replaceBits(tid_TCStatus, TCSTATUS_TDS, 0); 146 147 // Set Dirty TC to 1 148 replaceBits(tid_TCStatus, TCSTATUS_DT, 1); 149 150 // Set Activated to 1 151 replaceBits(tid_TCStatus, TCSTATUS_A, 1); 152 153 // Set status to previous thread's status 154 replaceBits(tid_TCStatus, TCSTATUS_TKSU_HI, TCSTATUS_TKSU_LO, status_ksu); 155 156 // Set ASID to previous thread's state 157 replaceBits(tid_TCStatus, TCSTATUS_ASID_HI, TCSTATUS_ASID_LO, tc_status_asid); 158 159 // Write Status Register 160 tc->setRegOtherThread(MipsISA::TCStatus + Ctrl_Base_DepTag, 161 tid_TCStatus, tid); 162 163 // Mark As Successful Fork 164 success = 1; 165 } 166 } else { 167 std::cerr << "Bad VPEs" << endl; 168 } 169 } 170 171 if (success == 0) { 172 unsigned vpe_control = tc->readMiscRegNoEffect(MipsISA::VPEControl); 173 tc->setMiscReg(VPEControl, insertBits(vpe_control, VPEC_EXCPT_HI, VPEC_EXCPT_LO, 1)); 174 fault = new ThreadFault(); 175 } 176} 177 178 179template <class TC> 180int 181yieldThread(TC *tc, Fault &fault, int src_reg, uint32_t yield_mask) 182{ 183 if (src_reg == 0) { 184 unsigned mvpconf0 = tc->readMiscRegNoEffect(MVPConf0); 185 int num_threads = bits(mvpconf0, MVPC0_PTC_HI, MVPC0_PTC_LO) + 1; 186 187 int ok = 0; 188 189 // Get Current VPE & TC numbers from calling thread 190 unsigned tcbind = tc->readMiscRegNoEffect(TCBind); 191 unsigned cur_vpe = bits(tcbind, TCB_CUR_VPE_HI, TCB_CUR_VPE_LO); 192 unsigned cur_tc = bits(tcbind, TCB_CUR_TC_HI, TCB_CUR_TC_LO); 193 194 for (int tid = 0; tid < num_threads; tid++) { 195 unsigned tid_TCStatus = tc->readRegOtherThread(MipsISA::TCStatus + Ctrl_Base_DepTag, 196 tid); 197 unsigned tid_TCHalt = tc->readRegOtherThread(MipsISA::TCHalt + Ctrl_Base_DepTag, 198 tid); 199 unsigned tid_TCBind = tc->readRegOtherThread(MipsISA::TCBind + Ctrl_Base_DepTag, 200 tid); 201 202 unsigned tid_vpe = bits(tid_TCBind, TCB_CUR_VPE_HI, TCB_CUR_VPE_LO); 203 unsigned tid_tc = bits(tid_TCBind, TCB_CUR_TC_HI, TCB_CUR_TC_LO); 204 unsigned tid_tcstatus_da = bits(tid_TCStatus, TCS_DA); 205 unsigned tid_tcstatus_a = bits(tid_TCStatus, TCS_A); 206 unsigned tid_tchalt_h = bits(tid_TCHalt, TCH_H); 207 208 if (tid_vpe == cur_vpe && 209 tid_tc == cur_tc && 210 tid_tcstatus_da == 1 && 211 tid_tchalt_h == 0 && 212 tid_tcstatus_a == 1) { 213 ok = 1; 214 } 215 } 216 217 if (ok == 1) { 218 unsigned tcstatus = tc->readMiscRegNoEffect(TCStatus); 219 tc->setMiscReg(TCStatus, insertBits(tcstatus, TCS_A, TCS_A, 0)); 220 warn("%i: Deactivating Hardware Thread Context #%i", curTick, tc->getThreadNum()); 221 } 222 } else if (src_reg > 0) { 223 if (src_reg & !yield_mask != 0) { 224 unsigned vpe_control = tc->readMiscReg(VPEControl); 225 tc->setMiscReg(VPEControl, insertBits(vpe_control, VPEC_EXCPT_HI, VPEC_EXCPT_LO, 2)); 226 fault = new ThreadFault(); 227 } else { 228 //tc->setThreadRescheduleCondition(src_reg & yield_mask); 229 } 230 } else if (src_reg != -2) { 231 unsigned tcstatus = tc->readMiscRegNoEffect(TCStatus); 232 unsigned vpe_control = tc->readMiscRegNoEffect(VPEControl); 233 unsigned tcstatus_dt = bits(tcstatus, TCS_DT); 234 unsigned vpe_control_ysi = bits(vpe_control, VPEC_YSI); 235 236 if (vpe_control_ysi == 1 && tcstatus_dt == 1 ) { 237 tc->setMiscReg(VPEControl, insertBits(vpe_control, VPEC_EXCPT_HI, VPEC_EXCPT_LO, 4)); 238 fault = new ThreadFault(); 239 } else { 240 //tc->ScheduleOtherThreads(); 241 //std::cerr << "T" << tc->getThreadNum() << "YIELD: Schedule Other Threads.\n" << std::endl; 242 //tc->suspend(); 243 // Save last known PC in TCRestart 244 // @TODO: Needs to check if this is a branch and if so, take previous instruction 245 //tc->setMiscRegWithEffect(TCRestart, tc->readNextPC()); 246 } 247 } 248 249 return src_reg & yield_mask; 250} 251 252 253// TC will usually be a object derived from ThreadContext 254// (src/cpu/thread_context.hh) 255template <class TC> 256inline void 257updateStatusView(TC *tc) 258{ 259 // TCStatus' register view must be the same as 260 // Status register view for CU, MX, KSU bits 261 MiscReg tc_status = tc->readMiscRegNoEffect(TCStatus); 262 MiscReg status = tc->readMiscRegNoEffect(Status); 263 264 unsigned cu_bits = bits(tc_status, TCS_TCU_HI, TCS_TCU_LO); 265 replaceBits(status, S_CU_HI, S_CU_LO, cu_bits); 266 267 unsigned mx_bits = bits(tc_status, TCS_TMX); 268 replaceBits(status, S_MX, S_MX, mx_bits); 269 270 unsigned ksu_bits = bits(tc_status, TCS_TKSU_HI, TCS_TKSU_LO); 271 replaceBits(status, S_KSU_HI, S_KSU_LO, ksu_bits); 272 273 tc->setMiscRegNoEffect(Status, status); 274} 275 276// TC will usually be a object derived from ThreadContext 277// (src/cpu/thread_context.hh) 278template <class TC> 279inline void 280updateTCStatusView(TC *tc) 281{ 282 // TCStatus' register view must be the same as 283 // Status register view for CU, MX, KSU bits 284 MiscReg tc_status = tc->readMiscRegNoEffect(TCStatus); 285 MiscReg status = tc->readMiscRegNoEffect(Status); 286 287 unsigned cu_bits = bits(status, S_CU_HI, S_CU_LO); 288 replaceBits(tc_status, TCS_TCU_HI, TCS_TCU_LO, cu_bits); 289 290 unsigned mx_bits = bits(status, S_MX, S_MX); 291 replaceBits(tc_status, TCS_TMX, mx_bits); 292 293 unsigned ksu_bits = bits(status, S_KSU_HI, S_KSU_LO); 294 replaceBits(tc_status, TCS_TKSU_HI, TCS_TKSU_LO, ksu_bits); 295 296 tc->setMiscRegNoEffect(TCStatus, tc_status); 297} 298 299} // namespace MipsISA 300 301 302#endif
| 36 */ 37 38#ifndef __ARCH_MIPS_MT_HH__ 39#define __ARCH_MIPS_MT_HH__ 40 41/** 42 * @file 43 * 44 * ISA-specific helper functions for multithreaded execution. 45 */ 46 47#include "arch/isa_traits.hh" 48#include "arch/mips/faults.hh" 49#include "arch/mips/mt_constants.hh" 50#include "base/bitfield.hh" 51#include "base/trace.hh" 52#include "base/misc.hh" 53 54#include <iostream> 55using namespace std; 56 57namespace MipsISA 58{ 59 60 61template <class TC> 62inline unsigned 63getVirtProcNum(TC *tc) 64{ 65 MiscReg tcbind = tc->readMiscRegNoEffect(TCBind); 66 return bits(tcbind, TCB_CUR_VPE_HI, TCB_CUR_VPE_LO); 67} 68 69template <class TC> 70inline unsigned 71getTargetThread(TC *tc) 72{ 73 MiscReg vpec_ctrl = tc->readMiscRegNoEffect(VPEControl); 74 return bits(vpec_ctrl, VPEC_TARG_TC_HI, VPEC_TARG_TC_LO); 75} 76 77template <class TC> 78inline void 79haltThread(TC *tc) 80{ 81 if (tc->status() == TC::Active) { 82 tc->halt(); 83 84 // Save last known PC in TCRestart 85 // @TODO: Needs to check if this is a branch and if so, take previous instruction 86 tc->setMiscReg(TCRestart, tc->readNextPC()); 87 88 warn("%i: Halting thread %i in %s @ PC %x, setting restart PC to %x", curTick, tc->getThreadNum(), tc->getCpuPtr()->name(), 89 tc->readPC(), tc->readNextPC()); 90 } 91} 92 93template <class TC> 94inline void 95restoreThread(TC *tc) 96{ 97 if (tc->status() != TC::Active) { 98 // Restore PC from TCRestart 99 IntReg pc = tc->readMiscRegNoEffect(TCRestart); 100 101 // TODO: SET PC WITH AN EVENT INSTEAD OF INSTANTANEOUSLY 102 // tc->setPCEvent(pc, pc + 4, pc + 8); 103 tc->setPC(pc); 104 tc->setNextPC(pc + 4); 105 tc->setNextNPC(pc + 8); 106 tc->activate(0); 107 108 warn("%i: Restoring thread %i in %s @ PC %x", curTick, tc->getThreadNum(), tc->getCpuPtr()->name(), 109 tc->readPC()); 110 } 111} 112 113template <class TC> 114void 115forkThread(TC *tc, Fault &fault, int Rd_bits, int Rs, int Rt) 116{ 117 int num_threads = bits(tc->readMiscRegNoEffect(MVPConf0), MVPC0_PTC_HI, MVPC0_PTC_LO) + 1; 118 119 int success = 0; 120 for (int tid = 0; tid < num_threads && success == 0; tid++) { 121 unsigned tid_TCBind = tc->readRegOtherThread(MipsISA::TCBind + Ctrl_Base_DepTag, 122 tid); 123 unsigned tc_bind = tc->readMiscRegNoEffect(MipsISA::TCBind); 124 125 if (bits(tid_TCBind, TCB_CUR_VPE_HI, TCB_CUR_VPE_LO) == 126 bits(tc_bind, TCB_CUR_VPE_HI, TCB_CUR_VPE_LO)) { 127 128 unsigned tid_TCStatus = tc->readRegOtherThread(MipsISA::TCStatus + Ctrl_Base_DepTag, 129 tid); 130 131 unsigned tid_TCHalt = tc->readRegOtherThread(MipsISA::TCHalt + Ctrl_Base_DepTag, 132 tid); 133 134 if (bits(tid_TCStatus, TCS_DA) == 1 && 135 bits(tid_TCHalt, TCH_H) == 0 && 136 bits(tid_TCStatus, TCS_A) == 0 && 137 success == 0) { 138 139 tc->setRegOtherThread(MipsISA::TCRestart + Ctrl_Base_DepTag, Rs, tid); 140 141 tc->setRegOtherThread(Rd_bits, Rt, tid); 142 143 unsigned status_ksu = bits(tc->readMiscReg(MipsISA::Status), 144 S_KSU_HI, S_KSU_LO); 145 unsigned tc_status_asid = bits(tc->readMiscReg(MipsISA::TCStatus), 146 TCS_ASID_HI, TCS_ASID_LO); 147 148 // Set Run-State to Running 149 replaceBits(tid_TCStatus, TCSTATUS_RNST_HI, TCSTATUS_RNST_LO, 0); 150 151 // Set Delay-Slot to 0 152 replaceBits(tid_TCStatus, TCSTATUS_TDS, 0); 153 154 // Set Dirty TC to 1 155 replaceBits(tid_TCStatus, TCSTATUS_DT, 1); 156 157 // Set Activated to 1 158 replaceBits(tid_TCStatus, TCSTATUS_A, 1); 159 160 // Set status to previous thread's status 161 replaceBits(tid_TCStatus, TCSTATUS_TKSU_HI, TCSTATUS_TKSU_LO, status_ksu); 162 163 // Set ASID to previous thread's state 164 replaceBits(tid_TCStatus, TCSTATUS_ASID_HI, TCSTATUS_ASID_LO, tc_status_asid); 165 166 // Write Status Register 167 tc->setRegOtherThread(MipsISA::TCStatus + Ctrl_Base_DepTag, 168 tid_TCStatus, tid); 169 170 // Mark As Successful Fork 171 success = 1; 172 } 173 } else { 174 std::cerr << "Bad VPEs" << endl; 175 } 176 } 177 178 if (success == 0) { 179 unsigned vpe_control = tc->readMiscRegNoEffect(MipsISA::VPEControl); 180 tc->setMiscReg(VPEControl, insertBits(vpe_control, VPEC_EXCPT_HI, VPEC_EXCPT_LO, 1)); 181 fault = new ThreadFault(); 182 } 183} 184 185 186template <class TC> 187int 188yieldThread(TC *tc, Fault &fault, int src_reg, uint32_t yield_mask) 189{ 190 if (src_reg == 0) { 191 unsigned mvpconf0 = tc->readMiscRegNoEffect(MVPConf0); 192 int num_threads = bits(mvpconf0, MVPC0_PTC_HI, MVPC0_PTC_LO) + 1; 193 194 int ok = 0; 195 196 // Get Current VPE & TC numbers from calling thread 197 unsigned tcbind = tc->readMiscRegNoEffect(TCBind); 198 unsigned cur_vpe = bits(tcbind, TCB_CUR_VPE_HI, TCB_CUR_VPE_LO); 199 unsigned cur_tc = bits(tcbind, TCB_CUR_TC_HI, TCB_CUR_TC_LO); 200 201 for (int tid = 0; tid < num_threads; tid++) { 202 unsigned tid_TCStatus = tc->readRegOtherThread(MipsISA::TCStatus + Ctrl_Base_DepTag, 203 tid); 204 unsigned tid_TCHalt = tc->readRegOtherThread(MipsISA::TCHalt + Ctrl_Base_DepTag, 205 tid); 206 unsigned tid_TCBind = tc->readRegOtherThread(MipsISA::TCBind + Ctrl_Base_DepTag, 207 tid); 208 209 unsigned tid_vpe = bits(tid_TCBind, TCB_CUR_VPE_HI, TCB_CUR_VPE_LO); 210 unsigned tid_tc = bits(tid_TCBind, TCB_CUR_TC_HI, TCB_CUR_TC_LO); 211 unsigned tid_tcstatus_da = bits(tid_TCStatus, TCS_DA); 212 unsigned tid_tcstatus_a = bits(tid_TCStatus, TCS_A); 213 unsigned tid_tchalt_h = bits(tid_TCHalt, TCH_H); 214 215 if (tid_vpe == cur_vpe && 216 tid_tc == cur_tc && 217 tid_tcstatus_da == 1 && 218 tid_tchalt_h == 0 && 219 tid_tcstatus_a == 1) { 220 ok = 1; 221 } 222 } 223 224 if (ok == 1) { 225 unsigned tcstatus = tc->readMiscRegNoEffect(TCStatus); 226 tc->setMiscReg(TCStatus, insertBits(tcstatus, TCS_A, TCS_A, 0)); 227 warn("%i: Deactivating Hardware Thread Context #%i", curTick, tc->getThreadNum()); 228 } 229 } else if (src_reg > 0) { 230 if (src_reg & !yield_mask != 0) { 231 unsigned vpe_control = tc->readMiscReg(VPEControl); 232 tc->setMiscReg(VPEControl, insertBits(vpe_control, VPEC_EXCPT_HI, VPEC_EXCPT_LO, 2)); 233 fault = new ThreadFault(); 234 } else { 235 //tc->setThreadRescheduleCondition(src_reg & yield_mask); 236 } 237 } else if (src_reg != -2) { 238 unsigned tcstatus = tc->readMiscRegNoEffect(TCStatus); 239 unsigned vpe_control = tc->readMiscRegNoEffect(VPEControl); 240 unsigned tcstatus_dt = bits(tcstatus, TCS_DT); 241 unsigned vpe_control_ysi = bits(vpe_control, VPEC_YSI); 242 243 if (vpe_control_ysi == 1 && tcstatus_dt == 1 ) { 244 tc->setMiscReg(VPEControl, insertBits(vpe_control, VPEC_EXCPT_HI, VPEC_EXCPT_LO, 4)); 245 fault = new ThreadFault(); 246 } else { 247 //tc->ScheduleOtherThreads(); 248 //std::cerr << "T" << tc->getThreadNum() << "YIELD: Schedule Other Threads.\n" << std::endl; 249 //tc->suspend(); 250 // Save last known PC in TCRestart 251 // @TODO: Needs to check if this is a branch and if so, take previous instruction 252 //tc->setMiscRegWithEffect(TCRestart, tc->readNextPC()); 253 } 254 } 255 256 return src_reg & yield_mask; 257} 258 259 260// TC will usually be a object derived from ThreadContext 261// (src/cpu/thread_context.hh) 262template <class TC> 263inline void 264updateStatusView(TC *tc) 265{ 266 // TCStatus' register view must be the same as 267 // Status register view for CU, MX, KSU bits 268 MiscReg tc_status = tc->readMiscRegNoEffect(TCStatus); 269 MiscReg status = tc->readMiscRegNoEffect(Status); 270 271 unsigned cu_bits = bits(tc_status, TCS_TCU_HI, TCS_TCU_LO); 272 replaceBits(status, S_CU_HI, S_CU_LO, cu_bits); 273 274 unsigned mx_bits = bits(tc_status, TCS_TMX); 275 replaceBits(status, S_MX, S_MX, mx_bits); 276 277 unsigned ksu_bits = bits(tc_status, TCS_TKSU_HI, TCS_TKSU_LO); 278 replaceBits(status, S_KSU_HI, S_KSU_LO, ksu_bits); 279 280 tc->setMiscRegNoEffect(Status, status); 281} 282 283// TC will usually be a object derived from ThreadContext 284// (src/cpu/thread_context.hh) 285template <class TC> 286inline void 287updateTCStatusView(TC *tc) 288{ 289 // TCStatus' register view must be the same as 290 // Status register view for CU, MX, KSU bits 291 MiscReg tc_status = tc->readMiscRegNoEffect(TCStatus); 292 MiscReg status = tc->readMiscRegNoEffect(Status); 293 294 unsigned cu_bits = bits(status, S_CU_HI, S_CU_LO); 295 replaceBits(tc_status, TCS_TCU_HI, TCS_TCU_LO, cu_bits); 296 297 unsigned mx_bits = bits(status, S_MX, S_MX); 298 replaceBits(tc_status, TCS_TMX, mx_bits); 299 300 unsigned ksu_bits = bits(status, S_KSU_HI, S_KSU_LO); 301 replaceBits(tc_status, TCS_TKSU_HI, TCS_TKSU_LO, ksu_bits); 302 303 tc->setMiscRegNoEffect(TCStatus, tc_status); 304} 305 306} // namespace MipsISA 307 308 309#endif
|