From 1c8dfd92543aba5f49e464b17e7e8143fc01a58c Mon Sep 17 00:00:00 2001 From: Korey Sewell Date: Tue, 12 May 2009 15:01:13 -0400 Subject: [PATCH] inorder-alpha-port: initial inorder support of ALPHA Edit AlphaISA to support the inorder model. Mostly alternate constructor functions and also a few skeleton multithreaded support functions * * * Remove namespace from header file. Causes compiler issues that are hard to find * * * Separate the TLB from the CPU and allow it to live in the TLBUnit resource. Give CPU accessor functions for access and also bind at construction time * * * Expose memory access size and flags through instruction object (temporarily memAccSize and memFlags to get TLB stuff working.) --- src/arch/SConscript | 1 + src/arch/alpha/floatregfile.hh | 56 ++++++++++++++++++++++ src/arch/alpha/isa/mem.isa | 39 ++++++++++++++- src/arch/alpha/miscregfile.cc | 16 +++++-- src/arch/alpha/miscregfile.hh | 23 +++++++-- src/arch/mips/regfile/misc_regfile.hh | 2 +- src/cpu/inorder/cpu.cc | 37 +++++++++++++- src/cpu/inorder/cpu.hh | 14 ++++-- src/cpu/inorder/inorder_dyn_inst.hh | 7 +++ src/cpu/inorder/resource_pool.cc | 15 ++++++ src/cpu/inorder/resource_pool.hh | 6 ++- src/cpu/inorder/resources/cache_unit.cc | 2 +- src/cpu/inorder/resources/mult_div_unit.cc | 2 +- src/cpu/inorder/resources/tlb_unit.cc | 25 ++++++++-- src/cpu/inorder/resources/tlb_unit.hh | 5 +- src/cpu/inorder/thread_context.hh | 8 ++-- 16 files changed, 232 insertions(+), 26 deletions(-) diff --git a/src/arch/SConscript b/src/arch/SConscript index b85ffbd89..0d801fcad 100644 --- a/src/arch/SConscript +++ b/src/arch/SConscript @@ -51,6 +51,7 @@ isa_switch_hdrs = Split(''' locked_mem.hh microcode_rom.hh mmaped_ipr.hh + mt.hh process.hh predecoder.hh regfile.hh diff --git a/src/arch/alpha/floatregfile.hh b/src/arch/alpha/floatregfile.hh index d5f9eec0f..a5a3a7861 100644 --- a/src/arch/alpha/floatregfile.hh +++ b/src/arch/alpha/floatregfile.hh @@ -42,6 +42,13 @@ class Checkpoint; namespace AlphaISA { +const int SingleWidth = 32; +const int SingleBytes = SingleWidth / 4; +const int DoubleWidth = 64; +const int DoubleBytes = DoubleWidth / 4; +const int QuadWidth = 128; +const int QuadBytes = QuadWidth / 4; + class FloatRegFile { public: @@ -54,6 +61,55 @@ class FloatRegFile void serialize(std::ostream &os); void unserialize(Checkpoint *cp, const std::string §ion); + + FloatReg + readReg(int floatReg) + { + return d[floatReg]; + } + + FloatReg + readReg(int floatReg, int width) + { + return readReg(floatReg); + } + + FloatRegBits + readRegBits(int floatReg) + { + return q[floatReg]; + } + + FloatRegBits + readRegBits(int floatReg, int width) + { + return readRegBits(floatReg); + } + + void + setReg(int floatReg, const FloatReg &val) + { + d[floatReg] = val; + } + + void + setReg(int floatReg, const FloatReg &val, int width) + { + setReg(floatReg, val); + } + + void + setRegBits(int floatReg, const FloatRegBits &val) + { + q[floatReg] = val; + } + + void + setRegBits(int floatReg, const FloatRegBits &val, int width) + { + setRegBits(floatReg, val); + } + }; } // namespace AlphaISA diff --git a/src/arch/alpha/isa/mem.isa b/src/arch/alpha/isa/mem.isa index cd5e117ec..9a8503637 100644 --- a/src/arch/alpha/isa/mem.isa +++ b/src/arch/alpha/isa/mem.isa @@ -65,6 +65,8 @@ output header {{ const StaticInstPtr &eaCompInst() const { return eaCompPtr; } const StaticInstPtr &memAccInst() const { return memAccPtr; } + + Request::Flags memAccFlags() { return memAccessFlags; } }; /** @@ -176,6 +178,8 @@ def template LoadStoreDeclare {{ %(InitiateAccDeclare)s %(CompleteAccDeclare)s + + %(MemAccSizeDeclare)s }; }}; @@ -190,6 +194,25 @@ def template CompleteAccDeclare {{ Trace::InstRecord *) const; }}; +def template MemAccSizeDeclare {{ + int memAccSize(%(CPU_exec_context)s *xc); +}}; + +def template MiscMemAccSize {{ + int %(class_name)s::memAccSize(%(CPU_exec_context)s *xc) + { + panic("Misc instruction does not support split access method!"); + return 0; + } +}}; + +def template LoadStoreMemAccSize {{ + int %(class_name)s::memAccSize(%(CPU_exec_context)s *xc) + { + // Return the memory access size in bytes + return (%(mem_acc_size)d / 8); + } +}}; def template EACompConstructor {{ /** TODO: change op_class to AddrGenOp or something (requires @@ -620,6 +643,14 @@ def template MiscCompleteAcc {{ } }}; +def template MiscMemAccSize {{ + int %(class_name)s::memAccSize(%(CPU_exec_context)s *xc) + { + panic("Misc instruction does not support split access method!"); + return 0; + } +}}; + // load instructions use Ra as dest, so check for // Ra == 31 to detect nops def template LoadNopCheckDecode {{ @@ -693,6 +724,11 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, initiateAccTemplate = eval(exec_template_base + 'InitiateAcc') completeAccTemplate = eval(exec_template_base + 'CompleteAcc') + if (exec_template_base == 'Load' or exec_template_base == 'Store'): + memAccSizeTemplate = eval('LoadStoreMemAccSize') + else: + memAccSizeTemplate = eval('MiscMemAccSize') + # (header_output, decoder_output, decode_block, exec_output) return (LoadStoreDeclare.subst(iop), EACompConstructor.subst(ea_iop) @@ -703,7 +739,8 @@ def LoadStoreBase(name, Name, ea_code, memacc_code, mem_flags, inst_flags, + memAccExecTemplate.subst(memacc_iop) + fullExecTemplate.subst(iop) + initiateAccTemplate.subst(iop) - + completeAccTemplate.subst(iop)) + + completeAccTemplate.subst(iop) + + memAccSizeTemplate.subst(memacc_iop)) }}; def format LoadOrNop(memacc_code, ea_code = {{ EA = Rb + disp; }}, diff --git a/src/arch/alpha/miscregfile.cc b/src/arch/alpha/miscregfile.cc index 61a86f1fb..5dc316a83 100644 --- a/src/arch/alpha/miscregfile.cc +++ b/src/arch/alpha/miscregfile.cc @@ -57,8 +57,15 @@ MiscRegFile::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_ARRAY(ipr, NumInternalProcRegs); } +MiscRegFile::MiscRegFile(BaseCPU *_cpu) +{ + cpu = _cpu; + initializeIprTable(); +} + + MiscReg -MiscRegFile::readRegNoEffect(int misc_reg) +MiscRegFile::readRegNoEffect(int misc_reg, unsigned tid ) { switch (misc_reg) { case MISCREG_FPCR: @@ -78,7 +85,7 @@ MiscRegFile::readRegNoEffect(int misc_reg) } MiscReg -MiscRegFile::readReg(int misc_reg, ThreadContext *tc) +MiscRegFile::readReg(int misc_reg, ThreadContext *tc, unsigned tid ) { switch (misc_reg) { case MISCREG_FPCR: @@ -97,7 +104,7 @@ MiscRegFile::readReg(int misc_reg, ThreadContext *tc) } void -MiscRegFile::setRegNoEffect(int misc_reg, const MiscReg &val) +MiscRegFile::setRegNoEffect(int misc_reg, const MiscReg &val, unsigned tid) { switch (misc_reg) { case MISCREG_FPCR: @@ -123,7 +130,8 @@ MiscRegFile::setRegNoEffect(int misc_reg, const MiscReg &val) } void -MiscRegFile::setReg(int misc_reg, const MiscReg &val, ThreadContext *tc) +MiscRegFile::setReg(int misc_reg, const MiscReg &val, ThreadContext *tc, + unsigned tid) { switch (misc_reg) { case MISCREG_FPCR: diff --git a/src/arch/alpha/miscregfile.hh b/src/arch/alpha/miscregfile.hh index 6105ce683..b194e00bb 100644 --- a/src/arch/alpha/miscregfile.hh +++ b/src/arch/alpha/miscregfile.hh @@ -41,6 +41,7 @@ class Checkpoint; class ThreadContext; +class BaseCPU; namespace AlphaISA { @@ -68,6 +69,8 @@ class MiscRegFile InternalProcReg ipr[NumInternalProcRegs]; // Internal processor regs + BaseCPU *cpu; + protected: InternalProcReg readIpr(int idx, ThreadContext *tc); void setIpr(int idx, InternalProcReg val, ThreadContext *tc); @@ -78,16 +81,18 @@ class MiscRegFile initializeIprTable(); } + MiscRegFile(BaseCPU *cpu); + // These functions should be removed once the simplescalar cpu // model has been replaced. int getInstAsid(); int getDataAsid(); - MiscReg readRegNoEffect(int misc_reg); - MiscReg readReg(int misc_reg, ThreadContext *tc); + MiscReg readRegNoEffect(int misc_reg, unsigned tid = 0); + MiscReg readReg(int misc_reg, ThreadContext *tc, unsigned tid = 0); - void setRegNoEffect(int misc_reg, const MiscReg &val); - void setReg(int misc_reg, const MiscReg &val, ThreadContext *tc); + void setRegNoEffect(int misc_reg, const MiscReg &val, unsigned tid = 0); + void setReg(int misc_reg, const MiscReg &val, ThreadContext *tc, unsigned tid = 0); void clear() @@ -101,6 +106,16 @@ class MiscRegFile void serialize(std::ostream &os); void unserialize(Checkpoint *cp, const std::string §ion); + + void reset(std::string core_name, unsigned num_threads, + unsigned num_vpes, BaseCPU *_cpu) + { } + + + void expandForMultithreading(unsigned num_threads, unsigned num_vpes) + { } + + }; void copyIprs(ThreadContext *src, ThreadContext *dest); diff --git a/src/arch/mips/regfile/misc_regfile.hh b/src/arch/mips/regfile/misc_regfile.hh index c611d94cc..0daf8f718 100644 --- a/src/arch/mips/regfile/misc_regfile.hh +++ b/src/arch/mips/regfile/misc_regfile.hh @@ -69,7 +69,7 @@ namespace MipsISA public: MiscRegFile(); - MiscRegFile(BaseCPU *cpu); + MiscRegFile(BaseCPU *_cpu); void init(); diff --git a/src/cpu/inorder/cpu.cc b/src/cpu/inorder/cpu.cc index 0b38f39bc..83e94e74d 100644 --- a/src/cpu/inorder/cpu.cc +++ b/src/cpu/inorder/cpu.cc @@ -180,15 +180,26 @@ InOrderCPU::InOrderCPU(Params *params) // Bind the fetch & data ports from the resource pool. fetchPortIdx = resPool->getPortIdx(params->fetchMemPort); if (fetchPortIdx == 0) { - warn("Unable to find port to fetch instructions from.\n"); + fatal("Unable to find port to fetch instructions from.\n"); } dataPortIdx = resPool->getPortIdx(params->dataMemPort); if (dataPortIdx == 0) { - warn("Unable to find port for data.\n"); + fatal("Unable to find port for data.\n"); } + // Hard-Code Bindings to ITB & DTB + itbIdx = resPool->getResIdx(name() + "." + "I-TLB"); + if (itbIdx == 0) { + fatal("Unable to find ITB resource.\n"); + } + + dtbIdx = resPool->getResIdx(name() + "." + "D-TLB"); + if (dtbIdx == 0) { + fatal("Unable to find DTB resource.\n"); + } + for (int i = 0; i < numThreads; ++i) { if (i < params->workload.size()) { DPRINTF(InOrderCPU, "Workload[%i] process is %#x\n", @@ -814,6 +825,13 @@ InOrderCPU::removeThread(unsigned tid) /** Broadcast to CPU resources*/ } +PipelineStage* +InOrderCPU::getPipeStage(int stage_num) +{ + return pipelineStage[stage_num]; +} + + void InOrderCPU::activateWhenReady(int tid) { @@ -1245,3 +1263,18 @@ InOrderCPU::write(DynInstPtr inst) Resource *mem_res = resPool->getResource(dataPortIdx); return mem_res->doDataAccess(inst); } + +TheISA::ITB* +InOrderCPU::getITBPtr() +{ + TLBUnit *itb_res = dynamic_cast(resPool->getResource(itbIdx)); + return dynamic_cast(itb_res->tlb()); +} + + +TheISA::DTB* +InOrderCPU::getDTBPtr() +{ + TLBUnit *dtb_res = dynamic_cast(resPool->getResource(dtbIdx)); + return dynamic_cast(dtb_res->tlb()); +} diff --git a/src/cpu/inorder/cpu.hh b/src/cpu/inorder/cpu.hh index 744dd5cf9..8b2442ac0 100644 --- a/src/cpu/inorder/cpu.hh +++ b/src/cpu/inorder/cpu.hh @@ -103,9 +103,6 @@ class InOrderCPU : public BaseCPU Params *cpu_params; - TheISA::TLB * itb; - TheISA::TLB * dtb; - public: enum Status { Running, @@ -236,11 +233,17 @@ class InOrderCPU : public BaseCPU */ unsigned fetchPortIdx; + /** Identifies the resource id that identifies a ITB */ + unsigned itbIdx; + /** Identifies the resource id that identifies a data * access unit. */ unsigned dataPortIdx; + /** Identifies the resource id that identifies a DTB */ + unsigned dtbIdx; + /** The Pipeline Stages for the CPU */ PipelineStage *pipelineStage[ThePipeline::NumStages]; @@ -262,6 +265,9 @@ class InOrderCPU : public BaseCPU /** Communication structure that sits in between pipeline stages */ StageQueue *stageQueue[ThePipeline::NumStages-1]; + TheISA::ITB *getITBPtr(); + TheISA::DTB *getDTBPtr(); + public: /** Registers statistics. */ @@ -308,6 +314,8 @@ class InOrderCPU : public BaseCPU void deallocateThread(unsigned tid); void deactivateThread(unsigned tid); + PipelineStage* getPipeStage(int stage_num); + int contextId() { diff --git a/src/cpu/inorder/inorder_dyn_inst.hh b/src/cpu/inorder/inorder_dyn_inst.hh index 3b47624fb..12a9a4176 100644 --- a/src/cpu/inorder/inorder_dyn_inst.hh +++ b/src/cpu/inorder/inorder_dyn_inst.hh @@ -37,7 +37,10 @@ #include #include +#include "arch/isa_traits.hh" #include "arch/faults.hh" +#include "arch/types.hh" +#include "arch/mt.hh" #include "base/fast_alloc.hh" #include "base/trace.hh" #include "cpu/inorder/inorder_trace.hh" @@ -827,6 +830,10 @@ class InOrderDynInst : public FastAlloc, public RefCounted virtual uint64_t readRegOtherThread(unsigned idx, int tid = -1); virtual void setRegOtherThread(unsigned idx, const uint64_t &val, int tid = -1); + /** Sets the number of consecutive store conditional failures. */ + void setStCondFailures(unsigned sc_failures) + { thread->storeCondFailures = sc_failures; } + ////////////////////////////////////////////////////////////// // // INSTRUCTION STATUS FLAGS (READ/SET) diff --git a/src/cpu/inorder/resource_pool.cc b/src/cpu/inorder/resource_pool.cc index 94af68c7a..725f6cbb3 100644 --- a/src/cpu/inorder/resource_pool.cc +++ b/src/cpu/inorder/resource_pool.cc @@ -143,6 +143,21 @@ ResourcePool::getPortIdx(const std::string &port_name) return 0; } +unsigned +ResourcePool::getResIdx(const std::string &res_name) +{ + DPRINTF(Resource, "Finding Resource Idx for %s.\n", res_name); + + int num_resources = resources.size(); + + for (int idx = 0; idx < num_resources; idx++) { + if (resources[idx]->name() == res_name) + return idx; + } + + return 0; +} + ResReqPtr ResourcePool::request(int res_idx, DynInstPtr inst) { diff --git a/src/cpu/inorder/resource_pool.hh b/src/cpu/inorder/resource_pool.hh index 35fce7db7..6cc1f77e6 100644 --- a/src/cpu/inorder/resource_pool.hh +++ b/src/cpu/inorder/resource_pool.hh @@ -131,8 +131,12 @@ class ResourcePool { Port* getPort(const std::string &if_name, int idx); /** Returns a specific port. */ - unsigned getPortIdx(const std::string &if_name); + unsigned getPortIdx(const std::string &port_name); + /** Returns a specific resource. */ + unsigned getResIdx(const std::string &res_name); + + /** Returns a pointer to a resource */ Resource* getResource(int res_idx) { return resources[res_idx]; } /** Request usage of this resource. Returns -1 if not granted and diff --git a/src/cpu/inorder/resources/cache_unit.cc b/src/cpu/inorder/resources/cache_unit.cc index 772437638..d273d7247 100644 --- a/src/cpu/inorder/resources/cache_unit.cc +++ b/src/cpu/inorder/resources/cache_unit.cc @@ -32,7 +32,7 @@ #include #include #include "arch/isa_traits.hh" -#include "arch/mips/locked_mem.hh" +#include "arch/locked_mem.hh" #include "arch/utility.hh" #include "cpu/inorder/resources/cache_unit.hh" #include "cpu/inorder/pipeline_traits.hh" diff --git a/src/cpu/inorder/resources/mult_div_unit.cc b/src/cpu/inorder/resources/mult_div_unit.cc index b31d60ad5..df9d4c293 100644 --- a/src/cpu/inorder/resources/mult_div_unit.cc +++ b/src/cpu/inorder/resources/mult_div_unit.cc @@ -47,7 +47,7 @@ MultDivUnit::MultDivUnit(string res_name, int res_id, int res_width, div16RepeatRate(params->div16RepeatRate), div16Latency(params->div16Latency), div24RepeatRate(params->div24RepeatRate), div24Latency(params->div24Latency), div32RepeatRate(params->div32RepeatRate), div32Latency(params->div32Latency), - lastMDUCycle(0) + lastMDUCycle(0), lastOpType(No_OpClass) { } void diff --git a/src/cpu/inorder/resources/tlb_unit.cc b/src/cpu/inorder/resources/tlb_unit.cc index b3757d707..fbc6bc195 100644 --- a/src/cpu/inorder/resources/tlb_unit.cc +++ b/src/cpu/inorder/resources/tlb_unit.cc @@ -33,6 +33,7 @@ #include #include "arch/isa_traits.hh" #include "cpu/inorder/pipeline_traits.hh" +#include "cpu/inorder/first_stage.hh" #include "cpu/inorder/resources/tlb_unit.hh" #include "cpu/inorder/cpu.hh" @@ -44,11 +45,26 @@ TLBUnit::TLBUnit(string res_name, int res_id, int res_width, int res_latency, InOrderCPU *_cpu, ThePipeline::Params *params) : InstBuffer(res_name, res_id, res_width, res_latency, _cpu, params) { + // Hard-Code Selection For Now + if (res_name == "I-TLB") + _tlb = params->itb; + else if (res_name == "D-TLB") + _tlb = params->dtb; + else + fatal("Unrecognized TLB name passed by user"); + for (int i=0; i < MaxThreads; i++) { tlbBlocked[i] = false; } } +TheISA::TLB* +TLBUnit::tlb() +{ + return _tlb; + +} + void TLBUnit::init() { @@ -82,7 +98,7 @@ TLBUnit::execute(int slot_idx) // After this is working, change this to a reinterpret cast // for performance considerations TLBUnitRequest* tlb_req = dynamic_cast(reqMap[slot_idx]); - assert(tlb_req); + assert(tlb_req != 0x0); DynInstPtr inst = tlb_req->inst; int tid, seq_num, stage_num; @@ -93,12 +109,15 @@ TLBUnit::execute(int slot_idx) tlb_req->fault = NoFault; + assert(cpu->thread[tid]->getTC() != 0x0); + assert(cpu->pipelineStage[stage_num] != 0x0); + switch (tlb_req->cmd) { case FetchLookup: { tlb_req->fault = - this->cpu->itb->translateAtomic(tlb_req->memReq, + _tlb->translateAtomic(tlb_req->memReq, cpu->thread[tid]->getTC(), false, true); if (tlb_req->fault != NoFault) { @@ -129,7 +148,7 @@ TLBUnit::execute(int slot_idx) tid, seq_num, tlb_req->memReq->getVaddr()); tlb_req->fault = - this->cpu->itb->translateAtomic(tlb_req->memReq, + _tlb->translateAtomic(tlb_req->memReq, cpu->thread[tid]->getTC()); if (tlb_req->fault != NoFault) { diff --git a/src/cpu/inorder/resources/tlb_unit.hh b/src/cpu/inorder/resources/tlb_unit.hh index c7fee6030..b53f251fc 100644 --- a/src/cpu/inorder/resources/tlb_unit.hh +++ b/src/cpu/inorder/resources/tlb_unit.hh @@ -67,14 +67,15 @@ class TLBUnit : public InstBuffer { bool tlbBlocked[ThePipeline::MaxThreads]; + TheISA::TLB* tlb(); + protected: /** List of instructions this resource is currently * processing. */ std::list instList; - /** @todo: Add Resource Stats Here */ - + TheISA::TLB *_tlb; }; class TLBUnitEvent : public ResourceEvent { diff --git a/src/cpu/inorder/thread_context.hh b/src/cpu/inorder/thread_context.hh index ec8cc1979..cde377dfc 100644 --- a/src/cpu/inorder/thread_context.hh +++ b/src/cpu/inorder/thread_context.hh @@ -57,7 +57,7 @@ class InOrderThreadContext : public ThreadContext public: InOrderThreadContext() { } - /** Pointer to the CPU. */ + /** Pointer to the CPU. */ InOrderCPU *cpu; /** Pointer to the thread state that this TC corrseponds to. */ @@ -65,10 +65,12 @@ class InOrderThreadContext : public ThreadContext /** Returns a pointer to the ITB. */ - TheISA::TLB *getITBPtr() { return cpu->itb; } + /** @TODO: PERF: Should we bind this to a pointer in constructor? */ + TheISA::TLB *getITBPtr() { return cpu->getITBPtr(); } /** Returns a pointer to the DTB. */ - TheISA::TLB *getDTBPtr() { return cpu->dtb; } + /** @TODO: PERF: Should we bind this to a pointer in constructor? */ + TheISA::TLB *getDTBPtr() { return cpu->getDTBPtr(); } System *getSystemPtr() { return cpu->system; } -- 2.30.2