private void PrepareRegisters()
 {
     registers = new DoubleWordRegisterCollection(this, new Dictionary <long, DoubleWordRegister>
     {
         { (long)Registers.PortAData, new DoubleWordRegister(this)
           .WithValueField(0, 32, writeCallback: (_, val) =>
             {
                 var bits = BitHelper.GetBits(val);
                 for (int i = 0; i < bits.Length; i++)
                 {
                     if (PortDataDirection[i] == PinDirection.Output)
                     {
                         Connections[i].Set(bits[i]);
                         State[i] = bits[i];
                     }
                 }
             }, valueProviderCallback: _ => { return(BitHelper.GetValueFromBitsArray(State)); }) },
         { (long)Registers.PortADataDirection, new DoubleWordRegister(this)
           .WithValueField(0, 32, writeCallback: (_, val) => Array.Copy(BitHelper.GetBits(val).Select(x => x ? PinDirection.Output : PinDirection.Input).ToArray(), PortDataDirection, 32),
                           valueProviderCallback: _ => BitHelper.GetValueFromBitsArray(PortDataDirection.Select(x => x == PinDirection.Output))) },
         { (long)Registers.InterruptEnable, new DoubleWordRegister(this)
           .WithValueField(0, 32, writeCallback: (_, val) => {
                 Array.Copy(BitHelper.GetBits(val), InterruptEnable, 32);
                 RefreshInterrupts();
             },
                           valueProviderCallback: _ => BitHelper.GetValueFromBitsArray(InterruptEnable)) },
         { (long)Registers.InterruptType, new DoubleWordRegister(this)
           // true = edge sensitive; false = level sensitive
           .WithValueField(0, 32, out interruptTypeField, writeCallback: (_, val) => CalculateInterruptTypes()) },
         { (long)Registers.InterruptPolarity, new DoubleWordRegister(this)
           // true = rising edge / active high; false = falling edge / active low
           .WithValueField(0, 32, out interruptPolarityField, writeCallback: (_, val) => CalculateInterruptTypes()) },
         { (long)Registers.InterruptBothEdgeType, new DoubleWordRegister(this)
           .WithValueField(0, 32, out interruptBothEdgeField, writeCallback: (_, val) => CalculateInterruptTypes()) },
         { (long)Registers.InterruptMask, new DoubleWordRegister(this)
           .WithValueField(0, 32, writeCallback: (_, val) => {
                 Array.Copy(BitHelper.GetBits(val), InterruptMask, 32);
                 RefreshInterrupts();
             },
                           valueProviderCallback: _ => BitHelper.GetValueFromBitsArray(InterruptMask)) },
         { (long)Registers.PortAExternalPort, new DoubleWordRegister(this)
           .WithValueField(0, 32, FieldMode.Read, valueProviderCallback: _ => BitHelper.GetValueFromBitsArray(State)) },
         { (long)Registers.ClearInterrupt, new DoubleWordRegister(this)
           .WithValueField(0, 32, FieldMode.Write, writeCallback: (_, val) =>
             {
                 foreach (var bit in BitHelper.GetSetBits(val))
                 {
                     activeInterrupts[bit] = false;
                 }
                 RefreshInterrupts();
             }) },
         { (long)Registers.InterruptStatus, new DoubleWordRegister(this)
           .WithValueField(0, 32, FieldMode.Read, valueProviderCallback: _ => BitHelper.GetValueFromBitsArray(activeInterrupts.Zip(InterruptMask, (isActive, isMasked) => isActive && !isMasked))) },
         { (long)Registers.RawInterruptStatus, new DoubleWordRegister(this)
           .WithValueField(0, 32, FieldMode.Read, valueProviderCallback: _ => BitHelper.GetValueFromBitsArray(activeInterrupts)) }
     });
 }
예제 #2
0
        public void DosDateTimeToFileTimeTest()
        {
            var ft = new DateTime(2019, 10, 29, 13, 51, 24, DateTimeKind.Local).ToFileTimeStruct();

            Assert.That(FileTimeToDosDateTime(ft, out var fatDate, out var fatTime), ResultIs.Successful);
            Assert.That(BitHelper.GetBits(fatDate, 5, 4), Is.EqualTo(10));
            Assert.That(DosDateTimeToFileTime(fatDate, fatTime, out var outFt), ResultIs.Successful);
            Assert.That(outFt.ToUInt64(), Is.EqualTo(ft.ToUInt64()));
        }
예제 #3
0
        private void RefreshConnectionsState()
        {
            var outputBits = BitHelper.GetBits(outputEnable.Value);
            var bits       = BitHelper.GetBits(output.Value);

            for (var i = 0; i < 32; i++)
            {
                Connections[i].Set(bits[i] && outputBits[i]);
            }
        }
예제 #4
0
        private void ActionOnChannels(Action <Channel, bool> action, uint selector)
        {
            var index = 0;

            foreach (var bit in BitHelper.GetBits(selector))
            {
                action(channels[index], bit);
                index++;
            }
        }
