Archived
Private
Public Access
1
0
This repository has been archived on 2026-02-04. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
ProjectBackup/C#/DigiSim/Logic/Gates/CustomGate.cs
2022-09-04 12:45:01 +02:00

142 lines
5.0 KiB
C#

using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;
namespace DigiSim.Logic.Gates {
public class CustomGate : Gate {
public int Inputs { get; }
public int Outputs { get; }
public string Symbol { get; }
public LookupTable Lookup { get; }
public CustomGate(double x, double y) : base(x, y, 50, 50) { }
private CustomGate(string symbol, LookupTable lookup) {
Symbol = symbol;
Lookup = lookup;
Inputs = lookup.InputCount;
Outputs = lookup.OutputCount;
Constructor(0, 0, 0, 0);
}
protected override void InternalSetup(Canvas canvas) {
Shape = new Rectangle();
int connectorCount = Math.Max(Inputs, Outputs);
Size = new Size(50, connectorCount * 25);
SetInputs(Inputs);
SetOutputs(Outputs);
CreateConnections();
Text = Symbol;
Instantiate();
}
public override void Update(Gate source) {
bool[] snapshot = new bool[ConnectedInputs.Length];
for (var i = 0; i < snapshot.Length; i++) {
snapshot[i] = ConnectedInputs[i].IsPowered;
}
bool[] outputs = Lookup.GetOutputs(snapshot);
for (var i = 0; i < ConnectedOutputs.Length; i++) {
ConnectedOutputs[i].IsPowered = outputs[i];
}
UpdateShapes();
UpdateConnectedGates(source);
}
public struct LookupTable {
public bool[,] Inputs { get; }
public bool[,] Outputs { get; }
public int InputCount { get; }
public int OutputCount { get; }
public int Length { get; }
public LookupTable(int inputCount, int outputCount, int length) {
Inputs = new bool[length, inputCount];
Outputs = new bool[length, outputCount];
InputCount = inputCount;
OutputCount = outputCount;
Length = length;
}
public bool[] GetOutputs(bool[] inputs) {
if (inputs.Length != InputCount) throw new ArgumentOutOfRangeException(nameof(inputs));
for (int i = 0; i < Length; i++) {
bool found = true;
for (int j = 0; j < InputCount; j++) {
if (Inputs[i, j] != inputs[j]) {
found = false;
break;
}
}
if (found) {
bool[] output = new bool[OutputCount];
for (int o = 0; o < OutputCount; o++) {
output[o] = Outputs[i, o];
}
return output;
}
}
return new bool[OutputCount];
}
public void SetLookup(bool[] inputs, bool[] outputs, int index) {
if (index >= Length) throw new IndexOutOfRangeException(nameof(index));
for (var i = 0; i < inputs.Length; i++) {
Inputs[index, i] = inputs[i];
}
for (var i = 0; i < outputs.Length; i++) {
Outputs[index, i] = outputs[i];
}
}
}
private static LookupTable CreateLookup(Gate[] gates) {
List<Input> inputs = new List<Input>();
List<Output> outputs = new List<Output>();
foreach (var gate in gates) {
if (gate is Input)
inputs.Add(gate as Input);
if (gate is Output)
outputs.Add(gate as Output);
}
int possibilities = (int) Math.Pow(2, inputs.Count);
LookupTable lookupTable = new LookupTable(inputs.Count, outputs.Count, possibilities);
for (var i = 0; i < possibilities; i++) {
bool[] inputSequenze = new bool[inputs.Count];
bool[] outputSequenze = new bool[outputs.Count];
char[] sequenze = Convert.ToString(i, 2).PadLeft(inputs.Count, '0').ToCharArray();
for (var j = 0; j < sequenze.Length; j++) {
inputSequenze[j] = sequenze[j] == '1';
inputs[j].Powered = sequenze[j] == '1';
inputs[j].Update(inputs[j]);
}
for (var j = 0; j < outputs.Count; j++) {
outputSequenze[j] = outputs[j].ConnectedInputs[0].IsPowered;
}
lookupTable.SetLookup(inputSequenze, outputSequenze, i);
}
return lookupTable;
}
public static CustomGate CreateCustomGateFromBoard(Gate[] gates, string symbol) {
return new CustomGate(symbol, CreateLookup(gates));
}
}
}