/// <summary> /// Gets the result of the current Arithmetic and Logic unit operation. /// </summary> /// <param name="state">Current GPU state</param> /// <returns>Operation result</returns> private int GetAluResult(IDeviceState state) { AluOperation op = (AluOperation)(_opCode & 7); switch (op) { case AluOperation.AluReg: return(GetAluResult((AluRegOperation)((_opCode >> 17) & 0x1f), GetGprA(), GetGprB())); case AluOperation.AddImmediate: return(GetGprA() + GetImm()); case AluOperation.BitfieldReplace: case AluOperation.BitfieldExtractLslImm: case AluOperation.BitfieldExtractLslReg: int bfSrcBit = (_opCode >> 17) & 0x1f; int bfSize = (_opCode >> 22) & 0x1f; int bfDstBit = (_opCode >> 27) & 0x1f; int bfMask = (1 << bfSize) - 1; int dst = GetGprA(); int src = GetGprB(); switch (op) { case AluOperation.BitfieldReplace: src = (int)((uint)src >> bfSrcBit) & bfMask; dst &= ~(bfMask << bfDstBit); dst |= src << bfDstBit; return(dst); case AluOperation.BitfieldExtractLslImm: src = (int)((uint)src >> dst) & bfMask; return(src << bfDstBit); case AluOperation.BitfieldExtractLslReg: src = (int)((uint)src >> bfSrcBit) & bfMask; return(src << dst); } break; case AluOperation.ReadImmediate: return(Read(state, GetGprA() + GetImm())); } throw new InvalidOperationException($"Invalid operation \"{op}\" on instruction 0x{_opCode:X8}."); }
/// <summary> /// Executes a macro program until it exits. /// </summary> /// <param name="code">Code of the program to execute</param> /// <param name="state">Current GPU state</param> /// <param name="arg0">Optional argument passed to the program, 0 if not used</param> public void Execute(ReadOnlySpan <int> code, IDeviceState state, int arg0) { if (_execute == null) { MacroJitCompiler compiler = new MacroJitCompiler(); _execute = compiler.Compile(code); } _execute(_context, state, arg0); }
public ThiDevice(ClassId classId, IDeviceState device, SyncptIncrManager syncptIncrMgr) { _classId = classId; _device = device; _syncptIncrMgr = syncptIncrMgr; _commandQueue = new AsyncWorkQueue <CommandAction>(Process, $"Ryujinx.{classId}Processor"); _state = new DeviceState <ThiRegisters>(new Dictionary <string, RwCallback> { { nameof(ThiRegisters.IncrSyncpt), new RwCallback(IncrSyncpt, null) }, { nameof(ThiRegisters.Method1), new RwCallback(Method1, null) } }); }
/// <summary> /// Executes a macro program until it exits. /// </summary> /// <param name="code">Code of the program to execute</param> /// <param name="state">GPU state at the time of the call</param> /// <param name="arg0">Optional argument passed to the program, 0 if not used</param> public void Execute(ReadOnlySpan <int> code, IDeviceState state, int arg0) { switch (_functionName) { case MacroHLEFunctionName.MultiDrawElementsIndirectCount: MultiDrawElementsIndirectCount(state, arg0); break; default: throw new NotImplementedException(_functionName.ToString()); } }
public static string FormatNaturalLanguageDescription(IDeviceState device) { var result = new StringBuilder(); if (device.Name != null) { result.Append("The "); result.Append(device.Name); } else { result.Append("an unnamed device"); } result.Append(" in "); if (device.Location.IsSet) { // TODO: update this logic to better account for location higherarchy result.Append("The "); result.Append(device.Location.LastPart()); } else { result.Append(" an unknown location"); } result.Append(", connected to "); if (device.NetworkState != null) { if (device.NetworkState.Name != null) { result.Append("the "); result.Append(device.NetworkState.Name); } else { result.Append("an unnamed network"); } } else { result.Append("no network"); } return(result.ToString()); }
public static Device Create(int id, IDeviceState state) { var result = new Device( address: null, lastPing: null, id: id, name: null, network: null, scripts: null, state: state, tasks: null, type: null ); return(result); }
public Device(string address, DateTime? lastPing, int id, string name, Network network, IScriptRepository scripts, IDeviceState state, ITaskRepository tasks, DeviceType type) : this() { Address = address; LastPing = lastPing; Id = id; Name = name; Network = network; ScriptRepository = scripts; TaskRepository = tasks; Type = type; if (state != null) { Update(state, false); } }
/// <summary> /// Executes a macro program until it exits. /// </summary> /// <param name="code">Code of the program to execute</param> /// <param name="state">Current GPU state</param> /// <param name="arg0">Optional argument passed to the program, 0 if not used</param> public void Execute(ReadOnlySpan <int> code, IDeviceState state, int arg0) { Reset(); _gprs[1] = arg0; _pc = 0; FetchOpCode(code); while (Step(code, state)) { } // Due to the delay slot, we still need to execute // one more instruction before we actually exit. Step(code, state); }
public static string Format(IDeviceState device, bool justAddresses = false, string remarks = null) { var network = device.NetworkState; var virtualAddress = new VirtualAddress { NetworkNodeId = network.Address, NetworkName = (justAddresses) ? (null) : (network.Name), //TODO: fix this NetworkLocation = null, //(justAddresses) ? (null) : network.Location_Hack, DeviceNodeId = device.Address, DeviceName = (justAddresses) ? (null) : (device.Name), DeviceLocation = (justAddresses || device.Location == null) ? (null) : (device.Location.Format()), Remark = remarks }; return virtualAddress.Format(); }
public static string Format(IDeviceState device, bool justAddresses = false, string remarks = null) { var network = device.NetworkState; var virtualAddress = new VirtualAddress { NetworkNodeId = network.Address, NetworkName = (justAddresses) ? (null) : (network.Name), //TODO: fix this NetworkLocation = null, //(justAddresses) ? (null) : network.Location_Hack, DeviceNodeId = device.Address, DeviceName = (justAddresses) ? (null) : (device.Name), DeviceLocation = (justAddresses || device.Location == null) ? (null) : (device.Location.Format()), Remark = remarks }; return(virtualAddress.Format()); }
public override async Task <IResult> Handle(ButtonUpEvent message, IDeviceState state, IMessageAcceptor emitter) { if (!(state is ButtonState buttonState)) { return(Result.Failure("Invalid State")); } if (buttonState.Pressed) { buttonState.Pressed = false; emitter.AcceptMessage(new DeviceStateChangedEvent { DeviceId = message.DeviceId, MessageId = Guid.NewGuid(), State = state }); } return(Result.Success()); }
private IServerDeltaDeviceState GetDeviceStateDelta(IDeviceState state) { if (!DeltaDeviceStates.ContainsKey(state.ProviderName)) { DeltaDeviceStates[state.ProviderName] = new Dictionary <string, IServerDeltaDeviceState>(); } if (!DeltaDeviceStates[state.ProviderName].ContainsKey(state.InputName)) { var deltaState = new DeltaDeviceState { InputName = state.InputName, ProviderName = state.ProviderName, IsEnabled = false, TimeDelta = 1 }; DeltaDeviceStates[state.ProviderName][state.InputName] = deltaState; AllDeltas.Add(deltaState); return(deltaState); } return(DeltaDeviceStates[state.ProviderName][state.InputName]); }
/// <summary> /// Performs a GPU method call. /// </summary> /// <param name="state">Current GPU state</param> /// <param name="methAddr">Address, in words, of the method</param> /// <param name="value">Call argument</param> private static void Send(IDeviceState state, int methAddr, int value) { state.Write(methAddr * 4, value); }
/// <summary> /// Performs a indirect multi-draw, with parameters from a GPU buffer. /// </summary> /// <param name="state">GPU state at the time of the call</param> /// <param name="arg0">First argument of the call</param> private void MultiDrawElementsIndirectCount(IDeviceState state, int arg0) { int arg1 = FetchParam().Word; int arg2 = FetchParam().Word; int arg3 = FetchParam().Word; int startDraw = arg0; int endDraw = arg1; var topology = (PrimitiveTopology)arg2; int paddingWords = arg3; int stride = paddingWords * 4 + 0x14; ulong parameterBufferGpuVa = FetchParam().GpuVa; int maxDrawCount = endDraw - startDraw; if (startDraw != 0) { int drawCount = _processor.MemoryManager.Read <int>(parameterBufferGpuVa, tracked: true); // Calculate maximum draw count based on the previous draw count and current draw count. if ((uint)drawCount <= (uint)startDraw) { // The start draw is past our total draw count, so all draws were already performed. maxDrawCount = 0; } else { // Perform just the missing number of draws. maxDrawCount = (int)Math.Min((uint)maxDrawCount, (uint)(drawCount - startDraw)); } } if (maxDrawCount == 0) { Fifo.Clear(); return; } int indirectBufferSize = maxDrawCount * stride; ulong indirectBufferGpuVa = 0; int indexCount = 0; for (int i = 0; i < maxDrawCount; i++) { var count = FetchParam(); var instanceCount = FetchParam(); var firstIndex = FetchParam(); var baseVertex = FetchParam(); var baseInstance = FetchParam(); if (i == 0) { indirectBufferGpuVa = count.GpuVa; } indexCount = Math.Max(indexCount, count.Word + firstIndex.Word); if (i != maxDrawCount - 1) { for (int j = 0; j < paddingWords; j++) { FetchParam(); } } } // It should be empty at this point, but clear it just to be safe. Fifo.Clear(); var bufferCache = _processor.MemoryManager.Physical.BufferCache; var parameterBuffer = bufferCache.GetGpuBufferRange(_processor.MemoryManager, parameterBufferGpuVa, 4); var indirectBuffer = bufferCache.GetGpuBufferRange(_processor.MemoryManager, indirectBufferGpuVa, (ulong)indirectBufferSize); _processor.ThreedClass.MultiDrawIndirectCount(indexCount, topology, indirectBuffer, parameterBuffer, maxDrawCount, stride); }
/// <summary> /// Executes a single instruction of the program. /// </summary> /// <param name="code">Program code to execute</param> /// <param name="state">Current GPU state</param> /// <returns>True to continue execution, false if the program exited</returns> private bool Step(ReadOnlySpan <int> code, IDeviceState state) { int baseAddr = _pc - 1; FetchOpCode(code); if ((_opCode & 7) < 7) { // Operation produces a value. AssignmentOperation asgOp = (AssignmentOperation)((_opCode >> 4) & 7); int result = GetAluResult(state); switch (asgOp) { // Fetch parameter and ignore result. case AssignmentOperation.IgnoreAndFetch: SetDstGpr(FetchParam()); break; // Move result. case AssignmentOperation.Move: SetDstGpr(result); break; // Move result and use as Method Address. case AssignmentOperation.MoveAndSetMaddr: SetDstGpr(result); SetMethAddr(result); break; // Fetch parameter and send result. case AssignmentOperation.FetchAndSend: SetDstGpr(FetchParam()); Send(state, result); break; // Move and send result. case AssignmentOperation.MoveAndSend: SetDstGpr(result); Send(state, result); break; // Fetch parameter and use result as Method Address. case AssignmentOperation.FetchAndSetMaddr: SetDstGpr(FetchParam()); SetMethAddr(result); break; // Move result and use as Method Address, then fetch and send parameter. case AssignmentOperation.MoveAndSetMaddrThenFetchAndSend: SetDstGpr(result); SetMethAddr(result); Send(state, FetchParam()); break; // Move result and use as Method Address, then send bits 17:12 of result. case AssignmentOperation.MoveAndSetMaddrThenSendHigh: SetDstGpr(result); SetMethAddr(result); Send(state, (result >> 12) & 0x3f); break; } } else { // Branch. bool onNotZero = ((_opCode >> 4) & 1) != 0; bool taken = onNotZero ? GetGprA() != 0 : GetGprA() == 0; if (taken) { _pc = baseAddr + GetImm(); bool noDelays = (_opCode & 0x20) != 0; if (noDelays) { FetchOpCode(code); } else { // The delay slot instruction exit flag should be ignored. _ignoreExitFlag = true; } return(true); } } bool exit = (_opCode & 0x80) != 0 && !_ignoreExitFlag; _ignoreExitFlag = false; return(!exit); }
public void Update(int id, IDeviceState state) { _devices.Update(id, state); }
/// <summary> /// Sends a uncompressed method for processing by the graphics pipeline. /// </summary> /// <param name="gpuVa">GPU virtual address where the command word is located</param> /// <param name="meth">Method to be processed</param> private void Send(ulong gpuVa, int offset, int argument, int subChannel, bool isLastCall) { if (offset < 0x60) { _fifoClass.Write(offset * 4, argument); } else if (offset < 0xe00) { offset *= 4; switch (subChannel) { case 0: _3dClass.Write(offset, argument); break; case 1: _computeClass.Write(offset, argument); break; case 2: _i2mClass.Write(offset, argument); break; case 3: _2dClass.Write(offset, argument); break; case 4: _dmaClass.Write(offset, argument); break; } } else { IDeviceState state = subChannel switch { 0 => _3dClass, 3 => _2dClass, _ => null }; if (state != null) { int macroIndex = (offset >> 1) & MacroIndexMask; if ((offset & 1) != 0) { _fifoClass.MmePushArgument(macroIndex, gpuVa, argument); } else { _fifoClass.MmeStart(macroIndex, argument); } if (isLastCall) { _fifoClass.CallMme(macroIndex, state); _3dClass.PerformDeferredDraws(); } } } }
public static ReadOnlyDeviceState Copy(this IDeviceState state) { return(ReadOnlyDeviceState.CopyFrom(state)); }
public void SwitchOff() { _currentState = _states[DeviceState.Offline]; }
/// <summary> /// Clears the current depth-stencil target. /// </summary> /// <param name="state">GPU state at the time of the call</param> /// <param name="arg0">First argument of the call</param> private void ClearDepthStencil(IDeviceState state, int arg0) { int layerCount = state.Read(ZetaLayerCountOffset); _processor.ThreedClass.Clear(arg0, layerCount); }
public Device(string address, DateTime?lastPing, int id, string name, Network network, IScriptRepository scripts, IDeviceState state, ITaskRepository tasks, DeviceType type) : this() { Address = address; LastPing = lastPing; Id = id; Name = name; Network = network; ScriptRepository = scripts; TaskRepository = tasks; Type = type; if (state != null) { Update(state, false); } }
protected override string GetMeasurement(IDeviceState state) { return(state?.CurrentAction); }
public void Update(IDeviceState state, bool fromDatabase = false) { //TODO: update more properties? if (!fromDatabase) { if (Name == null && state.Name != null) { Name = state.Name; } if ((Type == null || Type.Equals(DeviceType.Unknown)) && state.Type != null) { Type = state.Type; } } Location = (state.Location == null) ? null : new Location(state.Location.GetParts()); IsConnected = state.IsConnected; CurrentAction = state.CurrentAction; BinarySwitch.Update(state.BinarySwitchState ?? ReadOnlyBinarySwitchSwitchState.Blank()); MultilevelSwitch.Update(state.MultilevelSwitchState ?? ReadOnlyMultilevelSwitchState.Blank()); ColorSwitch.Update(state.ColorSwitchState ?? ReadOnlyColorSwitchState.Blank()); BinarySensor.Update(state.BinarySensorState ?? ReadOnlyBinarySensorState.Blank()); PowerSensor.Update(state.PowerSensorState ?? ReadOnlyMultilevelSensorState<IPower>.Blank()); TemperatureSensor.Update(state.TemperatureSensorState ?? ReadOnlyMultilevelSensorState<ITemperature>.Blank()); HumiditySensor.Update(state.HumiditySensorState ?? ReadOnlyMultilevelSensorState<IHumidity>.Blank()); IlluminanceSensor.Update(state.IlluminanceSensorState ?? ReadOnlyMultilevelSensorState<IIlluminance>.Blank()); Thermostat.Update(state.ThermostatState ?? ReadOnlyThermostatState.Blank()); }
public void Update(int id, IDeviceState state) { //TODO: improve this var device = Get(id); device.Update(state, false); var model = _devices.Find(id); model.Notes = DeviceModel.FromRepositoryType(device, _networks).Notes; _save(); }
//TODO: unit test this public static ReadOnlyDeviceState CopyFrom(IDeviceState source) { var result = new ReadOnlyDeviceState { Name = source.Name, Address = source.Address, Location = source.Location.Copy(), NetworkState = source.NetworkState, IsConnected = source.IsConnected, Type = source.Type, CurrentAction = source.CurrentAction, BinarySwitchState = (source.BinarySwitchState == null) ? null : source.BinarySwitchState.Copy(), PowerSensorState = (source.PowerSensorState == null)?null:source.PowerSensorState.Copy(), TemperatureSensorState = (source.TemperatureSensorState == null) ? null : source.TemperatureSensorState.Copy(), HumiditySensorState = (source.HumiditySensorState == null) ? null : source.HumiditySensorState.Copy(), IlluminanceSensorState = (source.IlluminanceSensorState == null) ? null : source.IlluminanceSensorState.Copy(), MultilevelSwitchState = (source.MultilevelSwitchState == null) ? null : source.MultilevelSwitchState.Copy(), ColorSwitchState = (source.ColorSwitchState == null) ? null : source.ColorSwitchState.Copy(), BinarySensorState = (source.BinarySensorState == null)?null : source.BinarySensorState.Copy(), ThermostatState = (source.ThermostatState == null) ? null : source.ThermostatState.Copy(), KeypadState = (source.KeypadState == null) ? null : source.KeypadState.Copy() }; return result; }
public void SwitchOn() { _currentState = _states[DeviceState.Online]; }
/// <summary> /// Sets the state of the device from the specified object /// </summary> /// <param name="state">Device state</param> public override void RestoreState(IDeviceState state) => state.RestoreDeviceState(this);
public static string Describe(this IDeviceState device) { var parts = new List <string>(); if (device.Type == DeviceType.BinarySwitch || (device.BinarySwitchState != null && device.BinarySwitchState.Power != null)) { parts.Add(device.BinarySwitchState.Describe()); } if (device.Type == DeviceType.MultilevelSwitch || (device.MultilevelSwitchState != null && device.MultilevelSwitchState.Power != null)) { parts.Add(device.MultilevelSwitchState.Describe()); } if (device.Type == DeviceType.Thermostat || (device.ThermostatState != null && device.ThermostatState.HasData())) { parts.Add(device.ThermostatState.Describe()); } if (device.Type == DeviceType.Keypad || (device.KeypadState != null && device.KeypadState.Buttons != null && device.KeypadState.Buttons.Any())) { parts.Add(device.KeypadState.Describe()); } if (device.CurrentAction != null) { parts.Add("Current Action = " + device.CurrentAction); } if (device.ColorSwitchState != null && device.ColorSwitchState.Value != null) { parts.Add(device.ColorSwitchState.Describe()); } if (device.BinarySensorState != null && device.BinarySensorState.Value != null) { parts.Add(device.BinarySensorState.Describe()); } if (device.PowerSensorState != null && device.PowerSensorState.Value != null) { parts.Add(device.PowerSensorState.Describe()); } if (device.TemperatureSensorState != null && device.TemperatureSensorState.Value != null) { parts.Add(device.TemperatureSensorState.Describe()); } if (device.HumiditySensorState != null && device.HumiditySensorState.Value != null) { parts.Add(device.HumiditySensorState.Describe()); } if (device.IlluminanceSensorState != null && device.IlluminanceSensorState.Value != null) { parts.Add(device.IlluminanceSensorState.Describe()); } var result = string.Join(", ", parts); return(result); }
/// <summary> /// Sets the state of the device from the specified object /// </summary> /// <param name="state">Device state</param> public override void RestoreState(IDeviceState state) { }
public static XElement ToXElement(this IDeviceState state, string nodeName = "HomeAutomationDevice") { var result = new XElement(nodeName); if (!String.IsNullOrWhiteSpace(state.Address)) { result.Add(new XAttribute("Address", state.Address)); } if (!String.IsNullOrWhiteSpace(state.Name)) { result.Add(new XAttribute("Name", state.Name)); } if (state.Location != null && state.Location.IsSet) { result.Add(new XAttribute("Location", state.Location.Format())); } result.Add(new XAttribute("Type", state.Type)); if (state.CurrentAction != null) { result.Add(new XAttribute("CurrentAction", state.CurrentAction)); } //TODO: LastPoll //TODO: this is included for compatibility. remove it soon if (state.MultilevelSwitchState != null && state.MultilevelSwitchState.Power != null) { result.Add(new XAttribute("Power", state.MultilevelSwitchState.Power.Value)); } if (state.IsConnected != null) { result.Add(new XAttribute("IsConnected", state.IsConnected)); } if (state.BinarySwitchState != null) { var element = state.BinarySwitchState.ToXElement(); result.AddIfHasData(element); } if (state.MultilevelSwitchState != null) { var element = state.MultilevelSwitchState.ToXElement(); result.AddIfHasData(element); } if (state.ColorSwitchState != null) { var element = state.ColorSwitchState.ToXElement(); result.AddIfHasData(element); } if (state.BinarySensorState != null) { var element = state.BinarySensorState.ToXElement(); result.AddIfHasData(element); } if (state.PowerSensorState != null) { var element = state.PowerSensorState.ToXElement("PowerSensor"); result.AddIfHasData(element); } if (state.TemperatureSensorState != null) { var element = state.TemperatureSensorState.ToXElement("TemperatureSensor"); result.AddIfHasData(element); } if (state.HumiditySensorState != null) { var element = state.HumiditySensorState.ToXElement("HumiditySensor"); result.AddIfHasData(element); } if (state.IlluminanceSensorState != null) { var element = state.IlluminanceSensorState.ToXElement("IlluminanceSensor"); result.AddIfHasData(element); } if (state.ThermostatState != null) { var element = state.ThermostatState.ToXElement(); result.AddIfHasData(element); } if (state.KeypadState != null) { var element = state.KeypadState.ToXElement(); result.AddIfHasData(element); } return(result); }
/// <summary> /// Sets the state of the device from the specified object /// </summary> /// <param name="state">Device state</param> public void RestoreState(IDeviceState state) => state.RestoreDeviceState(this);
public static string FormatNaturalLanguageDescription(IDeviceState device) { var result = new StringBuilder(); if (device.Name != null) { result.Append("The "); result.Append(device.Name); } else { result.Append("an unnamed device"); } result.Append(" in "); if (device.Location.IsSet) { // TODO: update this logic to better account for location higherarchy result.Append("The "); result.Append(device.Location.LastPart()); } else { result.Append(" an unknown location"); } result.Append(", connected to "); if (device.NetworkState != null) { if (device.NetworkState.Name != null) { result.Append("the "); result.Append(device.NetworkState.Name); } else { result.Append("an unnamed network"); } } else { result.Append("no network"); } return result.ToString(); }
public static Device Create(int id, IDeviceState state) { var result = new Device( address: null, lastPing: null, id: id, name: null, network: null, scripts: null, state: state, tasks: null, type: null ); return result; }
public abstract Task <IResult> Handle(T message, IDeviceState state, IMessageAcceptor emitter);
/// <summary> /// Sets the state of the device from the specified object /// </summary> /// <param name="state">Device state</param> public virtual void RestoreState(IDeviceState state) { }
/// <summary> /// Sets the state of the device from the specified object /// </summary> /// <param name="state">Device state</param> public void RestoreState(IDeviceState state) { throw new NotImplementedException(); }
/// <summary> /// Reads data from a GPU register. /// </summary> /// <param name="state">Current GPU state</param> /// <param name="reg">Register offset to read</param> /// <returns>GPU register value</returns> private int Read(IDeviceState state, int reg) { return(state.Read(reg * 4)); }
/// <summary> /// Sets the state of the device from the specified object /// </summary> /// <param name="state">Device state</param> public void RestoreState(IDeviceState state) { }
/// <summary> /// Performs a GPU method call. /// </summary> /// <param name="state">Current GPU state</param> /// <param name="value">Call argument</param> private void Send(IDeviceState state, int value) { state.Write(_methAddr * 4, value); _methAddr += _methIncr; }
public void Update(int id, IDeviceState state) { _devices.Update(id, state); }
public void Update(IDeviceState state) { Name = state.Name; Address = state.Address; Location.Update(state.Location); Type = state.Type; //TODO: update subdevices? }