void WriteBackStage() { var pcMisaligned = new RTLBitArray(internalNextPC[1, 0]) != 0; var isMRET = ID.SystemCode == SystemCodes.E && ID.SysTypeCode == SysTypeCodes.TRAP && ID.RetTypeCode == RetTypeCodes.MRET; if (pcMisaligned) { // address misalign caused trap, store current address SwitchToTrapHandler(State.PC, internalNextPC, MCAUSE.InstAddrMisalign); } else { NextState.State = CPUState.IF; if (isMIE && Inputs.ExtIRQ) { // if external cause trap, store next instruction, as current once completed successfully SwitchToTrapHandler(internalNextPC, 0, MCAUSE.MExternalIRQ); } else if (isMRET) { NextState.PC = State.CSR[(byte)SupportedCSRAddr.mepc]; EnableInterrupts(); } else { NextState.PC = internalNextPC; } } }
public TimerModule(ulong clocks) { var maxCount = clocks - 1; CapacityBits = RTLCalculators.CalcBitsForValue(maxCount); countTo = new RTLBitArray(maxCount).Resized(CapacityBits).Unsigned(); }
void OnBranch() { RTLBitArray branchOffset = ID.BTypeImm; switch (ID.BranchTypeCode) { case BranchTypeCodes.EQ: if (CMP.EQ) { NextState.PCOffset = branchOffset; } break; case BranchTypeCodes.NE: if (CMP.NE) { NextState.PCOffset = branchOffset; } break; case BranchTypeCodes.GE: if (CMP.GTS || CMP.EQ) { NextState.PCOffset = branchOffset; } break; case BranchTypeCodes.GEU: if (CMP.GTU || CMP.EQ) { NextState.PCOffset = branchOffset; } break; case BranchTypeCodes.LT: if (CMP.LTS) { NextState.PCOffset = branchOffset; } break; case BranchTypeCodes.LTU: if (CMP.LTU) { NextState.PCOffset = branchOffset; } break; default: Halt(HaltCode.BranchTypeCode); break; } }
static void Main(string[] args) { Console.WriteLine($"Quokka.FPGA version: {typeof(QuokkaRunner).Assembly.GetName().Version}"); Console.WriteLine($"Quokka.RTL version: {typeof(RTLBitArray).Assembly.GetName().Version}"); Ctor(); var c = new C() { v = true }; var sw = new Stopwatch(); sw.Start(); var sim = new RTLSimulator <VGAModule, VGAModuleInputs>(); var tl = sim.TopLevel; //sim.TraceToVCD(VCDOutputPath()); var b = new RTLBitArray(100000).Unsigned(); for (int i = 0; i < 80000; i++) { if (b < i) { throw new Exception(); } } var lapsed = sw.ElapsedMilliseconds; sw.Restart(); int vSyncCounter = 0, hSyncCounter = 0; for (int row = 0; row < 100 /*525*/; row++) { for (int col = 0; col < 800; col++) { sim.ClockCycle(new VGAModuleInputs()); if (!tl.VSync) { vSyncCounter++; } if (!tl.HSync) { hSyncCounter++; } } } Console.WriteLine($"Done in {sw.ElapsedMilliseconds} ms"); }
static void Ctor() { var sw = new Stopwatch(); sw.Start(); for (int i = 0; i < 80000; i++) { var b = new RTLBitArray(i).Unsigned(); } var lapsed = sw.ElapsedMilliseconds; }
public void SLLI() { var sim = PowerUp(); var tl = sim.TopLevel; var instructions = Inst.FromAsmFile("slli"); sim.RunAll(instructions); var data = new RTLBitArray(uint.MaxValue); Assert.AreEqual((uint)(data << 1), tl.Regs.State.x[2]); Assert.AreEqual((uint)(data << 31), tl.Regs.State.x[3]); }
public void SRAI() { var sim = PowerUp(); var tl = sim.TopLevel; var instructions = Inst.FromAsmFile("srai"); sim.RunAll(instructions); var data = new RTLBitArray(uint.MaxValue).Signed(); Assert.AreEqual((uint)(data >> 1), tl.Regs.State.x[2]); Assert.AreEqual((uint)(data >> 31), tl.Regs.State.x[3]); Assert.AreEqual((uint)(10 >> 1), tl.Regs.State.x[5]); }
public void SRL() { var sim = PowerUp(); var tl = sim.TopLevel; var instructions = Inst.FromAsmFile("srl"); sim.RunAll(instructions); var data = new RTLBitArray(uint.MaxValue); Assert.AreEqual((uint)(data >> 1), tl.Regs.State.x[6]); Assert.AreEqual((uint)(data >> 31), tl.Regs.State.x[7]); Assert.AreEqual((uint)data, tl.Regs.State.x[8]); Assert.AreEqual((uint)(data >> 1), tl.Regs.State.x[9]); }
public void Transmit() { var module = new TransmitterModule(); RTLBitArray sourceData = (byte)0xAA; Assert.IsTrue(module.IsReady); module.Schedule(() => new TransmitterInputs() { Trigger = true, Data = sourceData }); module.Stage(0); // property depends on state change Assert.IsTrue(module.IsTransmissionStarted); module.Commit(); Assert.IsTrue(module.IsTransmitting); Assert.IsFalse(module.IsTransmissionStarted); var result = new RTLBitArray(byte.MinValue); foreach (var idx in Enumerable.Range(0, 8)) { Assert.AreEqual(TransmitterFSM.Transmitting, module.State.FSM); result[idx] = module.Bit; module.Cycle(new TransmitterInputs()); } Assert.AreEqual(TransmitterFSM.WaitingForAck, module.State.FSM); // retrigger should be ignored module.Cycle(new TransmitterInputs() { Trigger = true }); Assert.AreEqual(TransmitterFSM.WaitingForAck, module.State.FSM); module.Cycle(new TransmitterInputs() { Ack = true }); Assert.AreEqual(TransmitterFSM.Idle, module.State.FSM); Assert.IsTrue(module.IsReady); Assert.AreEqual((byte)sourceData, (byte)result); }
public static IntDividerPipelineGeneratedState <T> DividerStage <T>(int idx, IntDividerPipelineGeneratedState <T> i) where T : struct { var denominator = new RTLBitArray(i.denominator, new RTLBitArray(0).Unsigned().Resized(31 - idx)); var flag = i.numerator >= denominator; var result = new RTLBitArray(i.result[30, 0], flag); var nextNumerator = flag ? (i.numerator - denominator)[31, 0] : i.numerator; return(new IntDividerPipelineGeneratedState <T>() { Payload = i.Payload, isRemainderNegative = i.isRemainderNegative, isResultNegative = i.isResultNegative, result = result, denominator = i.denominator, numerator = nextNumerator }); }
public void ShifterTests() { var shlData = new RTLBitArray((byte)0x81); var shaData = shlData.Signed(); var shifter = Module <ShifterModule>(); foreach (var shiftBy in Enumerable.Range(0, 8)) { var sb = new RTLBitArray(shiftBy).Unsigned().Resized(3); shifter.Cycle(new ShifterInputs() { Value = shlData, ShiftBy = sb }); Assert.AreEqual(shlData >> shiftBy, shifter.SHRL); Assert.AreEqual(shaData >> shiftBy, shifter.SHRA); Assert.AreEqual(shlData << shiftBy, shifter.SHLL); } }
public bool RunTillInstructionFetch() { int counter = 0; while (counter++ < 1000) { switch (TopLevel.State.State) { case CPUState.Halt: throw new Exception($"CPU Halted{Environment.NewLine}{TopLevel}"); case CPUState.E: switch (TopLevel.ID.SysTypeCode) { case SysTypeCodes.CALL: { ECall(); } break; case SysTypeCodes.BREAK: { // ebreak Debugger.Break(); DebuggerCalls++; } break; } ClockCycle(); break; case CPUState.MEM: if (wordAddress >= MemoryBlock.Length) { throw new IndexOutOfRangeException($"Requested address in IF was outside of memory block: {wordAddress}"); } if (TopLevel.MemRead) { var word = new RTLBitArray(MemoryBlock[wordAddress]); var data = word >> byteAddress; ClockCycle(new RISCVModuleInputs() { MemReady = true, MemReadData = data }); } else if (TopLevel.MemWrite) { var word = new RTLBitArray(MemoryBlock[wordAddress]); var mask = new RTLBitArray(uint.MinValue); var value = (TopLevel.MemWriteData << byteAddress).Resized(32); switch ((byte)TopLevel.MemAccessMode) { case 0: mask = (new RTLBitArray(byte.MaxValue) << byteAddress).Resized(32); break; case 1: mask = (new RTLBitArray(ushort.MaxValue) << byteAddress).Resized(32); break; case 2: mask = new RTLBitArray(uint.MaxValue); break; default: throw new Exception($"Unsupported mem write mode: {TopLevel.MemAccessMode}"); } word &= !mask; var part = value & mask; word |= part; // write data back to mem MemoryBlock[wordAddress] = word; ClockCycle(new RISCVModuleInputs() { MemReady = true }); } else { throw new Exception($"No operation in mem stage"); } break; case CPUState.IF: return(true); default: ClockCycle(); break; } } throw new Exception("CPU seems to hang"); }