예제 #5
0
        private void CreateRegisters()
        {
            var regs = new Dictionary <long, DoubleWordRegister>()
            {
                { (long)Registers.ExternalInterruptPortSelectLow, new DoubleWordRegister(this)
                  .WithValueField(0, 32, changeCallback: (oldValue, newValue) => ReroutePort(oldValue, newValue, false), name: "EXTIPSEL") },
                { (long)Registers.ExternalInterruptPortSelectHigh, new DoubleWordRegister(this)
                  .WithValueField(0, 32, changeCallback: (oldValue, newValue) => ReroutePort(oldValue, newValue, true), name: "EXTIPSEL") },
                { (long)Registers.ExternalInterruptPinSelectLow, new DoubleWordRegister(this, 0x32103210)
                  .WithValueField(0, 32, changeCallback: (oldValue, newValue) => ReroutePin(oldValue, newValue, false), name: "EXTIPINSEL") },
                { (long)Registers.ExternalInterruptPinSelectHigh, new DoubleWordRegister(this, 0x32103210)
                  .WithValueField(0, 32, changeCallback: (oldValue, newValue) => ReroutePin(oldValue, newValue, true), name: "EXTIPINSEL") },
                { (long)Registers.ExternalInterruptRisingEdgeTrigger, new DoubleWordRegister(this)
                  .WithValueField(0, 16, changeCallback: (_, value) => SetEdgeSensitivity(value, InterruptTrigger.RisingEdge)) },
                { (long)Registers.ExternalInterruptFallingEdgeTrigger, new DoubleWordRegister(this)
                  .WithValueField(0, 16, changeCallback: (_, value) => SetEdgeSensitivity(value, InterruptTrigger.FallingEdge)) },
                { (long)Registers.InterruptFlag, new DoubleWordRegister(this)
                  .WithValueField(0, 16, FieldMode.Read, valueProviderCallback: (_) => BitHelper.GetValueFromBitsArray(externalInterrupt), name: "EXT")
                  .WithTag("EM4WU", 16, 16) },
                { (long)Registers.InterruptFlagSet, new DoubleWordRegister(this)
                  .WithValueField(0, 16, FieldMode.Write, writeCallback: (_, value) => UpdateExternalInterruptBits(value, true), name: "EXT")
                  .WithTag("EM4WU", 16, 16) },
                { (long)Registers.InterruptFlagClear, new DoubleWordRegister(this)
                  .WithValueField(0, 16, writeCallback: (_, value) => UpdateExternalInterruptBits(value, false), valueProviderCallback: (_) =>
                    {
                        var result = BitHelper.GetValueFromBitsArray(externalInterrupt);
                        for (var i = 0; i < NumberOfExternalInterrupts; ++i)
                        {
                            externalInterrupt[i] = false;
                        }
                        UpdateInterrupts();
                        return(result);
                    }, name: "EXT")
                  .WithTag("EM4WU", 16, 16) },
                { (long)Registers.InterruptEnable, new DoubleWordRegister(this)
                  .WithValueField(0, 16, writeCallback: (_, value) =>
                    {
                        Array.Copy(BitHelper.GetBits(value), interruptEnable, NumberOfExternalInterrupts);
                        UpdateInterrupts();
                    },
                                  valueProviderCallback: (_) => BitHelper.GetValueFromBitsArray(interruptEnable), name: "EXT")
                  .WithTag("EM4WU", 16, 16) },
                { (long)Registers.ConfigurationLock, new DoubleWordRegister(this)
                  .WithValueField(0, 16, writeCallback: (_, value) => configurationLocked = (value != UnlockCode),
                                  valueProviderCallback: (_) => configurationLocked ? 1 : 0u, name: "LOCKKEY") },
            };

            for (var i = 0; i < NumberOfPorts; ++i)
            {
                CreatePortRegisters(regs, i);
            }
            registers = new DoubleWordRegisterCollection(this, regs);
        }
예제 #6
0
        public SimplePeripheral(Machine machine) : base(machine)
        {
            IValueRegisterField value;

            Registers.Base.Define(this)
            .WithValueField(0, 32, out value, FieldMode.Write);

            Registers.Multiplier.Define(this)
            .WithValueField(0, 32, FieldMode.Read, valueProviderCallback: _ => value.Value * 2);

            Registers.BitCounter.Define(this)
            .WithValueField(0, 32, FieldMode.Read, valueProviderCallback: _ => (uint)BitHelper.GetBits(value.Value).Where(x => x).Select(x => 1).Sum(x => x));
        }
예제 #7
0
        private void MipChanged(uint mip)
        {
            var previousMip = BitHelper.GetBits(TlibGetMip());
            var currentMip  = BitHelper.GetBits(mip);

            foreach (var gpio in intTypeToVal.Lefts)
            {
                intTypeToVal.TryGetValue(gpio, out IrqType decodedType);
                if (previousMip[(int)decodedType] != currentMip[(int)decodedType])
                {
                    OnGPIO(gpio, currentMip[(int)decodedType]);
                }
            }
        }
예제 #8
0
        private void SetOutputEnableMasked(uint value, bool lower)
        {
            var offset = lower ? 0 : 16;
            var data   = BitHelper.GetBits(value & 0xFFFF);
            var mask   = BitHelper.GetBits(value >> 16);

            for (var i = 0; i < 16; ++i)
            {
                if (mask[i])
                {
                    directOutputEnabled[i + offset] = data[i];
                }
            }
            UpdateConnections();
        }
예제 #9
0
        private void SetEdgeSensitivity(uint value, InterruptTrigger trigger)
        {
            var bits = BitHelper.GetBits(value);

            for (var i = 0; i < interruptTriggers.Length; ++i)
            {
                if (bits[i])
                {
                    interruptTriggers[i] |= trigger;
                }
                else
                {
                    interruptTriggers[i] ^= trigger;
                }
            }
        }
        public SiFive_GPIO(Machine machine) : base(machine, 32)
        {
            locker = new object();

            var registersMap = new Dictionary <long, DoubleWordRegister>
            {
                { (long)Registers.OutputPortValue, new DoubleWordRegister(this)
                  .WithValueField(0, 32,
                                  valueProviderCallback: _ =>
                    {
                        lock (locker)
                        {
                            return(BitHelper.GetValueFromBitsArray(Connections.Where(x => x.Key >= 0).OrderBy(x => x.Key).Select(x => x.Value.IsSet)));
                        }
                    },
                                  writeCallback: (_, val) =>
                    {
                        lock (locker)
                        {
                            var bits = BitHelper.GetBits(val);
                            for (var i = 0; i < bits.Length; i++)
                            {
                                Connections[i].Set(State[i] || bits[i]);
                            }
                        }
                    }) },

                { (long)Registers.RiseInterruptPending, new DoubleWordRegister(this)
                  .WithValueField(0, 32, writeCallback: (_, val) =>
                    {
                        lock (locker)
                        {
                            var bits = BitHelper.GetBits(val);
                            for (var i = 0; i < bits.Length; i++)
                            {
                                if (bits[i])
                                {
                                    Connections[i].Set(State[i]);
                                }
                            }
                        }
                    }) }
            };

            registers = new DoubleWordRegisterCollection(this, registersMap);
        }
