private void Decode() { int maxDecode = 0; while (!DE_RN.Stalled && FE_DE.Instructions.Count > 0 && maxDecode < 4) { IData d = FE_DE.Instructions.Dequeue(); UInt32 i = d.Data; DecodedOp op; op.PC = d.PC; op.Op = (byte)(i >> 25); op.Const = (UInt32)(i >> 4) & 0x1FFFFFU; op.Var = (UInt32)(i >> 8) & 0x1FFFF; op.Dst = (byte)((i >> 8) & 0xf); op.Src1 = (byte)((i >> 4) & 0xf); op.Src2 = (byte)((i >> 0) & 0xf); OpCodes.OpInfo opd = OpCodes.GetInfo((OpCodes.Op)op.Op); op.Meta = opd; DE_RN.Ops.Enqueue(op); // Optimization: Check op is a branch and if it is use branch prediction // to load in new instructions and do a partial pipeline flush. maxDecode++; } // Renamer is stalled for some reason, we will have to stall and propogate stall to fetch stage. FE_DE.Stalled = DE_RN.Stalled && FE_DE.Instructions.Count >= 4; this.StalledDecodeCycles += (4 - maxDecode); }
private void Rename() { int maxRename = 0; while (PhysFreeList.PhysicalRegisterAvailable() && !this.IQueue.IsFull() && !ROB.Full() && DE_RN.Ops.Count > 0 && maxRename < 4) { DecodedOp o = DE_RN.Ops.Dequeue(); byte op = o.Op; OpCodes.OpInfo opi = o.Meta; byte dst = 0; if (opi.HasOutput) { // TODO: Don't cast this. Do it properly. dst = (byte)PhysFreeList.GetUnusedRegister(); PhysRegisters.SetReady(dst, false); } byte src1 = (byte)ArchToPhysTable.GetPhysicalRegisterId(opi.Src1Dep ? o.Src1 : 0); byte src2 = (byte)ArchToPhysTable.GetPhysicalRegisterId(opi.Src2Dep ? o.Src2 : 0); bool rd1 = opi.Src1Dep ? PhysRegisters.IsReady(src1) : true; bool rd2 = opi.Src2Dep ? PhysRegisters.IsReady(src2) : true; if (opi.HasOutput) { byte archReg = 0; switch (opi.OutputSource) { case OpCodes.DstSource.Dst: archReg = o.Dst; break; case OpCodes.DstSource.Src1: archReg = o.Src1; break; case OpCodes.DstSource.Src2: archReg = o.Src2; break; } ArchToPhysTable.MapArchToPhys(archReg, dst); // Redirect dst register to the correct destination. o.Dst = archReg; } // Resulting register of this operation should be declared not ready until it has executed. Console.WriteLine("Rename: rd1={0}, rd2={1}, src1={2}, src2={3}, dst={4}", rd1, rd2, (int)src1, (int)src2, (int)dst); // Add entry to issue queue and re-order buffer this.IQueue.AddToQueue(o.PC, op, src1, src2, dst, rd1, rd2, o.Const, o.Meta); this.ROB.AddToQueue(o.PC, o.Dst, dst, o.Meta.HasOutput); maxRename++; } // Stallable by multiple resource hazards: re-order buffer full, issue queue full or lack of physical registers. // Therefore a stall may occur, resulting in wasted cycles. this.DE_RN.Stalled = !PhysFreeList.PhysicalRegisterAvailable() || this.IQueue.IsFull() || ROB.Full() || DE_RN.Ops.Count >= 4; this.StalledRenameCycles += (4 - maxRename); }
public void AddToQueue(UInt32 pc, byte op, byte src1, byte src2, byte dst, bool rd1, bool rd2, UInt32 constant, OpCodes.OpInfo info) { Debug.Assert(!IsFull()); IQueue.Add(new Entry() { PC = pc, Op = op, Src1 = src1, Src2 = src2, Rd1 = rd1, Rd2 = rd2, Dst = dst, Const = constant, Meta = info }); }