public uint Lookup(uint baddr, uint btarget, DynamicInstruction dynamicInst, out BranchPredictorUpdate dirUpdate, out uint stackRecoverIndex) { StaticInstruction staticInst = dynamicInst.StaticInstruction; if (!staticInst.IsControl) { dirUpdate = null; stackRecoverIndex = 0; return 0; } dirUpdate = new BranchPredictorUpdate (); dirUpdate.Ras = false; dirUpdate.Pdir1 = null; dirUpdate.Pdir2 = null; dirUpdate.Pmeta = null; if (staticInst.IsControl && !staticInst.IsUnconditionalBranch) { BranchPredictorInfo bimodCtr = this.Bimod.Lookup (baddr); BranchPredictorInfo twoLevelCtr = this.TwoLevel.Lookup (baddr); BranchPredictorInfo metaCtr = this.Meta.Lookup (baddr); dirUpdate.Pmeta = metaCtr; dirUpdate.Meta = (metaCtr.Value >= 2); dirUpdate.Bimod = (bimodCtr.Value >= 2); dirUpdate.TwoLevel = (bimodCtr.Value >= 2); if (metaCtr.Value >= 2) { dirUpdate.Pdir1 = twoLevelCtr; dirUpdate.Pdir2 = bimodCtr; } else { dirUpdate.Pdir1 = bimodCtr; dirUpdate.Pdir2 = twoLevelCtr; } } if (this.Ras.Size > 0) { stackRecoverIndex = this.Ras.TopOfStack; } else { stackRecoverIndex = 0; } if (staticInst.IsFunctionReturn && this.Ras.Size > 0) { this.Ras.TopOfStack = (this.Ras.TopOfStack + this.Ras.Size - 1) % this.Ras.Size; dirUpdate.Ras = true; } if (staticInst.IsFunctionCall && this.Ras.Size > 0) { this.Ras.TopOfStack = (this.Ras.TopOfStack + 1) % this.Ras.Size; this.Ras[this.Ras.TopOfStack].Target = (uint)(baddr + Marshal.SizeOf (typeof(uint))); } uint index = (baddr >> (int)BranchPredictorConstants.BRANCH_SHIFT) & (this.Btb.NumSets - 1); BranchTargetBufferEntry btbEntry = null; if (this.Btb.Associativity > 1) { index *= this.Btb.Associativity; for (uint i = index; i < (index + this.Btb.Associativity); i++) { if (this.Btb[i].Addr == baddr) { btbEntry = this.Btb[i]; break; } } } else { btbEntry = this.Btb[index]; if (btbEntry.Addr != baddr) { btbEntry = null; } } if (staticInst.IsControl && staticInst.IsUnconditionalBranch) { return btbEntry != null ? btbEntry.Target : 1; } if (btbEntry == null) { return (uint)(dirUpdate.Pdir1.Value >= 2 ? 1 : 0); } else { return (uint)(dirUpdate.Pdir1.Value >= 2 ? btbEntry.Target : 0); } }
public void Update(uint baddr, uint btarget, bool isTaken, bool isPredTaken, bool isCorrect, DynamicInstruction dynamicInst, BranchPredictorUpdate dirUpdate) { StaticInstruction staticInst = dynamicInst.StaticInstruction; BranchTargetBufferEntry btbEntry = null; if (!staticInst.IsControl) { return; } if (staticInst.IsControl && !staticInst.IsUnconditionalBranch) { uint l1Index = (baddr >> (int)BranchPredictorConstants.BRANCH_SHIFT) & (this.TwoLevel.L1Size - 1); uint shiftReg = (this.TwoLevel.ShiftRegs[l1Index] << 1) | (uint)(isTaken ? 1 : 0); this.TwoLevel.ShiftRegs[l1Index] = (uint)(shiftReg & ((1 << (int)this.TwoLevel.ShiftWidth) - 1)); } if (isTaken) { uint index = (baddr >> (int)BranchPredictorConstants.BRANCH_SHIFT) & (this.Btb.NumSets - 1); if (this.Btb.Associativity > 1) { index *= this.Btb.Associativity; BranchTargetBufferEntry lruHead = null, lruItem = null; for (uint i = index; i < (index + this.Btb.Associativity); i++) { if (this.Btb[i].Addr == baddr) { btbEntry = this.Btb[i]; } if (this.Btb[i].Prev == null) { lruHead = this.Btb[i]; } if (this.Btb[i].Next == null) { lruItem = this.Btb[i]; } } if (btbEntry == null) { btbEntry = lruItem; } if (btbEntry != lruHead) { if (btbEntry.Prev != null) { btbEntry.Prev.Next = btbEntry.Next; } if (btbEntry.Next != null) { btbEntry.Next.Prev = btbEntry.Prev; } btbEntry.Next = lruHead; btbEntry.Prev = null; lruHead.Prev = btbEntry; } } else { btbEntry = this.Btb[index]; } } if (dirUpdate.Pdir1 != null) { if (isTaken) { if (dirUpdate.Pdir1.Value < 3) { dirUpdate.Pdir1.Value++; } } else { if (dirUpdate.Pdir1.Value > 0) { dirUpdate.Pdir1.Value--; } } } if (dirUpdate.Pdir2 != null) { if (isTaken) { if (dirUpdate.Pdir2.Value < 3) { dirUpdate.Pdir2.Value++; } } else { if (dirUpdate.Pdir2.Value > 0) { dirUpdate.Pdir2.Value--; } } } if (dirUpdate.Pmeta != null) { if (dirUpdate.Bimod != dirUpdate.TwoLevel) { if (dirUpdate.TwoLevel == isTaken) { if (dirUpdate.Pmeta.Value < 3) { dirUpdate.Pmeta.Value++; } } else { if (dirUpdate.Pmeta.Value > 0) { dirUpdate.Pmeta.Value--; } } } } if (btbEntry != null) { if (btbEntry.Addr == baddr) { if (!isCorrect) { btbEntry.Target = btarget; } } else { btbEntry.Addr = baddr; btbEntry.StaticInstruction = staticInst; btbEntry.Target = btarget; } } }
public void Fetch() { uint cacheLineToFetch = BitHelper.Aligned (this.FetchNpc, this.Core.ICache.Cache.LineSize); if (cacheLineToFetch != this.LastFetchedCacheLine) { this.LastFetchedCacheLine = cacheLineToFetch; this.IFetch (this.Core.Processor.MMU.GetPhysicalAddress (this.MemoryMapId, this.FetchNpc), false, () => this.IsFetchStalled = false); this.IsFetchStalled = true; } bool hasDone = false; while (!hasDone && !this.DecodeBuffer.IsFull (this.Core.Processor.Config.DecodeBufferCapcity) && !this.IsFetchStalled) { if (this.SetNpc ()) { this.Regs.IsSpeculative = this.IsSpeculative = true; } this.FetchPc = this.FetchNpc; this.FetchNpc = this.FetchNnpc; DynamicInstruction dynamicInst = this.DecodeAndExecute (); if (this.FetchNpc != this.FetchPc + Marshal.SizeOf (typeof(uint))) { hasDone = true; } if ((this.FetchPc + Marshal.SizeOf (typeof(uint))) % this.Core.ICache.Cache.LineSize == 0) { hasDone = true; } uint stackRecoverIndex; BranchPredictorUpdate dirUpdate = new BranchPredictorUpdate (); uint dest = this.Bpred.Lookup (this.Core.Processor.MMU.GetPhysicalAddress (this.MemoryMapId, this.FetchPc), 0, dynamicInst, out dirUpdate, out stackRecoverIndex); this.FetchNnpc = dest <= 1 ? (uint)(this.FetchNpc + Marshal.SizeOf (typeof(uint))) : dest; this.FetchNnpc = this.Regs.Nnpc; //TODO: remove it DecodeBufferEntry decodeBufferEntry = new DecodeBufferEntry (dynamicInst); decodeBufferEntry.Npc = this.Regs.Npc; decodeBufferEntry.Nnpc = this.Regs.Nnpc; decodeBufferEntry.PredNpc = this.FetchNpc; decodeBufferEntry.PredNnpc = this.FetchNnpc; decodeBufferEntry.StackRecoverIndex = stackRecoverIndex; decodeBufferEntry.DirUpdate = dirUpdate; decodeBufferEntry.IsSpeculative = this.IsSpeculative; this.DecodeBuffer.Add (decodeBufferEntry); } }