示例#1
0
文件: Cog.cs 项目: mbaeten/gear-emu
        public const int TOTAL_COG_MEMORY = 0x200;  // 512 longs of memory

        /// @brief Default constructor.
        public Cog(PropellerCPU host, uint programAddress, uint param, uint frequency, PLLGroup pll)
        {
            Hub = host;

            Memory         = new uint[TOTAL_COG_MEMORY];
            ProgramAddress = programAddress;
            ParamAddress   = param;

            FreqA           = new FreqGenerator(host, pll, true);
            FreqB           = new FreqGenerator(host, pll, false);
            Video           = new VideoGenerator(host);
            PhaseLockedLoop = pll;

            // Attach the video generator to PLLs
            PhaseLockedLoop.SetupPLL(Video);

            PC = 0;
            BreakPointCogCursor = -1;    // Breakpoint disabled initially

            // We are in boot time load
            Memory[(int)Assembly.RegisterAddress.PAR] = param;
            State      = CogRunState.WAIT_LOAD_PROGRAM;
            StateCount = 0;

            // Clear the special purpose registers
            for (int i = (int)Assembly.RegisterAddress.CNT; i <= 0x1FF; i++)
            {
                this[i] = 0;
            }

            SetClock(frequency);
        }
示例#2
0
 /// @brief Default constructor for a Cog running in PASM mode.
 /// @param host PropellerCPU where this cog resides.
 /// @param programAddress Start of program to load from main memory.
 /// @param paramAddress PARAM value given to the Cog.
 /// @param frequency Frequency running the cog (the same as the Propeller).
 /// @param pll PLL Multiplier running the cog (the same as the Propeller).
 public NativeCog(PropellerCPU host,
                  uint programAddress, uint paramAddress, uint frequency,
                  PLLGroup pll)
     : base(host, programAddress, paramAddress, frequency, pll)
 {
     Carry = false;
     Zero  = false;
 }
