Beispiel #1
0
        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;
                }
            }
        }
Beispiel #2
0
        public TimerModule(ulong clocks)
        {
            var maxCount = clocks - 1;

            CapacityBits = RTLCalculators.CalcBitsForValue(maxCount);
            countTo      = new RTLBitArray(maxCount).Resized(CapacityBits).Unsigned();
        }
Beispiel #3
0
        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;
            }
        }
Beispiel #4
0
        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");
        }
Beispiel #5
0
        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;
        }
Beispiel #6
0
        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]);
        }
Beispiel #7
0
        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]);
        }
Beispiel #8
0
        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
            });
        }
Beispiel #11
0
        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);
            }
        }
Beispiel #12
0
        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");
        }