/******************************************************************************* * This file is part of logisim-evolution. * * logisim-evolution is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * logisim-evolution is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with logisim-evolution. If not, see <http://www.gnu.org/licenses/>. * * Original code by Carl Burch (http://www.cburch.com), 2011. * Subsequent modifications by : * + Haute École Spécialisée Bernoise * http://www.bfh.ch * + Haute École du paysage, d'ingénierie et d'architecture de Genève * http://hepia.hesge.ch/ * + Haute École d'Ingénierie et de Gestion du Canton de Vaud * http://www.heig-vd.ch/ * The project is currently maintained by : * + REDS Institute - HEIG-VD * Yverdon-les-Bains, Switzerland * http://reds.heig-vd.ch *******************************************************************************/ package com.cburch.logisim.std.gates; import java.util.ArrayList; import java.util.SortedMap; import java.util.TreeMap; import com.bfh.logisim.designrulecheck.Netlist; import com.bfh.logisim.designrulecheck.NetlistComponent; import com.bfh.logisim.fpgagui.FPGAReport; import com.bfh.logisim.hdlgenerator.AbstractHDLGeneratorFactory; import com.bfh.logisim.settings.Settings; import com.cburch.logisim.data.AttributeSet; import com.cburch.logisim.instance.StdAttr; public class AbstractGateHDLGenerator extends AbstractHDLGeneratorFactory { private final static int BitWidthGeneric = -1; private final static String BitWidthString = "NrOfBits"; private final static int BubblesGeneric = -2; private final static String BubblesString = "BubblesMask"; @Override public String getComponentStringIdentifier() { return "GATE"; } public boolean GetFloatingValue(boolean is_inverted) { return !is_inverted; } @Override public SortedMap<String, Integer> GetInputList(Netlist TheNetlist, AttributeSet attrs) { SortedMap<String, Integer> MyInputs = new TreeMap<String, Integer>(); int Bitwidth = (is_bus(attrs)) ? BitWidthGeneric : 1; int NrOfInputs = attrs.containsAttribute(GateAttributes.ATTR_INPUTS) ? attrs .getValue(GateAttributes.ATTR_INPUTS) : 1; for (int i = 0; i < NrOfInputs; i++) { MyInputs.put("Input_" + Integer.toString(i + 1), Bitwidth); } return MyInputs; } public ArrayList<String> GetLogicFunction(int nr_of_inputs, int bitwidth, boolean is_one_hot, String HDLType) { return new ArrayList<String>(); } @Override public ArrayList<String> GetModuleFunctionality(Netlist TheNetlist, AttributeSet attrs, FPGAReport Reporter, String HDLType) { ArrayList<String> Contents = new ArrayList<String>(); int Bitwidth = attrs.getValue(StdAttr.WIDTH).getWidth(); int NrOfInputs = attrs.containsAttribute(GateAttributes.ATTR_INPUTS) ? attrs .getValue(GateAttributes.ATTR_INPUTS) : 1; if (NrOfInputs > 1) { Contents.add(""); Contents.addAll(MakeRemarkBlock("Here the bubbles are processed", 3, HDLType)); if (HDLType.equals(Settings.VHDL)) { String AllignmentSpaces; if (NrOfInputs < 10) AllignmentSpaces = " "; else if (NrOfInputs < 100) AllignmentSpaces = " "; else AllignmentSpaces = " "; Contents.add(" s_signal_invert_mask <= std_logic_vector(to_unsigned(" + BubblesString + "," + Integer.toString(NrOfInputs) + "));"); String WhenLineBegin = ""; for (int i = 0; i < 21 + AllignmentSpaces.length(); i++) WhenLineBegin += " "; for (int i = 0; i < NrOfInputs; i++) { String LocalSpaces; if (i < 10) LocalSpaces = AllignmentSpaces; else if (i < 100) LocalSpaces = AllignmentSpaces.substring(0, AllignmentSpaces.length() - 1); else if (i < 1000) LocalSpaces = AllignmentSpaces.substring(0, AllignmentSpaces.length() - 2); else LocalSpaces = " "; Contents.add(" s_real_input_" + Integer.toString(i + 1) + LocalSpaces + " <= NOT( Input_" + Integer.toString(i + 1) + " )"); Contents.add(WhenLineBegin + " WHEN s_signal_invert_mask(" + Integer.toString(i) + ") = '1' ELSE"); Contents.add(WhenLineBegin + "Input_" + Integer.toString(i + 1) + ";"); } } else { Contents.add(" assign s_signal_invert_mask = " + BubblesString + ";"); for (int i = 0; i < NrOfInputs; i++) { Contents.add(" assign s_real_input_" + Integer.toString(i + 1) + " = (s_signal_invert_mask[" + Integer.toString(i) + "]) ? ~Input_" + Integer.toString(i + 1) + ":" + " Input_" + Integer.toString(i + 1) + ";"); } } } Contents.add(""); Contents.addAll(MakeRemarkBlock("Here the functionality is defined", 3, HDLType)); boolean onehot = false; if (attrs.containsAttribute(GateAttributes.ATTR_XOR)) { onehot = attrs.getValue(GateAttributes.ATTR_XOR) == GateAttributes.XOR_ONE; } Contents.addAll(GetLogicFunction(NrOfInputs, Bitwidth, onehot, HDLType)); return Contents; } public ArrayList<String> GetOneHot(boolean inverted, int nr_of_inputs, boolean is_bus, String HDLType) { ArrayList<String> Lines = new ArrayList<String>(); String Spaces = " "; String IndexString = ""; String NotOperation = (HDLType.equals(Settings.VHDL)) ? "NOT" : "~"; String AndOperation = (HDLType.equals(Settings.VHDL)) ? "AND" : "&"; String OrOperation = (HDLType.equals(Settings.VHDL)) ? "OR" : "|"; String Preamble = (HDLType.equals(Settings.VHDL)) ? "" : "assign "; String AssignOperation = (HDLType.equals(Settings.VHDL)) ? " <= " : " = "; if (is_bus) { if (HDLType.equals(Settings.VHDL)) { Lines.add(Spaces + "GenBits : FOR n IN (" + BitWidthString + "-1) DOWNTO 0 GENERATE"); Spaces += " "; IndexString = "(n)"; } else { Lines.add(" genvar n;"); Lines.add(" generate"); Lines.add(" for (n = 0 ; n < " + BitWidthString + " ; n = n + 1)"); Lines.add(" begin: bit"); Spaces += " "; IndexString = "[n]"; } } StringBuffer OneLine = new StringBuffer(); OneLine.append(Spaces + Preamble + "Result" + IndexString + AssignOperation); if (inverted) OneLine.append(NotOperation + "("); int spaces = OneLine.length(); for (int termloop = 0; termloop < nr_of_inputs; termloop++) { while (OneLine.length() < spaces) { OneLine.append(" "); } OneLine.append("("); for (int i = 0; i < nr_of_inputs; i++) { if (i == termloop) OneLine.append("s_real_input_" + Integer.toString(i + 1) + IndexString); else OneLine.append(NotOperation + "(s_real_input_" + Integer.toString(i + 1) + IndexString + ")"); if (i < (nr_of_inputs - 1)) { OneLine.append(" " + AndOperation + " "); } } OneLine.append(")"); if (termloop < (nr_of_inputs - 1)) { OneLine.append(" " + OrOperation + " "); } else { if (inverted) OneLine.append(")"); OneLine.append(";"); } Lines.add(OneLine.toString()); OneLine.setLength(0); } if (is_bus) { if (HDLType.equals(Settings.VHDL)) { Lines.add(" END GENERATE GenBits;"); } else { Lines.add(" end"); Lines.add(" endgenerate"); } } return Lines; } @Override public SortedMap<String, Integer> GetOutputList(Netlist TheNetlist, AttributeSet attrs) { SortedMap<String, Integer> MyOutputs = new TreeMap<String, Integer>(); int Bitwidth = (is_bus(attrs)) ? BitWidthGeneric : 1; MyOutputs.put("Result", Bitwidth); return MyOutputs; } @Override public SortedMap<Integer, String> GetParameterList(AttributeSet attrs) { SortedMap<Integer, String> MyParameters = new TreeMap<Integer, String>(); int NrOfInputs = attrs.containsAttribute(GateAttributes.ATTR_INPUTS) ? attrs .getValue(GateAttributes.ATTR_INPUTS) : 1; if (is_bus(attrs)) { MyParameters.put(BitWidthGeneric, BitWidthString); } if (NrOfInputs > 1) { MyParameters.put(BubblesGeneric, BubblesString); } return MyParameters; } @Override public SortedMap<String, Integer> GetParameterMap(Netlist Nets, NetlistComponent ComponentInfo, FPGAReport Reporter) { SortedMap<String, Integer> ParameterMap = new TreeMap<String, Integer>(); boolean is_bus = is_bus(ComponentInfo.GetComponent().getAttributeSet()); AttributeSet Myattrs = ComponentInfo.GetComponent().getAttributeSet(); int NrOfInputs = Myattrs.containsAttribute(GateAttributes.ATTR_INPUTS) ? Myattrs .getValue(GateAttributes.ATTR_INPUTS) : 1; int bubleMask, mask; if (is_bus) { ParameterMap.put(BitWidthString, Myattrs.getValue(StdAttr.WIDTH) .getWidth()); } if (NrOfInputs > 1) { bubleMask = 0; mask = 1; for (int i = 0; i < NrOfInputs; i++) { boolean input_is_inverted = ComponentInfo.GetComponent() .getAttributeSet() .getValue(new NegateAttribute(i, null)); if (input_is_inverted) bubleMask |= mask; mask <<= 1; } ParameterMap.put(BubblesString, bubleMask); } return ParameterMap; } public ArrayList<String> GetParity(boolean inverted, int nr_of_inputs, boolean is_bus, String HDLType) { ArrayList<String> Lines = new ArrayList<String>(); String Spaces = " "; String IndexString = ""; String XorOperation = (HDLType.equals(Settings.VHDL)) ? " XOR" : "^"; String NotOperation = (HDLType.equals(Settings.VHDL)) ? "NOT" : "~"; String Preamble = (HDLType.equals(Settings.VHDL)) ? "" : "assign "; String AssignOperation = (HDLType.equals(Settings.VHDL)) ? " <= " : " = "; if (is_bus) { if (HDLType.equals(Settings.VHDL)) { Lines.add(Spaces + "GenBits : FOR n IN (" + BitWidthString + "-1) DOWNTO 0 GENERATE"); Spaces += " "; IndexString = "(n)"; } else { Lines.add(" genvar n;"); Lines.add(" generate"); Lines.add(" for (n = 0 ; n < " + BitWidthString + " ; n = n + 1)"); Lines.add(" begin: bit"); Spaces += " "; IndexString = "[n]"; } } StringBuffer OneLine = new StringBuffer(); OneLine.append(Spaces + Preamble + "Result" + IndexString + AssignOperation); if (inverted) OneLine.append(NotOperation + "("); int spaces = OneLine.length(); for (int i = 0; i < nr_of_inputs; i++) { while (OneLine.length() < spaces) { OneLine.append(" "); } OneLine.append("s_real_input_" + Integer.toString(i + 1) + IndexString); if (i < (nr_of_inputs - 1)) { OneLine.append(XorOperation); } else { if (inverted) OneLine.append(")"); OneLine.append(";"); } Lines.add(OneLine.toString()); OneLine.setLength(0); } if (is_bus) { if (HDLType.equals(Settings.VHDL)) { Lines.add(" END GENERATE GenBits;"); } else { Lines.add(" end"); Lines.add(" endgenerate"); } } return Lines; } @Override public SortedMap<String, String> GetPortMap(Netlist Nets, NetlistComponent ComponentInfo, FPGAReport Reporter, String HDLType) { SortedMap<String, String> PortMap = new TreeMap<String, String>(); AttributeSet attrs = ComponentInfo.GetComponent().getAttributeSet(); int NrOfInputs = attrs.containsAttribute(GateAttributes.ATTR_INPUTS) ? attrs .getValue(GateAttributes.ATTR_INPUTS) : 1; boolean[] InputFloatingValues = new boolean[NrOfInputs]; if (NrOfInputs == 1) { InputFloatingValues[0] = true; } else { for (int i = 1; i <= NrOfInputs; i++) { boolean input_is_inverted = attrs.getValue(new NegateAttribute( i - 1, null)); InputFloatingValues[i - 1] = GetFloatingValue(input_is_inverted); } } for (int i = 1; i <= NrOfInputs; i++) { PortMap.putAll(GetNetMap("Input_" + Integer.toString(i), InputFloatingValues[i - 1], ComponentInfo, i, Reporter, HDLType, Nets)); } PortMap.putAll(GetNetMap("Result", true, ComponentInfo, 0, Reporter, HDLType, Nets)); return PortMap; } @Override public String GetSubDir() { /* * this method returns the module directory where the HDL code needs to * be placed */ return "gates"; } @Override public SortedMap<String, Integer> GetWireList(AttributeSet attrs, Netlist Nets) { SortedMap<String, Integer> Wires = new TreeMap<String, Integer>(); int Bitwidth = attrs.getValue(StdAttr.WIDTH).getWidth(); int NrOfInputs = attrs.containsAttribute(GateAttributes.ATTR_INPUTS) ? attrs .getValue(GateAttributes.ATTR_INPUTS) : 1; if (NrOfInputs > 1) { for (int i = 0; i < NrOfInputs; i++) { if (Bitwidth > 1) Wires.put("s_real_input_" + Integer.toString(i + 1), BitWidthGeneric); else Wires.put("s_real_input_" + Integer.toString(i + 1), 1); } Wires.put("s_signal_invert_mask", NrOfInputs); } return Wires; } @Override public boolean HDLTargetSupported(String HDLType, AttributeSet attrs) { return true; } private boolean is_bus(AttributeSet attrs) { return attrs.getValue(StdAttr.WIDTH).getWidth() != 1; } }