decode_impl.hh revision 1060
12SN/A#ifndef __SIMPLE_DECODE_CC__ 22188SN/A#define __SIMPLE_DECODE_CC__ 32SN/A 42SN/A#include "cpu/beta_cpu/decode.hh" 52SN/A 62SN/Atemplate<class Impl> 72SN/ASimpleDecode<Impl>::SimpleDecode(Params ¶ms) 82SN/A : renameToDecodeDelay(params.renameToDecodeDelay), 92SN/A iewToDecodeDelay(params.iewToDecodeDelay), 102SN/A commitToDecodeDelay(params.commitToDecodeDelay), 112SN/A fetchToDecodeDelay(params.fetchToDecodeDelay), 122SN/A decodeWidth(params.decodeWidth) 132SN/A{ 142SN/A DPRINTF(Decode, "Decode: decodeWidth=%i.\n", decodeWidth); 152SN/A _status = Idle; 162SN/A} 172SN/A 182SN/Atemplate<class Impl> 192SN/Avoid 202SN/ASimpleDecode<Impl>::setCPU(FullCPU *cpu_ptr) 212SN/A{ 222SN/A DPRINTF(Decode, "Decode: Setting CPU pointer.\n"); 232SN/A cpu = cpu_ptr; 242SN/A} 252SN/A 262SN/Atemplate<class Impl> 272665SN/Avoid 282665SN/ASimpleDecode<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr) 292665SN/A{ 302SN/A DPRINTF(Decode, "Decode: Setting time buffer pointer.\n"); 312SN/A timeBuffer = tb_ptr; 322683Sktlim@umich.edu 332683Sktlim@umich.edu // Setup wire to write information back to fetch. 342SN/A toFetch = timeBuffer->getWire(0); 352190SN/A 363776Sgblack@eecs.umich.edu // Create wires to get information from proper places in time buffer. 374997Sgblack@eecs.umich.edu fromRename = timeBuffer->getWire(-renameToDecodeDelay); 386216Snate@binkert.org fromIEW = timeBuffer->getWire(-iewToDecodeDelay); 391858SN/A fromCommit = timeBuffer->getWire(-commitToDecodeDelay); 402680SN/A} 412683Sktlim@umich.edu 422395SN/Atemplate<class Impl> 432190SN/Avoid 442188SN/ASimpleDecode<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr) 45217SN/A{ 462SN/A DPRINTF(Decode, "Decode: Setting decode queue pointer.\n"); 472SN/A decodeQueue = dq_ptr; 482SN/A 491858SN/A // Setup wire to write information to proper place in decode queue. 502SN/A toRename = decodeQueue->getWire(0); 511070SN/A} 521070SN/A 531917SN/Atemplate<class Impl> 541917SN/Avoid 552521SN/ASimpleDecode<Impl>::setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr) 562521SN/A{ 572521SN/A DPRINTF(Decode, "Decode: Setting fetch queue pointer.\n"); 583548Sgblack@eecs.umich.edu fetchQueue = fq_ptr; 593548Sgblack@eecs.umich.edu 603548Sgblack@eecs.umich.edu // Setup wire to read information from fetch queue. 613548Sgblack@eecs.umich.edu fromFetch = fetchQueue->getWire(-fetchToDecodeDelay); 622330SN/A} 632330SN/A 642SN/Atemplate<class Impl> 652SN/Avoid 66360SN/ASimpleDecode<Impl>::block() 672462SN/A{ 682420SN/A DPRINTF(Decode, "Decode: Blocking.\n"); 692SN/A 702SN/A // Set the status to Blocked. 712SN/A _status = Blocked; 722683Sktlim@umich.edu 732683Sktlim@umich.edu // Add the current inputs to the skid buffer so they can be 742683Sktlim@umich.edu // reprocessed when this stage unblocks. 752683Sktlim@umich.edu skidBuffer.push(*fromFetch); 762683Sktlim@umich.edu 772683Sktlim@umich.edu // Note that this stage only signals previous stages to stall when 782683Sktlim@umich.edu // it is the cause of the stall originates at this stage. Otherwise 792683Sktlim@umich.edu // the previous stages are expected to check all possible stall signals. 802683Sktlim@umich.edu} 812683Sktlim@umich.edu 822683Sktlim@umich.edutemplate<class Impl> 832683Sktlim@umich.eduinline void 842683Sktlim@umich.eduSimpleDecode<Impl>::unblock() 852683Sktlim@umich.edu{ 862683Sktlim@umich.edu DPRINTF(Decode, "Decode: Unblocking, going to remove " 872SN/A "instructions from skid buffer.\n"); 882683Sktlim@umich.edu // Remove the now processed instructions from the skid buffer. 892SN/A skidBuffer.pop(); 902107SN/A 912107SN/A // If there's still information in the skid buffer, then 922107SN/A // continue to tell previous stages to stall. They will be 932107SN/A // able to restart once the skid buffer is empty. 942159SN/A if (!skidBuffer.empty()) { 952455SN/A toFetch->decodeInfo.stall = true; 962455SN/A } else { 972SN/A DPRINTF(Decode, "Decode: Finished unblocking.\n"); 982680SN/A _status = Running; 992SN/A } 1002190SN/A} 1015543Ssaidi@eecs.umich.edu 1022SN/A// This squash is specifically for when Decode detects a PC-relative branch 1032190SN/A// was predicted incorrectly. 1042683Sktlim@umich.edutemplate<class Impl> 1052SN/Avoid 1062SN/ASimpleDecode<Impl>::squash(DynInst *inst) 1072683Sktlim@umich.edu{ 1082188SN/A DPRINTF(Decode, "Decode: Squashing due to incorrect branch prediction " 1092378SN/A "detected at decode.\n"); 1102400SN/A Addr new_PC = inst->nextPC; 1116022Sgblack@eecs.umich.edu 1126022Sgblack@eecs.umich.edu toFetch->decodeInfo.predIncorrect = true; 1132SN/A toFetch->decodeInfo.squash = true; 1142683Sktlim@umich.edu toFetch->decodeInfo.nextPC = new_PC; 1151858SN/A 1162683Sktlim@umich.edu // Set status to squashing. 1176022Sgblack@eecs.umich.edu _status = Squashing; 1182683Sktlim@umich.edu 1192SN/A // Maybe advance the time buffer? Not sure what to do in the normal 1204997Sgblack@eecs.umich.edu // case. 1216022Sgblack@eecs.umich.edu 1222SN/A // Clear the skid buffer in case it has any data in it. 1232862Sktlim@umich.edu while (!skidBuffer.empty()) 1242864Sktlim@umich.edu { 1252862Sktlim@umich.edu skidBuffer.pop(); 1262683Sktlim@umich.edu } 1272SN/A} 1282680SN/A 129180SN/Atemplate<class Impl> 1302SN/Avoid 1312SN/ASimpleDecode<Impl>::squash() 1322864Sktlim@umich.edu{ 1332864Sktlim@umich.edu DPRINTF(Decode, "Decode: Squashing.\n"); 1342862Sktlim@umich.edu // Set status to squashing. 1352862Sktlim@umich.edu _status = Squashing; 136217SN/A 137237SN/A // Maybe advance the time buffer? Not sure what to do in the normal 138217SN/A // case. 1392683Sktlim@umich.edu 1402683Sktlim@umich.edu // Clear the skid buffer in case it has any data in it. 1415891Sgblack@eecs.umich.edu while (!skidBuffer.empty()) 1422683Sktlim@umich.edu { 1432190SN/A skidBuffer.pop(); 1442683Sktlim@umich.edu } 1452683Sktlim@umich.edu} 1462683Sktlim@umich.edu 1472683Sktlim@umich.edutemplate<class Impl> 1482680SN/Avoid 1492190SN/ASimpleDecode<Impl>::tick() 1505358Sgblack@eecs.umich.edu{ 1515358Sgblack@eecs.umich.edu // Decode should try to execute as many instructions as its bandwidth 1525358Sgblack@eecs.umich.edu // will allow, as long as it is not currently blocked. 1535358Sgblack@eecs.umich.edu if (_status != Blocked && _status != Squashing) { 1545358Sgblack@eecs.umich.edu DPRINTF(Decode, "Decode: Not blocked, so attempting to run " 1555358Sgblack@eecs.umich.edu "stage.\n"); 1565358Sgblack@eecs.umich.edu // Make sure that the skid buffer has something in it if the 1575358Sgblack@eecs.umich.edu // status is unblocking. 1585358Sgblack@eecs.umich.edu assert(_status == Unblocking ? !skidBuffer.empty() : 1); 1595358Sgblack@eecs.umich.edu 1605358Sgblack@eecs.umich.edu decode(); 1615358Sgblack@eecs.umich.edu 1625358Sgblack@eecs.umich.edu // If the status was unblocking, then instructions from the skid 1635358Sgblack@eecs.umich.edu // buffer were used. Remove those instructions and handle 1645358Sgblack@eecs.umich.edu // the rest of unblocking. 1655358Sgblack@eecs.umich.edu if (_status == Unblocking) { 1664997Sgblack@eecs.umich.edu unblock(); 1674997Sgblack@eecs.umich.edu } 1684997Sgblack@eecs.umich.edu } else if (_status == Blocked) { 1694997Sgblack@eecs.umich.edu if (fromFetch->insts[0] != NULL) { 1702683Sktlim@umich.edu block(); 1712521SN/A } 1725702Ssaidi@eecs.umich.edu 1735702Ssaidi@eecs.umich.edu if (!fromRename->renameInfo.stall && 1745702Ssaidi@eecs.umich.edu !fromIEW->iewInfo.stall && 1755702Ssaidi@eecs.umich.edu !fromCommit->commitInfo.stall) { 1762683Sktlim@umich.edu DPRINTF(Decode, "Decode: Stall signals cleared, going to " 1772SN/A "unblock.\n"); 1782683Sktlim@umich.edu _status = Unblocking; 1792683Sktlim@umich.edu 1802683Sktlim@umich.edu // Continue to tell previous stage to block until this 1812683Sktlim@umich.edu // stage is done unblocking. 1822683Sktlim@umich.edu toFetch->decodeInfo.stall = true; 1832683Sktlim@umich.edu } else { 1846022Sgblack@eecs.umich.edu DPRINTF(Decode, "Decode: Still blocked.\n"); 1852683Sktlim@umich.edu toFetch->decodeInfo.stall = true; 1866022Sgblack@eecs.umich.edu } 1872683Sktlim@umich.edu 1884997Sgblack@eecs.umich.edu if (fromCommit->commitInfo.squash || 1894997Sgblack@eecs.umich.edu fromCommit->commitInfo.robSquashing) { 1905803Snate@binkert.org squash(); 1912683Sktlim@umich.edu } 1922683Sktlim@umich.edu } else if (_status == Squashing) { 1935499Ssaidi@eecs.umich.edu if (!fromCommit->commitInfo.squash && 1945499Ssaidi@eecs.umich.edu !fromCommit->commitInfo.robSquashing) { 1955499Ssaidi@eecs.umich.edu _status = Running; 1965499Ssaidi@eecs.umich.edu } else if (fromCommit->commitInfo.squash) { 1975499Ssaidi@eecs.umich.edu squash(); 1982SN/A } 1992SN/A } 2002683Sktlim@umich.edu} 2012683Sktlim@umich.edu 2022683Sktlim@umich.edutemplate<class Impl> 2032683Sktlim@umich.eduvoid 2042683Sktlim@umich.eduSimpleDecode<Impl>::decode() 2052683Sktlim@umich.edu{ 2062683Sktlim@umich.edu // Check time buffer if being told to squash. 2072683Sktlim@umich.edu if (/* fromRename->renameInfo.squash || */ 2082683Sktlim@umich.edu /* fromIEW->iewInfo.squash || */ 2092683Sktlim@umich.edu fromCommit->commitInfo.squash) { 2102683Sktlim@umich.edu squash(); 2112683Sktlim@umich.edu return; 2122683Sktlim@umich.edu } 2132683Sktlim@umich.edu 2142SN/A // Check time buffer if being told to stall. 2152SN/A if (fromRename->renameInfo.stall || 2162532SN/A fromIEW->iewInfo.stall || 217716SN/A fromCommit->commitInfo.stall) 2182378SN/A { 2192378SN/A block(); 2202423SN/A return; 221716SN/A } 222716SN/A 2232683Sktlim@umich.edu // Check fetch queue to see if instructions are available. 2242190SN/A // If no available instructions, do nothing, unless this stage is 2252683Sktlim@umich.edu // currently unblocking. 2262190SN/A if (fromFetch->insts[0] == NULL && _status != Unblocking) { 2272SN/A DPRINTF(Decode, "Decode: Nothing to do, breaking out early.\n"); 2282SN/A // Should I change the status to idle? 2292SN/A return; 2302SN/A } 2312SN/A 2325082Sgblack@eecs.umich.edu DynInst *inst; 2335082Sgblack@eecs.umich.edu // Instead have a class member variable that records which instruction 2342SN/A // was the last one that was ended on. At the tick() stage, it can 2352SN/A // check if that's equal to 0. If not, then don't pop stuff off. 2362455SN/A unsigned num_inst = 0; 2372SN/A bool insts_available = _status == Unblocking ? 2385088Sgblack@eecs.umich.edu skidBuffer.front().insts[num_inst] != NULL : 2395082Sgblack@eecs.umich.edu fromFetch->insts[num_inst] != NULL; 2402SN/A 2412SN/A // Debug block... 2422455SN/A#if 0 2432SN/A if (insts_available) { 2445088Sgblack@eecs.umich.edu DPRINTF(Decode, "Decode: Instructions available.\n"); 2455082Sgblack@eecs.umich.edu } else { 2462SN/A if (_status == Unblocking && skidBuffer.empty()) { 2472SN/A DPRINTF(Decode, "Decode: No instructions available, skid buffer " 2482455SN/A "empty.\n"); 2492SN/A } else if (_status != Unblocking && 2505088Sgblack@eecs.umich.edu fromFetch->insts[0] == NULL) { 2515082Sgblack@eecs.umich.edu DPRINTF(Decode, "Decode: No instructions available, fetch queue " 2522455SN/A "empty.\n"); 2532455SN/A } else { 2542455SN/A panic("Decode: No instructions available, unexpected condition!" 2552455SN/A "\n"); 2565088Sgblack@eecs.umich.edu } 2575082Sgblack@eecs.umich.edu } 2582SN/A#endif 2592SN/A 2602SN/A // Check to make sure that instructions coming from fetch are valid. 2612SN/A // Normally at this stage the branch target of PC-relative branches 2625082Sgblack@eecs.umich.edu // should be computed here. However in this simple model all 2635082Sgblack@eecs.umich.edu // computation will take place at execute. Hence doneTargCalc() 2642SN/A // will always be false. 2652SN/A while (num_inst < decodeWidth && 2662455SN/A insts_available) 2672SN/A { 2685088Sgblack@eecs.umich.edu DPRINTF(Decode, "Decode: Sending instruction to rename.\n"); 2695082Sgblack@eecs.umich.edu // Might create some sort of accessor to get an instruction 2702SN/A // on a per thread basis. Or might be faster to just get 2712SN/A // a pointer to an array or list of instructions and use that 2722455SN/A // within this code. 2732SN/A inst = _status == Unblocking ? skidBuffer.front().insts[num_inst] : 2745088Sgblack@eecs.umich.edu fromFetch->insts[num_inst]; 2755082Sgblack@eecs.umich.edu DPRINTF(Decode, "Decode: Processing instruction %i with PC %#x\n", 2762SN/A inst, inst->readPC()); 2772SN/A 2782455SN/A // This current instruction is valid, so add it into the decode 2792SN/A // queue. The next instruction may not be valid, so check to 2805088Sgblack@eecs.umich.edu // see if branches were predicted correctly. 2815082Sgblack@eecs.umich.edu toRename->insts[num_inst] = inst; 2822455SN/A 2832455SN/A // Ensure that if it was predicted as a branch, it really is a 2842455SN/A // branch. This case should never happen in this model. 2852455SN/A if (inst->predTaken() && !inst->isControl()) { 2865088Sgblack@eecs.umich.edu panic("Instruction predicted as a branch!"); 2875082Sgblack@eecs.umich.edu 2882SN/A // Might want to set some sort of boolean and just do 2892SN/A // a check at the end 2902SN/A squash(inst); 2912SN/A break; 2922525SN/A } 2932SN/A 2942SN/A // Ensure that the predicted branch target is the actual branch 2952190SN/A // target if possible (branches that are PC relative). 2962190SN/A if (inst->isControl() && inst->doneTargCalc()) { 2972525SN/A if (inst->mispredicted()) { 2982190SN/A // Might want to set some sort of boolean and just do 2992190SN/A // a check at the end 3003276Sgblack@eecs.umich.edu squash(inst); 3013276Sgblack@eecs.umich.edu break; 3023276Sgblack@eecs.umich.edu } 3033276Sgblack@eecs.umich.edu } 3043276Sgblack@eecs.umich.edu 3053276Sgblack@eecs.umich.edu // Also check if instructions have no source registers. Mark 3063276Sgblack@eecs.umich.edu // them as ready to issue at any time. Not sure if this check 3073276Sgblack@eecs.umich.edu // should exist here or at a later stage; however it doesn't matter 3083276Sgblack@eecs.umich.edu // too much for function correctness. 3093276Sgblack@eecs.umich.edu if (inst->numSrcRegs() == 0) { 3102190SN/A inst->setCanIssue(); 3112190SN/A } 3122525SN/A 3132190SN/A // Increment which instruction we're looking at. 3142190SN/A ++num_inst; 3152SN/A 3162SN/A // Check whether or not there are instructions available. 3172525SN/A // Either need to check within the skid buffer, or the fetch 3182SN/A // queue, depending if this stage is unblocking or not. 3192SN/A insts_available = _status == Unblocking ? 3203276Sgblack@eecs.umich.edu skidBuffer.front().insts[num_inst] == NULL : 3213276Sgblack@eecs.umich.edu fromFetch->insts[num_inst] == NULL; 3223276Sgblack@eecs.umich.edu } 3233276Sgblack@eecs.umich.edu} 3243276Sgblack@eecs.umich.edu 3253276Sgblack@eecs.umich.edu#endif // __SIMPLE_DECODE_CC__ 3263276Sgblack@eecs.umich.edu