package com.bfh.logisim.library;
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.data.BitWidth;
public class bin2bcdHDLGeneratorFactory extends AbstractHDLGeneratorFactory{
final private static String NrOfBitsStr = "NrOfBits";
final private static int NrOfBitsId = -1;
@Override
public String getComponentStringIdentifier() {
return "BIN2BCD";
}
@Override
public SortedMap<String, Integer> GetInputList( Netlist TheNetlist,
AttributeSet attrs) {
SortedMap<String, Integer> Inputs = new TreeMap<String, Integer>();
Inputs.put("BinValue", NrOfBitsId);
return Inputs;
}
@Override
public SortedMap<String, Integer> GetOutputList( Netlist TheNetlist,
AttributeSet attrs) {
SortedMap<String, Integer> Outputs = new TreeMap<String, Integer>();
BitWidth nrofbits=attrs.getValue(bin2bcd.ATTR_BinBits);
int NrOfPorts = (int)(Math.log10(1<<nrofbits.getWidth())+1.0);
for (int i = 1 ; i <= NrOfPorts; i++) {
Outputs.put("BCD"+Integer.toString((int)(Math.pow(10, i-1))) , 4);
}
return Outputs;
}
@Override
public SortedMap<Integer, String> GetParameterList( AttributeSet attrs ) {
SortedMap<Integer, String> ParameterList = new TreeMap<Integer, String>();
ParameterList.put(NrOfBitsId, NrOfBitsStr);
return ParameterList;
}
@Override
public String GetSubDir() {
return "bfh";
}
@Override
public boolean HDLTargetSupported( String HDLType,
AttributeSet attrs) {
return HDLType.equals(Settings.VHDL);
}
@Override
public SortedMap<String, Integer> GetParameterMap(Netlist Nets,
NetlistComponent ComponentInfo,
FPGAReport Reporter) {
SortedMap<String, Integer> ParameterMap = new TreeMap<String, Integer>();
int BinBits = ComponentInfo.GetComponent().getEnd(0).getWidth().getWidth();
ParameterMap.put(NrOfBitsStr, BinBits);
return ParameterMap;
}
@Override
public SortedMap<String, String> GetPortMap(Netlist Nets,
NetlistComponent ComponentInfo,
FPGAReport Reporter,
String HDLType) {
SortedMap<String, String> PortMap = new TreeMap<String, String>();
int BinBits = ComponentInfo.GetComponent().getEnd(0).getWidth().getWidth();
int NrOfPorts = (int)(Math.log10(1<<BinBits)+1.0);
PortMap.putAll(GetNetMap("BinValue",true,ComponentInfo,0,Reporter,HDLType,Nets));
for (int i = 1 ; i <= NrOfPorts ; i++)
PortMap.putAll(GetNetMap("BCD"+Integer.toString((int)(Math.pow(10, i-1))),true,
ComponentInfo,i,Reporter,HDLType,Nets));
return PortMap;
}
@Override
public SortedMap<String, Integer> GetWireList(AttributeSet attrs,
Netlist Nets) {
SortedMap<String, Integer> Wires = new TreeMap<String, Integer>();
BitWidth nrofbits=attrs.getValue(bin2bcd.ATTR_BinBits);
int NrOfPorts = (int)(Math.log10(1<<nrofbits.getWidth())+1.0);
switch (NrOfPorts) {
case 2 : Wires.put("s_level_0", 7);
Wires.put("s_level_1", 7);
Wires.put("s_level_2", 7);
Wires.put("s_level_3", 7);
break;
case 3 : Wires.put("s_level_0", 11);
Wires.put("s_level_1", 11);
Wires.put("s_level_2", 11);
Wires.put("s_level_3", 11);
Wires.put("s_level_4", 11);
Wires.put("s_level_5", 11);
Wires.put("s_level_6", 11);
break;
case 4 : Wires.put("s_level_0", 16);
Wires.put("s_level_1", 16);
Wires.put("s_level_2", 16);
Wires.put("s_level_3", 16);
Wires.put("s_level_4", 16);
Wires.put("s_level_5", 16);
Wires.put("s_level_6", 16);
Wires.put("s_level_7", 16);
Wires.put("s_level_8", 16);
Wires.put("s_level_9", 16);
Wires.put("s_level_10", 16);
break;
}
return Wires;
}
@Override
public ArrayList<String> GetModuleFunctionality( Netlist TheNetlist,
AttributeSet attrs,
FPGAReport Reporter,
String HDLType) {
ArrayList<String> Contents = new ArrayList<String>();
BitWidth nrofbits=attrs.getValue(bin2bcd.ATTR_BinBits);
int NrOfPorts = (int)(Math.log10(1<<nrofbits.getWidth())+1.0);
if (HDLType.equals(Settings.VHDL)) {
switch (NrOfPorts) {
case 2 : Contents.add(" s_level_0(6 DOWNTO "+NrOfBitsStr+") <= (OTHERS => '0');");
Contents.add(" s_level_0("+NrOfBitsStr+"-1 DOWNTO 0) <= BinValue;");
Contents.add(" s_level_1(2 DOWNTO 0) <= s_level_0(2 DOWNTO 0);");
Contents.add(" s_level_2(1 DOWNTO 0) <= s_level_1(1 DOWNTO 0);");
Contents.add(" s_level_2(6) <= s_level_1(6);");
Contents.add(" s_level_3(6 DOWNTO 5) <= s_level_2(6 DOWNTO 5);");
Contents.add(" s_level_3(0) <= s_level_2(0);");
Contents.add(" ");
Contents.add(" BCD1 <= s_level_3( 3 DOWNTO 0);");
Contents.add(" BCD10 <= \"0\"&s_level_3(6 DOWNTO 4);" );
Contents.addAll(GetAdd3Block("s_level_0",6,"s_level_1",6,"C1"));
Contents.addAll(GetAdd3Block("s_level_1",5,"s_level_2",5,"C2"));
Contents.addAll(GetAdd3Block("s_level_2",4,"s_level_3",4,"C3"));
break;
case 3 : Contents.add(" s_level_0(10 DOWNTO "+NrOfBitsStr+") <= (OTHERS => '0');");
Contents.add(" s_level_0("+NrOfBitsStr+"-1 DOWNTO 0) <= BinValue;");
Contents.add(" s_level_1(10) <= s_level_0(10);");
Contents.add(" s_level_1( 5 DOWNTO 0) <= s_level_0( 5 DOWNTO 0);");
Contents.add(" s_level_2(10 DOWNTO 9) <= s_level_1(10 DOWNTO 9);");
Contents.add(" s_level_2( 4 DOWNTO 0) <= s_level_1( 4 DOWNTO 0);");
Contents.add(" s_level_3(10 DOWNTO 8) <= s_level_2(10 DOWNTO 8);");
Contents.add(" s_level_3( 3 DOWNTO 0) <= s_level_2( 3 DOWNTO 0);");
Contents.add(" s_level_4( 2 DOWNTO 0) <= s_level_3( 2 DOWNTO 0);");
Contents.add(" s_level_5(10) <= s_level_4(10);");
Contents.add(" s_level_5( 1 DOWNTO 0) <= s_level_4( 1 DOWNTO 0);");
Contents.add(" s_level_6(10 DOWNTO 9) <= s_level_5(10 DOWNTO 9);");
Contents.add(" s_level_6(0) <= s_level_5(0);");
Contents.add(" ");
Contents.add(" BCD1 <= s_level_6( 3 DOWNTO 0 );");
Contents.add(" BCD10 <= s_level_6( 7 DOWNTO 4 );");
Contents.add(" BCD100 <= \"0\"&s_level_6(10 DOWNTO 8);");
Contents.addAll(GetAdd3Block("s_level_0",9,"s_level_1",9,"C0"));
Contents.addAll(GetAdd3Block("s_level_1",8,"s_level_2",8,"C1"));
Contents.addAll(GetAdd3Block("s_level_2",7,"s_level_3",7,"C2"));
Contents.addAll(GetAdd3Block("s_level_3",6,"s_level_4",6,"C3"));
Contents.addAll(GetAdd3Block("s_level_4",5,"s_level_5",5,"C4"));
Contents.addAll(GetAdd3Block("s_level_5",4,"s_level_6",4,"C5"));
Contents.addAll(GetAdd3Block("s_level_3",10,"s_level_4",10,"C6"));
Contents.addAll(GetAdd3Block("s_level_4",9,"s_level_5",9,"C7"));
Contents.addAll(GetAdd3Block("s_level_5",8,"s_level_6",8,"C8"));
break;
case 4 : Contents.add(" s_level_0(15 DOWNTO "+NrOfBitsStr+") <= (OTHERS => '0');");
Contents.add(" s_level_0("+NrOfBitsStr+"-1 DOWNTO 0) <= BinValue;");
Contents.add(" s_level_1(15 DOWNTO 14) <= s_level_0(15 DOWNTO 14);");
Contents.add(" s_level_1( 9 DOWNTO 0) <= s_level_0( 9 DOWNTO 0);");
Contents.add(" s_level_2(15 DOWNTO 13) <= s_level_1(15 DOWNTO 13);");
Contents.add(" s_level_2( 8 DOWNTO 0) <= s_level_1( 8 DOWNTO 0);");
Contents.add(" s_level_3(15 DOWNTO 12) <= s_level_2(15 DOWNTO 12);");
Contents.add(" s_level_3( 7 DOWNTO 0) <= s_level_2( 7 DOWNTO 0);");
Contents.add(" s_level_4(15) <= s_level_3(15);");
Contents.add(" s_level_4( 6 DOWNTO 0) <= s_level_3( 6 DOWNTO 0);");
Contents.add(" s_level_5(15 DOWNTO 14) <= s_level_4(15 DOWNTO 14);");
Contents.add(" s_level_5( 5 DOWNTO 0) <= s_level_4( 5 DOWNTO 0);");
Contents.add(" s_level_6(15 DOWNTO 13) <= s_level_5(15 DOWNTO 13);");
Contents.add(" s_level_6( 4 DOWNTO 0) <= s_level_5( 4 DOWNTO 0);");
Contents.add(" s_level_7( 3 DOWNTO 0) <= s_level_6( 3 DOWNTO 0);");
Contents.add(" s_level_8(15) <= s_level_7(15);");
Contents.add(" s_level_8( 2 DOWNTO 0) <= s_level_7( 2 DOWNTO 0);");
Contents.add(" s_level_9(15 DOWNTO 14) <= s_level_8(15 DOWNTO 14);");
Contents.add(" s_level_9( 1 DOWNTO 0) <= s_level_8( 1 DOWNTO 0);");
Contents.add(" s_level_10(15 DOWNTO 13) <= s_level_9(15 DOWNTO 13);");
Contents.add(" s_level_10(0) <= s_level_9(0);");
Contents.add(" ");
Contents.add(" BCD1 <= s_level_10( 3 DOWNTO 0 );");
Contents.add(" BCD10 <= s_level_10( 7 DOWNTO 4 );");
Contents.add(" BCD100 <= s_level_10(11 DOWNTO 8);");
Contents.add(" BCD1000 <= s_level_10(15 DOWNTO 12);");
Contents.addAll(GetAdd3Block("s_level_0",13,"s_level_1" ,13,"C0"));
Contents.addAll(GetAdd3Block("s_level_1",12,"s_level_2" ,12,"C1"));
Contents.addAll(GetAdd3Block("s_level_2",11,"s_level_3" ,11,"C2"));
Contents.addAll(GetAdd3Block("s_level_3",10,"s_level_4" ,10,"C3"));
Contents.addAll(GetAdd3Block("s_level_4", 9,"s_level_5" , 9,"C4"));
Contents.addAll(GetAdd3Block("s_level_5", 8,"s_level_6" , 8,"C5"));
Contents.addAll(GetAdd3Block("s_level_6", 7,"s_level_7" , 7,"C6"));
Contents.addAll(GetAdd3Block("s_level_7", 6,"s_level_8" , 6,"C7"));
Contents.addAll(GetAdd3Block("s_level_8", 5,"s_level_9" , 5,"C8"));
Contents.addAll(GetAdd3Block("s_level_9", 4,"s_level_10", 4,"C9"));
Contents.addAll(GetAdd3Block("s_level_3",14,"s_level_4" ,14,"C10"));
Contents.addAll(GetAdd3Block("s_level_4",13,"s_level_5" ,13,"C11"));
Contents.addAll(GetAdd3Block("s_level_5",12,"s_level_6" ,12,"C12"));
Contents.addAll(GetAdd3Block("s_level_6",11,"s_level_7" ,11,"C13"));
Contents.addAll(GetAdd3Block("s_level_7",10,"s_level_8" ,10,"C14"));
Contents.addAll(GetAdd3Block("s_level_8", 9,"s_level_9" , 9,"C15"));
Contents.addAll(GetAdd3Block("s_level_9", 8,"s_level_10", 8,"C16"));
Contents.addAll(GetAdd3Block("s_level_6",15,"s_level_7" ,15,"C17"));
Contents.addAll(GetAdd3Block("s_level_7",14,"s_level_8" ,14,"C18"));
Contents.addAll(GetAdd3Block("s_level_8",13,"s_level_9" ,13,"C19"));
Contents.addAll(GetAdd3Block("s_level_9",12,"s_level_10",12,"C20"));
break;
}
} else {
Reporter.AddFatalError("Strange, this should not happen as Verilog is not yet supported!\n");
}
return Contents;
}
private ArrayList<String> GetAdd3Block(String SourceName,
int SourceStartId,
String DestName,
int DestStartId,
String ProcessName) {
ArrayList<String> Contents = new ArrayList<String>();
Contents.add(" ");
Contents.add(" ADD3_"+ProcessName+" : PROCESS("+SourceName+")");
Contents.add(" BEGIN");
Contents.add(" CASE ("+SourceName+"("+Integer.toString(SourceStartId)+" DOWNTO "+
Integer.toString(SourceStartId-3)+") ) IS");
Contents.add(" WHEN \"0000\" => "+DestName+"( "+
Integer.toString(DestStartId)+" DOWNTO "+
Integer.toString(DestStartId-3)+" ) <= \"0000\";");
Contents.add(" WHEN \"0001\" => "+DestName+"( "+
Integer.toString(DestStartId)+" DOWNTO "+
Integer.toString(DestStartId-3)+" ) <= \"0001\";");
Contents.add(" WHEN \"0010\" => "+DestName+"( "+
Integer.toString(DestStartId)+" DOWNTO "+
Integer.toString(DestStartId-3)+" ) <= \"0010\";");
Contents.add(" WHEN \"0011\" => "+DestName+"( "+
Integer.toString(DestStartId)+" DOWNTO "+
Integer.toString(DestStartId-3)+" ) <= \"0011\";");
Contents.add(" WHEN \"0100\" => "+DestName+"( "+
Integer.toString(DestStartId)+" DOWNTO "+
Integer.toString(DestStartId-3)+" ) <= \"0100\";");
Contents.add(" WHEN \"0101\" => "+DestName+"( "+
Integer.toString(DestStartId)+" DOWNTO "+
Integer.toString(DestStartId-3)+" ) <= \"1000\";");
Contents.add(" WHEN \"0110\" => "+DestName+"( "+
Integer.toString(DestStartId)+" DOWNTO "+
Integer.toString(DestStartId-3)+" ) <= \"1001\";");
Contents.add(" WHEN \"0111\" => "+DestName+"( "+
Integer.toString(DestStartId)+" DOWNTO "+
Integer.toString(DestStartId-3)+" ) <= \"1010\";");
Contents.add(" WHEN \"1000\" => "+DestName+"( "+
Integer.toString(DestStartId)+" DOWNTO "+
Integer.toString(DestStartId-3)+" ) <= \"1011\";");
Contents.add(" WHEN \"1001\" => "+DestName+"( "+
Integer.toString(DestStartId)+" DOWNTO "+
Integer.toString(DestStartId-3)+" ) <= \"1100\";");
Contents.add(" WHEN OTHERS => "+DestName+"( "+
Integer.toString(DestStartId)+" DOWNTO "+
Integer.toString(DestStartId-3)+" ) <= \"----\";");
Contents.add(" END CASE;");
Contents.add(" END PROCESS ADD3_"+ProcessName+";");
return Contents;
}
}