📄 exec.cc
字号:
/* * Copyright (c) 2002 The Board of Trustees of the University of Illinois and * William Marsh Rice University * Copyright (c) 2002 The University of Utah * Copyright (c) 2002 The University of Notre Dame du Lac * * All rights reserved. * * Based on RSIM 1.0, developed by: * Professor Sarita Adve's RSIM research group * University of Illinois at Urbana-Champaign and William Marsh Rice University * http://www.cs.uiuc.edu/rsim and http://www.ece.rice.edu/~rsim/dist.html * ML-RSIM/URSIM extensions by: * The Impulse Research Group, University of Utah * http://www.cs.utah.edu/impulse * Lambert Schaelicke, University of Utah and University of Notre Dame du Lac * http://www.cse.nd.edu/~lambert * Mike Parker, University of Utah * http://www.cs.utah.edu/~map * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal with the Software without restriction, including without * limitation the rights to use, copy, modify, merge, publish, distribute, * sublicense, and/or sell copies of the Software, and to permit persons to * whom the Software is furnished to do so, subject to the following * conditions: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimers. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimers in the * documentation and/or other materials provided with the distribution. * 3. Neither the names of Professor Sarita Adve's RSIM research group, * the University of Illinois at Urbana-Champaign, William Marsh Rice * University, nor the names of its contributors may be used to endorse * or promote products derived from this Software without specific prior * written permission. * 4. Neither the names of the ML-RSIM project, the URSIM project, the * Impulse research group, the University of Utah, the University of * Notre Dame du Lac, nor the names of its contributors may be used to * endorse or promote products derived from this software without specific * prior written permission. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS WITH THE SOFTWARE. */#include <sys/time.h>#include <limits.h>extern "C"{#include "sim_main/simsys.h"} #include "Processor/procstate.h"#include "Processor/branchpred.h"#include "Processor/memunit.h"#include "Processor/mainsim.h"#include "Processor/exec.h"#include "Processor/fetch_queue.h"#include "Processor/simio.h"#include "Processor/fastnews.h"#include "Processor/fsr.h"#include "Processor/tagcvt.hh"#include "Processor/active.hh"#include "Processor/procstate.hh"#include "Processor/memunit.hh"#include "Processor/stallq.hh"#include "Processor/exec.hh"#ifdef sgi#define LLONG_MAX LONGLONG_MAX#endif#if !defined(LLONG_MAX)# define LLONG_MAX 9223372036854775807LL#endif#ifdef sparc#pragma align 8 (TheBadPC)#endifinstr *TheBadPC = new instr(iSETHI);#ifdef sgi#pragma align_symbol (TheBadPC, 8)#endif#define min(a, b) ((a) > (b) ? (b) : (a))/***************************************************************************//***************************************************************************/int fetch_cycle(ProcState * proc){ instr *instrn; int rc, attributes, count; unsigned phys_pc; Queue<fetch_queue_entry> *fetch_queue = proc->fetch_queue; fetch_queue_entry fqe; if ((proc->interrupt_pending) && (PSTATE_GET_IE(proc->pstate) && (fetch_queue->NumItems() < proc->fetch_queue_size))) { int n = 31; while (((proc->interrupt_pending & (0x00000001 << n)) == 0) && (n > 0)) n--; if (n > proc->pil) { fqe.exception_code = (enum except)(INTERRUPT_00 - n); fqe.inst = NewInstance(TheBadPC, proc); // TLB miss or prot. fault fqe.pc = proc->fetch_pc; // insert NOP with exception set fetch_queue->Enqueue(fqe); return(0); } } if ((!proc->fetch_done) || (L1IQ_FULL[proc->proc_id])) return(0); count = min(proc->fetch_rate, (ARCH_linesz1i - (proc->fetch_pc % ARCH_linesz1i)) / SIZE_OF_SPARC_INSTRUCTION); //------------------------------------------------------------------------- // do one TLB access if I-TLB is enabled phys_pc = proc->fetch_pc; attributes = 0; if (PSTATE_GET_ITE(proc->pstate)) { rc = proc->itlb-> LookUp(&phys_pc, &attributes, proc->log_int_reg_file[arch_to_log(proc, proc->cwp, PRIV_TLB_CONTEXT)], 0, PSTATE_GET_PRIV(proc->pstate), LLONG_MAX); if (rc != TLB_HIT) { if (fetch_queue->NumItems() < proc->fetch_queue_size) { if (rc == TLB_MISS) fqe.exception_code = ITLB_MISS; if (rc == TLB_FAULT) fqe.exception_code = INSTR_FAULT; fqe.inst = NewInstance(TheBadPC, proc); fqe.pc = proc->fetch_pc; // insert NOP with exception set fetch_queue->Enqueue(fqe); } return(0); } } ICache_recv_addr(proc->proc_id, proc->fetch_pc, phys_pc, count, attributes, proc->pstate); proc->fetch_done = 0; return 0;}/*************************************************************************//* decode_cycle : brings new instructions into active list *//*************************************************************************/ /* decode_cycle() -- The decode routine called every cycle *//* This is organized into two main parts - *//* 1. Check the stall queue for instructions stalled from previous *//* cycles. *//* 2. Check the instructions for this cycle. *//*************************************************************************/int decode_cycle(ProcState * proc){#ifdef COREFILE if (proc->curr_cycle > DEBUG_TIME) fprintf(corefile, "ENTERING DECODE CYCLE-CYCLE NUMBER %d. UnitsFree: " "%d %d %d %d\n", proc->curr_cycle, proc->UnitsFree[uALU], proc->UnitsFree[uFP], proc->UnitsFree[uADDR], proc->UnitsFree[uMEM]);#endif instance *inst; Queue<fetch_queue_entry> *fetch_queue = proc->fetch_queue; fetch_queue_entry fqe; int brk = 0; int badpc = 0; int count = 0; int decoderate = proc->decode_rate; /* DECODE THIS CYCLE'S INSTRUCTIONS. */ if (proc->inst_save) { count++; if (check_dependencies(proc->inst_save, proc) != 0) brk = 1; else proc->inst_save = NULL; } if (proc->stall_the_rest) brk = 1; if (proc->stall_the_rest == -1ll) unstall_the_rest(proc);#ifdef DEBUG if (brk) return(0); if (proc->inst_save) YS__errmsg(proc->proc_id / ARCH_cpus, "proc->inst_save == %lld\n", proc->inst_save->tag);#endif /* Read in more instructions only if there are no branch stalls (or if there is a branch stall and the delay slot has to be read in) */ while ((count < decoderate) && (brk == 0) && !proc->sync) { /* get the instruction from the fetch queue */ if (fetch_queue->Empty()) { if (proc->fetch_pc != proc->pc) { proc->fetch_pc = proc->pc; proc->fetch_done = 1; } return -1; }#if 0#ifdef COREFILE instrn->print();#endif#endif fetch_queue->GetHead(fqe); fetch_queue->Dequeue(); inst = fqe.inst; if (fqe.pc != proc->pc) { DeleteInstance(inst, proc); continue; } count++; inst->decode_instruction(proc); AddtoTagConverter(inst->tag, inst, proc); if (fqe.exception_code != OK) { inst->exception_code = fqe.exception_code; proc->stall_the_rest = inst->tag; proc->type_of_stall_rest = eBADBR; } /* If there are dependencies, put it in the stall queue. check_dependencies takes care of issuing it if there are no dependencies */ if (check_dependencies(inst, proc) != 0) { proc->inst_save = inst; brk = 1; } /* If a pipeline bubble has to be inserted, then... */ if (proc->stall_the_rest) brk = 1; if (proc->stall_the_rest == -1ll) unstall_the_rest(proc); // this is just a xfer, not a real stall } return 0;}/**************************************************************************** * This functions reads in an instruction and converts to an instance. It * converts the static instruction to the dynamic instance. Initializes the * elements of instance and also does a preliminary check for hazards. ***************************************************************************/int instance::decode_instruction(ProcState * proc){ /* INITIALIZE DATA ELEMENTS OF INST */ tag = proc->instruction_count; /* Our instruction id henceforth! */ proc->instruction_count++; /* Increment Global variable */ unit_type = unit[code.instruction]; win_num = proc->cwp; /* before any change in this instruction. */ addr = 0; addr_ready = 0; mem_ready = 0; stallqs = 0; busybits = 0; in_memunit = 0; partial_overlap = 0; limbo = 0; kill = 0; vsbfwd = 0; miss = L1DHIT; latepf = 0; rs1valf = rs2valf = 0; rsccvali = 0; rsdvalf = 0; rccvali = rdvali = 0; time_active_list = YS__Simtime; issuetime = LLONG_MAX; // start it out as high as possible addrissuetime = LLONG_MAX; // used only in static sched; start out high /* Set up default dependency values */ truedep = 1; addrdep = 1; strucdep = 0; branchdep = 0; /* Make all other values zero */ completion = 0; newpc = 0; exception_code = OK; mispredicted = 0; taken = 0; memprogress = 0; proc->stall_the_rest = 0; proc->type_of_stall_rest = eNOEFF_LOSS; /* This is the first time the instruction is being processed, we will have to convert the window pointer, register number combination to a logical number and then allocate physical registers, etc.. */ /* Source register 1 */ switch (code.rs1_regtype) { case REG_FSR: case REG_INT: case REG_INT64: lrs1 = arch_to_log(proc, win_num, code.rs1); prs1 = proc->intmapper[lrs1]; break; case REG_FP: lrs1 = code.rs1; prs1 = proc->fpmapper[lrs1]; break; case REG_FPHALF: lrs1 = code.rs1; prs1 = proc->fpmapper[unsigned (lrs1) & ~1U]; break; case REG_INTPAIR: if (code.rs1 & 1) { /* odd source reg. */ exception_code = ILLEGAL; lrs1 = prs1 = prs1p = 0; } else { lrs1 = arch_to_log(proc, win_num, code.rs1); prs1 = proc->intmapper[lrs1]; prs1p = proc->intmapper[lrs1 + 1]; } break; default: break; } /* Source register 2 */ switch (code.rs2_regtype) { case REG_INT: case REG_INT64: lrs2 = arch_to_log(proc, win_num, code.rs2); prs2 = proc->intmapper[lrs2]; break; case REG_FP: lrs2 = code.rs2; prs2 = proc->fpmapper[lrs2]; break; case REG_FPHALF: lrs2 = code.rs2; prs2 = proc->fpmapper[unsigned (lrs2) & ~1U]; break; default: break; } /* Conditon code as a source register rscc */ lrscc = arch_to_log(proc, win_num, code.rscc); prscc = proc->intmapper[lrscc]; if (code.rd_regtype == REG_FPHALF) { /* Since FPs are mapped/renamed by doubles, we need to make the destination register as source also in this case */ lrsd = code.rd; prsd = proc->fpmapper[unsigned (lrsd) & ~1U]; } /*************************************************************/ /***************** Register window operations ****************/ /*************************************************************/ // Lets us NOW bump up or bring down the cwp if its a save/restore // instruction. Note that the source registers do not see the effect // of the change in the cwp while the destination registers do
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -