142 lines
5.0 KiB
C#
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));
|
|
}
|
|
}
|
|
} |