diff options
Diffstat (limited to 'src/arch/mips/regfile/misc_regfile.cc')
-rwxr-xr-x | src/arch/mips/regfile/misc_regfile.cc | 377 |
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(); +} |