예제 #11
0
        private void DefineRegisters()
        {
            // according to LiteX-generated `csr.h` this register is readable
            Registers.Leds.Define(this)
            .WithValueField(0, LedsCount,
                            valueProviderCallback: _ => BitHelper.GetValueFromBitsArray(Connections.Where(x => x.Key >= 0).OrderBy(x => x.Key).Select(x => x.Value.IsSet)),
                            writeCallback: (_, val) =>
            {
                var bits = BitHelper.GetBits(val);
                for (var i = 0; i < LedsCount; i++)
                {
                    Connections[i].Set(bits[i]);
                }
            })
            ;

            Registers.Switches.Define(this)
            .WithValueField(0, SwitchesCount, FieldMode.Read,
                            valueProviderCallback: _ => BitHelper.GetValueFromBitsArray(this.State.Skip(LedsCount).Take(SwitchesCount)))
            ;

            Registers.ButtonsStatus.Define(this)
            .WithValueField(0, ButtonsCount, FieldMode.Read,
                            valueProviderCallback: _ => BitHelper.GetValueFromBitsArray(this.State.Skip(LedsCount + SwitchesCount).Take(ButtonsCount)))
            ;

            Registers.ButtonsPending.Define(this)
            .WithValueField(0, ButtonsCount,
                            valueProviderCallback: _ => BitHelper.GetValueFromBitsArray(buttonsPending),
                            writeCallback: (_, val) =>
            {
                foreach (var bit in BitHelper.GetSetBits(val))
                {
                    buttonsPending[bit] = false;
                }

                UpdateInterrupt();
            })
            ;

            Registers.ButtonsEnabled.Define(this)
            .WithValueField(0, ButtonsCount, out buttonsEnabled, writeCallback: (_, __) => { UpdateInterrupt(); })
            ;
        }
예제 #12
0
        private int DefineOutRegisters(long offset)
        {
            var size = 0;

            ((Registers)offset).Define(this)
            .WithValueField(0, NumberOfPins, name: "Out",
                            writeCallback: (_, val) =>
            {
                var bits = BitHelper.GetBits(val);
                for (var i = 0; i < bits.Length; i++)
                {
                    Connections[i].Set(bits[i]);
                }
            },
                            valueProviderCallback: _ => BitHelper.GetValueFromBitsArray(Connections.Where(x => x.Key >= 0).OrderBy(x => x.Key).Select(x => x.Value.IsSet)));
            size += 0x4;

            return(size);
        }
        private void AddTargetEnablesRegister(Dictionary <long, DoubleWordRegister> registersMap, long address, uint hartId, PrivilegeLevel level, int numberOfSources)
        {
            var maximumSourceDoubleWords = (int)Math.Ceiling((numberOfSources + 1) / 32.0) * 4;

            for (var offset = 0u; offset < maximumSourceDoubleWords; offset += 4)
            {
                var lOffset = offset;
                registersMap.Add(address + offset, new DoubleWordRegister(this).WithValueField(0, 32, writeCallback: (_, value) =>
                {
                    lock (irqSources)
                    {
                        // Each source is represented by one bit. offset and lOffset indicate the offset in double words from TargetXEnables,
                        // `bit` is the bit number in the given double word,
                        // and `sourceIdBase + bit` indicate the source number.
                        var sourceIdBase = lOffset * 8;
                        var bits         = BitHelper.GetBits(value);
                        for (var bit = 0u; bit < bits.Length; bit++)
                        {
                            var sourceNumber = sourceIdBase + bit;
                            if (sourceNumber == 0)
                            {
                                // Source number 0 is not used.
                                continue;
                            }
                            if (irqSources.Length <= sourceNumber)
                            {
                                if (bits[bit])
                                {
                                    this.Log(LogLevel.Noisy, "Trying to enable non-existing source: {0}", sourceNumber);
                                }
                                continue;
                            }

                            this.Log(LogLevel.Noisy, "{0} source #{1} for hart {2} on level {3}", bits[bit] ? "Enabling" : "Disabling", sourceNumber, hartId, level);
                            irqTargets[hartId].levels[(int)level].EnableSource(irqSources[sourceNumber], bits[bit]);
                        }
                        RefreshInterrupts();
                    }
                }));
            }
        }
예제 #14
0
        public uint ReadDoubleWord(long offset)
        {
            lock (locker)
            {
                if (offset < 0x400)
                {
                    var mask   = BitHelper.GetBits((uint)(offset >> 2) & 0xFF);
                    var bits   = BitHelper.GetBits(registers.Read(0));
                    var result = new bool[8];
                    for (var i = 0; i < 8; i++)
                    {
                        if (mask[i])
                        {
                            result[i] = bits[i];
                        }
                    }

                    return(BitHelper.GetValueFromBitsArray(result));
                }

                return(registers.Read(offset));
            }
        }
예제 #15
0
 public void WriteDoubleWord(long offset, uint value)
 {
     lock (locker)
     {
         if (offset < 0x400)
         {
             var mask = BitHelper.GetBits((uint)(offset >> 2) & 0xFF);
             var bits = BitHelper.GetBits(value);
             for (var i = 0; i < 8; i++)
             {
                 if (mask[i])
                 {
                     Connections[i].Set(bits[i]);
                     State[i] = bits[i];
                 }
             }
         }
         else
         {
             registers.Write(offset, value);
         }
     }
 }