示例#3
0
        public FreqGenerator(PropellerCPU host, PLLGroup phaseLockLoop, bool freqA)
        {
            Host  = host;
            OutA  = false;
            OutB  = false;
            FreqA = freqA;

            PhaseLockLoop = phaseLockLoop;
        }
        /// @brief Reset the propeller CPU to initial state.
        /// @details Release cog instances, clock sources, clear locks and pins, and reset plugins.
        /// @version 15.03.26 - Separate reset loops for clock sources, cogs and locks.
        public void Reset()
        {
            ResetMemory.CopyTo(Memory, 0);

            SystemCounter = 0;
            Time          = 0;
            RingPosition  = 0;
            for (int i = 0; i < ClockSources.Length; i++)   //clear clock source references
            {
                ClockSources[i] = null;
            }
            for (int i = 0; i < TOTAL_COGS; i++)    //clear cog references
            {
                Cogs[i] = null;
            }
            CogsRunning = 0;

            for (int i = 0; i < TOTAL_LOCKS; i++)    //clear locks state
            {
                LocksAvailable[i] = true;
                LocksState[i]     = false;
            }

            PinChanged();   //update situation of pins

            foreach (PluginCommon plugin in PlugIns)
            {
                plugin.OnReset();
            }

            SetClockMode((byte)(ClockMode & 0x7F));

            // Start the runtime in interpreted mode (fake boot)

            // Pushes the 3 primary offsets (local offset, var offset, and object offset)
            // Stack -1 is the boot parameter

            uint InitFrame = ReadWord(10);

            WriteWord(InitFrame - 8, ReadWord(6));  // Object
            WriteWord(InitFrame - 6, ReadWord(8));  // Var
            WriteWord(InitFrame - 4, ReadWord(12)); // Local
            WriteWord(InitFrame - 2, ReadWord(14)); // Stack

            // Boot parameter is Initial PC in the lo word, and the stack frame in the hi word
            ClockSources[0] = new PLLGroup();

            Cogs[0]     = new InterpretedCog(this, InitFrame, CoreFreq, (PLLGroup)ClockSources[0]);
            CogsRunning = 1;
        }
        /// @brief Execute the hub operations.
        /// @details This method is called from a cog to do the operations related to all the CPU.
        /// @version 15.03.26 - corrected problem in COGSTOP return.
        /// @param[in] caller Reference to the caller Cog of this method.
        /// @param[in] operation Hub operation to execute.
        /// @param[in] argument Parameter given to the opcode (destination field in PASM).
        /// @param[in,out] carry Carry flag that could be affected by the operation.
        /// @param[in,out] zero Zero flag that could be affected by the operation.
        /// @returns Value depending on operation.
        /// @note Reference of supported Operations, based in Propeller Manual v1.2:
        /// @arg HUBOP_CLKSET - page 271.
        /// @arg HUBOP_COGID - page 283.
        /// @arg HUBOP_COGINIT - page 284.
        /// @arg HUBOP_COGSTOP - page 286.
        /// @arg HUBOP_LOCKNEW - page 304.
        /// @arg HUBOP_LOCKRET - page 305.
        /// @arg HUBOP_LOCKSET - page 306.
        /// @arg HUBOP_LOCKCLR - page 303.
        public uint HubOp(Cog caller, uint operation, uint argument, ref bool carry, ref bool zero)
        {
            uint maskedArg = (argument & 0x7);
            uint cog       = (uint)Cogs.Length;

            switch ((HubOperationCodes)operation)
            {
            case HubOperationCodes.HUBOP_CLKSET:
                zero  = false;
                carry = false;
                SetClockMode((byte)argument);
                break;

            case HubOperationCodes.HUBOP_COGID:
                carry = false;
                cog   = CogID(caller);
                zero  = (cog == 0) ? true : false;
                return(cog);

            case HubOperationCodes.HUBOP_COGINIT:
                //determine witch cog start
                if ((argument & 0x8) != 0)                 //if free cog should be started (bit 3 is set)
                {
                    for (uint i = 0; i < Cogs.Length; i++) //assign the first free cog
                    {
                        if (Cogs[i] == null)
                        {
                            cog = i;
                            break;
                        }
                    }
                    if (cog >= Cogs.Length)
                    {
                        carry = true;       //no free cog
                        return(0xFFFFFFFF);
                    }
                    else
                    {
                        carry = false;
                    }
                }
                else      // instead specific cog should be started
                {
                    cog = maskedArg;
                }

                zero = (cog == 0) ? true : false;

                PLLGroup pll = new PLLGroup();
                ClockSources[cog] = (ClockSource)pll;
                uint param = (argument >> 16) & 0xFFFC;       //decode param value
                uint progm = (argument >> 2) & 0xFFFC;        //decode program address to load to
                if (progm == 0xF004)
                {
                    Cogs[cog] = new InterpretedCog(this, param, CoreFreq, pll);
                }
                else
                {
                    Cogs[cog] = new NativeCog(this, progm, param, CoreFreq, pll);
                }
                CogsRunning++;
                return((uint)cog);

            case HubOperationCodes.HUBOP_COGSTOP:
                zero  = (maskedArg == 0) ? true: false;
                carry = (CogsRunning < TOTAL_COGS) ? false : true;
                Stop((int)maskedArg);
                CogsRunning--;
                return(maskedArg);

            case HubOperationCodes.HUBOP_LOCKCLR:
                zero  = (maskedArg == 0) ? true : false;
                carry = LocksState[maskedArg];
                LocksState[maskedArg] = false;
                return(argument);

            case HubOperationCodes.HUBOP_LOCKNEW:
                zero  = false;      // initial value if no Locks available
                carry = true;       // initial value if no Locks available
                for (uint i = 0; i < LocksAvailable.Length; i++)
                {
                    if (LocksAvailable[i])
                    {
                        LocksAvailable[i] = false;
                        carry             = false;
                        if (i == 0)
                        {
                            zero = true;
                        }
                        return(i);
                    }
                }
                return(7);      // if all are occupied, return a 7, but carry is true

            case HubOperationCodes.HUBOP_LOCKRET:
                zero  = (maskedArg == 0) ? true : false;
                carry = true;       // initial value if no Locks available
                for (uint i = 0; i < LocksAvailable.Length; i++)
                {
                    if (LocksAvailable[i])
                    {
                        carry = false;
                    }
                }
                LocksAvailable[maskedArg] = true;
                return(maskedArg);

            case HubOperationCodes.HUBOP_LOCKSET:
                zero  = (maskedArg == 0) ? true : false;
                carry = LocksState[maskedArg];
                LocksState[maskedArg] = true;
                return(maskedArg);

            default:
                // TODO: RAISE EXCEPTION
                break;
            }

            return(0);
        }