/// <summary> /// This method is used as a way to map out connection names for the HDL. It also verifies there is never more than one input to a wire group. /// *****NOTE: This is NOT where we actually link wires to gates, this is ONLY for determining input and output naming of wire groups /// For the most part we only care about inputs with this, because inputs are what can conflict and what we will use to determine naming /// </summary> /// <param name="circuit">The circuit you want to process</param> /// <returns>The same circuit with parsed wiregroup inputs</returns> public static LogicalCircuit FindWireGroupInputs(LogicalCircuit circuit) { //We run through pins first, as they tend to define how HDL is written in many cases foreach (var pin in circuit.circuits) { if (pin.GetType() == typeof(Pin)) //We only continue if we find a pin here { Pin temp = (Pin)pin; //Load the pin Coords pinLocation = new Coords(temp.Symbol.Location); //Load the pins location if (temp.Type == PinType.Input) { pinLocation.x = pinLocation.x + temp.rightOffset.OffsetX;//Correct the location for offset. pinLocation.y = pinLocation.y + temp.rightOffset.OffsetY; for (int i = 0; i < circuit.wireGroups.Count; i++) { if (circuit.wireGroups[i].coords.Exists(x => x.x == pinLocation.x && x.y == pinLocation.y)) //Read through wiregroups to see if the pin connects to them { circuit.wireGroups[i].inputList.Add(temp.Name); //If they do add them to the input list. //As a note, this input list **SHOULD** only ever have ONE(1) item in it, if there is more than one the project is invalid.(or we messed up parsing) circuit.outputNames.Add(temp.Name); //Save the name break; } } } else if (temp.Type == PinType.Output)//This is the same as the input section, with a different offset, AND there CAN be more than one output { pinLocation.x = pinLocation.x + temp.leftOffset.OffsetX; pinLocation.y = pinLocation.y + temp.leftOffset.OffsetY; for (int i = 0; i < circuit.wireGroups.Count; i++) { if (circuit.wireGroups[i].coords.Exists(x => x.x == pinLocation.x && x.y == pinLocation.y)) { circuit.wireGroups[i].outputList.Add(temp.Name); circuit.outputNames.Add(temp.Name); break; } } } else { continue; } } } foreach (var gate in circuit.gates) //Iterate through gates to find outputs(Or inputs) { Coords pinLocation = new Coords(gate.Symbol.Location); //Load the location pinLocation.x = pinLocation.x + gate.RightPinOffset[gate.GetSize()].OffsetX; //Correct for offset based on size. pinLocation.y = pinLocation.y + gate.RightPinOffset[gate.GetSize()].OffsetY; for (int i = 0; i < circuit.wireGroups.Count; i++)//Run through each wiregroup { if (circuit.wireGroups[i].coords.Exists(x => x.x == pinLocation.x && x.y == pinLocation.y)) { var name = CheckUnusedName(gate.HDLGateNotation, circuit); gate.OutputName = name; circuit.outputNames.Add(name); circuit.wireGroups[i].inputList.Add(name); break; } } } foreach (var group in circuit.wireGroups)//Check each group to make sure there isnt more than one input { if (group.inputList.Count > 1) { throw new Exception("WireGroup Source Count Exception: There cannot be more than one data source on a wire group!"); } } return(circuit); }
/// <summary> /// This function maps circuitsymbols to their associated circuit. /// If a symbol does not have an associated circuit it is a gate. /// </summary> /// <param name="circuits">All circuits in a group</param> /// <param name="symbols">All symbols</param> /// <param name="parent">The logical circuit parent of the circuits.</param> /// <returns></returns> public static List <CircuitBase> ConnectSymbolsToCircuits(List <CircuitBase> circuits, List <CircuitSymbol> symbols, LogicalCircuit parent) { foreach (var symbol in symbols) { int index = circuits.FindIndex(x => x.Id == symbol.CircuitId); if (index != -1) { circuits[index].Symbol = symbol; } else if (symbol.CircuitId == parent.Id) { parent.locationSymbols.Add(symbol); } } return(circuits); }
/// <summary> /// This method is used to write the HDL for this gate /// NOTE: There is a CUSTOM implementation of this method for the NOT gate /// </summary> /// <param name="groups">The wiregroups in the logicalcircuit this gate exists in.</param> /// <param name="circuit">The logical circuit this gate exists in</param> /// <returns>The HDL string of this gate</returns> public string WriteGateHDL(List <WireGroup> groups, LogicalCircuit circuit) { int size = GetSize(); string output = ""; string tempName = ""; string overrideOutputName = ""; bool gateConnectsToOutput = false; //This is used to determine if we connect to the output pin, which overrides wiregroup naming conventions Coords outputCoords = new Coords(Symbol.Location); //Find the location of this gate outputCoords.x = outputCoords.x + RightPinOffset[size].OffsetX; //Set location to output pin of gate outputCoords.y = outputCoords.y + RightPinOffset[size].OffsetY; foreach (var group in groups) //Find the wiregroup connected to the outpu { if (ConnectsToRightWireGroup(group)) { if (group.outputList.Count > 0) { gateConnectsToOutput = true; overrideOutputName = group.outputList[0]; tempName = overrideOutputName; } } } if (!gateConnectsToOutput) { tempName = OutputName; } //This block created a linked set of the base HDL gate, which allows us to support logiccircuits multi-input(up to 18, but we support as many as there is in theory) Dictionary <int, string> inputs = FindConnectedGroups(groups); if (inputs.Count == size) { if (size > 2) //If there is more than two outputs we must nest with the built-in HDL gate type { if (gateConnectsToOutput) //This causes a naming override { tempName = Converter.CheckUnusedName(overrideOutputName, circuit); } else { tempName = Converter.CheckUnusedName(OutputName, circuit); } output += "\t" + HDLGateNotation + "(a=" + inputs[0] + ", b=" + inputs[1] + ", out=" + tempName + ");" + Environment.NewLine;//Write the initial gate for (int i = 2; i < inputs.Count; i++) { if (i == (inputs.Count - 1)) { output += "\t" + HDLGateNotation + "(a=" + tempName + ", b=" + inputs[i];//Create another which connects one more input and the output of the previous gate. if (gateConnectsToOutput) { tempName = overrideOutputName; } else { tempName = OutputName; } output += ", out=" + tempName + ");" + Environment.NewLine; } else { output += "\t" + HDLGateNotation + "(a=" + tempName + ", b=" + inputs[i];//On the last nest we connect output. if (gateConnectsToOutput) { tempName = Converter.CheckUnusedName(overrideOutputName, circuit); } else { tempName = Converter.CheckUnusedName(OutputName, circuit); } output += ", out=" + tempName + ");" + Environment.NewLine; } } } else//If this size is two, we can write one line { return("\t" + HDLGateNotation + "(a=" + inputs[0] + ", b=" + inputs[1] + ", out=" + tempName + ");" + Environment.NewLine); } } else { throw new Exception("Invalid Input Count Error: " + inputs.Count + " inputs were provided but the gate reports a size of " + size); } return(output); }