예제 #16
0
        public PSE_GPIO(Machine machine) : base(machine, 32)
        {
            locker     = new object();
            IRQ        = new GPIO();
            irqManager = new GPIOInterruptManager(IRQ, State);

            var registersMap = new Dictionary <long, DoubleWordRegister>
            {
                { (long)Registers.InterruptRegister, new DoubleWordRegister(this)
                  .WithValueField(0, 32,
                                  writeCallback: (_, val) =>
                    {
                        foreach (var i in BitHelper.GetSetBits(val))
                        {
                            irqManager.ClearInterrupt(i);
                            if ((irqManager.PinDirection[i] & GPIOInterruptManager.Direction.Input) != 0)
                            {
                                Connections[i].Set(false);
                            }
                        }
                    },
                                  valueProviderCallback: _ => BitHelper.GetValueFromBitsArray(irqManager.ActiveInterrupts), name: "INTR") },

                { (long)Registers.InputRegister, new DoubleWordRegister(this)
                  .WithValueField(0, 32, out inputReg, FieldMode.Read,
                                  valueProviderCallback: val =>
                    {
                        var pins   = irqManager.PinDirection.Select(x => (x & GPIOInterruptManager.Direction.Input) != 0);
                        var result = pins.Zip(State, (pin, state) => pin && state);
                        return(BitHelper.GetValueFromBitsArray(result));
                    }, name: "GPIN") },

                { (long)Registers.OutputRegister, new DoubleWordRegister(this)
                  .WithValueField(0, 32,
                                  valueProviderCallback: val =>
                    {
                        var pins   = irqManager.PinDirection.Select(x => (x & GPIOInterruptManager.Direction.Output) != 0);
                        var result = pins.Zip(Connections.Values, (pin, state) => pin && state.IsSet);
                        return(BitHelper.GetValueFromBitsArray(result));
                    },
                                  writeCallback: (_, val) =>
                    {
                        // Potentially we should raise an exception, as GPIO is bidirectional,
                        // but we do not have such infrastructure.
                        var bits = BitHelper.GetBits(val);
                        for (var i = 0; i < bits.Length; i++)
                        {
                            if ((irqManager.PinDirection[i] & GPIOInterruptManager.Direction.Output) != 0)
                            {
                                Connections[i].Set(bits[i]);
                            }
                        }
                    }, name: "GPOUT") },

                { (long)Registers.ClearRegister, new DoubleWordRegister(this)
                  .WithValueField(0, 32, writeCallback: (_, val) => SetRegisterBits(val, false), name: "CLEAR_BITS") },

                { (long)Registers.SetRegister, new DoubleWordRegister(this)
                  .WithValueField(0, 32, writeCallback: (_, val) => SetRegisterBits(val, true), name: "SET_BITS") },
            };

            var intTypeToVal = new TwoWayDictionary <GPIOInterruptManager.InterruptTrigger, uint>();

            intTypeToVal.Add(GPIOInterruptManager.InterruptTrigger.ActiveHigh, 0);
            intTypeToVal.Add(GPIOInterruptManager.InterruptTrigger.ActiveLow, 1);
            intTypeToVal.Add(GPIOInterruptManager.InterruptTrigger.RisingEdge, 2);
            intTypeToVal.Add(GPIOInterruptManager.InterruptTrigger.FallingEdge, 3);
            intTypeToVal.Add(GPIOInterruptManager.InterruptTrigger.BothEdges, 4);

            for (var i = 0; i < RegisterLength; i++)
            {
                var j = i;
                registersMap.Add(i * RegisterOffset, new DoubleWordRegister(this)
                                 .WithFlag(0,
                                           writeCallback: (_, val) =>
                {
                    if (val)
                    {
                        irqManager.PinDirection[j] |= GPIOInterruptManager.Direction.Output;
                    }
                    else
                    {
                        irqManager.PinDirection[j] &= ~GPIOInterruptManager.Direction.Output;
                    }
                },
                                           valueProviderCallback: _ => (irqManager.PinDirection[j] & GPIOInterruptManager.Direction.Output) != 0, name: "OutputRegEnable")
                                 .WithFlag(1,
                                           writeCallback: (_, value) =>
                {
                    if (value)
                    {
                        irqManager.PinDirection[j] |= GPIOInterruptManager.Direction.Input;
                    }
                    else
                    {
                        irqManager.PinDirection[j] &= ~GPIOInterruptManager.Direction.Input;
                    }
                },
                                           valueProviderCallback: _ => (irqManager.PinDirection[j] & GPIOInterruptManager.Direction.Input) != 0, name: "InputRegEnable")
                                 .WithTag("OutputBufferEnable", 2, 1)
                                 .WithFlag(3, writeCallback: (_, v) => { irqManager.InterruptEnable[j] = v; }, valueProviderCallback: _ => irqManager.InterruptEnable[j], name: "InterruptEnable")
                                 .WithReservedBits(4, 1)
                                 .WithValueField(5, 3,
                                                 writeCallback: (_, value) =>
                {
                    if (!intTypeToVal.TryGetValue(value, out var type))
                    {
                        this.Log(LogLevel.Warning, "Invalid interrupt type for pin #{0}: {1}", j, value);
                        return;
                    }
                    irqManager.InterruptType[j] = type;
                },
                                                 valueProviderCallback: _ => intTypeToVal[irqManager.InterruptType[j]], name: "InterruptType"));
            }
            registers = new DoubleWordRegisterCollection(this, registersMap);
        }
예제 #17
0
        public Raptor_GPIO(Machine machine) : base(machine, NumberOfPins)
        {
            locker = new object();
            pins   = new Pin[NumberOfPins];

            var registersMap = new Dictionary <long, DoubleWordRegister>
            {
                { (long)Registers.GPIO_DATA, new DoubleWordRegister(this)
                  .WithValueField(0, 16,
                                  valueProviderCallback: val =>
                    {
                        var readOperations = pins.Select(x => (x.pinOperation & Operation.Read) != 0);            // select pins configured as input pins
                        var result         = readOperations.Zip(State, (operation, state) => operation && state); //  update with the incoming signals
                        return(BitHelper.GetValueFromBitsArray(result));                                          // register value after adjusting the read value for read pins
                    })

                  .WithValueField(16, 16,
                                  valueProviderCallback: val =>
                    {
                        var writeOperations = pins.Select(x => (x.pinOperation & Operation.Write) != 0);                               // select pins configured as output pins
                        var result          = writeOperations.Zip(Connections.Values, (operation, state) => operation && state.IsSet); // update with outgoing signals
                        return(BitHelper.GetValueFromBitsArray(result));
                    }) },

                { (long)Registers.GPIO_ENB, new DoubleWordRegister(this)
                  .WithValueField(0, 16,
                                  writeCallback: (_, val) =>
                    {
                        var bits = BitHelper.GetBits(val);          // put the register bits in an array after they are written
                        for (var i = 0; i < bits.Length; i++)
                        {
                            if (bits[i])             // input
                            {
                                pins[i].pinOperation = Operation.Read;
                            }
                            else              // output
                            {
                                pins[i].pinOperation = Operation.Write;
                            }
                        }
                    })
                  .WithTag("RESERVED", 16, 16) },

                { (long)Registers.GPIO_PUB, new DoubleWordRegister(this)
                  .WithValueField(0, 16,
                                  writeCallback: (_, val) =>
                    {
                        var bits = BitHelper.GetBits(val);          // put the register bits in an array after they are written
                        for (var i = 0; i < bits.Length; i++)
                        {
                            //if(bits[i] == 1)  // pullup
                            // todo: not currently supported
                        }
                    })
                  .WithTag("RESERVED", 16, 16) },

                { (long)Registers.GPIO_PDB, new DoubleWordRegister(this)
                  .WithValueField(0, 16,
                                  writeCallback: (_, val) =>
                    {
                        var bits = BitHelper.GetBits(val);          // put the register bits in an array after they are written
                        for (var i = 0; i < bits.Length; i++)
                        {
                            //if(bits[i] == 1)  // pulldown
                            // todo: not currently supported
                        }
                    })
                  .WithTag("RESERVED", 16, 16) }
            };

            registers = new DoubleWordRegisterCollection(this, registersMap);
        }
