summaryrefslogtreecommitdiff
path: root/src/arch/mips/regfile/misc_regfile.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/mips/regfile/misc_regfile.cc')
-rwxr-xr-xsrc/arch/mips/regfile/misc_regfile.cc377
1 files changed, 377 insertions, 0 deletions
diff --git a/src/arch/mips/regfile/misc_regfile.cc b/src/arch/mips/regfile/misc_regfile.cc
new file mode 100755
index 000000000..c97d93cf9
--- /dev/null
+++ b/src/arch/mips/regfile/misc_regfile.cc
@@ -0,0 +1,377 @@
+/*
+ * Copyright (c) 2006 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Korey Sewell
+ */
+
+#include "base/bitfield.hh"
+
+#include "arch/mips/regfile/misc_regfile.hh"
+#include "arch/mips/mt_constants.hh"
+#include "arch/mips/faults.hh"
+
+#include "cpu/thread_context.hh"
+#include "cpu/base.hh"
+#include "cpu/exetrace.hh"
+//#include "cpu/mixie/cpu.hh"
+
+using namespace std;
+
+std::string MiscRegFile::miscRegNames[NumMiscRegs] =
+{"Index", "MVPControl", "MVPConf0", "MVPConf1", "", "", "", "",
+ "Random", "VPEControl", "VPEConf0", "VPEConf1", "YQMask", "VPESchedule", "VPEScheFBack", "VPEOpt",
+ "EntryLo0", "TCStatus", "TCBind", "TCRestart", "TCHalt", "TCContext", "TCSchedule", "TCScheFBack",
+ "EntryLo1", "", "", "", "", "", "", "",
+ "Context", "ContextConfig", "", "", "", "", "", "",
+ "PageMask", "PageGrain", "", "", "", "", "", "",
+ "Wired", "SRSConf0", "SRCConf1", "SRSConf2", "SRSConf3", "SRSConf4", "", "",
+ "HWREna", "", "", "", "", "", "", "",
+ "BadVAddr", "", "", "", "", "", "", "",
+ "Count", "", "", "", "", "", "", "",
+ "EntryHi", "", "", "", "", "", "", "",
+ "Compare", "", "", "", "", "", "", "",
+ "Status", "IntCtl", "SRSCtl", "SRSMap", "", "", "", "",
+ "Cause", "", "", "", "", "", "", "",
+ "EPC", "", "", "", "", "", "", "",
+ "PRId", "EBase", "", "", "", "", "", "",
+ "Config", "Config1", "Config2", "Config3", "", "", "", "",
+ "LLAddr", "", "", "", "", "", "", "",
+ "WatchLo0", "WatchLo1", "WatchLo2", "WatchLo3", "WatchLo4", "WatchLo5", "WatchLo6", "WatchLo7",
+ "WatchHi0", "WatchHi1", "WatchHi2", "WatchHi3", "WatchHi4", "WatchHi5", "WatchHi6", "WatchHi7",
+ "XCContext64", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "",
+ "", "", "", "", "", "", "", "",
+ "Debug", "TraceControl1", "TraceControl2", "UserTraceData", "TraceBPC", "", "", "",
+ "DEPC", "", "", "", "", "", "", "",
+ "PerfCnt0", "PerfCnt1", "PerfCnt2", "PerfCnt3", "PerfCnt4", "PerfCnt5", "PerfCnt6", "PerfCnt7",
+ "ErrCtl", "", "", "", "", "", "", "",
+ "CacheErr0", "CacheErr1", "CacheErr2", "CacheErr3", "", "", "", "",
+ "TagLo0", "DataLo1", "TagLo2", "DataLo3", "TagLo4", "DataLo5", "TagLo6", "DataLo7",
+ "TagHi0", "DataHi1", "TagHi2", "DataHi3", "TagHi4", "DataHi5", "TagHi6", "DataHi7",
+ "ErrorEPC", "", "", "", "", "", "", "",
+ "DESAVE", "", "", "", "", "", "", "",
+ "LLFlag"
+};
+
+MiscRegFile::MiscRegFile()
+{
+ init();
+}
+
+MiscRegFile::MiscRegFile(BaseCPU *_cpu)
+{
+ cpu = _cpu;
+ init();
+}
+
+void
+MiscRegFile::init()
+{
+ miscRegFile.resize(NumMiscRegs);
+ bankType.resize(NumMiscRegs);
+
+ for (int i=0; i < NumMiscRegs; i++) {
+ miscRegFile[i].resize(1);
+ bankType[i] = perProcessor;
+ }
+
+ clear(0);
+}
+
+void
+MiscRegFile::clear(unsigned tid_or_vpn)
+{
+ for(int i = 0; i < NumMiscRegs; i++) {
+ miscRegFile[i][tid_or_vpn] = 0;
+ }
+}
+
+void
+MiscRegFile::expandForMultithreading(unsigned num_threads, unsigned num_vpes)
+{
+ // Initialize all Per-VPE regs
+ uint32_t per_vpe_regs[] = { VPEControl, VPEConf0, VPEConf1, YQMask,
+ VPESchedule, VPEScheFBack, VPEOpt, SRSConf0,
+ SRSConf1, SRSConf2, SRSConf3, SRSConf4,
+ EBase
+ };
+ uint32_t num_vpe_regs = sizeof(per_vpe_regs) / 4;
+ for (int i = 0; i < num_vpe_regs; i++) {
+ if (num_vpes > 1) {
+ miscRegFile[per_vpe_regs[i]].resize(num_vpes);
+ }
+ bankType[per_vpe_regs[i]] = perVirtProcessor;
+ }
+
+ // Initialize all Per-TC regs
+ uint32_t per_tc_regs[] = { Status, TCStatus, TCBind, TCRestart, TCHalt,
+ TCContext, TCSchedule, TCScheFBack, Debug,
+ LLAddr
+ };
+ uint32_t num_tc_regs = sizeof(per_tc_regs) / 4;
+
+ for (int i = 0; i < num_tc_regs; i++) {
+ miscRegFile[per_tc_regs[i]].resize(num_threads);
+ bankType[per_tc_regs[i]] = perThreadContext;
+ }
+
+
+ if (num_vpes > 1) {
+ for (int i=1; i < num_vpes; i++) {
+ clear(i);
+ }
+ }
+
+}
+
+//@TODO: Use MIPS STYLE CONSTANTS (e.g. TCHALT_H instead of TCH_H)
+void
+MiscRegFile::reset(std::string core_name, unsigned num_threads,
+ unsigned num_vpes)
+{
+ DPRINTF(MipsPRA, "Resetting CP0 State with %i TCs and %i VPEs\n",
+ num_threads, num_vpes);
+
+ // Do Default CP0 initialization HERE
+
+ // Do Initialization for MT cores here (eventually use
+ // core_name parameter to toggle this initialization)
+ // ===================================================
+ // Config
+ MiscReg cfg = readRegNoEffect(Config);
+ replaceBits(cfg, CFG_M, 1);
+ setRegNoEffect(Config, cfg);
+
+ // Config1
+ MiscReg cfg1 = readRegNoEffect(Config1);
+ replaceBits(cfg1, CFG1_M, 1);
+ setRegNoEffect(Config1, cfg1);
+
+ // Config2
+ MiscReg cfg2 = readRegNoEffect(Config2);
+ replaceBits(cfg2, CFG2_M, 1);
+ setRegNoEffect(Config2, cfg2);
+
+ // Config3
+ MiscReg cfg3 = readRegNoEffect(Config3);
+ replaceBits(cfg3, CFG3_MT, 1);
+ setRegNoEffect(Config3, cfg3);
+
+ // MVPConf0
+ MiscReg mvp_conf0 = readRegNoEffect(MVPConf0);
+ replaceBits(mvp_conf0, MVPC0_TCA, 1);
+ replaceBits(mvp_conf0, MVPC0_PVPE_HI, MVPC0_PVPE_LO, num_vpes - 1);
+ replaceBits(mvp_conf0, MVPC0_PTC_HI, MVPC0_PTC_LO, num_threads - 1);
+ setRegNoEffect(MVPConf0, mvp_conf0);
+
+ // VPEConf0
+ MiscReg vpe_conf0 = readRegNoEffect(VPEConf0);
+ replaceBits(vpe_conf0, VPEC0_MVP, 1);
+ setRegNoEffect(VPEConf0, vpe_conf0);
+
+ // TCBind
+ for (int tid = 0; tid < num_threads; tid++) {
+ MiscReg tc_bind = readRegNoEffect(TCBind, tid);
+ replaceBits(tc_bind, TCB_CUR_TC_HI, TCB_CUR_TC_LO, tid);
+ setRegNoEffect(TCBind, tc_bind, tid);
+ }
+
+ // TCHalt
+ MiscReg tc_halt = readRegNoEffect(TCHalt);
+ replaceBits(tc_halt, TCH_H, 0);
+ setRegNoEffect(TCHalt, tc_halt);
+ /*for (int tid = 1; tid < num_threads; tid++) {
+ // Set TCHalt Halt bit to 1 for all other threads
+ tc_halt = readRegNoEffect(TCHalt, tid);
+ replaceBits(tc_halt, TCH_H, 1);
+ setReg(TCHalt, tc_halt, tid);
+ }*/
+
+ // TCStatus
+ // Set TCStatus Activated to 1 for the initial thread that is running
+ MiscReg tc_status = readRegNoEffect(TCStatus);
+ replaceBits(tc_status, TCS_A, 1);
+ setRegNoEffect(TCStatus, tc_status);
+
+ // Set Dynamically Allocatable bit to 1 for all other threads
+ for (int tid = 0; tid < num_threads; tid++) {
+ tc_status = readRegNoEffect(TCStatus, tid);
+ replaceBits(tc_status, TCSTATUS_DA, 1);
+ setRegNoEffect(TCStatus, tc_status, tid);
+ }
+}
+
+inline std::string
+MipsISA::getMiscRegName(unsigned reg_idx)
+{
+ return MiscRegFile::miscRegNames[reg_idx];
+}
+
+inline unsigned
+MiscRegFile::getVPENum(unsigned tid)
+{
+ unsigned tc_bind = miscRegFile[TCBind][tid];
+ return bits(tc_bind, TCB_CUR_VPE_HI, TCB_CUR_VPE_LO);
+}
+
+MiscReg
+MiscRegFile::readRegNoEffect(int misc_reg, unsigned tid)
+{
+ unsigned reg_sel = (bankType[misc_reg] == perThreadContext)
+ ? tid : getVPENum(tid);
+
+ return miscRegFile[misc_reg][reg_sel];
+}
+
+//@TODO: MIPS MT's register view automatically connects
+// Status to TCStatus depending on current thread
+MiscReg
+MiscRegFile::readReg(int misc_reg,
+ ThreadContext *tc, unsigned tid)
+{
+ DPRINTF(MipsPRA, "Reading CP0 Register:%u Select:%u (%s) with effect.\n",
+ misc_reg / 8, misc_reg % 8, getMiscRegName(misc_reg));
+
+ unsigned reg_sel = (bankType[misc_reg] == perThreadContext)
+ ? tid : getVPENum(tid);
+
+ switch (misc_reg)
+ {
+ default:
+ return miscRegFile[misc_reg][reg_sel];
+ }
+}
+
+void
+MiscRegFile::setRegNoEffect(int misc_reg, const MiscReg &val, unsigned tid)
+{
+ unsigned reg_sel = (bankType[misc_reg] == perThreadContext)
+ ? tid : getVPENum(tid);
+
+ miscRegFile[misc_reg][reg_sel] = val;
+}
+
+// PROGRAMMER'S NOTES:
+// (1) Some CP0 Registers have fields that cannot
+// be overwritten. Make sure to handle those particular registers
+// with care!
+void
+MiscRegFile::setReg(int misc_reg, const MiscReg &val,
+ ThreadContext *tc, unsigned tid)
+{
+ unsigned reg_sel = (bankType[misc_reg] == perThreadContext)
+ ? tid : getVPENum(tid);
+
+ DPRINTF(MipsPRA, "[tid:%i]: Setting CP0 Register:%u Select:%u (%s) to %#x, with effect.\n",
+ tid, misc_reg / 8, misc_reg % 8, getMiscRegName(misc_reg), val);
+
+ MiscReg cp0_val = filterCP0Write(misc_reg, val);
+
+ miscRegFile[misc_reg][reg_sel] = cp0_val;
+
+ scheduleCP0Update();
+}
+
+void
+MiscRegFile::scheduleCP0Update(int delay)
+{
+ if (!cp0Updated) {
+ cp0Updated = true;
+
+ //schedule UPDATE
+ CP0Event *cp0_event = new CP0Event(this, cpu, UpdateCP0);
+ cp0_event->schedule(curTick + cpu->cycles(delay));
+ }
+}
+
+void
+MiscRegFile::updateCPU()
+{
+ ///////////////////////////////////////////////////////////////////
+ //
+ // EVALUATE CP0 STATE FOR MIPS MT
+ //
+ ///////////////////////////////////////////////////////////////////
+ unsigned mvp_conf0 = readRegNoEffect(MVPConf0);
+ unsigned num_threads = bits(mvp_conf0, MVPC0_PTC_HI, MVPC0_PTC_LO) + 1;
+
+ for (int tid = 0; tid < num_threads; tid++) {
+ MiscReg tc_status = readRegNoEffect(TCStatus, tid);
+ MiscReg tc_halt = readRegNoEffect(TCHalt, tid);
+
+ //@todo: add vpe/mt check here thru mvpcontrol & vpecontrol regs
+ if (bits(tc_halt, TCH_H) == 1 || bits(tc_status, TCS_A) == 0) {
+ haltThread(cpu->getContext(tid));
+ } else if (bits(tc_halt, TCH_H) == 0 && bits(tc_status, TCS_A) == 1) {
+ restoreThread(cpu->getContext(tid));
+ }
+ }
+
+ num_threads = bits(mvp_conf0, MVPC0_PTC_HI, MVPC0_PTC_LO) + 1;
+
+ // Toggle update flag after we finished updating
+ cp0Updated = false;
+}
+
+MiscRegFile::CP0Event::CP0Event(CP0 *_cp0, BaseCPU *_cpu, CP0EventType e_type)
+ : Event(&mainEventQueue, CPU_Tick_Pri), cp0(_cp0), cpu(_cpu), cp0EventType(e_type)
+{ }
+
+void
+MiscRegFile::CP0Event::process()
+{
+ switch (cp0EventType)
+ {
+ case UpdateCP0:
+ cp0->updateCPU();
+ break;
+ }
+
+ //cp0EventRemoveList.push(this);
+}
+
+const char *
+MiscRegFile::CP0Event::description()
+{
+ return "Coprocessor-0 event";
+}
+
+void
+MiscRegFile::CP0Event::scheduleEvent(int delay)
+{
+ if (squashed())
+ reschedule(curTick + cpu->cycles(delay));
+ else if (!scheduled())
+ schedule(curTick + cpu->cycles(delay));
+}
+
+void
+MiscRegFile::CP0Event::unscheduleEvent()
+{
+ if (scheduled())
+ squash();
+}