more gates definition + refactoring
This commit is contained in:
@@ -26,8 +26,8 @@ namespace UntitledLogicGame.UI
|
||||
var subimage = GetComponentInChildren<SVGImage>();
|
||||
subimage.sprite = sprite;
|
||||
subimage.GetComponent<RectTransform>().sizeDelta = new Vector2(100f, 100 * sprite.rect.width / 700f); // TODO get max width from UIManager
|
||||
gameObject.name = "UI_" + _gatePrefab.GateType.ToString();
|
||||
GetComponentInChildren<TextMeshProUGUI>().text = _gatePrefab.GateType.ToString();
|
||||
gameObject.name = "UI_" + _gatePrefab.Definition.Name;
|
||||
GetComponentInChildren<TextMeshProUGUI>().text = _gatePrefab.Definition.Name;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,6 @@ namespace UntitledLogicGame.UI
|
||||
#region Private Properties
|
||||
|
||||
private Gate _gatePrefab;
|
||||
private RectTransform _rectTransform;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ namespace UntitledLogicGame.Workspace
|
||||
{
|
||||
#region Unity Properties
|
||||
|
||||
public bool HasState;
|
||||
public GateType GateType;
|
||||
|
||||
#endregion
|
||||
@@ -71,7 +70,7 @@ namespace UntitledLogicGame.Workspace
|
||||
|
||||
private void Start()
|
||||
{
|
||||
Utils.RandomName(GateType.ToString(), gameObject);
|
||||
Utils.RandomName(Definition.Name, gameObject);
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
@@ -91,7 +90,7 @@ namespace UntitledLogicGame.Workspace
|
||||
|
||||
public bool HasInputAnchor(Anchor target)
|
||||
{
|
||||
return !HasState && (
|
||||
return !Definition.HasState && (
|
||||
InputAnchors.Contains(target) ||
|
||||
InputAnchors.Any(a => a.HasInputAnchor(target))
|
||||
);
|
||||
|
||||
@@ -1,263 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UntitledLogicGame.Workspace.Gates
|
||||
{
|
||||
public enum GateType
|
||||
{
|
||||
// 000 Technical
|
||||
NONE = 000,
|
||||
// 100 Special
|
||||
IN = 100,
|
||||
OUT = 110,
|
||||
// 200 Basic
|
||||
BUF = 200,
|
||||
AND = 210,
|
||||
OR = 220,
|
||||
XOR = 230,
|
||||
// 300 Inverted Basic
|
||||
NOT = 300,
|
||||
NAND = 310,
|
||||
NOR = 320,
|
||||
XNOR = 330,
|
||||
}
|
||||
|
||||
public abstract class GateDefinition
|
||||
{
|
||||
private static Dictionary<GateType, GateDefinition> Definitions;
|
||||
public abstract string[] Inputs { get; }
|
||||
public abstract string[] Outputs { get; }
|
||||
internal abstract Dictionary<State, State> TruthTable { get; }
|
||||
|
||||
private static void LoadAll()
|
||||
{
|
||||
Definitions = new Dictionary<GateType, GateDefinition>();
|
||||
foreach (var gateType in Enum.GetValues(typeof(GateType)).Cast<GateType>())
|
||||
{
|
||||
try
|
||||
{
|
||||
Type t = Type.GetType($"{typeof(GateDefinition).Namespace}.{gateType}Gate", true);
|
||||
Definitions[gateType] = (GateDefinition)t.GetConstructor(new Type[0]).Invoke(new object[0]);
|
||||
}
|
||||
catch
|
||||
{
|
||||
Definitions[gateType] = (GateDefinition)typeof(NoneGate).GetConstructor(new Type[0]).Invoke(new object[0]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static GateDefinition Get(GateType gateType, Gate gate)
|
||||
{
|
||||
if (Definitions == null)
|
||||
LoadAll();
|
||||
|
||||
GateDefinition definition = Definitions[gateType];
|
||||
|
||||
foreach (var inputName in definition.Inputs)
|
||||
{
|
||||
if(!gate.InputAnchors.Any(a => a.Name.Equals(inputName)))
|
||||
throw new InvalidOperationException($"Gate has no {inputName} input anchor");
|
||||
}
|
||||
|
||||
foreach (var outputName in definition.Outputs)
|
||||
{
|
||||
if (!gate.OutputAnchors.Any(a => a.Name.Equals(outputName)))
|
||||
throw new InvalidOperationException($"Gate has no {outputName} output anchor");
|
||||
}
|
||||
|
||||
return definition;
|
||||
}
|
||||
|
||||
internal GateDefinition()
|
||||
{
|
||||
foreach(var key in TruthTable.Keys)
|
||||
{
|
||||
if (key.Length != Inputs.Length)
|
||||
throw new InvalidOperationException($"{GetType()} invalid inputs ({key})");
|
||||
}
|
||||
if(Inputs.Length != 0)
|
||||
{
|
||||
foreach (var key in Utils.AllBoolArrayValues(Inputs.Length).Select(b => new State(b)))
|
||||
{
|
||||
if (!TruthTable.Keys.Contains(key))
|
||||
throw new InvalidOperationException($"{GetType()} no outputs for ({key})");
|
||||
var values = TruthTable[key];
|
||||
if (values.Length != Outputs.Length)
|
||||
throw new InvalidOperationException($"{GetType()} invalid outputs for ({key})");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool[] GetState(Gate gate)
|
||||
{
|
||||
return Inputs.Select(i => gate.InputAnchors.First(a => a.Name.Equals(i)).Activated).ToArray();
|
||||
}
|
||||
|
||||
public void Compute(Gate gate)
|
||||
{
|
||||
if(TruthTable.Count > 0)
|
||||
{
|
||||
State key = new State(GetState(gate));
|
||||
bool[] values = TruthTable[key].values;
|
||||
foreach (var output in Outputs.Select((value, i) => new { i, value }))
|
||||
{
|
||||
gate.OutputAnchors.First(a => a.Name.Equals(output.value)).Activated = values[output.i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class State
|
||||
{
|
||||
internal int Length => values.Length;
|
||||
|
||||
internal bool[] values;
|
||||
|
||||
public State(IEnumerable<bool> args)
|
||||
{
|
||||
values = args.ToArray();
|
||||
}
|
||||
|
||||
public State(params bool[] args)
|
||||
{
|
||||
values = args;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is State state && Enumerable.SequenceEqual(values, state.values);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
//https://stackoverflow.com/questions/6832139/gethashcode-from-booleans-only
|
||||
int hash = 17;
|
||||
for (int index = 0; index < values.Length; index++)
|
||||
hash = hash * 23 + values[index].GetHashCode();
|
||||
return hash;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Join(",", values);
|
||||
}
|
||||
}
|
||||
|
||||
#region Gates
|
||||
|
||||
internal class NoneGate : GateDefinition
|
||||
{
|
||||
public override string[] Inputs { get; } = new string[] { };
|
||||
public override string[] Outputs { get; } = new string[] { };
|
||||
internal override Dictionary<State, State> TruthTable { get; } = new Dictionary<State, State>
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
internal class BufferGate : GateDefinition
|
||||
{
|
||||
public override string[] Inputs { get; } = new string[] { "A" };
|
||||
public override string[] Outputs { get; } = new string[] { "Q" };
|
||||
internal override Dictionary<State, State> TruthTable { get; } = new Dictionary<State, State>
|
||||
{
|
||||
{ new State( false ), new State( false ) },
|
||||
{ new State( true ), new State( true ) },
|
||||
};
|
||||
}
|
||||
|
||||
internal class NOTGate : GateDefinition
|
||||
{
|
||||
public override string[] Inputs { get; } = new string[] { "A" };
|
||||
public override string[] Outputs { get; } = new string[] { "Q" };
|
||||
internal override Dictionary<State, State> TruthTable { get; } = new Dictionary<State, State>
|
||||
{
|
||||
{ new State( false ), new State( true ) },
|
||||
{ new State( true ), new State( false ) },
|
||||
};
|
||||
}
|
||||
|
||||
internal class ANDGate : GateDefinition
|
||||
{
|
||||
public override string[] Inputs { get; } = new string[] { "A", "B" };
|
||||
public override string[] Outputs { get; } = new string[] { "Q" };
|
||||
internal override Dictionary<State, State> TruthTable { get; } = new Dictionary<State, State>
|
||||
{
|
||||
{ new State( false, false ), new State( false ) },
|
||||
{ new State( false, true ), new State( false ) },
|
||||
{ new State( true, false ), new State( false ) },
|
||||
{ new State( true, true ), new State( true ) },
|
||||
};
|
||||
}
|
||||
|
||||
internal class ORGate : GateDefinition
|
||||
{
|
||||
public override string[] Inputs { get; } = new string[] { "A", "B" };
|
||||
public override string[] Outputs { get; } = new string[] { "Q" };
|
||||
internal override Dictionary<State, State> TruthTable { get; } = new Dictionary<State, State>
|
||||
{
|
||||
{ new State( false, false ), new State( false ) },
|
||||
{ new State( false, true ), new State( true ) },
|
||||
{ new State( true, false ), new State( true ) },
|
||||
{ new State( true, true ), new State( true ) },
|
||||
};
|
||||
}
|
||||
|
||||
internal class XORGate : GateDefinition
|
||||
{
|
||||
public override string[] Inputs { get; } = new string[] { "A", "B" };
|
||||
public override string[] Outputs { get; } = new string[] { "Q" };
|
||||
internal override Dictionary<State, State> TruthTable { get; } = new Dictionary<State, State>
|
||||
{
|
||||
{ new State( false, false ), new State( false ) },
|
||||
{ new State( false, true ), new State( true ) },
|
||||
{ new State( true, false ), new State( true ) },
|
||||
{ new State( true, true ), new State( false ) },
|
||||
};
|
||||
}
|
||||
|
||||
internal class NANDGate : GateDefinition
|
||||
{
|
||||
public override string[] Inputs { get; } = new string[]{ "A", "B" };
|
||||
public override string[] Outputs { get; } = new string[] { "Q" };
|
||||
internal override Dictionary<State, State> TruthTable { get; } = new Dictionary<State, State>
|
||||
{
|
||||
{ new State( false, false ), new State( true ) },
|
||||
{ new State( false, true ), new State( true ) },
|
||||
{ new State( true, false ), new State( true ) },
|
||||
{ new State( true, true ), new State( false ) },
|
||||
};
|
||||
}
|
||||
|
||||
internal class NORGate : GateDefinition
|
||||
{
|
||||
public override string[] Inputs { get; } = new string[] { "A", "B" };
|
||||
public override string[] Outputs { get; } = new string[] { "Q" };
|
||||
internal override Dictionary<State, State> TruthTable { get; } = new Dictionary<State, State>
|
||||
{
|
||||
{ new State( false, false ), new State( true ) },
|
||||
{ new State( false, true ), new State( false ) },
|
||||
{ new State( true, false ), new State( false ) },
|
||||
{ new State( true, true ), new State( false ) },
|
||||
};
|
||||
}
|
||||
|
||||
internal class XNORGate : GateDefinition
|
||||
{
|
||||
public override string[] Inputs { get; } = new string[] { "A", "B" };
|
||||
public override string[] Outputs { get; } = new string[] { "Q" };
|
||||
internal override Dictionary<State, State> TruthTable { get; } = new Dictionary<State, State>
|
||||
{
|
||||
{ new State( false, false ), new State( true ) },
|
||||
{ new State( false, true ), new State( false ) },
|
||||
{ new State( true, false ), new State( false ) },
|
||||
{ new State( true, true ), new State( true ) },
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
Executable
+8
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 28d635657f6056543894c99d2d021d36
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace UntitledLogicGame.Workspace.Gates
|
||||
{
|
||||
public abstract class GateDefinition
|
||||
{
|
||||
private static Dictionary<GateType, GateDefinition> Definitions;
|
||||
internal static Dictionary<InputState, OutputState> EmptyTruthTable = new Dictionary<InputState, OutputState>();
|
||||
public abstract string[] Inputs { get; }
|
||||
public abstract string[] Outputs { get; }
|
||||
internal abstract Dictionary<InputState, OutputState> TruthTable { get; }
|
||||
public string Name { get; internal set; }
|
||||
public bool HasState { get; } = false;
|
||||
public GateDefinition New => (GateDefinition)GetType().GetConstructor(new Type[0]).Invoke(new object[0]);
|
||||
|
||||
private static void LoadAll()
|
||||
{
|
||||
Definitions = new Dictionary<GateType, GateDefinition>();
|
||||
foreach (var gateType in Enum.GetValues(typeof(GateType)).Cast<GateType>())
|
||||
{
|
||||
try
|
||||
{
|
||||
Type t = Type.GetType($"{typeof(GateDefinition).Namespace}.{gateType}Gate", true);
|
||||
Definitions[gateType] = (GateDefinition)t.GetConstructor(new Type[0]).Invoke(new object[0]);
|
||||
Definitions[gateType].Name = gateType.ToString();
|
||||
}
|
||||
catch
|
||||
{
|
||||
Definitions[gateType] = (GateDefinition)typeof(NoneGate).GetConstructor(new Type[0]).Invoke(new object[0]);
|
||||
Definitions[gateType].Name = gateType.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static GateDefinition Get(GateType gateType, Gate gate)
|
||||
{
|
||||
if (Definitions == null)
|
||||
LoadAll();
|
||||
|
||||
GateDefinition definition = Definitions[gateType];
|
||||
|
||||
foreach (var inputName in definition.Inputs)
|
||||
{
|
||||
if(!gate.InputAnchors.Any(a => a.Name.Equals(inputName)))
|
||||
throw new InvalidOperationException($"Gate has no {inputName} input anchor");
|
||||
}
|
||||
|
||||
foreach (var outputName in definition.Outputs)
|
||||
{
|
||||
if (!gate.OutputAnchors.Any(a => a.Name.Equals(outputName)))
|
||||
throw new InvalidOperationException($"Gate has no {outputName} output anchor");
|
||||
}
|
||||
|
||||
if (definition.HasState)
|
||||
return definition.New;
|
||||
else
|
||||
return definition;
|
||||
}
|
||||
|
||||
internal GateDefinition()
|
||||
{
|
||||
foreach(var key in TruthTable.Keys)
|
||||
{
|
||||
if (key.Length != Inputs.Length)
|
||||
throw new InvalidOperationException($"{GetType()} invalid inputs ({key})");
|
||||
}
|
||||
if(Inputs.Length != 0)
|
||||
{
|
||||
foreach (var key in Utils.AllBoolArrayValues(Inputs.Length).Select(b => new InputState(b)))
|
||||
{
|
||||
if (!TruthTable.Keys.Contains(key))
|
||||
throw new InvalidOperationException($"{GetType()} no outputs for ({key})");
|
||||
var values = TruthTable[key];
|
||||
if (values.Length != Outputs.Length)
|
||||
throw new InvalidOperationException($"{GetType()} invalid outputs for ({key})");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool[] GetState(Gate gate)
|
||||
{
|
||||
return Inputs.Select(i => gate.InputAnchors.First(a => a.Name.Equals(i)).Activated).ToArray();
|
||||
}
|
||||
|
||||
public void Compute(Gate gate)
|
||||
{
|
||||
InputState input = new InputState(GetState(gate));
|
||||
State output = Compute(input);
|
||||
foreach (var outputAnchor in Outputs.Select((name, i) => new { i, name }))
|
||||
gate.OutputAnchors.First(a => a.Name.Equals(outputAnchor.name)).Activated = output[outputAnchor.i];
|
||||
}
|
||||
|
||||
internal OutputState Compute(InputState input)
|
||||
{
|
||||
if (TruthTable.Count > 0)
|
||||
{
|
||||
return TruthTable[input];
|
||||
}
|
||||
else
|
||||
{
|
||||
return new OutputState(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d351d9e762a4bc64c8491ae8fabcdede
|
||||
guid: 177f93d9946e90d4b863f2fcbdc743c8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
+300
@@ -0,0 +1,300 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace UntitledLogicGame.Workspace.Gates
|
||||
{
|
||||
#region 000 - Technical
|
||||
|
||||
internal class NoneGate : GateDefinition
|
||||
{
|
||||
public override string[] Inputs { get; } = new string[] { };
|
||||
public override string[] Outputs { get; } = new string[] { };
|
||||
internal override Dictionary<InputState, OutputState> TruthTable => EmptyTruthTable;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 100 - Special
|
||||
|
||||
#endregion
|
||||
|
||||
#region 200 - Basic
|
||||
|
||||
internal class BufferGate : GateDefinition
|
||||
{
|
||||
public override string[] Inputs { get; } = new string[] { "A" };
|
||||
public override string[] Outputs { get; } = new string[] { "Q" };
|
||||
internal override Dictionary<InputState, OutputState> TruthTable { get; } = new Dictionary<InputState, OutputState>
|
||||
{
|
||||
{ new InputState( false ), new OutputState( false ) },
|
||||
{ new InputState( true ), new OutputState( true ) },
|
||||
};
|
||||
}
|
||||
|
||||
internal class ANDGate : GateDefinition
|
||||
{
|
||||
public override string[] Inputs { get; } = new string[] { "A", "B" };
|
||||
public override string[] Outputs { get; } = new string[] { "Q" };
|
||||
internal override Dictionary<InputState, OutputState> TruthTable { get; } = new Dictionary<InputState, OutputState>
|
||||
{
|
||||
{ new InputState( false, false ), new OutputState( false ) },
|
||||
{ new InputState( false, true ), new OutputState( false ) },
|
||||
{ new InputState( true, false ), new OutputState( false ) },
|
||||
{ new InputState( true, true ), new OutputState( true ) },
|
||||
};
|
||||
}
|
||||
|
||||
internal class ORGate : GateDefinition
|
||||
{
|
||||
public override string[] Inputs { get; } = new string[] { "A", "B" };
|
||||
public override string[] Outputs { get; } = new string[] { "Q" };
|
||||
internal override Dictionary<InputState, OutputState> TruthTable { get; } = new Dictionary<InputState, OutputState>
|
||||
{
|
||||
{ new InputState( false, false ), new OutputState( false ) },
|
||||
{ new InputState( false, true ), new OutputState( true ) },
|
||||
{ new InputState( true, false ), new OutputState( true ) },
|
||||
{ new InputState( true, true ), new OutputState( true ) },
|
||||
};
|
||||
}
|
||||
|
||||
internal class XORGate : GateDefinition
|
||||
{
|
||||
public override string[] Inputs { get; } = new string[] { "A", "B" };
|
||||
public override string[] Outputs { get; } = new string[] { "Q" };
|
||||
internal override Dictionary<InputState, OutputState> TruthTable { get; } = new Dictionary<InputState, OutputState>
|
||||
{
|
||||
{ new InputState( false, false ), new OutputState( false ) },
|
||||
{ new InputState( false, true ), new OutputState( true ) },
|
||||
{ new InputState( true, false ), new OutputState( true ) },
|
||||
{ new InputState( true, true ), new OutputState( false ) },
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 300 - Inverted Basic
|
||||
|
||||
internal class NOTGate : GateDefinition
|
||||
{
|
||||
public override string[] Inputs { get; } = new string[] { "A" };
|
||||
public override string[] Outputs { get; } = new string[] { "Q" };
|
||||
internal override Dictionary<InputState, OutputState> TruthTable { get; } = new Dictionary<InputState, OutputState>
|
||||
{
|
||||
{ new InputState( false ), new OutputState( true ) },
|
||||
{ new InputState( true ), new OutputState( false ) },
|
||||
};
|
||||
}
|
||||
|
||||
internal class NANDGate : GateDefinition
|
||||
{
|
||||
public override string[] Inputs { get; } = new string[] { "A", "B" };
|
||||
public override string[] Outputs { get; } = new string[] { "Q" };
|
||||
internal override Dictionary<InputState, OutputState> TruthTable { get; } = new Dictionary<InputState, OutputState>
|
||||
{
|
||||
{ new InputState( false, false ), new OutputState( true ) },
|
||||
{ new InputState( false, true ), new OutputState( true ) },
|
||||
{ new InputState( true, false ), new OutputState( true ) },
|
||||
{ new InputState( true, true ), new OutputState( false ) },
|
||||
};
|
||||
}
|
||||
|
||||
internal class NORGate : GateDefinition
|
||||
{
|
||||
public override string[] Inputs { get; } = new string[] { "A", "B" };
|
||||
public override string[] Outputs { get; } = new string[] { "Q" };
|
||||
internal override Dictionary<InputState, OutputState> TruthTable { get; } = new Dictionary<InputState, OutputState>
|
||||
{
|
||||
{ new InputState( false, false ), new OutputState( true ) },
|
||||
{ new InputState( false, true ), new OutputState( false ) },
|
||||
{ new InputState( true, false ), new OutputState( false ) },
|
||||
{ new InputState( true, true ), new OutputState( false ) },
|
||||
};
|
||||
}
|
||||
|
||||
internal class XNORGate : GateDefinition
|
||||
{
|
||||
public override string[] Inputs { get; } = new string[] { "A", "B" };
|
||||
public override string[] Outputs { get; } = new string[] { "Q" };
|
||||
internal override Dictionary<InputState, OutputState> TruthTable { get; } = new Dictionary<InputState, OutputState>
|
||||
{
|
||||
{ new InputState( false, false ), new OutputState( true ) },
|
||||
{ new InputState( false, true ), new OutputState( false ) },
|
||||
{ new InputState( true, false ), new OutputState( false ) },
|
||||
{ new InputState( true, true ), new OutputState( true ) },
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 400 - Latches
|
||||
|
||||
internal class SRLatchGate : GateDefinition
|
||||
{
|
||||
public override string[] Inputs { get; } = new string[] { "S", "R" };
|
||||
public override string[] Outputs { get; } = new string[] { "Q" };
|
||||
internal override Dictionary<InputState, OutputState> TruthTable => EmptyTruthTable;
|
||||
public new string Name => "SR Latch";
|
||||
public new bool HasState => true;
|
||||
|
||||
private bool _q;
|
||||
|
||||
internal new OutputState Compute(InputState input)
|
||||
{
|
||||
bool s = input[0];
|
||||
bool r = input[1];
|
||||
if (r)
|
||||
_q = false;
|
||||
else if (s)
|
||||
_q = true;
|
||||
return new OutputState(_q);
|
||||
}
|
||||
}
|
||||
|
||||
internal class JKLatchGate : GateDefinition
|
||||
{
|
||||
public override string[] Inputs { get; } = new string[] { "J", "K" };
|
||||
public override string[] Outputs { get; } = new string[] { "Q" };
|
||||
internal override Dictionary<InputState, OutputState> TruthTable => EmptyTruthTable;
|
||||
public new string Name => "JK Latch";
|
||||
public new bool HasState => true;
|
||||
|
||||
private bool _q;
|
||||
|
||||
internal new OutputState Compute(InputState input)
|
||||
{
|
||||
bool j = input[0];
|
||||
bool k = input[1];
|
||||
if (k && j)
|
||||
_q = !_q;
|
||||
else if (k)
|
||||
_q = false;
|
||||
else if (j)
|
||||
_q = true;
|
||||
return new OutputState(_q);
|
||||
}
|
||||
}
|
||||
|
||||
internal class DLatchGate : GateDefinition
|
||||
{
|
||||
public override string[] Inputs { get; } = new string[] { "D", "E" };
|
||||
public override string[] Outputs { get; } = new string[] { "Q" };
|
||||
internal override Dictionary<InputState, OutputState> TruthTable => EmptyTruthTable;
|
||||
public new string Name => "D Latch";
|
||||
public new bool HasState => true;
|
||||
|
||||
private bool _q;
|
||||
|
||||
internal new OutputState Compute(InputState input)
|
||||
{
|
||||
bool d = input[0];
|
||||
bool e = input[1];
|
||||
if (e)
|
||||
_q = d;
|
||||
return new OutputState(_q);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 500 - Flip-Flops
|
||||
|
||||
internal class SRFlipFlopGate : GateDefinition
|
||||
{
|
||||
public override string[] Inputs { get; } = new string[] { "S", "R", "CLK" };
|
||||
public override string[] Outputs { get; } = new string[] { "Q" };
|
||||
internal override Dictionary<InputState, OutputState> TruthTable => EmptyTruthTable;
|
||||
public new string Name => "SR Flip-Flop";
|
||||
public new bool HasState => true;
|
||||
|
||||
private bool _q;
|
||||
private bool _lastClk;
|
||||
|
||||
internal new OutputState Compute(InputState input)
|
||||
{
|
||||
bool s = input[0];
|
||||
bool r = input[1];
|
||||
bool clk = input[2];
|
||||
if (clk && !_lastClk) // rising edge
|
||||
if (r)
|
||||
_q = false;
|
||||
else if (s)
|
||||
_q = true;
|
||||
_lastClk = clk;
|
||||
return new OutputState(_q);
|
||||
}
|
||||
}
|
||||
|
||||
internal class JKFlipFlopGate : GateDefinition
|
||||
{
|
||||
public override string[] Inputs { get; } = new string[] { "J", "K", "CLK" };
|
||||
public override string[] Outputs { get; } = new string[] { "Q" };
|
||||
internal override Dictionary<InputState, OutputState> TruthTable => EmptyTruthTable;
|
||||
public new string Name => "JK Flip-Flop";
|
||||
public new bool HasState => true;
|
||||
|
||||
private bool _q;
|
||||
private bool _lastClk;
|
||||
|
||||
internal new OutputState Compute(InputState input)
|
||||
{
|
||||
bool j = input[0];
|
||||
bool k = input[1];
|
||||
bool clk = input[2];
|
||||
if (clk && !_lastClk) // rising edge
|
||||
if (k && j)
|
||||
_q = !_q;
|
||||
else if (k)
|
||||
_q = false;
|
||||
else if (j)
|
||||
_q = true;
|
||||
_lastClk = clk;
|
||||
return new OutputState(_q);
|
||||
}
|
||||
}
|
||||
|
||||
internal class DFlipFlopGate : GateDefinition
|
||||
{
|
||||
public override string[] Inputs { get; } = new string[] { "D", "CLK" };
|
||||
public override string[] Outputs { get; } = new string[] { "Q" };
|
||||
internal override Dictionary<InputState, OutputState> TruthTable => EmptyTruthTable;
|
||||
public new string Name => "D Flip-Flop";
|
||||
public new bool HasState => true;
|
||||
|
||||
private bool _q;
|
||||
private bool _lastClk;
|
||||
|
||||
internal new OutputState Compute(InputState input)
|
||||
{
|
||||
bool d = input[0];
|
||||
bool clk = input[1];
|
||||
if (clk && !_lastClk) // rising edge
|
||||
_q = d;
|
||||
_lastClk = clk;
|
||||
return new OutputState(_q);
|
||||
}
|
||||
}
|
||||
|
||||
internal class TFlipFlopGate : GateDefinition
|
||||
{
|
||||
public override string[] Inputs { get; } = new string[] { "T", "CLK" };
|
||||
public override string[] Outputs { get; } = new string[] { "Q" };
|
||||
internal override Dictionary<InputState, OutputState> TruthTable => EmptyTruthTable;
|
||||
public new string Name => "T Flip-Flop";
|
||||
public new bool HasState => true;
|
||||
|
||||
private bool _q;
|
||||
private bool _lastClk;
|
||||
|
||||
internal new OutputState Compute(InputState input)
|
||||
{
|
||||
bool t = input[0];
|
||||
bool clk = input[1];
|
||||
if (clk && !_lastClk) // rising edge
|
||||
if (t)
|
||||
_q = !_q;
|
||||
_lastClk = clk;
|
||||
return new OutputState(_q);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fdbb8b9c639517440a7c57882d954ef1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Executable
+30
@@ -0,0 +1,30 @@
|
||||
namespace UntitledLogicGame.Workspace.Gates
|
||||
{
|
||||
public enum GateType
|
||||
{
|
||||
// 000 - Technical
|
||||
NONE = 000,
|
||||
// 100 - Special
|
||||
IN = 100,
|
||||
OUT = 110,
|
||||
// 200 - Basic
|
||||
BUF = 200,
|
||||
AND = 210,
|
||||
OR = 220,
|
||||
XOR = 230,
|
||||
// 300 - Inverted Basic
|
||||
NOT = 300,
|
||||
NAND = 310,
|
||||
NOR = 320,
|
||||
XNOR = 330,
|
||||
// 400 - Latches
|
||||
SRLatch = 400,
|
||||
JKLatch = 410,
|
||||
DLatch = 420,
|
||||
// 500 - Flip-Flops
|
||||
SRFlipFlop = 500,
|
||||
JKFlipFlop = 510,
|
||||
DFlipFlop = 520,
|
||||
TFlipFlop = 530
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4619035df28c4374498d0bafc176449e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Executable
+79
@@ -0,0 +1,79 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace UntitledLogicGame.Workspace.Gates
|
||||
{
|
||||
internal class InputState : State
|
||||
{
|
||||
public InputState(IEnumerable<bool> args) : base(args) { }
|
||||
|
||||
public InputState(params bool[] args) : base(args) { }
|
||||
|
||||
public InputState(int len) : base(len) { }
|
||||
}
|
||||
|
||||
internal class OutputState : State
|
||||
{
|
||||
public OutputState(IEnumerable<bool> args) : base(args) { }
|
||||
|
||||
public OutputState(params bool[] args) : base(args) { }
|
||||
|
||||
public OutputState(int len) : base(len) { }
|
||||
}
|
||||
|
||||
internal abstract class State
|
||||
{
|
||||
internal int Length => values.Length;
|
||||
|
||||
internal bool[] values;
|
||||
|
||||
public State(IEnumerable<bool> args)
|
||||
{
|
||||
values = args.ToArray();
|
||||
}
|
||||
|
||||
public State(params bool[] args)
|
||||
{
|
||||
values = args;
|
||||
}
|
||||
|
||||
public State(int len)
|
||||
{
|
||||
values = new bool[len];
|
||||
}
|
||||
|
||||
public bool this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (index < 0 || index >= values.Length)
|
||||
return false;
|
||||
return values[index];
|
||||
}
|
||||
set
|
||||
{
|
||||
if (index >= 0 && index < values.Length)
|
||||
values[index] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is State state && Enumerable.SequenceEqual(values, state.values);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
//https://stackoverflow.com/questions/6832139/gethashcode-from-booleans-only
|
||||
int hash = 17;
|
||||
for (int index = 0; index < values.Length; index++)
|
||||
hash = hash * 23 + values[index].GetHashCode();
|
||||
return hash;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Join(",", values);
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ae92d013688882845845e2ed4cba3896
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user