예제 #18
0
        private void CreatePortRegisters(Dictionary <long, DoubleWordRegister> regs, int portNumber)
        {
            var regOffset = PortOffset * portNumber;
            var pinOffset = portNumber * NumberOfPins;

            regs.Add((long)Registers.PortAControl + regOffset, new DoubleWordRegister(this, 0x700070)
                     .WithTag("DRIVESTRENGTH", 0, 1)
                     .WithTag("SLEWRATE", 4, 3)
                     .WithTag("DINDIS", 12, 1)
                     .WithTag("DRIVESTRENGTHALT", 16, 1)
                     .WithTag("SLEWRATEALT", 20, 3)
                     .WithTag("DINDISALT", 28, 1)
                     );

            var gpioModeLow  = new DoubleWordRegister(this);
            var gpioModeHigh = new DoubleWordRegister(this);

            for (var pinNumber = 0; pinNumber < 8; ++pinNumber)
            {
                pinModes[pinOffset + pinNumber] = gpioModeLow.DefineEnumField <PinMode>(pinNumber * 4, 4, name: "MODEX"); //TODO: pin locking
            }

            for (var pinNumber = 8; pinNumber < 16; ++pinNumber)
            {
                pinModes[pinOffset + pinNumber] = gpioModeHigh.DefineEnumField <PinMode>((pinNumber - 8) * 4, 4, name: "MODEX"); //TODO: pin locking
            }

            regs.Add((long)Registers.PortAModeLow + regOffset, gpioModeLow);
            regs.Add((long)Registers.PortAModeHigh + regOffset, gpioModeHigh);

            regs.Add((long)Registers.PortADataOut + regOffset, new DoubleWordRegister(this)
                     .WithValueField(0, 16,
                                     writeCallback: (_, newValue) =>
            {
                var bits = BitHelper.GetBits(newValue);
                for (var i = 0; i < 16; i++)
                {
                    var pin = pinOffset + i;
                    if (IsOutput(pinModes[pin].Value) && unlockedPins[pin].Value)
                    {
                        Connections[pin].Set(bits[i]);
                    }
                }
            },
                                     valueProviderCallback: _ => BitHelper.GetValueFromBitsArray(Connections.Where(x => x.Key >= 0).OrderBy(x => x.Key).Select(x => x.Value.IsSet))));

            regs.Add((long)Registers.PortADataOutToggle + regOffset, new DoubleWordRegister(this)
                     .WithValueField(0, 16, FieldMode.Write,
                                     writeCallback: (_, newValue) =>
            {
                var bits = BitHelper.GetSetBits(newValue);
                foreach (var bit in bits)
                {
                    var pin = pinOffset + bit;
                    if (IsOutput(pinModes[pin].Value) && unlockedPins[pin].Value)
                    {
                        Connections[pin].Toggle();
                    }
                }
            }));

            regs.Add((long)Registers.PortADataIn + regOffset, new DoubleWordRegister(this)
                     .WithValueField(0, 16, FieldMode.Read, valueProviderCallback: (oldValue) => BitHelper.GetValueFromBitsArray(State.Skip(pinOffset).Take(NumberOfPins))));

            var unlockedPinsRegister = new DoubleWordRegister(this, 0xFFFF);

            for (var pinNumber = 0; pinNumber < NumberOfPins; ++pinNumber)
            {
                unlockedPins[pinNumber + pinOffset] = unlockedPinsRegister.DefineFlagField(pinNumber, FieldMode.WriteZeroToClear);
            }
            regs.Add((long)Registers.PortAUnlockedPins + regOffset, unlockedPinsRegister);
        }
예제 #19
0
        // pixels
        private static Color[] DecodeUncompressedPixelDataToColors(byte[] pixelData, int bpp, int width, int height, bool palette)
        {
            Color[] pixels;
            int     pIdx = 0;

            switch (bpp)
            {
            case 32:
            {
                pixels = new Color[width * height];

                if (palette)
                {
                    for (int i = 0; i < pixelData.Length; i += 4)
                    {
                        pixels[pIdx++] = Color.FromArgb(BitConverter.ToInt32(pixelData, i));
                    }
                }
                else
                {
                    for (int y = height - 1; y >= 0; y--)
                    {
                        for (int x = 0; x < width; x++, pIdx += 4)
                        {
                            pixels[x + y * width] = Color.FromArgb(BitConverter.ToInt32(pixelData, pIdx));
                        }
                    }
                }
            }
            break;

            case 24:
            {
                pixels = new Color[width * height];

                if (palette)
                {
                    for (int i = 0; i < pixelData.Length; i += 3)
                    {
                        pixels[pIdx++] = Color.FromArgb(pixelData[i + 2], pixelData[i + 1], pixelData[i]);
                    }
                }
                else
                {
                    for (int y = height - 1; y >= 0; y--)
                    {
                        for (int x = 0; x < width; x++, pIdx += 3)
                        {
                            pixels[x + y * width] = Color.FromArgb(pixelData[pIdx + 2], pixelData[pIdx + 1], pixelData[pIdx]);
                        }
                    }
                }
            }
            break;

            case 16:
            {
                pixels = new Color[width * height];

                for (int y = height - 1; y >= 0; y--)
                {
                    for (int x = 0; x < width; x++, pIdx += 2)
                    {
                        ushort color = BitConverter.ToUInt16(pixelData, pIdx);
                        pixels[x + (height - 1 - y) * width] = Color.FromArgb(
                            BitHelper.IsBitSet(color, 15) ? 0 : byte.MaxValue,      // a
                            BitHelper.GetBits(color, 5, 0) << 3,                    // r
                                BitHelper.GetBits(color, 5, 5) << 3,                // g
                                BitHelper.GetBits(color, 5, 10) << 3);              // b
                    }
                }
            }
            break;

            default:
                throw new System.NotImplementedException();
            }
            return(pixels);
        }
