gem5  v21.1.0.2
mt.hh
Go to the documentation of this file.
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 
29 #ifndef __ARCH_MIPS_MT_HH__
30 #define __ARCH_MIPS_MT_HH__
31 
38 #include <iostream>
39 
40 #include "arch/mips/faults.hh"
43 #include "arch/mips/regs/misc.hh"
44 #include "base/bitfield.hh"
45 #include "base/logging.hh"
46 #include "base/trace.hh"
47 #include "cpu/exec_context.hh"
48 
49 namespace gem5
50 {
51 
52 namespace MipsISA
53 {
54 
55 static inline RegVal
58 {
59  ThreadContext *otc = nullptr;
60  if (tid != InvalidThreadID)
61  otc = tc->getCpuPtr()->getContext(tid);
62  else
63  otc = tc;
64 
65  switch (reg.classValue()) {
66  case IntRegClass:
67  return otc->readIntReg(reg.index());
68  break;
69  case FloatRegClass:
70  return otc->readFloatReg(reg.index());
71  break;
72  case MiscRegClass:
73  return otc->readMiscReg(reg.index());
74  default:
75  panic("Unexpected reg class! (%s)", reg.className());
76  }
77 }
78 
79 static inline void
82 {
83  ThreadContext *otc = nullptr;
84  if (tid != InvalidThreadID)
85  otc = tc->getCpuPtr()->getContext(tid);
86  else
87  otc = tc;
88 
89  switch (reg.classValue()) {
90  case IntRegClass:
91  return otc->setIntReg(reg.index(), val);
92  break;
93  case FloatRegClass:
94  return otc->setFloatReg(reg.index(), val);
95  break;
96  case MiscRegClass:
97  return otc->setMiscReg(reg.index(), val);
98  default:
99  panic("Unexpected reg class! (%s)", reg.className());
100  }
101 }
102 
103 static inline RegVal
106 {
107  return readRegOtherThread(xc->tcBase(), reg, tid);
108 }
109 
110 static inline void
113 {
114  setRegOtherThread(xc->tcBase(), reg, val, tid);
115 }
116 
117 template <class TC>
118 inline unsigned
120 {
121  TCBindReg tcbind = tc->readMiscRegNoEffect(MISCREG_TC_BIND);
122  return tcbind.curVPE;
123 }
124 
125 template <class TC>
126 inline unsigned
128 {
129  VPEControlReg vpeCtrl = tc->readMiscRegNoEffect(MISCREG_VPE_CONTROL);
130  return vpeCtrl.targTC;
131 }
132 
133 template <class TC>
134 inline void
135 haltThread(TC *tc)
136 {
137  if (tc->status() == TC::Active) {
138  tc->halt();
139 
140  // Save last known PC in TCRestart
141  // @TODO: Needs to check if this is a branch and if so,
142  // take previous instruction
143  PCState pc = tc->pcState();
144  tc->setMiscReg(MISCREG_TC_RESTART, pc.npc());
145 
146  warn("%i: Halting thread %i in %s @ PC %x, setting restart PC to %x",
147  curTick(), tc->threadId(), tc->getCpuPtr()->name(),
148  pc.pc(), pc.npc());
149  }
150 }
151 
152 template <class TC>
153 inline void
155 {
156  if (tc->status() != TC::Active) {
157  // Restore PC from TCRestart
158  Addr restartPC = tc->readMiscRegNoEffect(MISCREG_TC_RESTART);
159 
160  // TODO: SET PC WITH AN EVENT INSTEAD OF INSTANTANEOUSLY
161  tc->pcState(restartPC);
162  tc->activate();
163 
164  warn("%i: Restoring thread %i in %s @ PC %x",
165  curTick(), tc->threadId(), tc->getCpuPtr()->name(), restartPC);
166  }
167 }
168 
169 template <class TC>
170 void
171 forkThread(TC *tc, Fault &fault, int Rd_bits, int Rs, int Rt)
172 {
173  MVPConf0Reg mvpConf = tc->readMiscRegNoEffect(MISCREG_MVP_CONF0);
174  int num_threads = mvpConf.ptc + 1;
175 
176  int success = 0;
177  for (ThreadID tid = 0; tid < num_threads && success == 0; tid++) {
178  TCBindReg tidTCBind =
180  TCBindReg tcBind = tc->readMiscRegNoEffect(MISCREG_TC_BIND);
181 
182  if (tidTCBind.curVPE == tcBind.curVPE) {
183 
184  TCStatusReg tidTCStatus =
186  tid);
187 
188  TCHaltReg tidTCHalt =
190  tid);
191 
192  if (tidTCStatus.da == 1 && tidTCHalt.h == 0 &&
193  tidTCStatus.a == 0 && success == 0) {
194 
196  Rs, tid);
197  setRegOtherThread(tc, RegId(IntRegClass, Rd_bits), Rt, tid);
198 
199  StatusReg status = tc->readMiscReg(MISCREG_STATUS);
200  TCStatusReg tcStatus = tc->readMiscReg(MISCREG_TC_STATUS);
201 
202  // Set Run-State to Running
203  tidTCStatus.rnst = 0;
204  // Set Delay-Slot to 0
205  tidTCStatus.tds = 0;
206  // Set Dirty TC to 1
207  tidTCStatus.dt = 1;
208  // Set Activated to 1
209  tidTCStatus.a = 1;
210  // Set status to previous thread's status
211  tidTCStatus.tksu = status.ksu;
212  // Set ASID to previous thread's state
213  tidTCStatus.asid = tcStatus.asid;
214 
215  // Write Status Register
217  tidTCStatus, tid);
218 
219  // Mark As Successful Fork
220  success = 1;
221  }
222  } else {
223  std::cerr << "Bad VPEs" << std::endl;
224  }
225  }
226 
227  if (success == 0) {
228  VPEControlReg vpeControl =
229  tc->readMiscRegNoEffect(MISCREG_VPE_CONTROL);
230  vpeControl.excpt = 1;
231  tc->setMiscReg(MISCREG_VPE_CONTROL, vpeControl);
232  fault = std::make_shared<ThreadFault>();
233  }
234 }
235 
236 
237 template <class TC>
238 int
239 yieldThread(TC *tc, Fault &fault, int src_reg, uint32_t yield_mask)
240 {
241  if (src_reg == 0) {
242  MVPConf0Reg mvpConf0 = tc->readMiscRegNoEffect(MISCREG_MVP_CONF0);
243  ThreadID num_threads = mvpConf0.ptc + 1;
244 
245  int ok = 0;
246 
247  // Get Current VPE & TC numbers from calling thread
248  TCBindReg tcBind = tc->readMiscRegNoEffect(MISCREG_TC_BIND);
249 
250  for (ThreadID tid = 0; tid < num_threads; tid++) {
251  TCStatusReg tidTCStatus =
253  tid);
254  TCHaltReg tidTCHalt =
256  tid);
257  TCBindReg tidTCBind =
259  tid);
260 
261  if (tidTCBind.curVPE == tcBind.curVPE &&
262  tidTCBind.curTC == tcBind.curTC &&
263  tidTCStatus.da == 1 &&
264  tidTCHalt.h == 0 &&
265  tidTCStatus.a == 1) {
266  ok = 1;
267  }
268  }
269 
270  if (ok == 1) {
271  TCStatusReg tcStatus = tc->readMiscRegNoEffect(MISCREG_TC_STATUS);
272  tcStatus.a = 0;
273  tc->setMiscReg(MISCREG_TC_STATUS, tcStatus);
274  warn("%i: Deactivating Hardware Thread Context #%i",
275  curTick(), tc->threadId());
276  }
277  } else if (src_reg > 0) {
278  if ((src_reg & ~yield_mask) != 0) {
279  VPEControlReg vpeControl = tc->readMiscReg(MISCREG_VPE_CONTROL);
280  vpeControl.excpt = 2;
281  tc->setMiscReg(MISCREG_VPE_CONTROL, vpeControl);
282  fault = std::make_shared<ThreadFault>();
283  } else {
284  }
285  } else if (src_reg != -2) {
286  TCStatusReg tcStatus = tc->readMiscRegNoEffect(MISCREG_TC_STATUS);
287  VPEControlReg vpeControl =
288  tc->readMiscRegNoEffect(MISCREG_VPE_CONTROL);
289 
290  if (vpeControl.ysi == 1 && tcStatus.dt == 1 ) {
291  vpeControl.excpt = 4;
292  fault = std::make_shared<ThreadFault>();
293  } else {
294  }
295  }
296 
297  return src_reg & yield_mask;
298 }
299 
300 
301 // TC will usually be a object derived from ThreadContext
302 // (src/cpu/thread_context.hh)
303 template <class TC>
304 inline void
306 {
307  // TCStatus' register view must be the same as
308  // Status register view for CU, MX, KSU bits
309  TCStatusReg tcStatus = tc->readMiscRegNoEffect(MISCREG_TC_STATUS);
310  StatusReg status = tc->readMiscRegNoEffect(MISCREG_STATUS);
311 
312  status.cu = tcStatus.tcu;
313  status.mx = tcStatus.tmx;
314  status.ksu = tcStatus.tksu;
315 
316  tc->setMiscRegNoEffect(MISCREG_STATUS, status);
317 }
318 
319 // TC will usually be a object derived from ThreadContext
320 // (src/cpu/thread_context.hh)
321 template <class TC>
322 inline void
324 {
325  // TCStatus' register view must be the same as
326  // Status register view for CU, MX, KSU bits
327  TCStatusReg tcStatus = tc->readMiscRegNoEffect(MISCREG_TC_STATUS);
328  StatusReg status = tc->readMiscRegNoEffect(MISCREG_STATUS);
329 
330  tcStatus.tcu = status.cu;
331  tcStatus.tmx = status.mx;
332  tcStatus.tksu = status.ksu;
333 
334  tc->setMiscRegNoEffect(MISCREG_TC_STATUS, tcStatus);
335 }
336 
337 } // namespace MipsISA
338 } // namespace gem5
339 
340 #endif
gem5::ThreadContext::setIntReg
virtual void setIntReg(RegIndex reg_idx, RegVal val)=0
gem5::curTick
Tick curTick()
The universal simulation clock.
Definition: cur_tick.hh:46
misc.hh
gem5::ThreadContext::readMiscReg
virtual RegVal readMiscReg(RegIndex misc_reg)=0
warn
#define warn(...)
Definition: logging.hh:245
gem5::MipsISA::restoreThread
void restoreThread(TC *tc)
Definition: mt.hh:154
gem5::RegVal
uint64_t RegVal
Definition: types.hh:173
gem5::MipsISA::getVirtProcNum
unsigned getVirtProcNum(TC *tc)
Definition: mt.hh:119
gem5::ThreadContext::readFloatReg
virtual RegVal readFloatReg(RegIndex reg_idx) const =0
gem5::MipsISA::MISCREG_STATUS
@ MISCREG_STATUS
Definition: misc.hh:96
gem5::MipsISA::setRegOtherThread
static void setRegOtherThread(ThreadContext *tc, const RegId &reg, RegVal val, ThreadID tid=InvalidThreadID)
Definition: mt.hh:80
faults.hh
pra_constants.hh
gem5::FloatRegClass
@ FloatRegClass
Floating-point register.
Definition: reg_class.hh:58
gem5::MipsISA::MISCREG_TC_BIND
@ MISCREG_TC_BIND
Definition: misc.hh:64
gem5::X86ISA::val
Bitfield< 63 > val
Definition: misc.hh:775
gem5::MipsISA::updateStatusView
void updateStatusView(TC *tc)
Definition: mt.hh:305
gem5::MiscRegClass
@ MiscRegClass
Control (misc) register.
Definition: reg_class.hh:65
gem5::GenericISA::DelaySlotPCState< 4 >
gem5::MipsISA::updateTCStatusView
void updateTCStatusView(TC *tc)
Definition: mt.hh:323
bitfield.hh
gem5::ThreadContext
ThreadContext is the external interface to all thread state for anything outside of the CPU.
Definition: thread_context.hh:93
gem5::Fault
std::shared_ptr< FaultBase > Fault
Definition: types.hh:255
gem5::MipsISA::MISCREG_TC_STATUS
@ MISCREG_TC_STATUS
Definition: misc.hh:63
gem5::MipsISA::MISCREG_TC_HALT
@ MISCREG_TC_HALT
Definition: misc.hh:66
gem5::ExecContext::tcBase
virtual ThreadContext * tcBase() const =0
Returns a pointer to the ThreadContext.
gem5::InvalidThreadID
const ThreadID InvalidThreadID
Definition: types.hh:243
gem5::ThreadContext::setFloatReg
virtual void setFloatReg(RegIndex reg_idx, RegVal val)=0
gem5::BaseCPU::getContext
virtual ThreadContext * getContext(int tn)
Given a thread num get tho thread context for it.
Definition: base.hh:290
gem5::Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
gem5::ThreadContext::readIntReg
virtual RegVal readIntReg(RegIndex reg_idx) const =0
gem5::MipsISA::haltThread
void haltThread(TC *tc)
Definition: mt.hh:135
gem5::MipsISA::MISCREG_VPE_CONTROL
@ MISCREG_VPE_CONTROL
Definition: misc.hh:54
gem5::X86ISA::reg
Bitfield< 5, 3 > reg
Definition: types.hh:92
gem5::MipsISA::MISCREG_MVP_CONF0
@ MISCREG_MVP_CONF0
Definition: misc.hh:50
gem5::MipsISA::yieldThread
int yieldThread(TC *tc, Fault &fault, int src_reg, uint32_t yield_mask)
Definition: mt.hh:239
gem5::ThreadContext::setMiscReg
virtual void setMiscReg(RegIndex misc_reg, RegVal val)=0
exec_context.hh
gem5::MipsISA::pc
Bitfield< 4 > pc
Definition: pra_constants.hh:243
logging.hh
gem5::ExecContext
The ExecContext is an abstract base class the provides the interface used by the ISA to manipulate th...
Definition: exec_context.hh:73
gem5::MipsISA::getTargetThread
unsigned getTargetThread(TC *tc)
Definition: mt.hh:127
gem5::MipsISA::MISCREG_TC_RESTART
@ MISCREG_TC_RESTART
Definition: misc.hh:65
gem5::ThreadContext::getCpuPtr
virtual BaseCPU * getCpuPtr()=0
trace.hh
gem5::MipsISA::readRegOtherThread
static RegVal readRegOtherThread(ThreadContext *tc, const RegId &reg, ThreadID tid=InvalidThreadID)
Definition: mt.hh:56
gem5::IntRegClass
@ IntRegClass
Integer register.
Definition: reg_class.hh:57
gem5
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Definition: decoder.cc:40
mt_constants.hh
gem5::MipsISA::forkThread
void forkThread(TC *tc, Fault &fault, int Rd_bits, int Rs, int Rt)
Definition: mt.hh:171
gem5::ThreadID
int16_t ThreadID
Thread index/ID type.
Definition: types.hh:242
gem5::RegId
Register ID: describe an architectural register with its class and index.
Definition: reg_class.hh:88
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:177
gem5::ArmISA::status
Bitfield< 5, 0 > status
Definition: misc_types.hh:422

Generated on Tue Sep 21 2021 12:24:48 for gem5 by doxygen 1.8.17