/******************************************************************************* * 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.arith; 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 ShifterHDLGeneratorFactory extends AbstractHDLGeneratorFactory { final private static String ShiftModeStr = "ShifterMode"; final private static int ShiftModeId = -1; @Override public String getComponentStringIdentifier() { return "Shifter"; } @Override public SortedMap<String, Integer> GetInputList(Netlist TheNetlist, AttributeSet attrs) { SortedMap<String, Integer> Inputs = new TreeMap<String, Integer>(); Inputs.put("DataA", attrs.getValue(StdAttr.WIDTH).getWidth()); Inputs.put("ShiftAmount", getNrofShiftBits(attrs)); return Inputs; } @Override public ArrayList<String> GetModuleFunctionality(Netlist TheNetlist, AttributeSet attrs, FPGAReport Reporter, String HDLType) { ArrayList<String> Contents = new ArrayList<String>(); int nrOfBits = attrs.getValue(StdAttr.WIDTH).getWidth(); if (HDLType.equals(Settings.VHDL)) { Contents.add(" -----------------------------------------------------------------------------"); Contents.add(" --- ShifterMode represents when: ---"); Contents.add(" --- 0 : Logical Shift Left ---"); Contents.add(" --- 1 : Rotate Left ---"); Contents.add(" --- 2 : Logical Shift Right ---"); Contents.add(" --- 3 : Arithmetic Shift Right ---"); Contents.add(" --- 4 : Rotate Right ---"); Contents.add(" -----------------------------------------------------------------------------"); Contents.add(""); Contents.add(""); if (nrOfBits == 1) { Contents.add(" Result <= DataA WHEN " + ShiftModeStr + " = 1 OR"); Contents.add(" " + ShiftModeStr + " = 3 OR"); Contents.add(" " + ShiftModeStr + " = 4 ELSE DataA AND NOT(ShiftAmount);"); } else { int stage; for (stage = 0; stage < getNrofShiftBits(attrs); stage++) { Contents.addAll(GetStageFunctionalityVHDL(stage, nrOfBits)); } Contents.add(" -----------------------------------------------------------------------------"); Contents.add(" --- Here we assign the result ---"); Contents.add(" -----------------------------------------------------------------------------"); Contents.add(""); Contents.add(" Result <= s_stage_" + Integer.toString(getNrofShiftBits(attrs) - 1) + "_result;"); Contents.add(""); } } else { Contents.add(" /***************************************************************************"); Contents.add(" ** ShifterMode represents when: **"); Contents.add(" ** 0 : Logical Shift Left **"); Contents.add(" ** 1 : Rotate Left **"); Contents.add(" ** 2 : Logical Shift Right **"); Contents.add(" ** 3 : Arithmetic Shift Right **"); Contents.add(" ** 4 : Rotate Right **"); Contents.add(" ***************************************************************************/"); Contents.add(""); Contents.add(""); if (nrOfBits == 1) { Contents.add(" assign Result = ((" + ShiftModeStr + " == 1)||"); Contents.add(" (" + ShiftModeStr + " == 3)||"); Contents.add(" (" + ShiftModeStr + " == 4)) ? DataA : DataA&(~ShiftAmount);"); } else { int stage; for (stage = 0; stage < getNrofShiftBits(attrs); stage++) { Contents.addAll(GetStageFunctionalityVerilog(stage, nrOfBits)); } Contents.add(" /***************************************************************************"); Contents.add(" ** Here we assign the result **"); Contents.add(" ***************************************************************************/"); Contents.add(""); Contents.add(" assign Result = s_stage_" + Integer.toString(getNrofShiftBits(attrs) - 1) + "_result;"); Contents.add(""); } } return Contents; } private int getNrofShiftBits(AttributeSet attrs) { int inputbits = attrs.getValue(StdAttr.WIDTH).getWidth(); int shift = 1; while ((1 << shift) < inputbits) shift++; return shift; } @Override public SortedMap<String, Integer> GetOutputList(Netlist TheNetlist, AttributeSet attrs) { SortedMap<String, Integer> Outputs = new TreeMap<String, Integer>(); int inputbits = attrs.getValue(StdAttr.WIDTH).getWidth(); Outputs.put("Result", inputbits); return Outputs; } @Override public SortedMap<Integer, String> GetParameterList(AttributeSet attrs) { SortedMap<Integer, String> Parameters = new TreeMap<Integer, String>(); Parameters.put(ShiftModeId, ShiftModeStr); return Parameters; } @Override public SortedMap<String, Integer> GetParameterMap(Netlist Nets, NetlistComponent ComponentInfo, FPGAReport Reporter) { SortedMap<String, Integer> ParameterMap = new TreeMap<String, Integer>(); Object shift = ComponentInfo.GetComponent().getAttributeSet() .getValue(Shifter.ATTR_SHIFT); if (shift == Shifter.SHIFT_LOGICAL_LEFT) ParameterMap.put(ShiftModeStr, 0); else if (shift == Shifter.SHIFT_ROLL_LEFT) ParameterMap.put(ShiftModeStr, 1); else if (shift == Shifter.SHIFT_LOGICAL_RIGHT) ParameterMap.put(ShiftModeStr, 2); else if (shift == Shifter.SHIFT_ARITHMETIC_RIGHT) ParameterMap.put(ShiftModeStr, 3); else ParameterMap.put(ShiftModeStr, 4); return ParameterMap; } @Override public SortedMap<String, String> GetPortMap(Netlist Nets, NetlistComponent ComponentInfo, FPGAReport Reporter, String HDLType) { SortedMap<String, String> PortMap = new TreeMap<String, String>(); PortMap.putAll(GetNetMap("DataA", true, ComponentInfo, Shifter.IN0, Reporter, HDLType, Nets)); PortMap.putAll(GetNetMap("ShiftAmount", true, ComponentInfo, Shifter.IN1, Reporter, HDLType, Nets)); PortMap.putAll(GetNetMap("Result", true, ComponentInfo, Shifter.OUT, Reporter, HDLType, Nets)); return PortMap; } private ArrayList<String> GetStageFunctionalityVerilog(int StageNumber, int NrOfBits) { ArrayList<String> Contents = new ArrayList<String>(); int nr_of_bits_to_shift = (1 << StageNumber); Contents.add(" /***************************************************************************"); Contents.add(" ** Here stage " + StageNumber + " of the binairy shift tree is defined **"); Contents.add(" ***************************************************************************/"); Contents.add(""); if (StageNumber == 0) { Contents.add(" assign s_stage_0_shiftin = ((" + ShiftModeStr + "== 1)||(" + ShiftModeStr + "==3)) ?"); Contents.add(" DataA[" + Integer.toString(NrOfBits - 1) + "] :"); Contents.add(" (" + ShiftModeStr + "== 4) ? DataA[0] : 0;"); Contents.add(""); Contents.add(" assign s_stage_0_result = (ShiftAmount == 0) ? DataA :"); Contents.add(" ((" + ShiftModeStr + "== 0) || (" + ShiftModeStr + "== 1)) ?"); Contents.add(" {DataA[" + Integer.toString(NrOfBits - 2) + ":0],s_stage_0_shiftin} :"); Contents.add(" {s_stage_0_shiftin,DataA[" + Integer.toString(NrOfBits - 1) + ":1]};"); Contents.add(""); } else { Contents.add(" assign s_stage_" + StageNumber + "_shiftin = (" + ShiftModeStr + "== 1) ?"); Contents.add(" s_stage_" + Integer.toString(StageNumber - 1) + "_result[" + Integer.toString(NrOfBits - 1) + ":" + Integer.toString(NrOfBits - nr_of_bits_to_shift) + "] : "); Contents.add(" (" + ShiftModeStr + "== 3) ?"); Contents.add(" {" + nr_of_bits_to_shift + "{s_stage_" + Integer.toString(StageNumber - 1) + "_result[" + Integer.toString(NrOfBits - 1) + "]}} :"); Contents.add(" (" + ShiftModeStr + "== 4) ?"); Contents.add(" s_stage_" + Integer.toString(StageNumber - 1) + "_result[" + Integer.toString(nr_of_bits_to_shift - 1) + ":0] : 0;"); Contents.add(""); Contents.add(" assign s_stage_" + StageNumber + "_result = (ShiftAmount[" + StageNumber + "]==0) ?"); Contents.add(" s_stage_" + Integer.toString(StageNumber - 1) + "_result : "); Contents.add(" ((" + ShiftModeStr + "== 0)||(" + ShiftModeStr + "== 1)) ?"); Contents.add(" {s_stage_" + Integer.toString(StageNumber - 1) + "_result[" + Integer.toString(NrOfBits - nr_of_bits_to_shift - 1) + ":0],s_stage_" + StageNumber + "_shiftin} :"); Contents.add(" {s_stage_" + StageNumber + "_shiftin,s_stage_" + Integer.toString(StageNumber - 1) + "_result[" + Integer.toString(NrOfBits - 1) + ":" + Integer.toString(nr_of_bits_to_shift) + "]};"); Contents.add(""); } return Contents; } private ArrayList<String> GetStageFunctionalityVHDL(int StageNumber, int NrOfBits) { ArrayList<String> Contents = new ArrayList<String>(); int nr_of_bits_to_shift = (1 << StageNumber); Contents.add(" -----------------------------------------------------------------------------"); Contents.add(" --- Here stage " + StageNumber + " of the binairy shift tree is defined ---"); Contents.add(" -----------------------------------------------------------------------------"); Contents.add(""); if (StageNumber == 0) { Contents.add(" s_stage_0_shiftin <= DataA(" + Integer.toString(NrOfBits - 1) + ") WHEN " + ShiftModeStr + " = 1 OR " + ShiftModeStr + " = 3 ELSE"); Contents.add(" DataA(0) WHEN " + ShiftModeStr + " = 4 ELSE '0';"); Contents.add(""); Contents.add(" s_stage_0_result <= DataA"); if (NrOfBits == 2) Contents.add(" WHEN ShiftAmount = '0' ELSE"); else Contents.add(" WHEN ShiftAmount(0) = '0' ELSE"); Contents.add(" DataA(" + Integer.toString(NrOfBits - 2) + " DOWNTO 0)&s_stage_0_shiftin"); Contents.add(" WHEN " + ShiftModeStr + " = 0 OR " + ShiftModeStr + " = 1 ELSE"); Contents.add(" s_stage_0_shiftin&DataA(" + Integer.toString(NrOfBits - 1) + " DOWNTO 1);"); Contents.add(""); } else { Contents.add(" s_stage_" + StageNumber + "_shiftin <= s_stage_" + Integer.toString(StageNumber - 1) + "_result( " + Integer.toString(NrOfBits - 1) + " DOWNTO " + Integer.toString(NrOfBits - nr_of_bits_to_shift) + " ) WHEN " + ShiftModeStr + " = 1 ELSE"); Contents.add(" (OTHERS => s_stage_" + Integer.toString(StageNumber - 1) + "_result(" + Integer.toString(NrOfBits - 1) + ")) WHEN " + ShiftModeStr + " = 3 ELSE"); Contents.add(" s_stage_" + Integer.toString(StageNumber - 1) + "_result( " + Integer.toString(nr_of_bits_to_shift - 1) + " DOWNTO 0 ) WHEN " + ShiftModeStr + " = 4 ELSE"); Contents.add(" (OTHERS => '0');"); Contents.add(""); Contents.add(" s_stage_" + StageNumber + "_result <= s_stage_" + Integer.toString(StageNumber - 1) + "_result"); Contents.add(" WHEN ShiftAmount(" + StageNumber + ") = '0' ELSE"); Contents.add(" s_stage_" + Integer.toString(StageNumber - 1) + "_result( " + Integer.toString(NrOfBits - nr_of_bits_to_shift - 1) + " DOWNTO 0 )&s_stage_" + StageNumber + "_shiftin"); Contents.add(" WHEN " + ShiftModeStr + " = 0 OR " + ShiftModeStr + " = 1 ELSE"); Contents.add(" s_stage_" + StageNumber + "_shiftin&s_stage_" + Integer.toString(StageNumber - 1) + "_result( " + Integer.toString(NrOfBits - 1) + " DOWNTO " + Integer.toString(nr_of_bits_to_shift) + " );"); Contents.add(""); } return Contents; } @Override public String GetSubDir() { return "arithmetic"; } @Override public SortedMap<String, Integer> GetWireList(AttributeSet attrs, Netlist Nets) { SortedMap<String, Integer> Wires = new TreeMap<String, Integer>(); int shift = getNrofShiftBits(attrs); int loop; for (loop = 0; loop < shift; loop++) { Wires.put("s_stage_" + loop + "_result", attrs.getValue(StdAttr.WIDTH).getWidth()); Wires.put("s_stage_" + loop + "_shiftin", 1 << loop); } return Wires; } @Override public boolean HDLTargetSupported(String HDLType, AttributeSet attrs) { return true; } }