예제 #20
0
 private void PrepareRegisters()
 {
     registers = new DoubleWordRegisterCollection(this, new Dictionary <long, DoubleWordRegister>
     {
         { (long)Registers.Data, new DoubleWordRegister(this)
           .WithValueField(0, 8,
                           writeCallback: (_, val) =>
             {
                 var bits = BitHelper.GetBits(val);
                 for (int i = 0; i < 8; i++)
                 {
                     if (irqManager.PinDirection[i] == GPIOInterruptManager.Direction.Input)
                     {
                         Connections[i].Set(bits[i]);
                         State[i] = bits[i];
                     }
                 }
             },
                           valueProviderCallback: _ => { return(BitHelper.GetValueFromBitsArray(State)); }) },
         { (long)Registers.DataDirection, new DoubleWordRegister(this)
           .WithValueField(0, 8, writeCallback: (_, val) =>
             {
                 var bits = BitHelper.GetBits(val);
                 for (var i = 0; i < 8; i++)
                 {
                     irqManager.PinDirection[i] = bits[i] ? GPIOInterruptManager.Direction.Output : GPIOInterruptManager.Direction.Input;
                 }
             },
                           valueProviderCallback: _ => BitHelper.GetValueFromBitsArray(irqManager.PinDirection.Select(x => x == GPIOInterruptManager.Direction.Output))) },
         { (long)Registers.InterruptSense, new DoubleWordRegister(this)
           .WithValueField(0, 8, out interruptSenseField, writeCallback: (_, val) => CalculateInterruptTypes()) },
         { (long)Registers.InterruptBothEdges, new DoubleWordRegister(this)
           .WithValueField(0, 8, out interruptBothEdgeField, writeCallback: (_, val) => CalculateInterruptTypes()) },
         { (long)Registers.InterruptEvent, new DoubleWordRegister(this)
           .WithValueField(0, 8, out interruptEventField, writeCallback: (_, val) => CalculateInterruptTypes()) },
         { (long)Registers.InterruptEnable, new DoubleWordRegister(this)
           .WithValueField(0, 8, writeCallback: (_, val) =>
             {
                 var bits = BitHelper.GetBits(val);
                 for (var i = 0; i < 8; i++)
                 {
                     irqManager.InterruptEnable[i] = bits[i];
                     irqManager.InterruptMask[i]   = bits[i];
                 }
                 irqManager.RefreshInterrupts();
             },
                           valueProviderCallback: _ => BitHelper.GetValueFromBitsArray(irqManager.InterruptEnable)) },
         { (long)Registers.RawInterruptStatus, new DoubleWordRegister(this)
           .WithValueField(0, 8, valueProviderCallback: _ => BitHelper.GetValueFromBitsArray(irqManager.ActiveInterrupts)) },
         { (long)Registers.MaskedInterruptStatus, new DoubleWordRegister(this)
           .WithValueField(0, 8, valueProviderCallback: _ => CalculateMaskedInterruptValue()) },
         { (long)Registers.InterruptClear, new DoubleWordRegister(this)
           .WithValueField(0, 8, FieldMode.Write, writeCallback: (_, val) =>
             {
                 var bits = BitHelper.GetBits(val);
                 for (var i = 0; i < 8; i++)
                 {
                     if (bits[i])
                     {
                         irqManager.ClearInterrupt(i);
                     }
                 }
             }) },
         { (long)Registers.ModeControlSelect, new DoubleWordRegister(this)
           .WithTag("AFSEL", 0, 32) },
         { (long)Registers.PortEdgeControl, new DoubleWordRegister(this)
           .WithTag("P_EDGE_CTRL", 0, 32) },
         { (long)Registers.PowerUpInterruptEnable, new DoubleWordRegister(this)
           .WithTag("PI_IEN", 0, 32) },
         { (long)Registers.IOPortsIRQDetectACK, new DoubleWordRegister(this)
           .WithTag("IRQ_DETECT_ACK", 0, 32) },
         { (long)Registers.MaskedIRQDetectACK, new DoubleWordRegister(this)
           .WithTag("IRQ_DETECT_UNMASK", 0, 32) }
     });
 }
