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