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

Generated on Wed Dec 21 2022 10:22:27 for gem5 by doxygen 1.9.1