예제 #21
0
        public MiV_CoreGPIO(Machine machine) : base(machine, NumberOfInterrupts)
        {
            innerLock = new object();
            IRQ       = new GPIO();

            irqManager = new GPIOInterruptManager(IRQ, State);

            var registersMap = new Dictionary <long, DoubleWordRegister>
            {
                { (long)Registers.OutputRegister, new DoubleWordRegister(this).WithValueField(0, 32, FieldMode.Write, writeCallback: (_, value) =>
                    {
                        lock (innerLock)
                        {
                            var bits = BitHelper.GetBits(value);
                            for (var i = 0; i < bits.Length; i++)
                            {
                                Connections[i].Set(bits[i]);
                            }
                        }
                    }) },

                { (long)Registers.InputRegister, new DoubleWordRegister(this).WithValueField(0, 32, FieldMode.Read, valueProviderCallback: _ =>
                    {
                        lock (innerLock)
                        {
                            return(BitHelper.GetValueFromBitsArray(State));
                        }
                    }) },

                { (long)Registers.InterruptClearRegister, new DoubleWordRegister(this).WithValueField(0, 32, writeCallback: (_, value) =>
                    {
                        lock (innerLock)
                        {
                            foreach (var i in BitHelper.GetSetBits(value))
                            {
                                irqManager.ClearInterrupt((uint)i);
                            }
                        }
                    }, valueProviderCallback: _ => {
                        lock (innerLock)
                        {
                            return(BitHelper.GetValueFromBitsArray(irqManager.ActiveInterrupts));
                        }
                    }) }
            };

            var intTypeToVal = new TwoWayDictionary <GPIOInterruptManager.InterruptTrigger, uint>();

            intTypeToVal.Add(GPIOInterruptManager.InterruptTrigger.ActiveHigh, 0);
            intTypeToVal.Add(GPIOInterruptManager.InterruptTrigger.ActiveLow, 1);
            intTypeToVal.Add(GPIOInterruptManager.InterruptTrigger.RisingEdge, 2);
            intTypeToVal.Add(GPIOInterruptManager.InterruptTrigger.FallingEdge, 3);
            intTypeToVal.Add(GPIOInterruptManager.InterruptTrigger.BothEdges, 4);

            for (var i = 0; i < NumberOfInterrupts; i++)
            {
                var j = i;
                registersMap.Add((long)Registers.ConfigurationRegisterBase + i * 0x4, new DoubleWordRegister(this)
                                 .WithFlag(0, writeCallback: (_, v) =>
                {
                    if (v)
                    {
                        irqManager.PinDirection[j] |= GPIOInterruptManager.Direction.Output;
                    }
                    else
                    {
                        irqManager.PinDirection[j] &= ~GPIOInterruptManager.Direction.Output;
                    }
                },
                                           valueProviderCallback: _ => (irqManager.PinDirection[j] & GPIOInterruptManager.Direction.Output) != 0, name: "OUTREG")
                                 .WithFlag(1, writeCallback: (_, value) =>
                {
                    if (value)
                    {
                        irqManager.PinDirection[j] |= GPIOInterruptManager.Direction.Input;
                    }
                    else
                    {
                        irqManager.PinDirection[j] &= ~GPIOInterruptManager.Direction.Input;
                    }
                },
                                           valueProviderCallback: _ => (irqManager.PinDirection[j] & GPIOInterruptManager.Direction.Input) != 0, name: "INREG")
                                 .WithTag("OUTBUFF", 2, 1)
                                 .WithFlag(3, writeCallback: (_, v) => { irqManager.InterruptEnable[j] = v; }, valueProviderCallback: _ => irqManager.InterruptEnable[j], name: "INTENABLE")
                                 //bit 4 unused
                                 .WithValueField(5, 3, writeCallback: (_, value) =>
                {
                    if (!intTypeToVal.TryGetValue(value, out var type))
                    {
                        this.Log(LogLevel.Warning, "Invalid interrupt type for pin #{0}: {1}", j, value);
                        return;
                    }
                    irqManager.InterruptType[j] = type;
                }, valueProviderCallback: _ =>
                {
                    if (!intTypeToVal.TryGetValue(irqManager.InterruptType[j], out var value))
                    {
                        throw new ArgumentOutOfRangeException($"Unknown interrupt trigger type: {irqManager.InterruptType[j]}");
                    }
                    return(value);
                }, name: "INTTYPE"));
            }

            registers = new DoubleWordRegisterCollection(this, registersMap);
        }
예제 #22
0
        private void HandleClockRising(bool[] signals)
        {
            switch (state)
            {
            case State.Address:
            {
                this.Log(LogLevel.Noisy, "Appending address bit #{0}: {1}", bufferToDevice.Count, signals[DataSignal]);
                bufferToDevice.Push(signals[DataSignal]);

                if (bufferToDevice.Count == 7)
                {
                    var address = (int)BitHelper.GetValueFromBitsArray(bufferToDevice.PopAll());

                    this.Log(LogLevel.Noisy, "Address decoded: 0x{0:X}", address);
                    state = State.Operation;

                    if (!TryGetByAddress(address, out slave))
                    {
                        this.Log(LogLevel.Warning, "Trying to access a non-existing I2C device at address 0x{0:X}", address);
                    }
                }
                break;
            }

            case State.Operation:
            {
                isRead = signals[DataSignal];
                this.Log(LogLevel.Noisy, "Operation decoded: {0}", isRead ? "read" : "write");

                // write ACK(false) or NACK(true)
                bufferFromDevice.Enqueue(slave == null);

                state = State.AddressAck;
                break;
            }

            case State.AddressAck:
            {
                if (slave == null)
                {
                    // ignore the rest of transmission until the next (repeated) start condition
                    state = State.Idle;
                }
                else if (isRead)
                {
                    this.Log(LogLevel.Noisy, "Reading from device");
                    foreach (var @byte in slave.Read(6))
                    {
                        foreach (var bit in BitHelper.GetBits(@byte).Take(8).Reverse())
                        {
                            this.Log(LogLevel.Noisy, "Enqueuing bit: {0}", bit);
                            bufferFromDevice.Enqueue(bit);
                        }
                    }

                    tickCounter = 0;
                    state       = State.Read;
                }
                else     // it must be write
                {
                    state = State.Write;
                }
                break;
            }

            case State.Read:
            {
                tickCounter++;
                if (tickCounter == 8)
                {
                    state = State.ReadAck;
                }
                break;
            }

            case State.ReadAck:
            {
                tickCounter = 0;
                state       = State.Read;
                break;
            }

            case State.Write:
            {
                this.Log(LogLevel.Noisy, "Latching data bit #{0}: {1}", bufferToDevice.Count, signals[DataSignal]);
                bufferToDevice.Push(signals[DataSignal]);

                if (bufferToDevice.Count == 8)
                {
                    state = State.WriteAck;
                }
                break;
            }

            case State.WriteAck:
            {
                DebugHelper.Assert(bufferToDevice.Count == 8);

                var dataByte = (byte)BitHelper.GetValueFromBitsArray(bufferToDevice.PopAll());
                this.Log(LogLevel.Noisy, "Decoded data byte #{0}: 0x{1:X}", bytesToDevice.Count, dataByte);

                bytesToDevice.Enqueue(dataByte);

                // ACK
                this.Log(LogLevel.Noisy, "Enqueuing ACK");
                bufferFromDevice.Enqueue(false);

                state = State.Write;
                break;
            }
            }
        }
예제 #23
0
        private void UpdateInterrupt()
        {
            var enabled = BitHelper.GetBits(buttonsEnabled.Value).Take(ButtonsCount);

            IRQ.Set(enabled.Zip(buttonsPending, (en, pe) => en && pe).Any());
        }
        public PlatformLevelInterruptController(Machine machine, int numberOfSources, int numberOfTargets = 1, bool prioritiesEnabled = true)
        {
            if (numberOfTargets != 1)
            {
                throw new ConstructionException($"Current {this.GetType().Name} implementation does not support more than one target");
            }
            // numberOfSources has to fit between these two registers, one bit per source
            if (Math.Ceiling((numberOfSources + 1) / 32.0) * 4 > Registers.Target1Enables - Registers.Target0Enables)
            {
                throw new ConstructionException($"Current {this.GetType().Name} implementation more than {Registers.Target1Enables - Registers.Target0Enables} sources");
            }

            this.prioritiesEnabled = prioritiesEnabled;

            this.machine = machine;
            IRQ          = new GPIO();
            // irqSources are initialized from 1, as the source "0" is not used.
            irqSources = new IrqSource[numberOfSources + 1];
            for (var i = 1; i <= numberOfSources; i++)
            {
                irqSources[i] = new IrqSource();
            }
            activeInterrupts = new Stack <uint>();

            var registersMap = new Dictionary <long, DoubleWordRegister>
            {
                { (long)Registers.Target0ClaimComplete, new DoubleWordRegister(this).WithValueField(0, 32, valueProviderCallback: _ =>
                    {
                        return(AcknowledgePendingInterrupt());
                    }, writeCallback: (_, value) =>
                    {
                        CompleteHandlingInterrupt(value);
                    }
                                                                                                    ) }
            };

            registersMap.Add((long)Registers.Source0Priority, new DoubleWordRegister(this)
                             .WithValueField(0, 3, FieldMode.Read,
                                             writeCallback: (_, value) => { if (value != 0)
                                                                            {
                                                                                this.Log(LogLevel.Warning, $"Trying to set priority {value} to Source 0, which is illegal");
                                                                            }
                                             }));
            for (var i = 1; i <= numberOfSources; i++)
            {
                var j = i;
                registersMap[(long)Registers.Source1Priority * i] = new DoubleWordRegister(this)
                                                                    .WithValueField(0, 3,
                                                                                    valueProviderCallback: (_) => irqSources[j].Priority,
                                                                                    writeCallback: (_, value) => { if (prioritiesEnabled)
                                                                                                                   {
                                                                                                                       irqSources[j].Priority = value;
                                                                                                                   }
                                                                                    });
            }

            var vectorWidth = (uint)Registers.Target1Enables - (uint)Registers.Target0Enables;
            var maximumSourceDoubleWords = (int)Math.Ceiling((numberOfSources + 1) / 32.0) * 4;

            // When writing to TargetXEnables registers, the user will get an error in log when he tries to write to an
            // unused bit of a register that is at least partially used. A warning will be issued on a usual undefined register access otherwise.
            for (var target = 0u; target < numberOfTargets; target++)
            {
                for (var offset = 0u; offset < maximumSourceDoubleWords; offset += 4)
                {
                    var lTarget = target;
                    var lOffset = offset;
                    registersMap.Add((long)Registers.Target0Enables + (vectorWidth * target) + offset, new DoubleWordRegister(this).WithValueField(0, 32, writeCallback: (_, value) =>
                    {
                        lock (irqSources)
                        {
                            // Each source is represented by one bit. offset and lOffset indicate the offset in double words from TargetXEnables,
                            // `bit` is the bit number in the given double word,
                            // and `sourceIdBase + bit` indicate the source number.
                            var sourceIdBase = lOffset * 8;
                            var bits         = BitHelper.GetBits(value);
                            for (var bit = 0u; bit < bits.Length; bit++)
                            {
                                if (sourceIdBase + bit == 0)
                                {
                                    //Source number 0 is not used.
                                    continue;
                                }
                                if (irqSources.Length <= (sourceIdBase + bit))
                                {
                                    if (bits[bit])
                                    {
                                        this.Log(LogLevel.Error, "Trying to enable non-existing source: {0}", sourceIdBase + bit);
                                    }
                                    continue;
                                }
                                var targets = irqSources[sourceIdBase + bit].EnabledTargets;
                                if (bits[bit])
                                {
                                    targets.Add(lTarget);
                                }
                                else
                                {
                                    targets.Remove(lTarget);
                                }
                            }
                            RefreshInterrupts();
                        }
                    }));
                }
            }

            registers = new DoubleWordRegisterCollection(this, registersMap);
        }
예제 #25
0
        public SiFive_GPIO(Machine machine) : base(machine, NumberOfPins)
        {
            locker = new object();
            pins   = new Pin[NumberOfPins];

            var registersMap = new Dictionary <long, DoubleWordRegister>
            {
                { (long)Registers.PinValue, new DoubleWordRegister(this)
                  .WithValueField(0, 32,
                                  valueProviderCallback: _ =>
                    {
                        var readOperations = pins.Select(x => (x.pinOperation & Operation.Read) != 0);
                        var result         = readOperations.Zip(State, (operation, state) => operation && state);
                        return(BitHelper.GetValueFromBitsArray(result));
                    }) },

                { (long)Registers.PinInputEnable, new DoubleWordRegister(this)
                  .WithValueField(0, 32,
                                  writeCallback: (_, val) =>
                    {
                        var bits = BitHelper.GetBits(val);
                        for (var i = 0; i < bits.Length; i++)
                        {
                            Misc.FlipFlag(ref pins[i].pinOperation, Operation.Read, bits[i]);
                        }
                    }) },

                { (long)Registers.PinOutputEnable, new DoubleWordRegister(this)
                  .WithValueField(0, 32,
                                  writeCallback: (_, val) =>
                    {
                        var bits = BitHelper.GetBits(val);
                        for (var i = 0; i < bits.Length; i++)
                        {
                            Misc.FlipFlag(ref pins[i].pinOperation, Operation.Write, bits[i]);
                        }
                    }) },

                { (long)Registers.OutputPortValue, new DoubleWordRegister(this)
                  .WithValueField(0, 32,
                                  writeCallback: (_, val) =>
                    {
                        lock (locker)
                        {
                            var bits = BitHelper.GetBits(val);
                            for (var i = 0; i < bits.Length; i++)
                            {
                                if ((pins[i].pinOperation & Operation.Write) != 0)
                                {
                                    State[i] = bits[i];
                                    Connections[i].Set(bits[i]);
                                }
                            }
                        }
                    }) },

                { (long)Registers.RiseInterruptPending, new DoubleWordRegister(this)
                  .WithValueField(0, 32, writeCallback: (_, val) =>
                    {
                        lock (locker)
                        {
                            var bits = BitHelper.GetBits(val);
                            for (var i = 0; i < bits.Length; i++)
                            {
                                if (bits[i])
                                {
                                    Connections[i].Set(State[i]);
                                }
                            }
                        }
                    }) }
            };

            registers = new DoubleWordRegisterCollection(this, registersMap);
        }